Class CompositeSymbolResolver
Chains ISymbolResolvers: ResolveValue(string, ScopeKind, Uri) tries each in order and returns the first result that is not IsUnbound — a bound symbol, or an error result (a duplicate or ambiguous name found by an earlier resolver is not masked by a later fallback). The result is unbound only when every resolver is unbound.
public sealed class CompositeSymbolResolver : ISymbolResolver
- Inheritance
-
CompositeSymbolResolver
- Implements
- Inherited Members
- Extension Methods
Remarks
A compile-time composite — the value-binding members throw. Used to layer a workspace's ScopeTreeSymbolResolver over an intrinsic type-name resolver, most specific first.
Constructors
CompositeSymbolResolver(params ISymbolResolver[])
Chains ISymbolResolvers: ResolveValue(string, ScopeKind, Uri) tries each in order and returns the first result that is not IsUnbound — a bound symbol, or an error result (a duplicate or ambiguous name found by an earlier resolver is not masked by a later fallback). The result is unbound only when every resolver is unbound.
public CompositeSymbolResolver(params ISymbolResolver[] resolvers)
Parameters
resolversISymbolResolver[]The resolvers to try, in priority order.
Remarks
A compile-time composite — the value-binding members throw. Used to layer a workspace's ScopeTreeSymbolResolver over an intrinsic type-name resolver, most specific first.
Methods
GetValue(Symbol)
Gets the IBindingHandle currently associated with the specified Symbol.
public IBindingHandle GetValue(Symbol symbol)
Parameters
Returns
ResolveConditionalConstant(string, ScopeKind, Uri)
Resolves the specified identifier name as a reference to a conditional compilation
constant, as seen from the scope the symbol at handle belongs to.
public SymbolResolutionResult ResolveConditionalConstant(string name, ScopeKind scope, Uri handle)
Parameters
namestringThe name of the constant to resolve.
scopeScopeKindA memory-scope hint; the compile-time resolver does not consult it.
handleUriThe Uri of the symbol the lookup originates from.
Returns
- SymbolResolutionResult
A SymbolResolutionResult carrying the bound constant, or an unbound result — which §5.6.16.2 gives a meaning of its own: a conditional compilation constant that names nothing evaluates to
0, not to an error.
Remarks
Its own binding context, and the reason is MS-VBAL §3.4.1: a #Const "defines
a constant binding accessible to <cc-expression> elements of the containing module",
and §5.6.16.2 is the only place a reference to one is defined at all. So a
conditional compilation constant is not a name in the default binding context — x = Win64
in ordinary source does not bind it, and ResolveValue(string, ScopeKind, Uri) never returns one — while a
#If Win64 Then resolves it only here.
§3.4.1 also gives the shadowing rule this follows: a module's own #Const shadows a
project-level constant of the same name.
ResolveMember(Symbol, string, Uri)
Resolves name as a member of owner, a project or a procedural module: the
right-hand side of a member access whose left-hand side is one of them (MS-VBAL §5.6.12) —
Strings.LenB, VBA.Strings, VBA.LenB.
public SymbolResolutionResult ResolveMember(Symbol owner, string name, Uri handle)
Parameters
ownerSymbolThe project or procedural module the member belongs to.
namestringThe name of the member to resolve.
handleUriThe Uri of the symbol the lookup originates from, which decides what is accessible.
Returns
- SymbolResolutionResult
A SymbolResolutionResult carrying the member, an unbound result when there is none, or an AmbiguousName error with the colliding candidates.
Remarks
What the member of a procedural module can be is what the module declares and the lookup can reach:
a variable, property, function, subroutine or value, and not one declared Private unless the lookup
originates in the module itself.
What the member of a project can be is, in the order the specification gives them: a project, when
owner is the enclosing project; a procedural module of the project of that name; and, only
when there is no such module, the one accessible member of that name that exactly one of the project's
procedural modules has — a name two of them declare is ambiguous, and the reference has to qualify it.
👉 A class module is not an owner here: its members are reached through an instance of it, which is a member access on a value and not on a namespace.
ResolveQualifier(string, ScopeKind, Uri)
Resolves the specified identifier name as the qualifier of a qualified type name — the
A in A.B — in the type binding context (MS-VBAL §5.6.4), as seen from
the scope the symbol at handle belongs to. A qualifier is a namespace: it binds the project,
or a procedural or class module, and never a user-defined type or an Enum type, however the name ranks in
ResolveType(string, ScopeKind, Uri) — neither can contain a type. A local, parameter, constant, variable or procedure is
never a candidate either.
public SymbolResolutionResult ResolveQualifier(string name, ScopeKind scope, Uri handle)
Parameters
namestringThe name of the Symbol to resolve.
scopeScopeKindA memory-scope hint; the compile-time resolver does not consult it.
handleUriThe Uri of the symbol the lookup originates from.
Returns
- SymbolResolutionResult
A SymbolResolutionResult — the bound Symbol, an unbound result, or an AmbiguousName error with the colliding candidates.
Remarks
Which lookup a name uses is positional: the last part of A.B, like a bare name, is bound by
ResolveType(string, ScopeKind, Uri); only what precedes a dot is bound here. This holds wherever a type name appears —
an As clause, As New, the operand of New.
ResolveType(string, ScopeKind, Uri)
Resolves the specified identifier name in the type binding context
(MS-VBAL §5.6.4), as seen from the scope the symbol at handle
belongs to. This is the context of an expression that expects a type or class name — an
As clause, the operand of New: it binds a user-defined type, an Enum type, a class or
procedural module, or the project. A local, parameter, constant, variable or procedure is never a
candidate, however it is named, so it can neither be bound nor hide the type it shadows in
ResolveValue(string, ScopeKind, Uri). The qualifier of a qualified type name (A in A.B) is bound by
ResolveQualifier(string, ScopeKind, Uri) instead.
public SymbolResolutionResult ResolveType(string name, ScopeKind scope, Uri handle)
Parameters
namestringThe name of the Symbol to resolve.
scopeScopeKindA memory-scope hint; the compile-time resolver does not consult it.
handleUriThe Uri of the symbol the lookup originates from.
Returns
- SymbolResolutionResult
A SymbolResolutionResult — the bound Symbol, an unbound result, or a DuplicateDeclaration / AmbiguousName error with the colliding candidates.
ResolveValue(string, ScopeKind, Uri)
Resolves the specified identifier name in the default binding context
(MS-VBAL §5.6.4), as seen from the scope the symbol at handle
belongs to. This is the context of a simple name expression: it binds a variable, constant,
Enum type or member, property, function, subroutine, procedural module or project
(§5.6.10), and never a user-defined type or a class module, which are only ever
candidates in the type binding context (ResolveType(string, ScopeKind, Uri)). A class module is a name here
only through its predeclared instance (§5.2.4.1.2): a variable named after the class.
public SymbolResolutionResult ResolveValue(string name, ScopeKind scope, Uri handle)
Parameters
namestringThe name of the Symbol to resolve.
scopeScopeKindA memory-scope hint; the compile-time resolver does not consult it.
handleUriThe Uri of the symbol the lookup originates from.
Returns
- SymbolResolutionResult
A SymbolResolutionResult — the bound Symbol, an unbound result, or a DuplicateDeclaration / AmbiguousName error with the colliding candidates.
TryAllocate(Symbol, VBTypedValue, out MemoryAddress)
Reserves storage sized for value and binds it to symbol —
a Static local's own first-call allocation (MS-VBAL §5.4.3.1: module
extent, so it must persist past its own frame popping) chiefly. This is a storage-only
operation: it never affects name resolution, so it is never how a symbol's name itself becomes
resolvable — that rides on its own declaring symbol instead (a procedure's own
Locals/Parameters), the same way calling this twice for an already-allocated
symbol is safe (a fresh allocation, the previous one freed first) but never necessary.
public bool TryAllocate(Symbol symbol, VBTypedValue value, out MemoryAddress address)
Parameters
symbolSymbolThe symbol to reserve storage for.
valueVBTypedValueThe value to seed the new storage with.
addressMemoryAddressThe reserved address, on success.
Returns
- bool
falseif the underlying memory space is exhausted.
TryGetAddress(Symbol, out MemoryAddress)
Gets the MemoryAddress currently reserved for symbol, if any —
what a ByRef argument binds to (MS-VBAL §5.3.1.11: "a reference parameter
binding... referring to the variable referenced by the argument's expression").
public bool TryGetAddress(Symbol symbol, out MemoryAddress address)
Parameters
symbolSymbolThe Symbol whose address to look up.
addressMemoryAddressThe reserved address, if
symbolis currently allocated.
Returns
TryRead(MemoryAddress, out IBindingHandle?)
Gets the IBindingHandle at the specified address in the runtime memory map.
public bool TryRead(MemoryAddress address, out IBindingHandle? value)
Parameters
addressMemoryAddressThe memory address to read.
valueIBindingHandleThe retrieved binding, if successful.