private bool IsInByRefArgumentSet(NonNullImmutableList <NameToken> byRefArguments, NameToken reference)
        {
            if (byRefArguments == null)
            {
                throw new ArgumentNullException("byRefArguments");
            }
            if (reference == null)
            {
                throw new ArgumentNullException("reference");
            }

            return(byRefArguments.Any(
                       byRefArgument => _nameRewriter.GetMemberAccessTokenName(byRefArgument) == _nameRewriter.GetMemberAccessTokenName(reference)
                       ));
        }
        public static bool AreNamesEquivalent(this VBScriptNameRewriter nameRewriter, NameToken x, NameToken y)
        {
            if (nameRewriter == null)
            {
                throw new ArgumentNullException("nameRewriter");
            }
            if (x == null)
            {
                throw new ArgumentNullException("x");
            }
            if (y == null)
            {
                throw new ArgumentNullException("y");
            }

            return(nameRewriter.GetMemberAccessTokenName(x) == nameRewriter.GetMemberAccessTokenName(y));
        }
        public static Statement RewriteStatementUsingByRefArgumentMappings(this NonNullImmutableList <FuncByRefMapping> byRefArgumentsToRewrite, Statement statementBlock, VBScriptNameRewriter nameRewriter)
        {
            if (byRefArgumentsToRewrite == null)
            {
                throw new ArgumentNullException("byRefArgumentsToRewrite");
            }
            if (statementBlock == null)
            {
                throw new ArgumentNullException("statementBlock");
            }
            if (nameRewriter == null)
            {
                throw new ArgumentNullException("nameRewriter");
            }

            // Originally, this would throw an exception if there were no by-ref arguments (why bother calling this if there are no by-ref arguments to deal with; does this indicate an error in the calling
            // code?) but in some cases it's easier to be able to call it without having check whether there were any value that need rewriting and the cases where being so strict may catch unintentional
            // calls are few
            if (!byRefArgumentsToRewrite.Any())
            {
                return(statementBlock);
            }

            return(new Statement(
                       statementBlock.Tokens.Select(t =>
            {
                var nameToken = t as NameToken;
                if (nameToken == null)
                {
                    return t;
                }
                var referenceRewriteDetailsIfApplicable = byRefArgumentsToRewrite.FirstOrDefault(
                    r => nameRewriter.GetMemberAccessTokenName(r.From) == nameRewriter.GetMemberAccessTokenName(nameToken)
                    );
                return (referenceRewriteDetailsIfApplicable == null) ? t : new DoNotRenameNameToken(referenceRewriteDetailsIfApplicable.To.Name, t.LineIndex);
            }),
                       statementBlock.CallPrefix
                       ));
        }
Exemplo n.º 4
0
        /// <summary>
        /// Try to retrieve information about a name token. If there is nothing matching it in the current scope then null will be returned.
        /// </summary>
        public static DeclaredReferenceDetails TryToGetDeclaredReferenceDetails(
            this ScopeAccessInformation scopeInformation,
            NameToken target,
            VBScriptNameRewriter nameRewriter)
        {
            if (scopeInformation == null)
            {
                throw new ArgumentNullException("scopeInformation");
            }
            if (target == null)
            {
                throw new ArgumentNullException("target");
            }
            if (nameRewriter == null)
            {
                throw new ArgumentNullException("nameRewriter");
            }

            // If the target corresponds to the containing "WITH" reference (if any) then use that ("WITH a: .Go: END WITH" is translated
            // approximately into "var w123 = a; w123.Go();" where the "w123" is the DirectedWithReferenceIfAny and so we don't need to
            // check for other variables or functions that may apply, it's the local variable WITH construct target.
            var rewrittenTargetName = nameRewriter(target).Name;

            if (scopeInformation.DirectedWithReferenceIfAny != null)
            {
                // Note that WithinFunctionOrPropertyOrWith is always specified here for the scope location since the WITH target should
                // not be part of the "outer most scope" variable set like variables declared in that scope in the source script - this
                // target reference is not something that can be altered, it is set in the current scope and accessed directly.
                if (nameRewriter.GetMemberAccessTokenName(scopeInformation.DirectedWithReferenceIfAny.AsToken()) == rewrittenTargetName)
                {
                    return(new DeclaredReferenceDetails(ReferenceTypeOptions.Variable, ScopeLocationOptions.WithinFunctionOrPropertyOrWith));
                }
            }

            if (scopeInformation.ScopeDefiningParent != null)
            {
                if (scopeInformation.ScopeDefiningParent.ExplicitScopeAdditions.Any(t => nameRewriter.GetMemberAccessTokenName(t) == rewrittenTargetName))
                {
                    // ExplicitScopeAdditions should be things such as function arguments, so they will share the same ScopeLocation as the
                    // current scopeInformation reference
                    return(new DeclaredReferenceDetails(ReferenceTypeOptions.Variable, scopeInformation.ScopeDefiningParent.Scope));
                }
            }

            var firstExternalDependencyMatch = scopeInformation.ExternalDependencies
                                               .FirstOrDefault(t => nameRewriter.GetMemberAccessTokenName(t) == rewrittenTargetName);

            if (firstExternalDependencyMatch != null)
            {
                return(new DeclaredReferenceDetails(ReferenceTypeOptions.ExternalDependency, ScopeLocationOptions.OutermostScope));
            }

            var scopedNameTokens =
                scopeInformation.Classes.Select(t => Tuple.Create(t, ReferenceTypeOptions.Class))
                .Concat(scopeInformation.Functions.Select(t => Tuple.Create(t, ReferenceTypeOptions.Function)))
                .Concat(scopeInformation.Properties.Select(t => Tuple.Create(t, ReferenceTypeOptions.Property)))
                .Concat(scopeInformation.Constants.Select(t => Tuple.Create(t, ReferenceTypeOptions.Constant)))
                .Concat(scopeInformation.Variables.Select(t => Tuple.Create(t, ReferenceTypeOptions.Variable)));

            // There could be references matching the requested name in multiple scopes, start from the closest and work outwards
            var possibleScopes = new[]
            {
                ScopeLocationOptions.WithinFunctionOrPropertyOrWith,
                ScopeLocationOptions.WithinClass,
                ScopeLocationOptions.OutermostScope
            };

            foreach (var scope in possibleScopes)
            {
                var firstMatch = scopedNameTokens
                                 .Where(t => t.Item1.ScopeLocation == scope)
                                 .FirstOrDefault(t => nameRewriter.GetMemberAccessTokenName(t.Item1) == rewrittenTargetName);
                if (firstMatch != null)
                {
                    return(new DeclaredReferenceDetails(firstMatch.Item2, firstMatch.Item1.ScopeLocation));
                }
            }
            return(null);
        }