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; }
private ScriptFile[] GetBuiltinCommandScriptFiles( PSModuleInfo moduleInfo, Workspace workspace) { // if there is module info for this command if (moduleInfo != null) { string modPath = moduleInfo.Path; List<ScriptFile> scriptFiles = new List<ScriptFile>(); ScriptFile newFile; // find any files where the moduleInfo's path ends with ps1 or psm1 // and add it to allowed script files if (modPath.EndsWith(@".ps1") || modPath.EndsWith(@".psm1")) { newFile = workspace.GetFile(modPath); newFile.IsAnalysisEnabled = false; scriptFiles.Add(newFile); } if (moduleInfo.NestedModules.Count > 0) { foreach (PSModuleInfo nestedInfo in moduleInfo.NestedModules) { string nestedModPath = nestedInfo.Path; if (nestedModPath.EndsWith(@".ps1") || nestedModPath.EndsWith(@".psm1")) { newFile = workspace.GetFile(nestedModPath); newFile.IsAnalysisEnabled = false; scriptFiles.Add(newFile); } } } return scriptFiles.ToArray(); } return new List<ScriptFile>().ToArray(); }
/// <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> /// Starts the session using the provided IConsoleHost implementation /// for the ConsoleService. /// </summary> /// <param name="consoleHost"> /// An IConsoleHost implementation which is used to interact with the /// host's user interface. /// </param> public void StartSession(IConsoleHost consoleHost) { // Create a workspace to contain open files this.Workspace = new Workspace(); // Initialize all services this.PowerShellContext = new PowerShellContext(); this.LanguageService = new LanguageService(this.PowerShellContext); this.AnalysisService = new AnalysisService(); this.DebugService = new DebugService(this.PowerShellContext); }
/// <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> /// <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 => { 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); } }