Skip to content

Introducing basic file reference traversal support #18

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Aug 27, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/PowerShellEditorServices.Host/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class Program
[STAThread]
static void Main(string[] args)
{
#if DEBUG
// In the future, a more robust argument parser will be added here
bool waitForDebugger =
args.Any(
Expand All @@ -28,11 +29,15 @@ static void Main(string[] args)
// Should we wait for the debugger before starting?
if (waitForDebugger)
{
while (!Debugger.IsAttached)
// Wait for 15 seconds and then continue
int waitCountdown = 15;
while (!Debugger.IsAttached && waitCountdown > 0)
{
Thread.Sleep(500);
Thread.Sleep(1000);
waitCountdown--;
}
}
#endif

// TODO: Select host, console host, and transport based on command line arguments

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ public static DiagnosticEventBody Create(
new Diagnostic
{
Text = diagnosticMarker.Message,
Severity = (int)diagnosticMarker.Level + 1,
Start = new Location
{
Line = diagnosticMarker.ScriptRegion.StartLineNumber,
Expand Down Expand Up @@ -97,5 +98,7 @@ public class Diagnostic
public Location End { get; set; }

public string Text { get; set; }

public int Severity { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,31 @@ public override void ProcessMessage(
MessageWriter messageWriter)
{
ScriptFile scriptFile = this.GetScriptFile(editorSession);

GetDefinitionResult definition =
editorSession.LanguageService.GetDefinitionInFile(
SymbolReference foundSymbol =
editorSession.LanguageService.FindSymbolAtLocation(
scriptFile,
this.Arguments.Line,
this.Arguments.Offset);

if (definition != null)

GetDefinitionResult definition = null;
if (foundSymbol != null)
{
DefinitionResponse defResponse =
DefinitionResponse.Create(definition.FoundDefinition, this.Arguments.File);
definition =
editorSession.LanguageService.GetDefinitionOfSymbol(
scriptFile,
foundSymbol,
editorSession.Workspace);

}

messageWriter.WriteMessage(
this.PrepareResponse(defResponse));
DefinitionResponse defResponse = DefinitionResponse.Create();
if (definition != null && definition.FoundDefinition != null)
{
defResponse = DefinitionResponse.Create(definition.FoundDefinition);
}

messageWriter.WriteMessage(
this.PrepareResponse(defResponse));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,9 @@ public override void ProcessMessage(
// Get the requested files
foreach (string filePath in this.Arguments.Files)
{
ScriptFile scriptFile = null;

if (!editorSession.TryGetFile(filePath, out scriptFile))
{
// Skip this file and log the file load error
// TODO: Trace out the error message
continue;
}
ScriptFile scriptFile =
editorSession.Workspace.GetFile(
filePath);

var semanticMarkers =
editorSession.AnalysisService.GetSemanticMarkers(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,9 @@ public abstract class FileRequest<TArguments> : RequestBase<TArguments>
{
protected ScriptFile GetScriptFile(EditorSession editorSession)
{
ScriptFile scriptFile = null;

if(!editorSession.TryGetFile(
this.Arguments.File,
out scriptFile))
{
// TODO: Throw an exception that the message loop can create a response out of

throw new FileNotFoundException(
"A ScriptFile with the following path was not found in the EditorSession: {0}",
return
editorSession.Workspace.GetFile(
this.Arguments.File);
}

return scriptFile;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public override void ProcessMessage(
MessageWriter messageWriter)
{
// Open the file in the current session
editorSession.OpenFile(this.Arguments.File);
editorSession.Workspace.GetFile(this.Arguments.File);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,17 @@ public override void ProcessMessage(
MessageWriter messageWriter)
{
ScriptFile scriptFile = this.GetScriptFile(editorSession);

FindReferencesResult referencesResult =
editorSession.LanguageService.FindReferencesInFile(
SymbolReference foundSymbol =
editorSession.LanguageService.FindSymbolAtLocation(
scriptFile,
this.Arguments.Line,
this.Arguments.Offset);

FindReferencesResult referencesResult =
editorSession.LanguageService.FindReferencesOfSymbol(
foundSymbol,
editorSession.Workspace.ExpandScriptReferences(scriptFile));

ReferencesResponse referencesResponse =
ReferencesResponse.Create(referencesResult, this.Arguments.File);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Microsoft.PowerShell.EditorServices.Transport.Stdio.Response
[MessageTypeName("definition")]
public class DefinitionResponse : ResponseBase<FileSpan[]>
{
public static DefinitionResponse Create(SymbolReference result, string thisFile)
public static DefinitionResponse Create(SymbolReference result)
{
if (result != null)
{
Expand All @@ -31,7 +31,7 @@ public static DefinitionResponse Create(SymbolReference result, string thisFile)
Line = result.ScriptRegion.EndLineNumber,
Offset = result.ScriptRegion.EndColumnNumber
},
File = thisFile,
File = result.FilePath
});
return new DefinitionResponse
{
Expand All @@ -46,5 +46,12 @@ public static DefinitionResponse Create(SymbolReference result, string thisFile)
};
}
}
public static DefinitionResponse Create()
{
return new DefinitionResponse
{
Body = null
};
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ List<ReferencesResponseItem> referenceItems
Offset = reference.ScriptRegion.EndColumnNumber
},
IsWriteAccess = true,
File = thisFile,
File = reference.FilePath,
LineText = reference.SourceLine
});
}
Expand Down
51 changes: 31 additions & 20 deletions src/PowerShellEditorServices/Analysis/AnalysisService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ public AnalysisService(Runspace analysisRunspace)
this.scriptAnalyzer = new ScriptAnalyzer();
this.scriptAnalyzer.Initialize(
analysisRunspace,
new AnalysisOutputWriter());
new AnalysisOutputWriter(),
null,
null,
new string[] { "DscTestsPresent", "DscExamplesPresent" });
}

#endregion
Expand All @@ -55,26 +58,34 @@ public AnalysisService(Runspace analysisRunspace)
/// <returns>An array of ScriptFileMarkers containing semantic analysis results.</returns>
public ScriptFileMarker[] GetSemanticMarkers(ScriptFile file)
{
// TODO: This is a temporary fix until we can change how
// ScriptAnalyzer invokes their async tasks.
Task<ScriptFileMarker[]> analysisTask =
Task.Factory.StartNew<ScriptFileMarker[]>(
() =>
{
return
this.scriptAnalyzer
.AnalyzeSyntaxTree(
file.ScriptAst,
file.ScriptTokens,
file.FilePath)
.Select(ScriptFileMarker.FromDiagnosticRecord)
.ToArray();
},
CancellationToken.None,
TaskCreationOptions.None,
TaskScheduler.Default);
if (file.IsAnalysisEnabled)
{
// TODO: This is a temporary fix until we can change how
// ScriptAnalyzer invokes their async tasks.
Task<ScriptFileMarker[]> analysisTask =
Task.Factory.StartNew<ScriptFileMarker[]>(
() =>
{
return
this.scriptAnalyzer
.AnalyzeSyntaxTree(
file.ScriptAst,
file.ScriptTokens,
file.FilePath)
.Select(ScriptFileMarker.FromDiagnosticRecord)
.ToArray();
},
CancellationToken.None,
TaskCreationOptions.None,
TaskScheduler.Default);

return analysisTask.Result;
return analysisTask.Result;
}
else
{
// Return an empty marker list
return new ScriptFileMarker[0];
}
}

#endregion
Expand Down
61 changes: 55 additions & 6 deletions src/PowerShellEditorServices/Language/AstOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

using System;
using System.Collections.Generic;
using System.Linq;
using System.Management.Automation;
using System.Management.Automation.Language;
using System.Management.Automation.Runspaces;
Expand Down Expand Up @@ -107,33 +109,80 @@ static public SymbolReference FindCommandAtPosition(Ast scriptAst, int lineNumbe
}

/// <summary>
/// Finds all references in a script of the given symbol
/// 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>
/// <returns>A collection of SymbolReference objects that are refrences to the symbolRefrence</returns>
static public IEnumerable<SymbolReference> FindReferencesOfSymbol(Ast scriptAst, SymbolReference symbolReference)
/// <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);
FindReferencesVisitor referencesVisitor =
new FindReferencesVisitor(
symbolReference,
CmdletToAliasDictionary,
AliasToCmdletDictionary);
scriptAst.Visit(referencesVisitor);

return referencesVisitor.FoundReferences;

}
/// <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>
static public IEnumerable<SymbolReference> FindReferencesOfSymbol(
ScriptBlockAst scriptAst,
SymbolReference foundSymbol,
bool needsAliases)
{
FindReferencesVisitor referencesVisitor =
new FindReferencesVisitor(foundSymbol);
scriptAst.Visit(referencesVisitor);

return referencesVisitor.FoundReferences;
}

/// <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>
static public SymbolReference FindDefinitionOfSymbol(Ast scriptAst, SymbolReference symbolReference)
static public SymbolReference FindDefinitionOfSymbol(
Ast scriptAst,
SymbolReference symbolReference)
{
FindDeclartionVisitor declarationVisitor = new FindDeclartionVisitor(symbolReference);
FindDeclartionVisitor declarationVisitor =
new FindDeclartionVisitor(
symbolReference);
scriptAst.Visit(declarationVisitor);

return declarationVisitor.FoundDeclartion;
}

/// <summary>
/// Finds all files dot sourced in a script
/// </summary>
/// <param name="scriptAst">The abstract syntax tree of the given script</param>
/// <returns></returns>
static public string[] FindDotSourcedIncludes(Ast scriptAst)
{
FindDotSourcedVisitor dotSourcedVisitor = new FindDotSourcedVisitor();
scriptAst.Visit(dotSourcedVisitor);

return dotSourcedVisitor.DotSourcedFiles.ToArray();
}
}
}
5 changes: 3 additions & 2 deletions src/PowerShellEditorServices/Language/FindCommandVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ public FindCommandVisitor(int lineNumber, int columnNumber)
public override AstVisitAction VisitCommand(CommandAst commandAst)
{
Ast commandNameAst = commandAst.CommandElements[0];

// Only want commands that are using a trigger character, which requires at least 2 cmd elements
if (!(commandAst.CommandElements.Count > 1))
{
return base.VisitCommand(commandAst);
Expand All @@ -46,8 +48,7 @@ public override AstVisitAction VisitCommand(CommandAst commandAst)
this.FoundCommandReference =
new SymbolReference(
SymbolType.Function,
commandNameAst.Extent,
string.Empty);
commandNameAst.Extent);

return AstVisitAction.StopVisit;
}
Expand Down
Loading