public void Resolve(VBAParser.AsTypeClauseContext context) { var asType = context.type(); if (asType == null) { return; } Declaration type = null; IdentifierReference reference = null; var baseType = asType.baseType(); if (baseType != null) { var collection = baseType.COLLECTION(); if (collection != null) { type = _declarations[collection.GetText()].SingleOrDefault(item => item.IsBuiltIn && item.DeclarationType == DeclarationType.Class); reference = CreateReference(baseType, type); } } else { type = ResolveType(asType.complexType()); reference = CreateReference(asType.complexType(), type); } if (type != null) { type.AddReference(reference); _alreadyResolved.Add(reference.Context); } }
public void EnterWithBlock(VBAParser.WithStmtContext context) { Declaration qualifier = null; IdentifierReference reference = null; if (context.NEW() == null) { // with block is using an identifier declared elsewhere. var callee = ResolveInternal(context.implicitCallStmt_InStmt(), _currentScope, ContextAccessorType.GetValueOrReference); qualifier = ResolveType(callee); } else { // with block is using an anonymous declaration. // i.e. object variable reference is held by the with block itself. var typeContext = context.type(); var baseTypeContext = typeContext.baseType(); if (baseTypeContext != null) { var collectionContext = baseTypeContext.COLLECTION(); if (collectionContext != null) { // object variable is a built-in Collection class instance qualifier = _declarations.Items.Single(item => item.IsBuiltIn && item.IdentifierName == collectionContext.GetText() && item.DeclarationType == DeclarationType.Class); reference = CreateReference(baseTypeContext, qualifier); } } else { qualifier = ResolveType(typeContext.complexType()); } } if (qualifier != null && reference != null) { qualifier.AddReference(reference); _alreadyResolved.Add(reference.Context); } _withBlockQualifiers.Push(qualifier); // note: pushes null if unresolved }
private Declaration ResolveInternal(ParserRuleContext callSiteContext, Declaration localScope, ContextAccessorType accessorType = ContextAccessorType.GetValueOrReference, VBAParser.DictionaryCallStmtContext fieldCall = null, bool hasExplicitLetStatement = false, bool isAssignmentTarget = false) { if (callSiteContext == null || _alreadyResolved.Contains(callSiteContext)) { return(null); } if (!IdentifierContexts.Contains(callSiteContext.GetType())) { throw new ArgumentException("'" + callSiteContext.GetType().Name + "' is not an identifier context.", "callSiteContext"); } if (localScope == null) { localScope = _currentScope; } var parentContext = callSiteContext.Parent; var identifierName = callSiteContext.GetText(); Declaration callee = null; if (localScope.DeclarationType == DeclarationType.Variable) { // localScope is probably a UDT var udt = ResolveType(localScope); if (udt != null && udt.DeclarationType == DeclarationType.UserDefinedType) { callee = _declarations[identifierName].SingleOrDefault(item => item.Context != null && item.Context.Parent == udt.Context); } } else { callee = FindLocalScopeDeclaration(identifierName, localScope, parentContext, isAssignmentTarget) ?? FindModuleScopeProcedure(identifierName, localScope, accessorType, isAssignmentTarget) ?? FindModuleScopeDeclaration(identifierName, localScope) ?? FindProjectScopeDeclaration(identifierName); } if (callee == null) { // calls inside With block can still refer to identifiers in _currentScope localScope = _currentScope; identifierName = callSiteContext.GetText(); callee = FindLocalScopeDeclaration(identifierName, localScope, parentContext, isAssignmentTarget) ?? FindModuleScopeProcedure(identifierName, localScope, accessorType, isAssignmentTarget) ?? FindModuleScopeDeclaration(identifierName, localScope) ?? FindProjectScopeDeclaration(identifierName); } if (callee == null) { return(null); } var reference = CreateReference(callSiteContext, callee, isAssignmentTarget, hasExplicitLetStatement); callee.AddReference(reference); _alreadyResolved.Add(reference.Context); _alreadyResolved.Add(callSiteContext); if (fieldCall != null) { return(ResolveInternal(fieldCall, callee)); } return(callee); }