Appearance
| 1 | namespace Semantic.Symbols is | |
| 2 | // The names an indexer's accessors are declared under. | |
| 3 | // | |
| 4 | // .NET does not fix them: the indexer property carries whatever | |
| 5 | // name its declaring language chose (`System.String`'s is `Chars`, | |
| 6 | // C#'s default is `Item`, `IndexerName` overrides it), and the | |
| 7 | // declaring type names the real one with | |
| 8 | // `System.Reflection.DefaultMemberAttribute`. A type can also carry | |
| 9 | // indexed properties that are not that one. | |
| 10 | // | |
| 11 | // So an imported indexer is declared under these names whatever it | |
| 12 | // is called in metadata, and keeps its own name for emission via | |
| 13 | // `il_name_override`. Everything that resolves an `x[i]` expression | |
| 14 | // then has a single pair of names to look for, whether the type | |
| 15 | // came from source or from an assembly. | |
| 16 | class INDEXER_NAMES is | |
| 17 | // The property name a source indexer takes, and what the | |
| 18 | // default member is called on all but a handful of imported | |
| 19 | // types. | |
| 20 | // | |
| 21 | // Named in snake_case rather than as UPPER_SNAKE constants | |
| 22 | // because a static member's name is de-camelled when the | |
| 23 | // assembly is read back through reflection, so an UPPER_SNAKE | |
| 24 | // one is spelled differently either side of an assembly | |
| 25 | // boundary — `READ` here and `read` from the unit tests. | |
| 26 | property_name: string static => "Item" | |
| 27 | ||
| 28 | read: string static => "get_{property_name}" | |
| 29 | assign: string static => "set_{property_name}" | |
| 30 | ||
| 31 | // The name to declare an accessor of `property_name` under: | |
| 32 | // an indexer accessor is renamed, any other accessor keeps | |
| 33 | // the name it came in with. | |
| 34 | accessor(dotnet_name: string) -> string static => | |
| 35 | if dotnet_name.starts_with("set_") then | |
| 36 | assign | |
| 37 | else | |
| 38 | read | |
| 39 | fi | |
| 40 | ||
| 41 | // True when metadata already names the accessor the way it is | |
| 42 | // declared, so no second name is needed to reach it. | |
| 43 | is_canonical(dotnet_name: string) -> bool static => | |
| 44 | dotnet_name =~ read \/ dotnet_name =~ assign | |
| 45 | si | |
| 46 | si |