Skip to content

Commit 200aaf6

Browse files
committed
Merge pull request #18 from PowerShell/demo
Introducing basic file reference traversal support
2 parents 5b88e06 + 9de1f3a commit 200aaf6

38 files changed

+978
-320
lines changed

src/PowerShellEditorServices.Host/Program.cs

+7-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ class Program
1616
[STAThread]
1717
static void Main(string[] args)
1818
{
19+
#if DEBUG
1920
// In the future, a more robust argument parser will be added here
2021
bool waitForDebugger =
2122
args.Any(
@@ -28,11 +29,15 @@ static void Main(string[] args)
2829
// Should we wait for the debugger before starting?
2930
if (waitForDebugger)
3031
{
31-
while (!Debugger.IsAttached)
32+
// Wait for 15 seconds and then continue
33+
int waitCountdown = 15;
34+
while (!Debugger.IsAttached && waitCountdown > 0)
3235
{
33-
Thread.Sleep(500);
36+
Thread.Sleep(1000);
37+
waitCountdown--;
3438
}
3539
}
40+
#endif
3641

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

src/PowerShellEditorServices.Transport.Stdio/Event/DiagnosticEvent.cs

+3
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ public static DiagnosticEventBody Create(
6161
new Diagnostic
6262
{
6363
Text = diagnosticMarker.Message,
64+
Severity = (int)diagnosticMarker.Level + 1,
6465
Start = new Location
6566
{
6667
Line = diagnosticMarker.ScriptRegion.StartLineNumber,
@@ -97,5 +98,7 @@ public class Diagnostic
9798
public Location End { get; set; }
9899

99100
public string Text { get; set; }
101+
102+
public int Severity { get; set; }
100103
}
101104
}

src/PowerShellEditorServices.Transport.Stdio/Request/DeclarationRequest.cs

+19-9
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,31 @@ public override void ProcessMessage(
1818
MessageWriter messageWriter)
1919
{
2020
ScriptFile scriptFile = this.GetScriptFile(editorSession);
21-
22-
GetDefinitionResult definition =
23-
editorSession.LanguageService.GetDefinitionInFile(
21+
SymbolReference foundSymbol =
22+
editorSession.LanguageService.FindSymbolAtLocation(
2423
scriptFile,
2524
this.Arguments.Line,
2625
this.Arguments.Offset);
27-
28-
if (definition != null)
26+
27+
GetDefinitionResult definition = null;
28+
if (foundSymbol != null)
2929
{
30-
DefinitionResponse defResponse =
31-
DefinitionResponse.Create(definition.FoundDefinition, this.Arguments.File);
30+
definition =
31+
editorSession.LanguageService.GetDefinitionOfSymbol(
32+
scriptFile,
33+
foundSymbol,
34+
editorSession.Workspace);
35+
36+
}
3237

33-
messageWriter.WriteMessage(
34-
this.PrepareResponse(defResponse));
38+
DefinitionResponse defResponse = DefinitionResponse.Create();
39+
if (definition != null && definition.FoundDefinition != null)
40+
{
41+
defResponse = DefinitionResponse.Create(definition.FoundDefinition);
3542
}
43+
44+
messageWriter.WriteMessage(
45+
this.PrepareResponse(defResponse));
3646
}
3747
}
3848
}

src/PowerShellEditorServices.Transport.Stdio/Request/ErrorRequest.cs

+3-8
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,9 @@ public override void ProcessMessage(
3333
// Get the requested files
3434
foreach (string filePath in this.Arguments.Files)
3535
{
36-
ScriptFile scriptFile = null;
37-
38-
if (!editorSession.TryGetFile(filePath, out scriptFile))
39-
{
40-
// Skip this file and log the file load error
41-
// TODO: Trace out the error message
42-
continue;
43-
}
36+
ScriptFile scriptFile =
37+
editorSession.Workspace.GetFile(
38+
filePath);
4439

4540
var semanticMarkers =
4641
editorSession.AnalysisService.GetSemanticMarkers(

src/PowerShellEditorServices.Transport.Stdio/Request/FileRequest.cs

+2-13
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,9 @@ public abstract class FileRequest<TArguments> : RequestBase<TArguments>
1313
{
1414
protected ScriptFile GetScriptFile(EditorSession editorSession)
1515
{
16-
ScriptFile scriptFile = null;
17-
18-
if(!editorSession.TryGetFile(
19-
this.Arguments.File,
20-
out scriptFile))
21-
{
22-
// TODO: Throw an exception that the message loop can create a response out of
23-
24-
throw new FileNotFoundException(
25-
"A ScriptFile with the following path was not found in the EditorSession: {0}",
16+
return
17+
editorSession.Workspace.GetFile(
2618
this.Arguments.File);
27-
}
28-
29-
return scriptFile;
3019
}
3120
}
3221

src/PowerShellEditorServices.Transport.Stdio/Request/OpenFileRequest.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public override void ProcessMessage(
2727
MessageWriter messageWriter)
2828
{
2929
// Open the file in the current session
30-
editorSession.OpenFile(this.Arguments.File);
30+
editorSession.Workspace.GetFile(this.Arguments.File);
3131
}
3232
}
3333
}

src/PowerShellEditorServices.Transport.Stdio/Request/ReferencesRequest.cs

+7-3
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,17 @@ public override void ProcessMessage(
1818
MessageWriter messageWriter)
1919
{
2020
ScriptFile scriptFile = this.GetScriptFile(editorSession);
21-
22-
FindReferencesResult referencesResult =
23-
editorSession.LanguageService.FindReferencesInFile(
21+
SymbolReference foundSymbol =
22+
editorSession.LanguageService.FindSymbolAtLocation(
2423
scriptFile,
2524
this.Arguments.Line,
2625
this.Arguments.Offset);
2726

27+
FindReferencesResult referencesResult =
28+
editorSession.LanguageService.FindReferencesOfSymbol(
29+
foundSymbol,
30+
editorSession.Workspace.ExpandScriptReferences(scriptFile));
31+
2832
ReferencesResponse referencesResponse =
2933
ReferencesResponse.Create(referencesResult, this.Arguments.File);
3034

src/PowerShellEditorServices.Transport.Stdio/Response/DefinitionResponse.cs

+9-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ namespace Microsoft.PowerShell.EditorServices.Transport.Stdio.Response
1212
[MessageTypeName("definition")]
1313
public class DefinitionResponse : ResponseBase<FileSpan[]>
1414
{
15-
public static DefinitionResponse Create(SymbolReference result, string thisFile)
15+
public static DefinitionResponse Create(SymbolReference result)
1616
{
1717
if (result != null)
1818
{
@@ -31,7 +31,7 @@ public static DefinitionResponse Create(SymbolReference result, string thisFile)
3131
Line = result.ScriptRegion.EndLineNumber,
3232
Offset = result.ScriptRegion.EndColumnNumber
3333
},
34-
File = thisFile,
34+
File = result.FilePath
3535
});
3636
return new DefinitionResponse
3737
{
@@ -46,5 +46,12 @@ public static DefinitionResponse Create(SymbolReference result, string thisFile)
4646
};
4747
}
4848
}
49+
public static DefinitionResponse Create()
50+
{
51+
return new DefinitionResponse
52+
{
53+
Body = null
54+
};
55+
}
4956
}
5057
}

src/PowerShellEditorServices.Transport.Stdio/Response/ReferencesResponse.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ List<ReferencesResponseItem> referenceItems
3535
Offset = reference.ScriptRegion.EndColumnNumber
3636
},
3737
IsWriteAccess = true,
38-
File = thisFile,
38+
File = reference.FilePath,
3939
LineText = reference.SourceLine
4040
});
4141
}

src/PowerShellEditorServices/Analysis/AnalysisService.cs

+31-20
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@ public AnalysisService(Runspace analysisRunspace)
4040
this.scriptAnalyzer = new ScriptAnalyzer();
4141
this.scriptAnalyzer.Initialize(
4242
analysisRunspace,
43-
new AnalysisOutputWriter());
43+
new AnalysisOutputWriter(),
44+
null,
45+
null,
46+
new string[] { "DscTestsPresent", "DscExamplesPresent" });
4447
}
4548

4649
#endregion
@@ -55,26 +58,34 @@ public AnalysisService(Runspace analysisRunspace)
5558
/// <returns>An array of ScriptFileMarkers containing semantic analysis results.</returns>
5659
public ScriptFileMarker[] GetSemanticMarkers(ScriptFile file)
5760
{
58-
// TODO: This is a temporary fix until we can change how
59-
// ScriptAnalyzer invokes their async tasks.
60-
Task<ScriptFileMarker[]> analysisTask =
61-
Task.Factory.StartNew<ScriptFileMarker[]>(
62-
() =>
63-
{
64-
return
65-
this.scriptAnalyzer
66-
.AnalyzeSyntaxTree(
67-
file.ScriptAst,
68-
file.ScriptTokens,
69-
file.FilePath)
70-
.Select(ScriptFileMarker.FromDiagnosticRecord)
71-
.ToArray();
72-
},
73-
CancellationToken.None,
74-
TaskCreationOptions.None,
75-
TaskScheduler.Default);
61+
if (file.IsAnalysisEnabled)
62+
{
63+
// TODO: This is a temporary fix until we can change how
64+
// ScriptAnalyzer invokes their async tasks.
65+
Task<ScriptFileMarker[]> analysisTask =
66+
Task.Factory.StartNew<ScriptFileMarker[]>(
67+
() =>
68+
{
69+
return
70+
this.scriptAnalyzer
71+
.AnalyzeSyntaxTree(
72+
file.ScriptAst,
73+
file.ScriptTokens,
74+
file.FilePath)
75+
.Select(ScriptFileMarker.FromDiagnosticRecord)
76+
.ToArray();
77+
},
78+
CancellationToken.None,
79+
TaskCreationOptions.None,
80+
TaskScheduler.Default);
7681

77-
return analysisTask.Result;
82+
return analysisTask.Result;
83+
}
84+
else
85+
{
86+
// Return an empty marker list
87+
return new ScriptFileMarker[0];
88+
}
7889
}
7990

8091
#endregion

src/PowerShellEditorServices/Language/AstOperations.cs

+55-6
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
44
//
55

6+
using System;
67
using System.Collections.Generic;
8+
using System.Linq;
79
using System.Management.Automation;
810
using System.Management.Automation.Language;
911
using System.Management.Automation.Runspaces;
@@ -107,33 +109,80 @@ static public SymbolReference FindCommandAtPosition(Ast scriptAst, int lineNumbe
107109
}
108110

109111
/// <summary>
110-
/// Finds all references in a script of the given symbol
112+
/// Finds all references (including aliases) in a script for the given symbol
111113
/// </summary>
112114
/// <param name="scriptAst">The abstract syntax tree of the given script</param>
113115
/// <param name="symbolReference">The symbol that we are looking for referneces of</param>
114-
/// <returns>A collection of SymbolReference objects that are refrences to the symbolRefrence</returns>
115-
static public IEnumerable<SymbolReference> FindReferencesOfSymbol(Ast scriptAst, SymbolReference symbolReference)
116+
/// <param name="CmdletToAliasDictionary">Dictionary maping cmdlets to aliases for finding alias references</param>
117+
/// <param name="AliasToCmdletDictionary">Dictionary maping aliases to cmdlets for finding alias references</param>
118+
/// <returns></returns>
119+
static public IEnumerable<SymbolReference> FindReferencesOfSymbol(
120+
Ast scriptAst,
121+
SymbolReference symbolReference,
122+
Dictionary<String, List<String>> CmdletToAliasDictionary,
123+
Dictionary<String, String> AliasToCmdletDictionary)
116124
{
117125
// find the symbol evaluators for the node types we are handling
118-
FindReferencesVisitor referencesVisitor = new FindReferencesVisitor(symbolReference);
126+
FindReferencesVisitor referencesVisitor =
127+
new FindReferencesVisitor(
128+
symbolReference,
129+
CmdletToAliasDictionary,
130+
AliasToCmdletDictionary);
119131
scriptAst.Visit(referencesVisitor);
120132

121133
return referencesVisitor.FoundReferences;
122134

123135
}
136+
/// <summary>
137+
/// Finds all references (not including aliases) in a script for the given symbol
138+
/// </summary>
139+
/// <param name="scriptAst">The abstract syntax tree of the given script</param>
140+
/// <param name="foundSymbol">The symbol that we are looking for referneces of</param>
141+
/// <param name="needsAliases">If this reference search needs aliases.
142+
/// This should always be false and used for occurence requests</param>
143+
/// <returns>A collection of SymbolReference objects that are refrences to the symbolRefrence
144+
/// not including aliases</returns>
145+
static public IEnumerable<SymbolReference> FindReferencesOfSymbol(
146+
ScriptBlockAst scriptAst,
147+
SymbolReference foundSymbol,
148+
bool needsAliases)
149+
{
150+
FindReferencesVisitor referencesVisitor =
151+
new FindReferencesVisitor(foundSymbol);
152+
scriptAst.Visit(referencesVisitor);
153+
154+
return referencesVisitor.FoundReferences;
155+
}
124156

125157
/// <summary>
126158
/// Finds the definition of the symbol
127159
/// </summary>
128160
/// <param name="scriptAst">The abstract syntax tree of the given script</param>
129161
/// <param name="symbolReference">The symbol that we are looking for the definition of</param>
130162
/// <returns>A SymbolReference of the definition of the symbolReference</returns>
131-
static public SymbolReference FindDefinitionOfSymbol(Ast scriptAst, SymbolReference symbolReference)
163+
static public SymbolReference FindDefinitionOfSymbol(
164+
Ast scriptAst,
165+
SymbolReference symbolReference)
132166
{
133-
FindDeclartionVisitor declarationVisitor = new FindDeclartionVisitor(symbolReference);
167+
FindDeclartionVisitor declarationVisitor =
168+
new FindDeclartionVisitor(
169+
symbolReference);
134170
scriptAst.Visit(declarationVisitor);
135171

136172
return declarationVisitor.FoundDeclartion;
137173
}
174+
175+
/// <summary>
176+
/// Finds all files dot sourced in a script
177+
/// </summary>
178+
/// <param name="scriptAst">The abstract syntax tree of the given script</param>
179+
/// <returns></returns>
180+
static public string[] FindDotSourcedIncludes(Ast scriptAst)
181+
{
182+
FindDotSourcedVisitor dotSourcedVisitor = new FindDotSourcedVisitor();
183+
scriptAst.Visit(dotSourcedVisitor);
184+
185+
return dotSourcedVisitor.DotSourcedFiles.ToArray();
186+
}
138187
}
139188
}

src/PowerShellEditorServices/Language/FindCommandVisitor.cs

+3-2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ public FindCommandVisitor(int lineNumber, int columnNumber)
3333
public override AstVisitAction VisitCommand(CommandAst commandAst)
3434
{
3535
Ast commandNameAst = commandAst.CommandElements[0];
36+
37+
// Only want commands that are using a trigger character, which requires at least 2 cmd elements
3638
if (!(commandAst.CommandElements.Count > 1))
3739
{
3840
return base.VisitCommand(commandAst);
@@ -46,8 +48,7 @@ public override AstVisitAction VisitCommand(CommandAst commandAst)
4648
this.FoundCommandReference =
4749
new SymbolReference(
4850
SymbolType.Function,
49-
commandNameAst.Extent,
50-
string.Empty);
51+
commandNameAst.Extent);
5152

5253
return AstVisitAction.StopVisit;
5354
}

0 commit comments

Comments
 (0)