Skip to content

Commit a1530a2

Browse files
author
Kapil Borle
committed
Provide document symbols for psd1 file
1 parent 4e155bd commit a1530a2

File tree

3 files changed

+137
-7
lines changed

3 files changed

+137
-7
lines changed

src/PowerShellEditorServices/Language/AstOperations.cs

Lines changed: 85 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,14 +209,96 @@ static public IEnumerable<SymbolReference> FindSymbolsInDocument(Ast scriptAst,
209209
// }
210210
// else
211211
{
212-
FindSymbolsVisitor findSymbolsVisitor = new FindSymbolsVisitor();
213-
scriptAst.Visit(findSymbolsVisitor);
214-
symbolReferences = findSymbolsVisitor.SymbolReferences;
212+
// we don't have reliable access to the filename here
213+
// so we employ the following heuristic to check if the
214+
// contents are part of a psd1 file.
215+
if (IsPowerShellDataFile(scriptAst))
216+
{
217+
var findHashtableSymbolsVisitor = new FindHashtabeSymbolsVisitor();
218+
scriptAst.Visit(findHashtableSymbolsVisitor);
219+
symbolReferences = findHashtableSymbolsVisitor.SymbolReferences;
220+
}
221+
else
222+
{
223+
FindSymbolsVisitor findSymbolsVisitor = new FindSymbolsVisitor();
224+
scriptAst.Visit(findSymbolsVisitor);
225+
symbolReferences = findSymbolsVisitor.SymbolReferences;
226+
}
215227
}
216228

217229
return symbolReferences;
218230
}
219231

232+
static private bool IsPowerShellDataFile(Ast ast)
233+
{
234+
//var node = new { Item = ast, Children = new List<dynamic>() };
235+
//GenerateTree(node);
236+
//return node.Children.Count == 1 && node.Children[0].Item is NamedBlockAst
237+
// && node.Children[0].Children.Count == 1 && node.Children[0].Children[0].Item is PipelineAst
238+
// && node.Children[0].Children[0].Children.Count == 1 && ;
239+
240+
return IsPowerShellDataFile(
241+
new { Item = ast, Children = new List<dynamic>() },
242+
new Type[] {
243+
typeof(ScriptBlockAst),
244+
typeof(NamedBlockAst),
245+
typeof(PipelineAst),
246+
typeof(CommandExpressionAst),
247+
typeof(HashtableAst) },
248+
0);
249+
}
250+
251+
static private bool IsPowerShellDataFile(dynamic node, Type[] levelAstMap, int level)
252+
{
253+
var levelAstTypeMatch = node.Item.GetType().Equals(levelAstMap[level]);
254+
if (!levelAstTypeMatch)
255+
{
256+
return false;
257+
}
258+
259+
if (level == levelAstMap.Length - 1)
260+
{
261+
return levelAstTypeMatch;
262+
}
263+
264+
var astsFound = (node.Item as Ast).FindAll(a => a is Ast, false);
265+
if (astsFound != null)
266+
{
267+
foreach (var astFound in astsFound)
268+
{
269+
if (!astFound.Equals(node.Item) && node.Item.Equals(astFound.Parent))
270+
{
271+
if (IsPowerShellDataFile(new { Item = astFound, Children = new List<dynamic>() }, levelAstMap, level + 1))
272+
{
273+
return true;
274+
}
275+
}
276+
}
277+
}
278+
279+
return false;
280+
}
281+
282+
static private void GenerateTree(dynamic node)
283+
{
284+
var astsFound = (node.Item as Ast).FindAll(a => a is Ast, false);
285+
if (astsFound != null)
286+
{
287+
foreach (var astFound in astsFound)
288+
{
289+
if (!astFound.Equals(node.Item) && node.Item.Equals(astFound.Parent))
290+
{
291+
node.Children.Add(new { Item = astFound, Children = new List<dynamic>() });
292+
}
293+
}
294+
}
295+
296+
foreach (var child in node.Children)
297+
{
298+
GenerateTree(child);
299+
}
300+
}
301+
220302
/// <summary>
221303
/// Finds all files dot sourced in a script
222304
/// </summary>

src/PowerShellEditorServices/Language/FindSymbolsVisitor.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,48 @@ private bool IsAssignedAtScriptScope(VariableExpressionAst variableExpressionAst
8989
return false;
9090
}
9191
}
92+
93+
internal class FindHashtabeSymbolsVisitor : AstVisitor
94+
{
95+
public List<SymbolReference> SymbolReferences { get; private set; }
96+
97+
public FindHashtabeSymbolsVisitor()
98+
{
99+
SymbolReferences = new List<SymbolReference>();
100+
}
101+
102+
public override AstVisitAction VisitHashtable(HashtableAst hashtableAst)
103+
{
104+
if (hashtableAst.KeyValuePairs == null)
105+
{
106+
return AstVisitAction.Continue;
107+
}
108+
109+
foreach (var kvp in hashtableAst.KeyValuePairs)
110+
{
111+
var keyStrConstExprAst = kvp.Item1 as StringConstantExpressionAst;
112+
if (keyStrConstExprAst != null)
113+
{
114+
IScriptExtent nameExtent = new ScriptExtent()
115+
{
116+
Text = keyStrConstExprAst.Value,
117+
StartLineNumber = kvp.Item1.Extent.StartLineNumber,
118+
EndLineNumber = kvp.Item2.Extent.EndLineNumber,
119+
StartColumnNumber = kvp.Item1.Extent.StartColumnNumber,
120+
EndColumnNumber = kvp.Item2.Extent.EndColumnNumber
121+
};
122+
123+
SymbolType symbolType = SymbolType.HashtableKey;
124+
125+
this.SymbolReferences.Add(
126+
new SymbolReference(
127+
symbolType,
128+
nameExtent));
129+
130+
}
131+
}
132+
133+
return AstVisitAction.Continue;
134+
}
135+
}
92136
}

src/PowerShellEditorServices/Language/SymbolType.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,17 @@ public enum SymbolType
1414
/// The symbol type is unknown
1515
/// </summary>
1616
Unknown = 0,
17-
17+
1818
/// <summary>
1919
/// The symbol is a vairable
2020
/// </summary>
2121
Variable,
22-
22+
2323
/// <summary>
2424
/// The symbol is a function
2525
/// </summary>
2626
Function,
27-
27+
2828
/// <summary>
2929
/// The symbol is a parameter
3030
/// </summary>
@@ -39,6 +39,10 @@ public enum SymbolType
3939
/// The symbol is a workflow
4040
/// </summary>
4141
Workflow,
42+
43+
/// <summary>
44+
/// The symbol is a hashtable key
45+
/// </summary>
46+
HashtableKey
4247
}
4348
}
44-

0 commit comments

Comments
 (0)