/// <summary>
        /// Decides if the current function defintion is the right defition
        /// for the symbol being searched for. The defintion of the symbol will be a of type 
        /// SymbolType.Function and have the same name as the symbol
        /// </summary>
        /// <param name="functionDefinitionAst">A FunctionDefinitionAst in the script's AST</param>
        /// <returns>A descion to stop searching if the right FunctionDefinitionAst was found, 
        /// or a decision to continue if it wasn't found</returns>
        public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst)
        {
            // Get the start column number of the function name, 
            // instead of the the start column of 'function' and create new extent for the functionName
            int startColumnNumber =
                functionDefinitionAst.Extent.Text.IndexOf(
                    functionDefinitionAst.Name) + 1;

            IScriptExtent nameExtent = new ScriptExtent()
            {
                Text = functionDefinitionAst.Name,
                StartLineNumber = functionDefinitionAst.Extent.StartLineNumber,
                StartColumnNumber = startColumnNumber,
                EndLineNumber = functionDefinitionAst.Extent.StartLineNumber,
                EndColumnNumber = startColumnNumber + functionDefinitionAst.Name.Length
            };

            if (symbolRef.SymbolType.Equals(SymbolType.Function) &&
                 nameExtent.Text.Equals(symbolRef.ScriptRegion.Text, StringComparison.InvariantCultureIgnoreCase))
            {
                this.FoundDeclartion =
                    new SymbolReference(
                        SymbolType.Function,
                        nameExtent);

                return AstVisitAction.StopVisit;
            }

            return base.VisitFunctionDefinition(functionDefinitionAst);
        }
        internal SymbolDetails(
            SymbolReference symbolReference, 
            Runspace runspace)
        {
            this.SymbolReference = symbolReference;

            // If the symbol is a command, get its documentation
            if (symbolReference.SymbolType == SymbolType.Function)
            {
                CommandInfo commandInfo =
                    CommandHelpers.GetCommandInfo(
                        symbolReference.SymbolName,
                        runspace);

                this.Documentation =
                    CommandHelpers.GetCommandSynopsis(
                        commandInfo,
                        runspace);

                this.DisplayString = "function " + symbolReference.SymbolName;
            }
            else if (symbolReference.SymbolType == SymbolType.Parameter)
            {
                // TODO: Get parameter help
                this.DisplayString = "(parameter) " + symbolReference.SymbolName;
            }
            else if (symbolReference.SymbolType == SymbolType.Variable)
            {
                this.DisplayString = symbolReference.SymbolName;
            }
        }
        /// <summary>
        /// Checks to see if this function definition is the symbol we are looking for.
        /// </summary>
        /// <param name="functionDefinitionAst">A functionDefinitionAst object in the script's AST</param>
        /// <returns>A descion to stop searching if the right symbol was found, 
        /// or a decision to continue if it wasn't found</returns>
        public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst)
        {
            int startColumnNumber =
                functionDefinitionAst.Extent.Text.IndexOf(
                    functionDefinitionAst.Name) + 1;

            IScriptExtent nameExtent = new ScriptExtent()
            {
                Text = functionDefinitionAst.Name,
                StartLineNumber = functionDefinitionAst.Extent.StartLineNumber,
                EndLineNumber = functionDefinitionAst.Extent.EndLineNumber,
                StartColumnNumber = startColumnNumber,
                EndColumnNumber = startColumnNumber + functionDefinitionAst.Name.Length
            };

            if (this.IsPositionInExtent(nameExtent))
            {
                this.FoundSymbolReference =
                    new SymbolReference(
                        SymbolType.Function,
                        nameExtent);

                return AstVisitAction.StopVisit;
            }

            return base.VisitFunctionDefinition(functionDefinitionAst);
        }
 /// <summary>
 /// Constructs an instance of a ParameterSetSignatures object
 /// </summary>
 /// <param name="commandInfoSet">Collection of parameter set info</param>
 /// <param name="foundSymbol"> The SymbolReference of the command</param>
 public ParameterSetSignatures(IEnumerable<CommandParameterSetInfo> commandInfoSet, SymbolReference foundSymbol)
 {
     List<ParameterSetSignature> paramSetSignatures = new List<ParameterSetSignature>();
     foreach (CommandParameterSetInfo setInfo in commandInfoSet)
     {
         paramSetSignatures.Add(new ParameterSetSignature(setInfo));
     }
     Signatures = paramSetSignatures.ToArray();
     CommandName = foundSymbol.ScriptRegion.Text;
     ScriptRegion = foundSymbol.ScriptRegion;
 }
        /// <summary>
        /// Finds the definition of the symbol 
        /// </summary>
        /// <param name="scriptAst">The abstract syntax tree of the given script</param>
        /// <param name="symbolReference">The symbol that we are looking for the definition of</param>
        /// <returns>A SymbolReference of the definition of the symbolReference</returns>
        public static SymbolReference FindDefinitionOfSymbol(
            Ast scriptAst,
            SymbolReference symbolReference)
        {
            FindDeclartionVisitor declarationVisitor =
                new FindDeclartionVisitor(
                    symbolReference);
            scriptAst.Visit(declarationVisitor);

            return declarationVisitor.FoundDeclartion;
        }
 /// <summary>
 /// Checks to see if this command parameter is the symbol we are looking for.
 /// </summary>
 /// <param name="commandParameterAst">A CommandParameterAst object in the script's AST</param>
 /// <returns>A descion to stop searching if the right symbol was found, 
 /// or a decision to continue if it wasn't found</returns>
 public override AstVisitAction VisitCommandParameter(CommandParameterAst commandParameterAst)
 {
     if (this.IsPositionInExtent(commandParameterAst.Extent))
     {
         this.FoundSymbolReference =
             new SymbolReference(
                 SymbolType.Parameter,
                 commandParameterAst.Extent);
         return AstVisitAction.StopVisit;
     }
     return AstVisitAction.Continue;
 }
        /// <summary>
        /// Decides if the current variable expression is the right defition for 
        /// the symbol being searched for. The defintion of the symbol will be a of type 
        /// SymbolType.Variable and have the same name as the symbol
        /// </summary>
        /// <param name="variableExpressionAst">A FunctionDefinitionAst in the script's AST</param>
        /// <returns>A descion to stop searching if the right VariableExpressionAst was found, 
        /// or a decision to continue if it wasn't found</returns>
        public override AstVisitAction VisitVariableExpression(VariableExpressionAst variableExpressionAst)
        {
            if(symbolRef.SymbolType.Equals(SymbolType.Variable) &&
                variableExpressionAst.Extent.Text.Equals(symbolRef.SymbolName, StringComparison.InvariantCultureIgnoreCase))
            {
                this.FoundDeclartion =
                    new SymbolReference(
                        SymbolType.Variable,
                        variableExpressionAst.Extent);

                return AstVisitAction.StopVisit;
            }

            return AstVisitAction.Continue;
        }
        internal SymbolDetails(
            SymbolReference symbolReference, 
            Runspace runspace)
        {
            this.SymbolReference = symbolReference;

            // If the symbol is a command, get its documentation
            if (symbolReference.SymbolType == SymbolType.Function)
            {
                CommandInfo commandInfo =
                    CommandHelpers.GetCommandInfo(
                        symbolReference.SymbolName,
                        runspace);

                if (commandInfo != null)
                {
                    this.Documentation =
                        CommandHelpers.GetCommandSynopsis(
                            commandInfo,
                            runspace);

                    if (commandInfo.CommandType == CommandTypes.Application)
                    {
                        this.DisplayString = "(application) " + symbolReference.SymbolName;
                    }
                    else
                    {
                        this.DisplayString = "function " + symbolReference.SymbolName;
                    }
                }
                else
                {
                    // Command information can't be loaded.  This is likely due to
                    // the symbol being a function that is defined in a file that
                    // hasn't been loaded in the runspace yet.
                    this.DisplayString = "function " + symbolReference.SymbolName;
                }
            }
            else if (symbolReference.SymbolType == SymbolType.Parameter)
            {
                // TODO: Get parameter help
                this.DisplayString = "(parameter) " + symbolReference.SymbolName;
            }
            else if (symbolReference.SymbolType == SymbolType.Variable)
            {
                this.DisplayString = symbolReference.SymbolName;
            }
        }
        /// <summary>
        /// Finds all references (including aliases) in a script for the given symbol
        /// </summary>
        /// <param name="scriptAst">The abstract syntax tree of the given script</param>
        /// <param name="symbolReference">The symbol that we are looking for referneces of</param>
        /// <param name="CmdletToAliasDictionary">Dictionary maping cmdlets to aliases for finding alias references</param>
        /// <param name="AliasToCmdletDictionary">Dictionary maping aliases to cmdlets for finding alias references</param>
        /// <returns></returns>
        public static IEnumerable<SymbolReference> FindReferencesOfSymbol(
            Ast scriptAst, 
            SymbolReference symbolReference, 
            Dictionary<String, List<String>> CmdletToAliasDictionary,
            Dictionary<String, String> AliasToCmdletDictionary)
        {
            // find the symbol evaluators for the node types we are handling
            FindReferencesVisitor referencesVisitor =
                new FindReferencesVisitor(
                    symbolReference,
                    CmdletToAliasDictionary,
                    AliasToCmdletDictionary);
            scriptAst.Visit(referencesVisitor);

            return referencesVisitor.FoundReferences;
        }
        /// <summary>
        /// Checks to see if this command ast is the symbol we are looking for.
        /// </summary>
        /// <param name="commandAst">A CommandAst object in the script's AST</param>
        /// <returns>A descion to stop searching if the right symbol was found, 
        /// or a decision to continue if it wasn't found</returns>
        public override AstVisitAction VisitCommand(CommandAst commandAst)
        {
            Ast commandNameAst = commandAst.CommandElements[0];

            if (this.IsPositionInExtent(commandNameAst.Extent))
            {
                this.FoundSymbolReference =
                    new SymbolReference(
                        SymbolType.Function,
                        commandNameAst.Extent);

                return AstVisitAction.StopVisit;
            }

            return base.VisitCommand(commandAst);
        }
        /// <summary>
        /// Finds all references (including aliases) in a script for the given symbol
        /// </summary>
        /// <param name="scriptAst">The abstract syntax tree of the given script</param>
        /// <param name="symbolReference">The symbol that we are looking for referneces of</param>
        /// <param name="CmdletToAliasDictionary">Dictionary maping cmdlets to aliases for finding alias references</param>
        /// <param name="AliasToCmdletDictionary">Dictionary maping aliases to cmdlets for finding alias references</param>
        /// <returns></returns>
        static public IEnumerable <SymbolReference> FindReferencesOfSymbol(
            Ast scriptAst,
            SymbolReference symbolReference,
            Dictionary <String, List <String> > CmdletToAliasDictionary,
            Dictionary <String, String> AliasToCmdletDictionary)
        {
            // find the symbol evaluators for the node types we are handling
            FindReferencesVisitor referencesVisitor =
                new FindReferencesVisitor(
                    symbolReference,
                    CmdletToAliasDictionary,
                    AliasToCmdletDictionary);

            scriptAst.Visit(referencesVisitor);

            return(referencesVisitor.FoundReferences);
        }
        /// <summary>
        /// Finds the symbol in the script given a file location
        /// </summary>
        /// <param name="scriptFile">The details and contents of a open script file</param>
        /// <param name="lineNumber">The line number of the cursor for the given script</param>
        /// <param name="columnNumber">The coulumn number of the cursor for the given script</param>
        /// <returns>A SymbolReference of the symbol found at the given location
        /// or null if there is no symbol at that location
        /// </returns>
        public SymbolReference FindSymbolAtLocation(
            ScriptFile scriptFile,
            int lineNumber,
            int columnNumber)
        {
            SymbolReference symbolReference =
                AstOperations.FindSymbolAtPosition(
                    scriptFile.ScriptAst,
                    lineNumber,
                    columnNumber);

            if (symbolReference != null)
            {
                symbolReference.FilePath = scriptFile.FilePath;
            }

            return(symbolReference);
        }
        /// <summary>
        /// Constructor used when searching for aliases is needed
        /// </summary>
        /// <param name="symbolReference">The found symbolReference that other symbols are being compared to</param>
        /// <param name="CmdletToAliasDictionary">Dictionary maping cmdlets to aliases for finding alias references</param>
        /// <param name="AliasToCmdletDictionary">Dictionary maping aliases to cmdlets for finding alias references</param>
        public FindReferencesVisitor(
            SymbolReference symbolReference,
            Dictionary<String, List<String>> CmdletToAliasDictionary,
            Dictionary<String, String> AliasToCmdletDictionary)
        {
            this.symbolRef = symbolReference;
            this.FoundReferences = new List<SymbolReference>();
            this.needsAliases = true;
            this.CmdletToAliasDictionary = CmdletToAliasDictionary;
            this.AliasToCmdletDictionary = AliasToCmdletDictionary;

            // Try to get the symbolReference's command name of an alias, 
            // if a command name does not exists (if the symbol isn't an alias to a command)
            // set symbolRefCommandName to and empty string value
            AliasToCmdletDictionary.TryGetValue(symbolReference.ScriptRegion.Text, out symbolRefCommandName);
            if (symbolRefCommandName == null) { symbolRefCommandName = string.Empty; }

        }
        public override AstVisitAction VisitPipeline(PipelineAst pipelineAst)
        {
            if (this.lineNumber == pipelineAst.Extent.StartLineNumber)
            {
                // Which command is the cursor in?
                foreach (var commandAst in pipelineAst.PipelineElements.OfType<CommandAst>())
                {
                    int trueEndColumnNumber = commandAst.Extent.EndColumnNumber;
                    string currentLine = commandAst.Extent.StartScriptPosition.Line;

                    if (currentLine.Length >= trueEndColumnNumber)
                    {
                        // Get the text left in the line after the command's extent
                        string remainingLine = 
                            currentLine.Substring(
                                commandAst.Extent.EndColumnNumber);

                        // Calculate the "true" end column number by finding out how many
                        // whitespace characters are between this command and the next (or
                        // the end of the line).
                        // NOTE: +1 is added to trueEndColumnNumber to account for the position
                        // just after the last character in the command string or script line.
                        int preTrimLength = remainingLine.Length;
                        int postTrimLength = remainingLine.TrimStart().Length;
                        trueEndColumnNumber = 
                            commandAst.Extent.EndColumnNumber + 
                            (preTrimLength - postTrimLength) + 1;
                    }

                    if (commandAst.Extent.StartColumnNumber <= columnNumber &&
                        trueEndColumnNumber >= columnNumber)
                    {
                        this.FoundCommandReference =
                            new SymbolReference(
                                SymbolType.Function,
                                commandAst.CommandElements[0].Extent);

                        return AstVisitAction.StopVisit;
                    }
                }
            }

            return base.VisitPipeline(pipelineAst);
        }
        public override AstVisitAction VisitPipeline(PipelineAst pipelineAst)
        {
            if (this.lineNumber == pipelineAst.Extent.StartLineNumber)
            {
                // Which command is the cursor in?
                foreach (var commandAst in pipelineAst.PipelineElements.OfType <CommandAst>())
                {
                    int    trueEndColumnNumber = commandAst.Extent.EndColumnNumber;
                    string currentLine         = commandAst.Extent.StartScriptPosition.Line;

                    if (currentLine.Length >= trueEndColumnNumber)
                    {
                        // Get the text left in the line after the command's extent
                        string remainingLine =
                            currentLine.Substring(
                                commandAst.Extent.EndColumnNumber);

                        // Calculate the "true" end column number by finding out how many
                        // whitespace characters are between this command and the next (or
                        // the end of the line).
                        // NOTE: +1 is added to trueEndColumnNumber to account for the position
                        // just after the last character in the command string or script line.
                        int preTrimLength  = remainingLine.Length;
                        int postTrimLength = remainingLine.TrimStart().Length;
                        trueEndColumnNumber =
                            commandAst.Extent.EndColumnNumber +
                            (preTrimLength - postTrimLength) + 1;
                    }

                    if (commandAst.Extent.StartColumnNumber <= columnNumber &&
                        trueEndColumnNumber >= columnNumber)
                    {
                        this.FoundCommandReference =
                            new SymbolReference(
                                SymbolType.Function,
                                commandAst.CommandElements[0].Extent);

                        return(AstVisitAction.StopVisit);
                    }
                }
            }

            return(base.VisitPipeline(pipelineAst));
        }
        /// <summary>
        /// Finds the parameter set hints of a specific command (determined by a given file location)
        /// </summary>
        /// <param name="file">The details and contents of a open script file</param>
        /// <param name="lineNumber">The line number of the cursor for the given script</param>
        /// <param name="columnNumber">The coulumn number of the cursor for the given script</param>
        /// <returns>ParameterSetSignatures</returns>
        public async Task <ParameterSetSignatures> FindParameterSetsInFile(
            ScriptFile file,
            int lineNumber,
            int columnNumber)
        {
            SymbolReference foundSymbol =
                AstOperations.FindCommandAtPosition(
                    file.ScriptAst,
                    lineNumber,
                    columnNumber);

            if (foundSymbol != null)
            {
                CommandInfo commandInfo =
                    await CommandHelpers.GetCommandInfo(
                        foundSymbol.SymbolName,
                        this.powerShellContext);

                if (commandInfo != null)
                {
                    try
                    {
                        IEnumerable <CommandParameterSetInfo> commandParamSets = commandInfo.ParameterSets;
                        return(new ParameterSetSignatures(commandParamSets, foundSymbol));
                    }
                    catch (InvalidOperationException)
                    {
                        // For some commands there are no paramsets (like applications).  Until
                        // the valid command types are better understood, catch this exception
                        // which gets raised when there are no ParameterSets for the command type.
                        return(null);
                    }
                }
                else
                {
                    return(null);
                }
            }
            else
            {
                return(null);
            }
        }
        /// <summary>
        /// Check if the left hand side of an assignmentStatementAst is a VariableExpressionAst
        /// with the same name as that of symbolRef.
        /// </summary>
        /// <param name="assignmentStatementAst">An AssignmentStatementAst</param>
        /// <returns>A decision to stop searching if the right VariableExpressionAst was found,
        /// or a decision to continue if it wasn't found</returns>
        public override AstVisitAction VisitAssignmentStatement(AssignmentStatementAst assignmentStatementAst)
        {
            if (variableName == null)
            {
                return(AstVisitAction.Continue);
            }

            // We want to check VariableExpressionAsts from within this AssignmentStatementAst so we visit it.
            FindDeclarationVariableExpressionVisitor visitor = new FindDeclarationVariableExpressionVisitor(symbolRef);

            assignmentStatementAst.Left.Visit(visitor);

            if (visitor.FoundDeclaration != null)
            {
                FoundDeclaration = visitor.FoundDeclaration;
                return(AstVisitAction.StopVisit);
            }
            return(AstVisitAction.Continue);
        }
Esempio n. 18
0
        /// <summary>
        /// Constructor used when searching for aliases is needed
        /// </summary>
        /// <param name="symbolReference">The found symbolReference that other symbols are being compared to</param>
        /// <param name="CmdletToAliasDictionary">Dictionary maping cmdlets to aliases for finding alias references</param>
        /// <param name="AliasToCmdletDictionary">Dictionary maping aliases to cmdlets for finding alias references</param>
        public FindReferencesVisitor(
            SymbolReference symbolReference,
            Dictionary <String, List <String> > CmdletToAliasDictionary,
            Dictionary <String, String> AliasToCmdletDictionary)
        {
            this.symbolRef               = symbolReference;
            this.FoundReferences         = new List <SymbolReference>();
            this.needsAliases            = true;
            this.CmdletToAliasDictionary = CmdletToAliasDictionary;
            this.AliasToCmdletDictionary = AliasToCmdletDictionary;

            // Try to get the symbolReference's command name of an alias,
            // if a command name does not exists (if the symbol isn't an alias to a command)
            // set symbolRefCommandName to and empty string value
            AliasToCmdletDictionary.TryGetValue(symbolReference.ScriptRegion.Text, out symbolRefCommandName);
            if (symbolRefCommandName == null)
            {
                symbolRefCommandName = string.Empty;
            }
        }
        private async Task <SymbolReference> FindDeclarationForBuiltinCommand(
            CommandInfo cmdInfo,
            SymbolReference foundSymbol,
            Workspace workspace)
        {
            SymbolReference foundDefinition = null;

            if (cmdInfo != null)
            {
                int          index = 0;
                ScriptFile[] nestedModuleFiles;

                CommandInfo commandInfo =
                    await CommandHelpers.GetCommandInfo(
                        foundSymbol.SymbolName,
                        this.powerShellContext);

                nestedModuleFiles =
                    GetBuiltinCommandScriptFiles(
                        commandInfo.Module,
                        workspace);

                while (foundDefinition == null && index < nestedModuleFiles.Length)
                {
                    foundDefinition =
                        AstOperations.FindDefinitionOfSymbol(
                            nestedModuleFiles[index].ScriptAst,
                            foundSymbol);

                    if (foundDefinition != null)
                    {
                        foundDefinition.FilePath = nestedModuleFiles[index].FilePath;
                    }

                    index++;
                }
            }

            return(foundDefinition);
        }
        /// <summary>
        /// Finds the definition of a symbol in the script file or any of the
        /// files that it references.
        /// </summary>
        /// <param name="sourceFile">The initial script file to be searched for the symbol's definition.</param>
        /// <param name="foundSymbol">The symbol for which a definition will be found.</param>
        /// <param name="workspace">The Workspace to which the ScriptFile belongs.</param>
        /// <returns>The resulting GetDefinitionResult for the symbol's definition.</returns>
        public async Task <GetDefinitionResult> GetDefinitionOfSymbol(
            ScriptFile sourceFile,
            SymbolReference foundSymbol,
            Workspace workspace)
        {
            Validate.IsNotNull("sourceFile", sourceFile);
            Validate.IsNotNull("foundSymbol", foundSymbol);
            Validate.IsNotNull("workspace", workspace);

            ScriptFile[] referencedFiles =
                workspace.ExpandScriptReferences(
                    sourceFile);

            var filesSearched = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

            // look through the referenced files until definition is found
            // or there are no more file to look through
            SymbolReference foundDefinition = null;

            for (int i = 0; i < referencedFiles.Length; i++)
            {
                foundDefinition =
                    AstOperations.FindDefinitionOfSymbol(
                        referencedFiles[i].ScriptAst,
                        foundSymbol);

                filesSearched.Add(referencedFiles[i].FilePath);
                if (foundDefinition != null)
                {
                    foundDefinition.FilePath = referencedFiles[i].FilePath;
                    break;
                }
            }

            // if the definition the not found in referenced files
            // look for it in all the files in the workspace
            if (foundDefinition == null)
            {
                // Get a list of all powershell files in the workspace path
                var allFiles = workspace.EnumeratePSFiles();
                foreach (var file in allFiles)
                {
                    if (filesSearched.Contains(file))
                    {
                        continue;
                    }

                    Token[]      tokens      = null;
                    ParseError[] parseErrors = null;
                    foundDefinition =
                        AstOperations.FindDefinitionOfSymbol(
                            Parser.ParseFile(file, out tokens, out parseErrors),
                            foundSymbol);

                    filesSearched.Add(file);
                    if (foundDefinition != null)
                    {
                        foundDefinition.FilePath = file;
                        break;
                    }
                }
            }

            // if definition is not found in file in the workspace
            // look for it in the builtin commands
            if (foundDefinition == null)
            {
                CommandInfo cmdInfo =
                    await CommandHelpers.GetCommandInfo(
                        foundSymbol.SymbolName,
                        this.powerShellContext);

                foundDefinition =
                    FindDeclarationForBuiltinCommand(
                        cmdInfo,
                        foundSymbol,
                        workspace);
            }

            return(foundDefinition != null ?
                   new GetDefinitionResult(foundDefinition) :
                   null);
        }
        /// <summary>
        /// Finds all the references of a symbol
        /// </summary>
        /// <param name="foundSymbol">The symbol to find all references for</param>
        /// <param name="referencedFiles">An array of scriptFiles too search for references in</param>
        /// <returns>FindReferencesResult</returns>
        public async Task<FindReferencesResult> FindReferencesOfSymbol(
            SymbolReference foundSymbol,
            ScriptFile[] referencedFiles)
        {                
            if (foundSymbol != null)
            {
                int symbolOffset = referencedFiles[0].GetOffsetAtPosition(
                    foundSymbol.ScriptRegion.StartLineNumber,
                    foundSymbol.ScriptRegion.StartColumnNumber);

                // Make sure aliases have been loaded
                await GetAliases();

                List<SymbolReference> symbolReferences = new List<SymbolReference>();
                foreach (ScriptFile file in referencedFiles)
                {
                    IEnumerable<SymbolReference> symbolReferencesinFile =
                    AstOperations
                        .FindReferencesOfSymbol(
                            file.ScriptAst,
                            foundSymbol,
                            CmdletToAliasDictionary,
                            AliasToCmdletDictionary)
                        .Select(
                            reference =>
                            {
                                reference.SourceLine =
                                    file.GetLine(reference.ScriptRegion.StartLineNumber);
                                reference.FilePath = file.FilePath;
                                return reference;
                            });

                    symbolReferences.AddRange(symbolReferencesinFile);
                }

                return
                    new FindReferencesResult
                    {
                        SymbolFileOffset = symbolOffset,
                        SymbolName = foundSymbol.SymbolName,
                        FoundReferences = symbolReferences
                    };
            }
            else { return null; }
        }
 public FindDeclartionVisitor(SymbolReference symbolRef)
 {
     this.symbolRef = symbolRef;
 }
        /// <summary>
        /// Finds all the references of a symbol
        /// </summary>
        /// <param name="foundSymbol">The symbol to find all references for</param>
        /// <param name="referencedFiles">An array of scriptFiles too search for references in</param>
        /// <param name="workspace">The workspace that will be searched for symbols</param>
        /// <returns>FindReferencesResult</returns>
        public async Task <FindReferencesResult> FindReferencesOfSymbol(
            SymbolReference foundSymbol,
            ScriptFile[] referencedFiles,
            Workspace workspace)
        {
            if (foundSymbol != null)
            {
                int symbolOffset = referencedFiles[0].GetOffsetAtPosition(
                    foundSymbol.ScriptRegion.StartLineNumber,
                    foundSymbol.ScriptRegion.StartColumnNumber);

                // Make sure aliases have been loaded
                await GetAliases();

                // We want to look for references first in referenced files, hence we use ordered dictionary
                var fileMap = new OrderedDictionary(StringComparer.OrdinalIgnoreCase);
                foreach (ScriptFile file in referencedFiles)
                {
                    fileMap.Add(file.FilePath, file);
                }

                var allFiles = workspace.EnumeratePSFiles();
                foreach (var file in allFiles)
                {
                    if (!fileMap.Contains(file))
                    {
                        fileMap.Add(file, new ScriptFile(file, null, this.powerShellContext.LocalPowerShellVersion.Version));
                    }
                }

                List <SymbolReference> symbolReferences = new List <SymbolReference>();
                foreach (var fileName in fileMap.Keys)
                {
                    var file = (ScriptFile)fileMap[fileName];
                    IEnumerable <SymbolReference> symbolReferencesinFile =
                        AstOperations
                        .FindReferencesOfSymbol(
                            file.ScriptAst,
                            foundSymbol,
                            CmdletToAliasDictionary,
                            AliasToCmdletDictionary)
                        .Select(
                            reference =>
                    {
                        try
                        {
                            reference.SourceLine =
                                file.GetLine(reference.ScriptRegion.StartLineNumber);
                        }
                        catch (ArgumentOutOfRangeException e)
                        {
                            reference.SourceLine = string.Empty;
                            this.logger.WriteException("Found reference is out of range in script file", e);
                        }

                        reference.FilePath = file.FilePath;
                        return(reference);
                    });

                    symbolReferences.AddRange(symbolReferencesinFile);
                }

                return
                    (new FindReferencesResult
                {
                    SymbolFileOffset = symbolOffset,
                    SymbolName = foundSymbol.SymbolName,
                    FoundReferences = symbolReferences
                });
            }
            else
            {
                return(null);
            }
        }
 /// <summary>
 /// Constructor used when searching for aliases is not needed
 /// </summary>
 /// <param name="foundSymbol">The found symbolReference that other symbols are being compared to</param>
 public FindReferencesVisitor(SymbolReference foundSymbol)
 {
     this.symbolRef = foundSymbol;
     this.FoundReferences = new List<SymbolReference>();
     this.needsAliases = false;
 }
        /// <summary>
        /// Constructs an instance of a ParameterSetSignatures object
        /// </summary>
        /// <param name="commandInfoSet">Collection of parameter set info</param>
        /// <param name="foundSymbol"> The SymbolReference of the command</param>
        public ParameterSetSignatures(IEnumerable <CommandParameterSetInfo> commandInfoSet, SymbolReference foundSymbol)
        {
            List <ParameterSetSignature> paramSetSignatures = new List <ParameterSetSignature>();

            foreach (CommandParameterSetInfo setInfo in commandInfoSet)
            {
                paramSetSignatures.Add(new ParameterSetSignature(setInfo));
            }
            Signatures   = paramSetSignatures.ToArray();
            CommandName  = foundSymbol.ScriptRegion.Text;
            ScriptRegion = foundSymbol.ScriptRegion;
        }
Esempio n. 26
0
        /// <summary>
        /// Finds the definition of a symbol in the script file or any of the
        /// files that it references.
        /// </summary>
        /// <param name="sourceFile">The initial script file to be searched for the symbol's definition.</param>
        /// <param name="foundSymbol">The symbol for which a definition will be found.</param>
        /// <param name="workspace">The Workspace to which the ScriptFile belongs.</param>
        /// <returns>The resulting GetDefinitionResult for the symbol's definition.</returns>
        public async Task <GetDefinitionResult> GetDefinitionOfSymbolAsync(
            ScriptFile sourceFile,
            SymbolReference foundSymbol,
            Workspace workspace)
        {
            Validate.IsNotNull(nameof(sourceFile), sourceFile);
            Validate.IsNotNull(nameof(foundSymbol), foundSymbol);
            Validate.IsNotNull(nameof(workspace), workspace);

            ScriptFile[] referencedFiles =
                workspace.ExpandScriptReferences(
                    sourceFile);

            var filesSearched = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

            // look through the referenced files until definition is found
            // or there are no more file to look through
            SymbolReference foundDefinition = null;

            foreach (ScriptFile scriptFile in referencedFiles)
            {
                foundDefinition =
                    AstOperations.FindDefinitionOfSymbol(
                        scriptFile.ScriptAst,
                        foundSymbol);

                filesSearched.Add(scriptFile.FilePath);
                if (foundDefinition != null)
                {
                    foundDefinition.FilePath = scriptFile.FilePath;
                    break;
                }

                if (foundSymbol.SymbolType == SymbolType.Function)
                {
                    // Dot-sourcing is parsed as a "Function" Symbol.
                    string dotSourcedPath = GetDotSourcedPath(foundSymbol, workspace, scriptFile);
                    if (scriptFile.FilePath == dotSourcedPath)
                    {
                        foundDefinition = new SymbolReference(SymbolType.Function, foundSymbol.SymbolName, scriptFile.ScriptAst.Extent, scriptFile.FilePath);
                        break;
                    }
                }
            }

            // if the definition the not found in referenced files
            // look for it in all the files in the workspace
            if (foundDefinition == null)
            {
                // Get a list of all powershell files in the workspace path
                IEnumerable <string> allFiles = workspace.EnumeratePSFiles();
                foreach (string file in allFiles)
                {
                    if (filesSearched.Contains(file))
                    {
                        continue;
                    }

                    Token[]      tokens      = null;
                    ParseError[] parseErrors = null;
                    foundDefinition =
                        AstOperations.FindDefinitionOfSymbol(
                            Parser.ParseFile(file, out tokens, out parseErrors),
                            foundSymbol);

                    filesSearched.Add(file);
                    if (foundDefinition != null)
                    {
                        foundDefinition.FilePath = file;
                        break;
                    }
                }
            }

            // if definition is not found in file in the workspace
            // look for it in the builtin commands
            if (foundDefinition == null)
            {
                CommandInfo cmdInfo =
                    await CommandHelpers.GetCommandInfoAsync(
                        foundSymbol.SymbolName,
                        _powerShellContext);

                foundDefinition =
                    FindDeclarationForBuiltinCommand(
                        cmdInfo,
                        foundSymbol,
                        workspace);
            }

            return(foundDefinition != null ?
                   new GetDefinitionResult(foundDefinition) :
                   null);
        }
        /// <summary>
        /// Finds all references (not including aliases) in a script for the given symbol
        /// </summary>
        /// <param name="scriptAst">The abstract syntax tree of the given script</param>
        /// <param name="foundSymbol">The symbol that we are looking for referneces of</param>
        /// <param name="needsAliases">If this reference search needs aliases.
        /// This should always be false and used for occurence requests</param>
        /// <returns>A collection of SymbolReference objects that are refrences to the symbolRefrence
        /// not including aliases</returns>
        public static IEnumerable<SymbolReference> FindReferencesOfSymbol(
            ScriptBlockAst scriptAst, 
            SymbolReference foundSymbol, 
            bool needsAliases)
        {
            FindReferencesVisitor referencesVisitor =
                new FindReferencesVisitor(foundSymbol);
            scriptAst.Visit(referencesVisitor);

            return referencesVisitor.FoundReferences;
        }
Esempio n. 28
0
        /// <summary>
        /// Finds all the references of a symbol
        /// </summary>
        /// <param name="foundSymbol">The symbol to find all references for</param>
        /// <param name="referencedFiles">An array of scriptFiles too search for references in</param>
        /// <param name="workspace">The workspace that will be searched for symbols</param>
        /// <returns>FindReferencesResult</returns>
        public async Task <FindReferencesResult> FindReferencesOfSymbolAsync(
            SymbolReference foundSymbol,
            ScriptFile[] referencedFiles,
            Workspace workspace)
        {
            if (foundSymbol == null)
            {
                return(null);
            }

            int symbolOffset = referencedFiles[0].GetOffsetAtPosition(
                foundSymbol.ScriptRegion.StartLineNumber,
                foundSymbol.ScriptRegion.StartColumnNumber);

            // Make sure aliases have been loaded
            await GetAliasesAsync();

            // We want to look for references first in referenced files, hence we use ordered dictionary
            // TODO: File system case-sensitivity is based on filesystem not OS, but OS is a much cheaper heuristic
            var fileMap = RuntimeInformation.IsOSPlatform(OSPlatform.Linux)
                ? new OrderedDictionary()
                : new OrderedDictionary(StringComparer.OrdinalIgnoreCase);

            foreach (ScriptFile scriptFile in referencedFiles)
            {
                fileMap[scriptFile.FilePath] = scriptFile;
            }

            foreach (string filePath in workspace.EnumeratePSFiles())
            {
                if (!fileMap.Contains(filePath))
                {
                    if (!workspace.TryGetFile(filePath, out ScriptFile scriptFile))
                    {
                        // If we can't access the file for some reason, just ignore it
                        continue;
                    }

                    fileMap[filePath] = scriptFile;
                }
            }

            var symbolReferences = new List <SymbolReference>();

            foreach (object fileName in fileMap.Keys)
            {
                var file = (ScriptFile)fileMap[fileName];
                await _aliasHandle.WaitAsync();

                try
                {
                    IEnumerable <SymbolReference> references = AstOperations.FindReferencesOfSymbol(
                        file.ScriptAst,
                        foundSymbol,
                        _cmdletToAliasDictionary,
                        _aliasToCmdletDictionary);

                    foreach (SymbolReference reference in references)
                    {
                        try
                        {
                            reference.SourceLine = file.GetLine(reference.ScriptRegion.StartLineNumber);
                        }
                        catch (ArgumentOutOfRangeException e)
                        {
                            reference.SourceLine = string.Empty;
                            _logger.WriteException("Found reference is out of range in script file", e);
                        }
                        reference.FilePath = file.FilePath;
                        symbolReferences.Add(reference);
                    }
                }
                finally
                {
                    _aliasHandle.Release();
                }
            }

            return(new FindReferencesResult
            {
                SymbolFileOffset = symbolOffset,
                SymbolName = foundSymbol.SymbolName,
                FoundReferences = symbolReferences
            });
        }
Esempio n. 29
0
 /// <summary>
 /// Constructor used when searching for aliases is not needed
 /// </summary>
 /// <param name="foundSymbol">The found symbolReference that other symbols are being compared to</param>
 public FindReferencesVisitor(SymbolReference foundSymbol)
 {
     this.symbolRef       = foundSymbol;
     this.FoundReferences = new List <SymbolReference>();
     this.needsAliases    = false;
 }
Esempio n. 30
0
        /// <summary>
        /// Finds all the references of a symbol
        /// </summary>
        /// <param name="foundSymbol">The symbol to find all references for</param>
        /// <param name="referencedFiles">An array of scriptFiles too search for references in</param>
        /// <param name="workspace">The workspace that will be searched for symbols</param>
        /// <returns>FindReferencesResult</returns>
        public async Task <FindReferencesResult> FindReferencesOfSymbol(
            SymbolReference foundSymbol,
            ScriptFile[] referencedFiles,
            Workspace workspace)
        {
            if (foundSymbol == null)
            {
                return(null);
            }

            int symbolOffset = referencedFiles[0].GetOffsetAtPosition(
                foundSymbol.ScriptRegion.StartLineNumber,
                foundSymbol.ScriptRegion.StartColumnNumber);

            // Make sure aliases have been loaded
            await GetAliases();

            // We want to look for references first in referenced files, hence we use ordered dictionary
            // TODO: File system case-sensitivity is based on filesystem not OS, but OS is a much cheaper heuristic
#if CoreCLR
            // The RuntimeInformation.IsOSPlatform is not supported in .NET Framework
            var fileMap = RuntimeInformation.IsOSPlatform(OSPlatform.Linux)
                ? new OrderedDictionary()
                : new OrderedDictionary(StringComparer.OrdinalIgnoreCase);
#else
            var fileMap = new OrderedDictionary(StringComparer.OrdinalIgnoreCase);
#endif
            foreach (ScriptFile file in referencedFiles)
            {
                fileMap.Add(file.FilePath, file);
            }

            foreach (string file in workspace.EnumeratePSFiles())
            {
                if (!fileMap.Contains(file))
                {
                    ScriptFile scriptFile;
                    try
                    {
                        scriptFile = workspace.GetFile(file);
                    }
                    catch (Exception e) when(e is IOException ||
                                             e is SecurityException ||
                                             e is FileNotFoundException ||
                                             e is DirectoryNotFoundException ||
                                             e is PathTooLongException ||
                                             e is UnauthorizedAccessException)
                    {
                        // If we can't access the file for some reason, just ignore it
                        continue;
                    }

                    fileMap.Add(file, scriptFile);
                }
            }

            var symbolReferences = new List <SymbolReference>();
            foreach (object fileName in fileMap.Keys)
            {
                var file = (ScriptFile)fileMap[fileName];

                IEnumerable <SymbolReference> references = AstOperations.FindReferencesOfSymbol(
                    file.ScriptAst,
                    foundSymbol,
                    _cmdletToAliasDictionary,
                    _aliasToCmdletDictionary);

                foreach (SymbolReference reference in references)
                {
                    try
                    {
                        reference.SourceLine = file.GetLine(reference.ScriptRegion.StartLineNumber);
                    }
                    catch (ArgumentOutOfRangeException e)
                    {
                        reference.SourceLine = string.Empty;
                        _logger.WriteException("Found reference is out of range in script file", e);
                    }
                    reference.FilePath = file.FilePath;
                    symbolReferences.Add(reference);
                }
            }

            return(new FindReferencesResult
            {
                SymbolFileOffset = symbolOffset,
                SymbolName = foundSymbol.SymbolName,
                FoundReferences = symbolReferences
            });
        }
        /// <summary>
        /// Finds the definition of a symbol in the script file or any of the
        /// files that it references.
        /// </summary>
        /// <param name="sourceFile">The initial script file to be searched for the symbol's definition.</param>
        /// <param name="foundSymbol">The symbol for which a definition will be found.</param>
        /// <param name="workspace">The Workspace to which the ScriptFile belongs.</param>
        /// <returns>The resulting GetDefinitionResult for the symbol's definition.</returns>
        public async Task<GetDefinitionResult> GetDefinitionOfSymbol(
            ScriptFile sourceFile,
            SymbolReference foundSymbol,
            Workspace workspace)
        {
            Validate.IsNotNull("sourceFile", sourceFile);
            Validate.IsNotNull("foundSymbol", foundSymbol);
            Validate.IsNotNull("workspace", workspace);

            ScriptFile[] referencedFiles =
                workspace.ExpandScriptReferences(
                    sourceFile);

            // look through the referenced files until definition is found
            // or there are no more file to look through
            SymbolReference foundDefinition = null;
            for (int i = 0; i < referencedFiles.Length; i++)
            {
                foundDefinition =
                    AstOperations.FindDefinitionOfSymbol(
                        referencedFiles[i].ScriptAst,
                        foundSymbol);

                if (foundDefinition != null)
                {
                    foundDefinition.FilePath = referencedFiles[i].FilePath;
                    break;
                }
            }

            // if definition is not found in referenced files 
            // look for it in the builtin commands
            if (foundDefinition == null)
            {
                CommandInfo cmdInfo = await GetCommandInfo(foundSymbol.SymbolName);

                foundDefinition = 
                    await FindDeclarationForBuiltinCommand(
                        cmdInfo, 
                        foundSymbol,
                        workspace);
            }

            return foundDefinition != null ?
                new GetDefinitionResult(foundDefinition) :
                null;
        }
        /// <summary>
        ///  Checks to see if this variable expression is the symbol we are looking for.
        /// </summary>
        /// <param name="variableExpressionAst">A VariableExpressionAst object in the script's AST</param>
        /// <returns>A descion to stop searching if the right symbol was found, 
        /// or a decision to continue if it wasn't found</returns>
        public override AstVisitAction VisitVariableExpression(VariableExpressionAst variableExpressionAst)
        {
            if (this.IsPositionInExtent(variableExpressionAst.Extent))
            {
                this.FoundSymbolReference =
                    new SymbolReference(
                        SymbolType.Variable,
                        variableExpressionAst.Extent);

                return AstVisitAction.StopVisit;
            }

            return AstVisitAction.Continue;
        }
        private async Task<SymbolReference> FindDeclarationForBuiltinCommand(
            CommandInfo cmdInfo, 
            SymbolReference foundSymbol,
            Workspace workspace)
        {
            SymbolReference foundDefinition = null;
            if (cmdInfo != null)
            {
                int index = 0;
                ScriptFile[] nestedModuleFiles;

                CommandInfo commandInfo = await GetCommandInfo(foundSymbol.SymbolName);

                nestedModuleFiles =
                    GetBuiltinCommandScriptFiles(
                        commandInfo.Module,
                        workspace);

                while (foundDefinition == null && index < nestedModuleFiles.Length)
                {
                    foundDefinition =
                        AstOperations.FindDefinitionOfSymbol(
                            nestedModuleFiles[index].ScriptAst,
                            foundSymbol);

                    if (foundDefinition != null)
                    {
                        foundDefinition.FilePath = nestedModuleFiles[index].FilePath;
                    }

                    index++;
                }
            }

            return foundDefinition;
        }
Esempio n. 34
0
 public FindDeclartionVisitor(SymbolReference symbolRef)
 {
     this.symbolRef = symbolRef;
 }