private static Declaration SelectedDeclarationViaArgument(QualifiedSelection qualifiedSelection, DeclarationFinder finder)
        {
            var members = finder.Members(qualifiedSelection.QualifiedName)
                          .Where(m => (m.DeclarationType.HasFlag(DeclarationType.Procedure) || // includes PropertyLet and PropertySet and LibraryProcedure
                                       m.DeclarationType.HasFlag(DeclarationType.Function)) && // includes PropertyGet and LibraryFunction
                                 !m.DeclarationType.HasFlag(DeclarationType.LibraryFunction) &&
                                 !m.DeclarationType.HasFlag(DeclarationType.LibraryProcedure));
            var enclosingProcedure = members.SingleOrDefault(m => m.Context.GetSelection().Contains(qualifiedSelection.Selection));

            if (enclosingProcedure == null)
            {
                return(null);
            }

            var allArguments = enclosingProcedure.Context.GetDescendents <VBAParser.ArgumentContext>();

            var context = allArguments
                          .Where(arg => arg.missingArgument() == null)
                          .FirstOrDefault(m =>
            {
                var isOnWhitespace = false;
                if (m.TryGetPrecedingContext <VBAParser.WhiteSpaceContext>(out var whitespace))
                {
                    isOnWhitespace = whitespace.GetSelection().ContainsFirstCharacter(qualifiedSelection.Selection);
                }
                return(isOnWhitespace || m.GetSelection().ContainsFirstCharacter(qualifiedSelection.Selection));
            });

            var skippedArg = allArguments
                             .Where(arg => arg.missingArgument() != null)
                             .FirstOrDefault(m =>
            {
                var isOnWhitespace = false;
                if (m.TryGetPrecedingContext <VBAParser.WhiteSpaceContext>(out var whitespace))
                {
                    isOnWhitespace = whitespace.GetSelection().ContainsFirstCharacter(qualifiedSelection.Selection);
                }
                return(isOnWhitespace || m.GetSelection().ContainsFirstCharacter(qualifiedSelection.Selection));
            });

            context = context ?? skippedArg;
            if (context != null)
            {
                return((Declaration)finder.FindParameterOfNonDefaultMemberFromSimpleArgumentNotPassedByValExplicitly(context, enclosingProcedure)
                       ?? finder.FindInvokedMemberFromArgumentContext(context, qualifiedSelection.QualifiedName)); // fallback to the invoked procedure declaration
            }

            return(null);
        }
        private static bool IsAssignedByRefArgument(Declaration enclosingProcedure, IdentifierReference reference, DeclarationFinder finder)
        {
            var argExpression = ImmediateArgumentExpressionContext(reference);

            if (argExpression is null)
            {
                return(false);
            }

            var parameter = finder.FindParameterOfNonDefaultMemberFromSimpleArgumentNotPassedByValExplicitly(argExpression, enclosingProcedure);

            // note: not recursive, by design.
            return(parameter != null &&
                   (parameter.IsImplicitByRef || parameter.IsByRef) &&
                   parameter.References.Any(r => r.IsAssignment));
        }
Exemple #3
0
        private static bool IsPotentiallyAssignedByRefArgument(QualifiedModuleName module, IdentifierReference reference, DeclarationFinder finder)
        {
            var argExpression = ImmediateArgumentExpressionContext(reference);

            if (argExpression == null)
            {
                return(false);
            }

            var parameter = finder.FindParameterOfNonDefaultMemberFromSimpleArgumentNotPassedByValExplicitly(argExpression, module);

            if (parameter == null)
            {
                //We have no idea what parameter it is passed to as argument. So, we have to err on the safe side and assume it is passed by reference.
                return(true);
            }

            //We do not check whether the argument the parameter is actually assigned to costly recursions.
            return(parameter.IsByRef);
        }
Exemple #4
0
        private static bool IsUsageAsAssignedToByRefArgument(IdentifierReference reference, DeclarationFinder finder)
        {
            var argExpression = ImmediateArgumentExpressionContext(reference);

            if (argExpression == null)
            {
                return(false);
            }

            var parameter = finder.FindParameterOfNonDefaultMemberFromSimpleArgumentNotPassedByValExplicitly(argExpression, reference.QualifiedModuleName);

            if (parameter == null)
            {
                //We have no idea what parameter it is passed to as argument. So, we have to err on the safe side and assume it is not passed by reference.
                return(false);
            }

            //We go only one level deep and make a conservative check to avoid a potentially costly recursion.
            return(parameter.IsByRef &&
                   parameter.References.Any(paramReference => paramReference.IsAssignment));
        }