コード例 #1
0
 private IExpressionBinding Visit(Declaration module, Declaration parent, VBAParser.CallStmtContext expression, IBoundExpression withBlockVariable, StatementResolutionContext statementContext)
 {
     // Call statements always have an argument list.
     // One of the reasons we're doing this is that an empty argument list could represent a call to a default member,
     // which requires us to use an IndexDefaultBinding.
     if (expression.CALL() == null)
     {
         dynamic lexpr        = expression.expression();
         var     lexprBinding = Visit(module, parent, lexpr, withBlockVariable, StatementResolutionContext.Undefined);
         var     argList      = VisitArgumentList(module, parent, expression.argumentList(), withBlockVariable, StatementResolutionContext.Undefined);
         SetLeftMatch(lexprBinding, argList.Arguments.Count);
         return(new IndexDefaultBinding(_declarationFinder, Declaration.GetProjectParent(parent), module, parent, expression.expression(), lexprBinding, argList));
     }
     else
     {
         var lexprBinding = Visit(module, parent, (dynamic)expression.expression(), withBlockVariable, StatementResolutionContext.Undefined);
         if (!(lexprBinding is IndexDefaultBinding))
         {
             return(new IndexDefaultBinding(_declarationFinder, Declaration.GetProjectParent(parent), module, parent, expression.expression(), lexprBinding, new ArgumentList()));
         }
         else
         {
             return(lexprBinding);
         }
     }
 }
コード例 #2
0
        protected override void OnExecute(object parameter)
        {
            if (_state.Status != ParserState.Ready)
            {
                return;
            }

            var declaration = parameter is CodeExplorerItemViewModel explorerItem
                ? explorerItem.Declaration
                : GetDeclaration();

            if (!(Declaration.GetProjectParent(declaration) is ProjectDeclaration project))
            {
                return;
            }

            var dialog = _factory.Create(project);

            var model = dialog?.Show();

            if (model is null)
            {
                return;
            }

            _reconciler.ReconcileReferences(model);
            _state.OnParseRequested(this);
        }
コード例 #3
0
        private IExpressionBinding Visit(Declaration module, Declaration parent, VBAParser.MemberAccessExprContext expression, IBoundExpression withBlockVariable, StatementResolutionContext statementContext)
        {
            dynamic lExpression        = expression.lExpression();
            var     lExpressionBinding = Visit(module, parent, lExpression, withBlockVariable, StatementResolutionContext.Undefined);

            return(new MemberAccessDefaultBinding(_declarationFinder, Declaration.GetProjectParent(parent), module, parent, expression, lExpressionBinding, statementContext, expression.unrestrictedIdentifier()));
        }
コード例 #4
0
        private IExpressionBinding Visit(Declaration module, Declaration parent, VBAParser.MemberAccessExprContext expression)
        {
            var lExpression        = expression.lExpression();
            var lExpressionBinding = Visit(module, parent, lExpression);

            return(new MemberAccessProcedurePointerBinding(_declarationFinder, Declaration.GetProjectParent(parent), module, parent, expression, expression.unrestrictedIdentifier(), lExpressionBinding));
        }
コード例 #5
0
 public AddRemoveReferencesPresenter Create()
 {
     using (var pane = _vbe.ActiveCodePane)
     {
         var selected = (ProjectDeclaration)Declaration.GetProjectParent(_state.DeclarationFinder.FindSelectedDeclaration(pane));
         return(selected is null ? null : Create(selected));
     }
 }
コード例 #6
0
        private IExpressionBinding Visit(Declaration module, Declaration parent, VBAParser.MemberAccessExprContext expression)
        {
            dynamic lExpression        = expression.lExpression();
            var     lExpressionBinding = Visit(module, parent, lExpression);

            SetPreferProjectOverUdt(lExpressionBinding);
            return(new MemberAccessTypeBinding(_declarationFinder, Declaration.GetProjectParent(parent), module, parent, expression, expression.unrestrictedIdentifier(), lExpressionBinding));
        }
コード例 #7
0
 private IExpressionBinding Visit(Declaration module, Declaration parent, VBAParser.WithMemberAccessExprContext expression, IBoundExpression withBlockVariable, StatementResolutionContext statementContext)
 {
     if (withBlockVariable == null)
     {
         withBlockVariable = new ResolutionFailedExpression(expression);
     }
     return(new MemberAccessDefaultBinding(_declarationFinder, Declaration.GetProjectParent(parent), module, parent, expression, withBlockVariable, expression.unrestrictedIdentifier().GetText(), statementContext, expression.unrestrictedIdentifier()));
 }
コード例 #8
0
        private IExpressionBinding Visit(Declaration module, Declaration parent, VBAParser.IndexExprContext expression, IBoundExpression withBlockVariable, StatementResolutionContext statementContext)
        {
            dynamic lExpression         = expression.lExpression();
            var     lExpressionBinding  = Visit(module, parent, lExpression, withBlockVariable, StatementResolutionContext.Undefined);
            var     argumentListBinding = VisitArgumentList(module, parent, expression.argumentList(), withBlockVariable, StatementResolutionContext.Undefined);

            SetLeftMatch(lExpressionBinding, argumentListBinding.Arguments.Count);
            return(new IndexDefaultBinding(_declarationFinder, Declaration.GetProjectParent(parent), module, parent, expression, lExpressionBinding, argumentListBinding));
        }
コード例 #9
0
        private IExpressionBinding VisitDictionaryAccessExpression(Declaration module, Declaration parent, ParserRuleContext expression, ParserRuleContext nameContext, IBoundExpression lExpression, StatementResolutionContext statementContext)
        {
            /*
             *  A dictionary access expression is syntactically translated into an index expression with the same
             *  expression for <l-expression> and an argument list with a single positional argument with a
             *  declared type of String and a value equal to the name value of <unrestricted-name>.
             */
            var fakeArgList = new ArgumentList();

            fakeArgList.AddArgument(new ArgumentListArgument(new LiteralDefaultBinding(nameContext), ArgumentListArgumentType.Positional));
            return(new IndexDefaultBinding(_declarationFinder, Declaration.GetProjectParent(parent), module, parent, expression, lExpression, fakeArgList));
        }
コード例 #10
0
        private IExpressionBinding Visit(Declaration module, Declaration parent, VBAParser.UnqualifiedObjectPrintStmtContext expression, IBoundExpression withBlockVariable)
        {
            var printMethodContext = expression.printMethod();
            var simpleNameBinding  = new SimpleNameDefaultBinding(
                _declarationFinder,
                Declaration.GetProjectParent(parent),
                module,
                parent,
                printMethodContext,
                printMethodContext.GetText(),
                StatementResolutionContext.Undefined);
            var outputListContext = expression.outputList();
            var outputListBinding = outputListContext != null
                ? Visit(
                module,
                parent,
                outputListContext,
                withBlockVariable)
                : null;

            return(new ObjectPrintDefaultBinding(expression, simpleNameBinding, outputListBinding));
        }
コード例 #11
0
        private IExpressionBinding Visit(Declaration module, Declaration parent, VBAParser.ObjectPrintExprContext expression, IBoundExpression withBlockVariable)
        {
            var lExpression         = expression.lExpression();
            var lExpressionBinding  = Visit(module, parent, lExpression, withBlockVariable, StatementResolutionContext.Undefined);
            var memberAccessBinding = new MemberAccessDefaultBinding(
                _declarationFinder,
                Declaration.GetProjectParent(parent),
                module,
                parent,
                expression,
                lExpressionBinding,
                StatementResolutionContext.Undefined,
                expression.printMethod());
            var outputListContext = expression.outputList();
            var outputListBinding = outputListContext != null
                ? Visit(
                module,
                parent,
                outputListContext,
                withBlockVariable)
                : null;

            return(new ObjectPrintDefaultBinding(expression, memberAccessBinding, outputListBinding));
        }
コード例 #12
0
 private IExpressionBinding Visit(Declaration module, Declaration parent, VBAParser.SimpleNameExprContext expression)
 {
     return(new SimpleNameTypeBinding(_declarationFinder, Declaration.GetProjectParent(parent), module, parent, expression));
 }
コード例 #13
0
 private IExpressionBinding Visit(Declaration module, Declaration parent, VBAParser.IdentifierValueContext expression, IBoundExpression withBlockVariable, StatementResolutionContext statementContext)
 {
     return(new SimpleNameDefaultBinding(_declarationFinder, Declaration.GetProjectParent(parent), module, parent, expression, Identifier.GetName(expression), statementContext));
 }
コード例 #14
0
 private IExpressionBinding Visit(Declaration module, Declaration parent, VBAParser.SimpleNameExprContext expression, StatementResolutionContext statementContext)
 {
     return(new SimpleNameDefaultBinding(_declarationFinder, Declaration.GetProjectParent(parent), module, parent, expression, Identifier.GetName(expression.identifier()), statementContext));
 }
コード例 #15
0
        /// <summary>
        /// Determines whether the 'Set' keyword is required (whether it's present or not) for the specified identifier reference.
        /// </summary>
        /// <param name="reference">The identifier reference to analyze</param>
        /// <param name="declarationFinderProvider">The parser state</param>
        public static bool RequiresSetAssignment(IdentifierReference reference, IDeclarationFinderProvider declarationFinderProvider)
        {
            if (!reference.IsAssignment)
            {
                // reference isn't assigning its declaration; not interesting
                return(false);
            }

            if (reference.IsSetAssignment)
            {
                // don't assume Set keyword is legit...
                return(reference.Declaration.IsObject);
            }

            var declaration = reference.Declaration;

            if (declaration.IsArray)
            {
                // arrays don't need a Set statement... todo figure out if array items are objects
                return(false);
            }

            var isObjectVariable = declaration.IsObject;

            if (!isObjectVariable && !(declaration.IsUndeclared || Tokens.Variant.Equals(declaration.AsTypeName)))
            {
                return(false);
            }

            // For Each iterators are implicitly set.
            var letStmtContext = reference.Context.GetAncestor <VBAParser.LetStmtContext>();

            if (reference.Context.GetAncestor <VBAParser.ForEachStmtContext>() != null && letStmtContext == null)
            {
                return(false);
            }

            if (isObjectVariable)
            {
                // get the members of the returning type, a default member could make us lie otherwise
                var classModule = declaration.AsTypeDeclaration as ClassModuleDeclaration;
                return(!HasPotentiallyNonObjectParameterlessDefaultMember(classModule));
            }

            // assigned declaration is a variant. we need to know about the RHS of the assignment.
            if (letStmtContext == null)
            {
                // not an assignment
                return(false);
            }

            var expression = letStmtContext.expression();

            if (expression == null)
            {
                Debug.Assert(false, "RHS expression is empty? What's going on here?");
                return(false);
            }


            var module = Declaration.GetModuleParent(reference.ParentScoping);

            if (expression is VBAParser.NewExprContext newExpr)
            {
                var newTypeExpression = newExpr.expression();

                // todo resolve expression type

                //Covers the case of a single type on the RHS of the assignment.
                var simpleTypeName = newTypeExpression.GetDescendent <VBAParser.SimpleNameExprContext>();
                if (simpleTypeName != null && simpleTypeName.GetText() == newTypeExpression.GetText())
                {
                    var qualifiedIdentifierSelection = new QualifiedSelection(module.QualifiedModuleName,
                                                                              simpleTypeName.identifier().GetSelection());
                    var identifierText = simpleTypeName.identifier().GetText();
                    return(declarationFinderProvider.DeclarationFinder.IdentifierReferences(qualifiedIdentifierSelection)
                           .Select(identifierReference => identifierReference.Declaration)
                           .Where(decl => identifierText == decl.IdentifierName)
                           .OfType <ClassModuleDeclaration>()
                           .Any(typeDecl => !HasPotentiallyNonObjectParameterlessDefaultMember(typeDecl)));
                }
                //Here, we err on the side of false-positives, but that seems more appropriate than not to treat qualified type expressions incorrectly.
                //Whether there is a legitimate use here for default members is questionable anyway.
                return(true);
            }

            var literalExpression = expression as VBAParser.LiteralExprContext;

            if (literalExpression?.literalExpression()?.literalIdentifier()?.objectLiteralIdentifier() != null)
            {
                // RHS is a 'Nothing' token - LHS needs a 'Set' keyword:
                return(true);
            }
            if (literalExpression != null)
            {
                return(false); // any other literal expression definitely isn't an object.
            }

            // todo resolve expression return type

            //Covers the case of a single variable on the RHS of the assignment.
            var simpleName = expression.GetDescendent <VBAParser.SimpleNameExprContext>();

            if (simpleName != null && simpleName.GetText() == expression.GetText())
            {
                var qualifiedIdentifierSelection = new QualifiedSelection(module.QualifiedModuleName,
                                                                          simpleName.identifier().GetSelection());
                return(declarationFinderProvider.DeclarationFinder.IdentifierReferences(qualifiedIdentifierSelection)
                       .Select(identifierReference => identifierReference.Declaration)
                       .Where(decl => decl.IsObject &&
                              simpleName.identifier().GetText() == decl.IdentifierName)
                       .Select(typeDeclaration => typeDeclaration.AsTypeDeclaration as ClassModuleDeclaration)
                       .Any(typeDecl => !HasPotentiallyNonObjectParameterlessDefaultMember(typeDecl)));
            }

            var project = Declaration.GetProjectParent(reference.ParentScoping);

            //todo: Use code path analysis to ensure that we are really picking up the last assignment to the RHS.
            // is the reference referring to something else in scope that's a object?
            return(declarationFinderProvider.DeclarationFinder.MatchName(expression.GetText())
                   .Any(decl => (decl.DeclarationType.HasFlag(DeclarationType.ClassModule) || Tokens.Object.Equals(decl.AsTypeName)) &&
                        AccessibilityCheck.IsAccessible(project, module, reference.ParentScoping, decl)));
        }
コード例 #16
0
        /// <summary>
        /// Determines whether the 'Set' keyword is required (whether it's present or not) for the specified identifier reference.
        /// </summary>
        /// <param name="reference">The identifier reference to analyze</param>
        /// <param name="declarationFinderProvider">The parser state</param>
        public static bool RequiresSetAssignment(IdentifierReference reference, IDeclarationFinderProvider declarationFinderProvider)
        {
            if (!reference.IsAssignment)
            {
                // reference isn't assigning its declaration; not interesting
                return(false);
            }

            if (reference.IsSetAssignment)
            {
                // don't assume Set keyword is legit...
                return(reference.Declaration.IsObject);
            }

            var declaration = reference.Declaration;

            if (declaration.IsArray)
            {
                // arrays don't need a Set statement... todo figure out if array items are objects
                return(false);
            }

            var isObjectVariable = declaration.IsObject;

            if (!isObjectVariable && !(declaration.IsUndeclared || Tokens.Variant.Equals(declaration.AsTypeName)))
            {
                return(false);
            }

            // For Each iterators are implicitly set.
            var letStmtContext = reference.Context.GetAncestor <VBAParser.LetStmtContext>();

            if (reference.Context.GetAncestor <VBAParser.ForEachStmtContext>() != null && letStmtContext == null)
            {
                return(false);
            }

            if (isObjectVariable)
            {
                // get the members of the returning type, a default member could make us lie otherwise
                var classModule = declaration.AsTypeDeclaration as ClassModuleDeclaration;
                if (classModule?.DefaultMember == null)
                {
                    return(true);
                }
                var parameters = (classModule.DefaultMember as IParameterizedDeclaration)?.Parameters;
                // assign declaration is an object without a default parameterless (or with all parameters optional) member - LHS needs a 'Set' keyword.
                return(parameters != null && parameters.All(p => p.IsOptional));
            }

            // assigned declaration is a variant. we need to know about the RHS of the assignment.
            if (letStmtContext == null)
            {
                // not an assignment
                return(false);
            }

            var expression = letStmtContext.expression();

            if (expression == null)
            {
                Debug.Assert(false, "RHS expression is empty? What's going on here?");
                return(false);
            }

            if (expression is VBAParser.NewExprContext)
            {
                // RHS expression is newing up an object reference - LHS needs a 'Set' keyword:
                return(true);
            }

            var literalExpression = expression as VBAParser.LiteralExprContext;

            if (literalExpression?.literalExpression()?.literalIdentifier()?.objectLiteralIdentifier() != null)
            {
                // RHS is a 'Nothing' token - LHS needs a 'Set' keyword:
                return(true);
            }
            if (literalExpression != null)
            {
                return(false); // any other literal expression definitely isn't an object.
            }

            // todo resolve expression return type
            var project = Declaration.GetProjectParent(reference.ParentScoping);
            var module  = Declaration.GetModuleParent(reference.ParentScoping);

            var simpleName = expression.GetDescendent <VBAParser.SimpleNameExprContext>();

            if (simpleName != null)
            {
                return(declarationFinderProvider.DeclarationFinder.MatchName(simpleName.identifier().GetText())
                       .Any(d => AccessibilityCheck.IsAccessible(project, module, reference.ParentScoping, d) && d.IsObject));
            }

            // is the reference referring to something else in scope that's a object?
            return(declarationFinderProvider.DeclarationFinder.MatchName(expression.GetText())
                   .Any(decl => (decl.DeclarationType.HasFlag(DeclarationType.ClassModule) || Tokens.Object.Equals(decl.AsTypeName)) &&
                        AccessibilityCheck.IsAccessible(project, module, reference.ParentScoping, decl)));
        }