private bool IsPropertyAccessor(Declaration item, ContextAccessorType accessorType, Declaration localScope, bool isAssignmentTarget = false) { var isProperty = item.DeclarationType.HasFlag(DeclarationType.Property); if (!isProperty) { return(false); } if (item.Equals(localScope) && item.DeclarationType == DeclarationType.PropertyGet) { // we're resolving the getter's return value assignment return(true); } if (item.Equals(localScope)) { // getter can't reference setter.. right? return(false); } return((accessorType == ContextAccessorType.AssignValue && item.DeclarationType == DeclarationType.PropertyLet) || (accessorType == ContextAccessorType.AssignReference && item.DeclarationType == DeclarationType.PropertySet) || (accessorType == ContextAccessorType.GetValueOrReference && item.DeclarationType == DeclarationType.PropertyGet && !isAssignmentTarget)); }
private Declaration FindModuleScopeProcedure(string identifierName, Declaration localScope, ContextAccessorType accessorType, bool isAssignmentTarget = false) { if (localScope == null) { localScope = _currentScope; } var matches = _declarations[identifierName]; try { return(matches.SingleOrDefault(item => item.Project == localScope.Project && item.ComponentName == localScope.ComponentName && (IsProcedure(item, localScope) || IsPropertyAccessor(item, accessorType, localScope, isAssignmentTarget)))); } catch (InvalidOperationException) { return(null); } }
private Declaration ResolveInternal(VBAParser.ImplicitCallStmt_InStmtContext callSiteContext, Declaration localScope, ContextAccessorType accessorType, bool hasExplicitLetStatement = false, bool isAssignmentTarget = false) { if (callSiteContext == null) { return(null); } var dictionaryCall = callSiteContext.iCS_S_DictionaryCall(); var fieldCall = dictionaryCall == null ? null : dictionaryCall.dictionaryCallStmt(); return(ResolveInternal(callSiteContext.iCS_S_VariableOrProcedureCall(), localScope, accessorType, hasExplicitLetStatement, isAssignmentTarget) ?? ResolveInternal(callSiteContext.iCS_S_ProcedureOrArrayCall(), localScope, accessorType, hasExplicitLetStatement, isAssignmentTarget) ?? ResolveInternal(callSiteContext.iCS_S_MembersCall(), accessorType, localScope, hasExplicitLetStatement, isAssignmentTarget) ?? ResolveInternal(callSiteContext.iCS_S_DictionaryCall(), localScope, accessorType, fieldCall, hasExplicitLetStatement, isAssignmentTarget)); }
private Declaration ResolveInternal(VBAParser.ICS_S_MembersCallContext context, ContextAccessorType accessorType, Declaration localScope = null, bool hasExplicitLetStatement = false, bool isAssignmentTarget = false) { if (context == null) { return(null); } Declaration parent; if (_withBlockQualifiers.Any()) { parent = _withBlockQualifiers.Peek(); } else { if (localScope == null) { localScope = _currentScope; } parent = ResolveInternal(context.iCS_S_ProcedureOrArrayCall(), localScope, accessorType, hasExplicitLetStatement, isAssignmentTarget) ?? ResolveInternal(context.iCS_S_VariableOrProcedureCall(), localScope, accessorType, hasExplicitLetStatement, isAssignmentTarget); parent = ResolveType(parent); } var chainedCalls = context.iCS_S_MemberCall(); var lastCall = chainedCalls.Last(); foreach (var memberCall in chainedCalls) { // if we're on the left side of an assignment, only the last memberCall is the assignment target. var isLast = memberCall.Equals(lastCall); var accessor = isLast ? accessorType : ContextAccessorType.GetValueOrReference; var isTarget = isLast && isAssignmentTarget; var member = ResolveInternal(memberCall.iCS_S_ProcedureOrArrayCall(), parent, accessor, hasExplicitLetStatement, isTarget) ?? ResolveInternal(memberCall.iCS_S_VariableOrProcedureCall(), parent, accessor, hasExplicitLetStatement, isTarget); if (member == null) { return(null); } parent = ResolveType(member); } var fieldCall = context.dictionaryCallStmt(); if (fieldCall == null) { return(parent); } return(ResolveInternal(fieldCall, parent, hasExplicitLetStatement, isAssignmentTarget)); }
private Declaration ResolveInternal(VBAParser.ICS_S_ProcedureOrArrayCallContext context, Declaration localScope, ContextAccessorType accessorType = ContextAccessorType.GetValueOrReference, bool hasExplicitLetStatement = false, bool isAssignmentTarget = false) { if (context == null) { return(null); } var identifierContext = context.ambiguousIdentifier(); var fieldCall = context.dictionaryCallStmt(); // todo: understand WTF [baseType] is doing in that grammar rule... return(ResolveInternal(identifierContext, localScope, accessorType, fieldCall, hasExplicitLetStatement, isAssignmentTarget)); }
private Declaration ResolveInternal(VBAParser.ICS_S_VariableOrProcedureCallContext context, Declaration localScope, ContextAccessorType accessorType = ContextAccessorType.GetValueOrReference, bool hasExplicitLetStatement = false, bool isAssignmentTarget = false) { if (context == null) { return(null); } var identifierContext = context.ambiguousIdentifier(); var fieldCall = context.dictionaryCallStmt(); return(ResolveInternal(identifierContext, localScope, accessorType, fieldCall, hasExplicitLetStatement, isAssignmentTarget)); }
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); }