Skip to content

Commit bede0e9

Browse files
author
Kayla Davis
committed
Add definition support for builtin commands
1 parent a365532 commit bede0e9

File tree

8 files changed

+127
-29
lines changed

8 files changed

+127
-29
lines changed

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,15 @@ public override void ProcessMessage(
3131

3232
if (definition != null)
3333
{
34-
DefinitionResponse defResponse =
35-
DefinitionResponse.Create(definition.FoundDefinition, this.Arguments.File);
34+
DefinitionResponse defResponse;
35+
if (definition.FoundDefinition != null)
36+
{
37+
defResponse = DefinitionResponse.Create(definition.FoundDefinition);
38+
}
39+
else
40+
{
41+
defResponse = DefinitionResponse.Create();
42+
}
3643

3744
messageWriter.WriteMessage(
3845
this.PrepareResponse(defResponse));

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

Lines changed: 9 additions & 2 deletions
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/Language/FindCommandVisitor.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,7 @@ public override AstVisitAction VisitCommand(CommandAst commandAst)
4646
this.FoundCommandReference =
4747
new SymbolReference(
4848
SymbolType.Function,
49-
commandNameAst.Extent,
50-
string.Empty);
49+
commandNameAst.Extent);
5150

5251
return AstVisitAction.StopVisit;
5352
}

src/PowerShellEditorServices/Language/FindDeclartionVisitor.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst fun
4040
Text = functionDefinitionAst.Name,
4141
StartLineNumber = functionDefinitionAst.Extent.StartLineNumber,
4242
StartColumnNumber = startColumnNumber,
43+
EndLineNumber = functionDefinitionAst.Extent.StartLineNumber,
4344
EndColumnNumber = startColumnNumber + functionDefinitionAst.Name.Length
4445
};
4546

@@ -49,8 +50,7 @@ public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst fun
4950
this.FoundDeclartion =
5051
new SymbolReference(
5152
SymbolType.Function,
52-
nameExtent,
53-
string.Empty);
53+
nameExtent);
5454

5555
return AstVisitAction.StopVisit;
5656
}
@@ -74,8 +74,7 @@ public override AstVisitAction VisitVariableExpression(VariableExpressionAst var
7474
this.FoundDeclartion =
7575
new SymbolReference(
7676
SymbolType.Variable,
77-
variableExpressionAst.Extent,
78-
string.Empty);
77+
variableExpressionAst.Extent);
7978

8079
return AstVisitAction.StopVisit;
8180
}

src/PowerShellEditorServices/Language/FindReferencesVisitor.cs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,7 @@ public override AstVisitAction VisitCommand(CommandAst commandAst)
3838
{
3939
this.FoundReferences.Add(new SymbolReference(
4040
SymbolType.Function,
41-
commandNameAst.Extent,
42-
string.Empty));
41+
commandNameAst.Extent));
4342
}
4443
return base.VisitCommand(commandAst);
4544
}
@@ -69,8 +68,7 @@ public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst fun
6968
{
7069
this.FoundReferences.Add(new SymbolReference(
7170
SymbolType.Function,
72-
nameExtent,
73-
string.Empty));
71+
nameExtent));
7472
}
7573
return base.VisitFunctionDefinition(functionDefinitionAst);
7674
}
@@ -88,8 +86,7 @@ public override AstVisitAction VisitCommandParameter(CommandParameterAst command
8886
{
8987
this.FoundReferences.Add(new SymbolReference(
9088
SymbolType.Parameter,
91-
commandParameterAst.Extent,
92-
string.Empty));
89+
commandParameterAst.Extent));
9390
}
9491
return AstVisitAction.Continue;
9592
}
@@ -107,8 +104,7 @@ public override AstVisitAction VisitVariableExpression(VariableExpressionAst var
107104
{
108105
this.FoundReferences.Add(new SymbolReference(
109106
SymbolType.Variable,
110-
variableExpressionAst.Extent,
111-
string.Empty));
107+
variableExpressionAst.Extent));
112108
}
113109
return AstVisitAction.Continue;
114110
}

src/PowerShellEditorServices/Language/FindSymbolVisitor.cs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,7 @@ public override AstVisitAction VisitCommand(CommandAst commandAst)
3838
this.FoundSymbolReference =
3939
new SymbolReference(
4040
SymbolType.Function,
41-
commandNameAst.Extent,
42-
string.Empty);
41+
commandNameAst.Extent);
4342

4443
return AstVisitAction.StopVisit;
4544
}
@@ -72,8 +71,7 @@ public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst fun
7271
this.FoundSymbolReference =
7372
new SymbolReference(
7473
SymbolType.Function,
75-
nameExtent,
76-
string.Empty);
74+
nameExtent);
7775

7876
return AstVisitAction.StopVisit;
7977
}
@@ -94,8 +92,7 @@ public override AstVisitAction VisitCommandParameter(CommandParameterAst command
9492
this.FoundSymbolReference =
9593
new SymbolReference(
9694
SymbolType.Parameter,
97-
commandParameterAst.Extent,
98-
string.Empty);
95+
commandParameterAst.Extent);
9996
return AstVisitAction.StopVisit;
10097
}
10198
return AstVisitAction.Continue;
@@ -114,8 +111,7 @@ public override AstVisitAction VisitVariableExpression(VariableExpressionAst var
114111
this.FoundSymbolReference =
115112
new SymbolReference(
116113
SymbolType.Variable,
117-
variableExpressionAst.Extent,
118-
string.Empty);
114+
variableExpressionAst.Extent);
119115

120116
return AstVisitAction.StopVisit;
121117
}

src/PowerShellEditorServices/Language/LanguageService.cs

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
namespace Microsoft.PowerShell.EditorServices.Language
1111
{
1212
using Microsoft.PowerShell.EditorServices.Utility;
13+
using System.IO;
1314
using System.Management.Automation;
1415
using System.Management.Automation.Runspaces;
16+
using System.Text;
1517

1618
/// <summary>
1719
/// Provides a high-level service for performing code completion and
@@ -135,11 +137,16 @@ public SymbolReference FindSymbolAtLocation(
135137
int lineNumber,
136138
int columnNumber)
137139
{
138-
return
140+
SymbolReference symbolReference =
139141
AstOperations.FindSymbolAtPosition(
140142
file.ScriptAst,
141143
lineNumber,
142144
columnNumber);
145+
if (symbolReference != null)
146+
{
147+
symbolReference.FilePath = file.FilePath;
148+
}
149+
return symbolReference;
143150
}
144151

145152
/// <summary>
@@ -171,6 +178,7 @@ public FindReferencesResult FindReferencesOfSymbol(
171178
{
172179
reference.SourceLine =
173180
file.GetLine(reference.ScriptRegion.StartLineNumber);
181+
reference.FilePath = file.FilePath;
174182
return reference;
175183
});
176184
symbolReferences.AddRange(symbolReferencesinFile);
@@ -199,16 +207,31 @@ public GetDefinitionResult GetDefinitionOfSymbol(
199207
{
200208
if (foundSymbol != null)
201209
{
202-
SymbolReference foundDefinition = null;
210+
// look through the referenced files until definition is found
211+
// or there are no more file to look through
203212
int index = 0;
213+
SymbolReference foundDefinition = null;
204214
while (foundDefinition == null && index < referencedFiles.Length)
205215
{
206216
foundDefinition =
207217
AstOperations.FindDefinitionOfSymbol(
208218
referencedFiles[index].ScriptAst,
209219
foundSymbol);
220+
if (foundDefinition != null)
221+
{
222+
foundDefinition.FilePath = referencedFiles[index].FilePath;
223+
}
210224
index++;
211225
}
226+
227+
// if definition is not found in referenced files
228+
// look for it in the builtin commands
229+
if (foundDefinition == null)
230+
{
231+
CommandInfo cmdInfo = GetCommandInfo(foundSymbol.SymbolName);
232+
foundDefinition = FindDeclarationForBuiltinCommand(cmdInfo, foundSymbol);
233+
}
234+
212235
return new GetDefinitionResult(foundDefinition);
213236
}
214237
else { return null; }
@@ -298,5 +321,69 @@ private CommandInfo GetCommandInfo(string commandName)
298321

299322
return commandInfo;
300323
}
324+
325+
private ScriptFile[] GetBuiltinCommandScriptFiles(PSModuleInfo moduleInfo)
326+
{
327+
if (moduleInfo != null)
328+
{
329+
string modPath = moduleInfo.Path;
330+
List<ScriptFile> scriptFiles = new List<ScriptFile>();
331+
ScriptFile newFile;
332+
333+
if (modPath.EndsWith(@".ps1") || modPath.EndsWith(@".psm1"))
334+
{
335+
using (StreamReader streamReader = new StreamReader(modPath, Encoding.UTF8))
336+
{
337+
newFile = new ScriptFile(modPath, streamReader);
338+
scriptFiles.Add(newFile);
339+
}
340+
}
341+
if (moduleInfo.NestedModules.Count > 0)
342+
{
343+
string nestedModPath;
344+
foreach (PSModuleInfo nestedInfo in moduleInfo.NestedModules)
345+
{
346+
nestedModPath = nestedInfo.Path;
347+
if (nestedModPath.EndsWith(@".ps1") || nestedModPath.EndsWith(@".psm1"))
348+
{
349+
using (StreamReader streamReader = new StreamReader(nestedModPath, Encoding.UTF8))
350+
{
351+
newFile = new ScriptFile(nestedModPath, streamReader);
352+
scriptFiles.Add(newFile);
353+
}
354+
}
355+
}
356+
}
357+
return scriptFiles.ToArray();
358+
}
359+
return new List<ScriptFile>().ToArray();
360+
}
361+
362+
private SymbolReference FindDeclarationForBuiltinCommand(CommandInfo cmdInfo, SymbolReference foundSymbol)
363+
{
364+
SymbolReference foundDefinition = null;
365+
if (cmdInfo != null)
366+
{
367+
int index = 0;
368+
ScriptFile[] nestedModuleFiles;
369+
370+
nestedModuleFiles =
371+
GetBuiltinCommandScriptFiles(GetCommandInfo(foundSymbol.SymbolName).Module);
372+
373+
while (foundDefinition == null && index < nestedModuleFiles.Length)
374+
{
375+
foundDefinition =
376+
AstOperations.FindDefinitionOfSymbol(
377+
nestedModuleFiles[index].ScriptAst,
378+
foundSymbol);
379+
if (foundDefinition != null)
380+
{
381+
foundDefinition.FilePath = nestedModuleFiles[index].FilePath;
382+
}
383+
index++;
384+
}
385+
}
386+
return foundDefinition;
387+
}
301388
}
302389
}

src/PowerShellEditorServices/Language/SymbolReference.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,18 +61,25 @@ public class SymbolReference
6161
public string SourceLine { get; internal set; }
6262
#endregion
6363

64+
/// <summary>
65+
/// Gets the Filepath of the symbol
66+
/// </summary>
67+
public string FilePath { get; internal set; }
68+
6469
/// <summary>
6570
/// Constructs and instance of a SymbolReference
6671
/// </summary>
6772
/// <param name="symbolType">The higher level type of the symbol</param>
6873
/// <param name="scriptExtent">The script extent of the symbol</param>
74+
/// <param name="filePath">The file path of the symbol</param>
6975
/// <param name="sourceLine">The line contents of the given symbol (defaults to empty string)</param>
70-
public SymbolReference(SymbolType symbolType, IScriptExtent scriptExtent, string sourceLine = "")
76+
public SymbolReference(SymbolType symbolType, IScriptExtent scriptExtent, string filePath = "", string sourceLine = "")
7177
{
7278
// TODO: Verify params
7379
this.SymbolType = symbolType;
7480
this.SymbolName = scriptExtent.Text;
7581
this.ScriptRegion = ScriptRegion.Create(scriptExtent);
82+
this.FilePath = filePath;
7683
this.SourceLine = sourceLine;
7784

7885
// TODO: Make sure end column number usage is correct

0 commit comments

Comments
 (0)