private IExpressionBinding Visit(Declaration module, Declaration parent, VBAParser.LExpressionContext expression, IBoundExpression withBlockVariable, StatementResolutionContext statementContext) { switch (expression) { case VBAParser.SimpleNameExprContext simpleNameExprContext: return(Visit(module, parent, simpleNameExprContext, statementContext)); case VBAParser.MemberAccessExprContext memberAccessExprContext: return(Visit(module, parent, memberAccessExprContext, withBlockVariable, statementContext)); case VBAParser.IndexExprContext indexExprContext: return(Visit(module, parent, indexExprContext, withBlockVariable)); case VBAParser.WithMemberAccessExprContext withMemberAccessExprContext: return(Visit(module, parent, withMemberAccessExprContext, withBlockVariable, statementContext)); case VBAParser.InstanceExprContext instanceExprContext: return(Visit(module, instanceExprContext)); case VBAParser.WhitespaceIndexExprContext whitespaceIndexExprContext: return(Visit(module, parent, whitespaceIndexExprContext, withBlockVariable)); case VBAParser.DictionaryAccessExprContext dictionaryAccessExprContext: return(Visit(module, parent, dictionaryAccessExprContext, withBlockVariable)); case VBAParser.WithDictionaryAccessExprContext withDictionaryAccessExprContext: return(Visit(module, parent, withDictionaryAccessExprContext, withBlockVariable)); case VBAParser.ObjectPrintExprContext objectPrintExprContext: return(Visit(module, parent, objectPrintExprContext, withBlockVariable)); default: throw new NotSupportedException($"Unexpected lExpression type {expression.GetType()}"); } }
private Declaration SetTypeDeclaration(VBAParser.LExpressionContext lExpression, QualifiedModuleName containingModule) { var finder = _declarationFinderProvider.DeclarationFinder; var setTypeDeterminingDeclaration = SetTypeDeterminingDeclarationOfExpression(lExpression, containingModule, finder); return(SetTypeDeclaration(setTypeDeterminingDeclaration.declaration)); }
private static ParserRuleContext DefaultMemberReferenceContext(VBAParser.LExpressionContext context) { if (context is VBAParser.DictionaryAccessExprContext dictionaryAccess) { return(dictionaryAccess.dictionaryAccess()); } return(((VBAParser.WithDictionaryAccessExprContext)context).dictionaryAccess()); }
private string SetTypeName(VBAParser.LExpressionContext lExpression, QualifiedModuleName containingModule) { var finder = _declarationFinderProvider.DeclarationFinder; var setTypeDeterminingDeclaration = SetTypeDeterminingDeclarationOfExpression(lExpression, containingModule, finder); return(setTypeDeterminingDeclaration.mightHaveSetType ? FullObjectTypeName(setTypeDeterminingDeclaration.declaration, lExpression) : NotAnObject); }
//Please note that the lExpression is the (whitespace) index expression itself and not the lExpression it contains. private Declaration ResolveIndexExpressionAsArrayAccess(VBAParser.LExpressionContext actualIndexExpr, QualifiedModuleName containingModule, DeclarationFinder finder) { // An array access references the entire (whitespace)indexExpr. var qualifiedSelection = new QualifiedSelection(containingModule, actualIndexExpr.GetSelection()); return(finder .IdentifierReferences(qualifiedSelection) .LastOrDefault(reference => reference.IsArrayAccess) ?.Declaration); }
private Declaration ResolveIndexExpressionAsDefaultMemberAccess(VBAParser.LExpressionContext lExpressionOfIndexExpression, QualifiedModuleName containingModule, DeclarationFinder finder) { // A default member access references the entire lExpression. // If there are multiple, the references are ordered by recursion depth. var qualifiedSelection = new QualifiedSelection(containingModule, lExpressionOfIndexExpression.GetSelection()); return(finder .IdentifierReferences(qualifiedSelection) .LastOrDefault(reference => reference.IsDefaultMemberAccess) ?.Declaration); }
private Declaration ResolveIndexExpressionAsMethod(VBAParser.LExpressionContext lExpressionOfIndexExpression, QualifiedModuleName containingModule, DeclarationFinder finder) { //For functions and properties, the identifier will be at the end of the lExpression. var qualifiedSelection = new QualifiedSelection(containingModule, lExpressionOfIndexExpression.GetSelection().Collapse()); var candidate = finder .ContainingIdentifierReferences(qualifiedSelection) .LastOrDefault() ?.Declaration; return(candidate?.DeclarationType.HasFlag(DeclarationType.Member) ?? false ? candidate : null); }
private IExpressionBinding Visit(Declaration module, Declaration parent, VBAParser.LExpressionContext expression) { switch (expression) { case VBAParser.SimpleNameExprContext simpleNameExprContext: return(Visit(module, parent, simpleNameExprContext)); case VBAParser.MemberAccessExprContext memberAccessExprContext: return(Visit(module, parent, memberAccessExprContext)); default: throw new NotSupportedException($"Unexpected lExpression type {expression.GetType()}"); } }
private (Declaration declaration, bool mightHaveSetType) SetTypeDeterminingDeclarationOfIndexExpression(VBAParser.LExpressionContext indexExpr, QualifiedModuleName containingModule, DeclarationFinder finder) { var lExpressionOfIndexExpression = indexExpr is VBAParser.IndexExprContext indexExpression ? indexExpression.lExpression() : (indexExpr as VBAParser.WhitespaceIndexExprContext)?.lExpression(); if (lExpressionOfIndexExpression == null) { throw new NotSupportedException("Called index expression resolution on expression, which is neither a properly built indexExpr nor a properly built whitespaceIndexExpr."); } //Passing the indexExpr itself is correct. var arrayDeclaration = ResolveIndexExpressionAsArrayAccess(indexExpr, containingModule, finder); if (arrayDeclaration != null) { return(arrayDeclaration, MightHaveSetTypeOnArrayAccess(arrayDeclaration)); } var declaration = ResolveIndexExpressionAsDefaultMemberAccess(lExpressionOfIndexExpression, containingModule, finder) ?? ResolveIndexExpressionAsMethod(lExpressionOfIndexExpression, containingModule, finder); return(declaration, MightHaveSetType(declaration)); }
private (Declaration declaration, bool mightHaveSetType) SetTypeDeterminingDeclarationOfExpression(VBAParser.LExpressionContext lExpression, QualifiedModuleName containingModule, DeclarationFinder finder) { switch (lExpression) { case VBAParser.SimpleNameExprContext simpleNameExpression: return(SetTypeDeterminingDeclarationOfExpression(simpleNameExpression.identifier(), containingModule, finder)); case VBAParser.InstanceExprContext instanceExpression: return(SetTypeDeterminingDeclarationOfInstance(containingModule, finder)); case VBAParser.IndexExprContext indexExpression: return(SetTypeDeterminingDeclarationOfIndexExpression(indexExpression, containingModule, finder)); case VBAParser.MemberAccessExprContext memberAccessExpression: return(SetTypeDeterminingDeclarationOfExpression(memberAccessExpression.unrestrictedIdentifier(), containingModule, finder)); case VBAParser.WithMemberAccessExprContext withMemberAccessExpression: return(SetTypeDeterminingDeclarationOfExpression(withMemberAccessExpression.unrestrictedIdentifier(), containingModule, finder)); case VBAParser.DictionaryAccessExprContext dictionaryAccessExpression: return(SetTypeDeterminingDeclarationOfExpression(dictionaryAccessExpression.dictionaryAccess(), containingModule, finder)); case VBAParser.WithDictionaryAccessExprContext withDictionaryAccessExpression: return(SetTypeDeterminingDeclarationOfExpression(withDictionaryAccessExpression.dictionaryAccess(), containingModule, finder)); case VBAParser.WhitespaceIndexExprContext whitespaceIndexExpression: return(SetTypeDeterminingDeclarationOfIndexExpression(whitespaceIndexExpression, containingModule, finder)); default: return(null, true); //We should already cover every case. Return the value indicating that we have no idea. } }
private static string FullObjectTypeName(Declaration setTypeDeterminingDeclaration, VBAParser.LExpressionContext lExpression) { if (setTypeDeterminingDeclaration == null) { return(null); } if (setTypeDeterminingDeclaration.DeclarationType.HasFlag(DeclarationType.ClassModule)) { return(setTypeDeterminingDeclaration.QualifiedModuleName.ToString()); } if (setTypeDeterminingDeclaration.IsObject || setTypeDeterminingDeclaration.IsObjectArray) { return(setTypeDeterminingDeclaration.FullAsTypeName); } return(setTypeDeterminingDeclaration.AsTypeName == Tokens.Variant ? setTypeDeterminingDeclaration.AsTypeName : NotAnObject); }