Module refinery.lib.scripts.ps1.dotnet
The grammar of .NET type names, as PowerShell source writes them and as .NET reflection reports
them. This module is purely syntactic: it turns the text of a type name into a Ps1TypeName and
back, and it knows nothing about which types exist. Deciding what a name refers to — resolving an
accelerator like int, supplying an omitted System. prefix, looking up members — requires the
collected metadata and belongs to refinery.lib.scripts.ps1.data.
The two spellings this has to bridge are the source form and the reflection form:
System.Collections.Generic.List[int]
System.Collections.Generic.List`1[[System.Int32, mscorlib]]
Both name the same open generic type, whose reflection FullName is the Ps1TypeName.definition
of either parse.
Expand source code Browse git
"""
The grammar of .NET type names, as PowerShell source writes them and as .NET reflection reports
them. This module is purely syntactic: it turns the text of a type name into a `Ps1TypeName` and
back, and it knows nothing about which types exist. Deciding what a name refers to — resolving an
accelerator like `int`, supplying an omitted `System.` prefix, looking up members — requires the
collected metadata and belongs to `refinery.lib.scripts.ps1.data`.
The two spellings this has to bridge are the source form and the reflection form:
System.Collections.Generic.List[int]
System.Collections.Generic.List`1[[System.Int32, mscorlib]]
Both name the same open generic type, whose reflection `FullName` is the `Ps1TypeName.definition`
of either parse.
"""
from __future__ import annotations
import re
from typing import NamedTuple
_ARITY_SUFFIX = re.compile(r'`(\d+)$')
_IDENTIFIER = re.compile(
r'''
[^\W\d]\w* (?: `\d+ )?
(?: [.+] [^\W\d]\w* (?: `\d+ )? )*
''',
re.VERBOSE,
)
class Ps1TypeName(NamedTuple):
"""
A parsed .NET type name.
The `name` is the dotted base name with no generic arity marker, no type arguments and no array
suffix; `System.Collections.Generic.List` for every spelling of a list type. `arity` is the
number of generic parameters, which a name can carry without naming them — an open generic. When
the arguments are named, `arguments` holds them and its length equals `arity`. `ranks` records
the array suffixes in the order they were written, one entry per suffix, holding that suffix's
dimension count, so `int[,][]` parses to `(2, 1)`. `pointers` counts trailing `*` suffixes and
`byref` records a trailing `&`, which is how reflection reports the type of an `out` or `ref`
parameter. `assembly` holds the assembly qualification that a reflection-form name may carry
after a comma.
The three suffix kinds are accepted only in the order the runtime writes them — arrays, then
pointers, then at most one `&` — so a name that composes them differently is rejected rather
than flattened onto fields that cannot express it.
"""
name: str
arity: int = 0
arguments: tuple[Ps1TypeName, ...] = ()
ranks: tuple[int, ...] = ()
pointers: int = 0
byref: bool = False
assembly: str | None = None
@property
def definition(self) -> str:
"""
The reflection `FullName` of the generic type definition, i.e. the base name carrying its
arity marker but not its arguments. This is the form the collected type table is keyed by,
because members are a property of the definition rather than of any one instantiation.
"""
if self.arity:
return F'{self.name}`{self.arity}'
return self.name
@property
def is_array(self) -> bool:
return bool(self.ranks)
def __str__(self):
"""
Render the name in PowerShell source form. The assembly qualification is deliberately not
rendered: it has no source spelling outside the bracketed reflection form, where it would
have to be re-bracketed to parse back.
"""
text = self.name
if self.arguments:
arguments = ', '.join(str(argument) for argument in self.arguments)
text = F'{text}[{arguments}]'
elif self.arity:
text = F'{text}`{self.arity}'
for rank in self.ranks:
commas = ',' * (rank - 1)
text = F'{text}[{commas}]'
text = text + '*' * self.pointers
if self.byref:
text = F'{text}&'
return text
class _TypeNameSyntaxError(Exception):
pass
class _TypeNameParser:
def __init__(self, text: str):
self._text = text
self._pos = 0
def parse(self) -> Ps1TypeName:
result = self._parse_type(qualified=True)
self._skip_space()
if self._pos != len(self._text):
raise _TypeNameSyntaxError
return result
def _skip_space(self):
text = self._text
while self._pos < len(text) and text[self._pos].isspace():
self._pos += 1
def _peek(self) -> str:
self._skip_space()
if self._pos >= len(self._text):
return ''
return self._text[self._pos]
def _parse_type(self, qualified: bool) -> Ps1TypeName:
name, arity = self._parse_name()
arguments: tuple[Ps1TypeName, ...] = ()
if self._peek() == '[' and not self._at_rank_specifier():
arguments = self._parse_arguments()
if arity == 0:
arity = len(arguments)
elif arity != len(arguments):
raise _TypeNameSyntaxError
ranks: list[int] = []
while self._peek() == '[':
if not self._at_rank_specifier():
raise _TypeNameSyntaxError
ranks.append(self._parse_rank())
pointers = 0
while self._peek() == '*':
pointers += 1
self._pos += 1
byref = self._peek() == '&'
if byref:
self._pos += 1
if self._peek() in ('[', '*', '&'):
raise _TypeNameSyntaxError
assembly = None
if qualified and self._peek() == ',':
self._pos += 1
assembly = self._parse_assembly()
return Ps1TypeName(name, arity, arguments, tuple(ranks), pointers, byref, assembly)
def _parse_name(self) -> tuple[str, int]:
text = self._text
parts: list[str] = []
while self._pos < len(text):
char = text[self._pos]
if char.isspace():
self._pos += 1
continue
if char in '[],*&':
break
parts.append(char)
self._pos += 1
name = ''.join(parts)
if not _IDENTIFIER.fullmatch(name):
raise _TypeNameSyntaxError
arity = 0
suffix = _ARITY_SUFFIX.search(name)
if suffix is not None:
arity = int(suffix[1])
name = name[:suffix.start()]
return name, arity
def _parse_arguments(self) -> tuple[Ps1TypeName, ...]:
self._pos += 1
arguments: list[Ps1TypeName] = []
while True:
arguments.append(self._parse_argument())
char = self._peek()
self._pos += 1
if char == ',':
continue
if char == ']':
return tuple(arguments)
raise _TypeNameSyntaxError
def _parse_argument(self) -> Ps1TypeName:
if self._peek() != '[':
return self._parse_type(qualified=False)
self._pos += 1
argument = self._parse_type(qualified=True)
if self._peek() != ']':
raise _TypeNameSyntaxError
self._pos += 1
return argument
def _at_rank_specifier(self) -> bool:
"""
Whether the bracket at the cursor opens an array suffix rather than a generic argument list.
The two are told apart by their contents: an array suffix holds only commas.
"""
text = self._text
cursor = self._pos + 1
while cursor < len(text):
char = text[cursor]
if char == ']':
return True
if char != ',' and not char.isspace():
return False
cursor += 1
return False
def _parse_rank(self) -> int:
self._pos += 1
rank = 1
while True:
char = self._peek()
self._pos += 1
if char == ',':
rank += 1
elif char == ']':
return rank
else:
raise _TypeNameSyntaxError
def _parse_assembly(self) -> str:
"""
Consume an assembly qualification, which runs to the bracket that closes the enclosing type
argument or, at the outermost level, to the end of the name. It cannot stop at a comma
because the qualification is itself a comma-separated list of assembly attributes.
"""
text = self._text
start = self._pos
depth = 0
while self._pos < len(text):
char = text[self._pos]
if char == '[':
depth += 1
elif char == ']':
if depth == 0:
break
depth -= 1
self._pos += 1
assembly = text[start:self._pos].strip()
if not assembly:
raise _TypeNameSyntaxError
return assembly
def parse_type_name(text: str) -> Ps1TypeName | None:
"""
Parse a .NET type name in either source or reflection form, returning `None` when the text is
not one. The input is the name alone: the brackets of a PowerShell type literal are the literal's
syntax rather than the name's, and the node model has already stripped them.
Returning `None` rather than a best effort is the point. A caller that receives a `Ps1TypeName`
has a name every part of which was understood, so a later lookup miss means the type is absent
from the metadata — not that the name was mangled on the way in.
"""
try:
return _TypeNameParser(text).parse()
except _TypeNameSyntaxError:
return None
Functions
def parse_type_name(text)-
Parse a .NET type name in either source or reflection form, returning
Nonewhen the text is not one. The input is the name alone: the brackets of a PowerShell type literal are the literal's syntax rather than the name's, and the node model has already stripped them.Returning
Nonerather than a best effort is the point. A caller that receives aPs1TypeNamehas a name every part of which was understood, so a later lookup miss means the type is absent from the metadata — not that the name was mangled on the way in.Expand source code Browse git
def parse_type_name(text: str) -> Ps1TypeName | None: """ Parse a .NET type name in either source or reflection form, returning `None` when the text is not one. The input is the name alone: the brackets of a PowerShell type literal are the literal's syntax rather than the name's, and the node model has already stripped them. Returning `None` rather than a best effort is the point. A caller that receives a `Ps1TypeName` has a name every part of which was understood, so a later lookup miss means the type is absent from the metadata — not that the name was mangled on the way in. """ try: return _TypeNameParser(text).parse() except _TypeNameSyntaxError: return None
Classes
class Ps1TypeName (name, arity=0, arguments=(), ranks=(), pointers=0, byref=False, assembly=None)-
A parsed .NET type name.
The
nameis the dotted base name with no generic arity marker, no type arguments and no array suffix;System.Collections.Generic.Listfor every spelling of a list type.arityis the number of generic parameters, which a name can carry without naming them — an open generic. When the arguments are named,argumentsholds them and its length equalsarity.ranksrecords the array suffixes in the order they were written, one entry per suffix, holding that suffix's dimension count, soint[,][]parses to(2, 1).pointerscounts trailing*suffixes andbyrefrecords a trailing&, which is how reflection reports the type of anoutorrefparameter.assemblyholds the assembly qualification that a reflection-form name may carry after a comma.The three suffix kinds are accepted only in the order the runtime writes them — arrays, then pointers, then at most one
&— so a name that composes them differently is rejected rather than flattened onto fields that cannot express it.Expand source code Browse git
class Ps1TypeName(NamedTuple): """ A parsed .NET type name. The `name` is the dotted base name with no generic arity marker, no type arguments and no array suffix; `System.Collections.Generic.List` for every spelling of a list type. `arity` is the number of generic parameters, which a name can carry without naming them — an open generic. When the arguments are named, `arguments` holds them and its length equals `arity`. `ranks` records the array suffixes in the order they were written, one entry per suffix, holding that suffix's dimension count, so `int[,][]` parses to `(2, 1)`. `pointers` counts trailing `*` suffixes and `byref` records a trailing `&`, which is how reflection reports the type of an `out` or `ref` parameter. `assembly` holds the assembly qualification that a reflection-form name may carry after a comma. The three suffix kinds are accepted only in the order the runtime writes them — arrays, then pointers, then at most one `&` — so a name that composes them differently is rejected rather than flattened onto fields that cannot express it. """ name: str arity: int = 0 arguments: tuple[Ps1TypeName, ...] = () ranks: tuple[int, ...] = () pointers: int = 0 byref: bool = False assembly: str | None = None @property def definition(self) -> str: """ The reflection `FullName` of the generic type definition, i.e. the base name carrying its arity marker but not its arguments. This is the form the collected type table is keyed by, because members are a property of the definition rather than of any one instantiation. """ if self.arity: return F'{self.name}`{self.arity}' return self.name @property def is_array(self) -> bool: return bool(self.ranks) def __str__(self): """ Render the name in PowerShell source form. The assembly qualification is deliberately not rendered: it has no source spelling outside the bracketed reflection form, where it would have to be re-bracketed to parse back. """ text = self.name if self.arguments: arguments = ', '.join(str(argument) for argument in self.arguments) text = F'{text}[{arguments}]' elif self.arity: text = F'{text}`{self.arity}' for rank in self.ranks: commas = ',' * (rank - 1) text = F'{text}[{commas}]' text = text + '*' * self.pointers if self.byref: text = F'{text}&' return textAncestors
- builtins.tuple
Instance variables
var name-
Alias for field number 0
Expand source code Browse git
class Ps1TypeName(NamedTuple): """ A parsed .NET type name. The `name` is the dotted base name with no generic arity marker, no type arguments and no array suffix; `System.Collections.Generic.List` for every spelling of a list type. `arity` is the number of generic parameters, which a name can carry without naming them — an open generic. When the arguments are named, `arguments` holds them and its length equals `arity`. `ranks` records the array suffixes in the order they were written, one entry per suffix, holding that suffix's dimension count, so `int[,][]` parses to `(2, 1)`. `pointers` counts trailing `*` suffixes and `byref` records a trailing `&`, which is how reflection reports the type of an `out` or `ref` parameter. `assembly` holds the assembly qualification that a reflection-form name may carry after a comma. The three suffix kinds are accepted only in the order the runtime writes them — arrays, then pointers, then at most one `&` — so a name that composes them differently is rejected rather than flattened onto fields that cannot express it. """ name: str arity: int = 0 arguments: tuple[Ps1TypeName, ...] = () ranks: tuple[int, ...] = () pointers: int = 0 byref: bool = False assembly: str | None = None @property def definition(self) -> str: """ The reflection `FullName` of the generic type definition, i.e. the base name carrying its arity marker but not its arguments. This is the form the collected type table is keyed by, because members are a property of the definition rather than of any one instantiation. """ if self.arity: return F'{self.name}`{self.arity}' return self.name @property def is_array(self) -> bool: return bool(self.ranks) def __str__(self): """ Render the name in PowerShell source form. The assembly qualification is deliberately not rendered: it has no source spelling outside the bracketed reflection form, where it would have to be re-bracketed to parse back. """ text = self.name if self.arguments: arguments = ', '.join(str(argument) for argument in self.arguments) text = F'{text}[{arguments}]' elif self.arity: text = F'{text}`{self.arity}' for rank in self.ranks: commas = ',' * (rank - 1) text = F'{text}[{commas}]' text = text + '*' * self.pointers if self.byref: text = F'{text}&' return text var arity-
Alias for field number 1
Expand source code Browse git
class Ps1TypeName(NamedTuple): """ A parsed .NET type name. The `name` is the dotted base name with no generic arity marker, no type arguments and no array suffix; `System.Collections.Generic.List` for every spelling of a list type. `arity` is the number of generic parameters, which a name can carry without naming them — an open generic. When the arguments are named, `arguments` holds them and its length equals `arity`. `ranks` records the array suffixes in the order they were written, one entry per suffix, holding that suffix's dimension count, so `int[,][]` parses to `(2, 1)`. `pointers` counts trailing `*` suffixes and `byref` records a trailing `&`, which is how reflection reports the type of an `out` or `ref` parameter. `assembly` holds the assembly qualification that a reflection-form name may carry after a comma. The three suffix kinds are accepted only in the order the runtime writes them — arrays, then pointers, then at most one `&` — so a name that composes them differently is rejected rather than flattened onto fields that cannot express it. """ name: str arity: int = 0 arguments: tuple[Ps1TypeName, ...] = () ranks: tuple[int, ...] = () pointers: int = 0 byref: bool = False assembly: str | None = None @property def definition(self) -> str: """ The reflection `FullName` of the generic type definition, i.e. the base name carrying its arity marker but not its arguments. This is the form the collected type table is keyed by, because members are a property of the definition rather than of any one instantiation. """ if self.arity: return F'{self.name}`{self.arity}' return self.name @property def is_array(self) -> bool: return bool(self.ranks) def __str__(self): """ Render the name in PowerShell source form. The assembly qualification is deliberately not rendered: it has no source spelling outside the bracketed reflection form, where it would have to be re-bracketed to parse back. """ text = self.name if self.arguments: arguments = ', '.join(str(argument) for argument in self.arguments) text = F'{text}[{arguments}]' elif self.arity: text = F'{text}`{self.arity}' for rank in self.ranks: commas = ',' * (rank - 1) text = F'{text}[{commas}]' text = text + '*' * self.pointers if self.byref: text = F'{text}&' return text var arguments-
Alias for field number 2
Expand source code Browse git
class Ps1TypeName(NamedTuple): """ A parsed .NET type name. The `name` is the dotted base name with no generic arity marker, no type arguments and no array suffix; `System.Collections.Generic.List` for every spelling of a list type. `arity` is the number of generic parameters, which a name can carry without naming them — an open generic. When the arguments are named, `arguments` holds them and its length equals `arity`. `ranks` records the array suffixes in the order they were written, one entry per suffix, holding that suffix's dimension count, so `int[,][]` parses to `(2, 1)`. `pointers` counts trailing `*` suffixes and `byref` records a trailing `&`, which is how reflection reports the type of an `out` or `ref` parameter. `assembly` holds the assembly qualification that a reflection-form name may carry after a comma. The three suffix kinds are accepted only in the order the runtime writes them — arrays, then pointers, then at most one `&` — so a name that composes them differently is rejected rather than flattened onto fields that cannot express it. """ name: str arity: int = 0 arguments: tuple[Ps1TypeName, ...] = () ranks: tuple[int, ...] = () pointers: int = 0 byref: bool = False assembly: str | None = None @property def definition(self) -> str: """ The reflection `FullName` of the generic type definition, i.e. the base name carrying its arity marker but not its arguments. This is the form the collected type table is keyed by, because members are a property of the definition rather than of any one instantiation. """ if self.arity: return F'{self.name}`{self.arity}' return self.name @property def is_array(self) -> bool: return bool(self.ranks) def __str__(self): """ Render the name in PowerShell source form. The assembly qualification is deliberately not rendered: it has no source spelling outside the bracketed reflection form, where it would have to be re-bracketed to parse back. """ text = self.name if self.arguments: arguments = ', '.join(str(argument) for argument in self.arguments) text = F'{text}[{arguments}]' elif self.arity: text = F'{text}`{self.arity}' for rank in self.ranks: commas = ',' * (rank - 1) text = F'{text}[{commas}]' text = text + '*' * self.pointers if self.byref: text = F'{text}&' return text var ranks-
Alias for field number 3
Expand source code Browse git
class Ps1TypeName(NamedTuple): """ A parsed .NET type name. The `name` is the dotted base name with no generic arity marker, no type arguments and no array suffix; `System.Collections.Generic.List` for every spelling of a list type. `arity` is the number of generic parameters, which a name can carry without naming them — an open generic. When the arguments are named, `arguments` holds them and its length equals `arity`. `ranks` records the array suffixes in the order they were written, one entry per suffix, holding that suffix's dimension count, so `int[,][]` parses to `(2, 1)`. `pointers` counts trailing `*` suffixes and `byref` records a trailing `&`, which is how reflection reports the type of an `out` or `ref` parameter. `assembly` holds the assembly qualification that a reflection-form name may carry after a comma. The three suffix kinds are accepted only in the order the runtime writes them — arrays, then pointers, then at most one `&` — so a name that composes them differently is rejected rather than flattened onto fields that cannot express it. """ name: str arity: int = 0 arguments: tuple[Ps1TypeName, ...] = () ranks: tuple[int, ...] = () pointers: int = 0 byref: bool = False assembly: str | None = None @property def definition(self) -> str: """ The reflection `FullName` of the generic type definition, i.e. the base name carrying its arity marker but not its arguments. This is the form the collected type table is keyed by, because members are a property of the definition rather than of any one instantiation. """ if self.arity: return F'{self.name}`{self.arity}' return self.name @property def is_array(self) -> bool: return bool(self.ranks) def __str__(self): """ Render the name in PowerShell source form. The assembly qualification is deliberately not rendered: it has no source spelling outside the bracketed reflection form, where it would have to be re-bracketed to parse back. """ text = self.name if self.arguments: arguments = ', '.join(str(argument) for argument in self.arguments) text = F'{text}[{arguments}]' elif self.arity: text = F'{text}`{self.arity}' for rank in self.ranks: commas = ',' * (rank - 1) text = F'{text}[{commas}]' text = text + '*' * self.pointers if self.byref: text = F'{text}&' return text var pointers-
Alias for field number 4
Expand source code Browse git
class Ps1TypeName(NamedTuple): """ A parsed .NET type name. The `name` is the dotted base name with no generic arity marker, no type arguments and no array suffix; `System.Collections.Generic.List` for every spelling of a list type. `arity` is the number of generic parameters, which a name can carry without naming them — an open generic. When the arguments are named, `arguments` holds them and its length equals `arity`. `ranks` records the array suffixes in the order they were written, one entry per suffix, holding that suffix's dimension count, so `int[,][]` parses to `(2, 1)`. `pointers` counts trailing `*` suffixes and `byref` records a trailing `&`, which is how reflection reports the type of an `out` or `ref` parameter. `assembly` holds the assembly qualification that a reflection-form name may carry after a comma. The three suffix kinds are accepted only in the order the runtime writes them — arrays, then pointers, then at most one `&` — so a name that composes them differently is rejected rather than flattened onto fields that cannot express it. """ name: str arity: int = 0 arguments: tuple[Ps1TypeName, ...] = () ranks: tuple[int, ...] = () pointers: int = 0 byref: bool = False assembly: str | None = None @property def definition(self) -> str: """ The reflection `FullName` of the generic type definition, i.e. the base name carrying its arity marker but not its arguments. This is the form the collected type table is keyed by, because members are a property of the definition rather than of any one instantiation. """ if self.arity: return F'{self.name}`{self.arity}' return self.name @property def is_array(self) -> bool: return bool(self.ranks) def __str__(self): """ Render the name in PowerShell source form. The assembly qualification is deliberately not rendered: it has no source spelling outside the bracketed reflection form, where it would have to be re-bracketed to parse back. """ text = self.name if self.arguments: arguments = ', '.join(str(argument) for argument in self.arguments) text = F'{text}[{arguments}]' elif self.arity: text = F'{text}`{self.arity}' for rank in self.ranks: commas = ',' * (rank - 1) text = F'{text}[{commas}]' text = text + '*' * self.pointers if self.byref: text = F'{text}&' return text var byref-
Alias for field number 5
Expand source code Browse git
class Ps1TypeName(NamedTuple): """ A parsed .NET type name. The `name` is the dotted base name with no generic arity marker, no type arguments and no array suffix; `System.Collections.Generic.List` for every spelling of a list type. `arity` is the number of generic parameters, which a name can carry without naming them — an open generic. When the arguments are named, `arguments` holds them and its length equals `arity`. `ranks` records the array suffixes in the order they were written, one entry per suffix, holding that suffix's dimension count, so `int[,][]` parses to `(2, 1)`. `pointers` counts trailing `*` suffixes and `byref` records a trailing `&`, which is how reflection reports the type of an `out` or `ref` parameter. `assembly` holds the assembly qualification that a reflection-form name may carry after a comma. The three suffix kinds are accepted only in the order the runtime writes them — arrays, then pointers, then at most one `&` — so a name that composes them differently is rejected rather than flattened onto fields that cannot express it. """ name: str arity: int = 0 arguments: tuple[Ps1TypeName, ...] = () ranks: tuple[int, ...] = () pointers: int = 0 byref: bool = False assembly: str | None = None @property def definition(self) -> str: """ The reflection `FullName` of the generic type definition, i.e. the base name carrying its arity marker but not its arguments. This is the form the collected type table is keyed by, because members are a property of the definition rather than of any one instantiation. """ if self.arity: return F'{self.name}`{self.arity}' return self.name @property def is_array(self) -> bool: return bool(self.ranks) def __str__(self): """ Render the name in PowerShell source form. The assembly qualification is deliberately not rendered: it has no source spelling outside the bracketed reflection form, where it would have to be re-bracketed to parse back. """ text = self.name if self.arguments: arguments = ', '.join(str(argument) for argument in self.arguments) text = F'{text}[{arguments}]' elif self.arity: text = F'{text}`{self.arity}' for rank in self.ranks: commas = ',' * (rank - 1) text = F'{text}[{commas}]' text = text + '*' * self.pointers if self.byref: text = F'{text}&' return text var assembly-
Alias for field number 6
Expand source code Browse git
class Ps1TypeName(NamedTuple): """ A parsed .NET type name. The `name` is the dotted base name with no generic arity marker, no type arguments and no array suffix; `System.Collections.Generic.List` for every spelling of a list type. `arity` is the number of generic parameters, which a name can carry without naming them — an open generic. When the arguments are named, `arguments` holds them and its length equals `arity`. `ranks` records the array suffixes in the order they were written, one entry per suffix, holding that suffix's dimension count, so `int[,][]` parses to `(2, 1)`. `pointers` counts trailing `*` suffixes and `byref` records a trailing `&`, which is how reflection reports the type of an `out` or `ref` parameter. `assembly` holds the assembly qualification that a reflection-form name may carry after a comma. The three suffix kinds are accepted only in the order the runtime writes them — arrays, then pointers, then at most one `&` — so a name that composes them differently is rejected rather than flattened onto fields that cannot express it. """ name: str arity: int = 0 arguments: tuple[Ps1TypeName, ...] = () ranks: tuple[int, ...] = () pointers: int = 0 byref: bool = False assembly: str | None = None @property def definition(self) -> str: """ The reflection `FullName` of the generic type definition, i.e. the base name carrying its arity marker but not its arguments. This is the form the collected type table is keyed by, because members are a property of the definition rather than of any one instantiation. """ if self.arity: return F'{self.name}`{self.arity}' return self.name @property def is_array(self) -> bool: return bool(self.ranks) def __str__(self): """ Render the name in PowerShell source form. The assembly qualification is deliberately not rendered: it has no source spelling outside the bracketed reflection form, where it would have to be re-bracketed to parse back. """ text = self.name if self.arguments: arguments = ', '.join(str(argument) for argument in self.arguments) text = F'{text}[{arguments}]' elif self.arity: text = F'{text}`{self.arity}' for rank in self.ranks: commas = ',' * (rank - 1) text = F'{text}[{commas}]' text = text + '*' * self.pointers if self.byref: text = F'{text}&' return text var definition-
The reflection
FullNameof the generic type definition, i.e. the base name carrying its arity marker but not its arguments. This is the form the collected type table is keyed by, because members are a property of the definition rather than of any one instantiation.Expand source code Browse git
@property def definition(self) -> str: """ The reflection `FullName` of the generic type definition, i.e. the base name carrying its arity marker but not its arguments. This is the form the collected type table is keyed by, because members are a property of the definition rather than of any one instantiation. """ if self.arity: return F'{self.name}`{self.arity}' return self.name var is_array-
Expand source code Browse git
@property def is_array(self) -> bool: return bool(self.ranks)