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)); }
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); }
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)); }