Skip to content

Commit 54b6c01

Browse files
committed
Track declarations on SymbolType so we can use ReferenceTable more
This lets us (nearly) replace `FindSymbolsInDocument` by using the references (symbols) from the `ScriptFile`.
1 parent 70bcd04 commit 54b6c01

File tree

7 files changed

+37
-63
lines changed

7 files changed

+37
-63
lines changed

src/PowerShellEditorServices/Services/CodeLens/ReferencesCodeLensProvider.cs

+5-26
Original file line numberDiff line numberDiff line change
@@ -84,19 +84,18 @@ SymbolType.Class or
8484
}
8585

8686
/// <summary>
87-
/// Take a codelens and create a new codelens object with updated references.
87+
/// Take a CodeLens and create a new CodeLens object with updated references.
8888
/// </summary>
8989
/// <param name="codeLens">The old code lens to get updated references for.</param>
9090
/// <param name="scriptFile"></param>
9191
/// <param name="cancellationToken"></param>
92-
/// <returns>A new code lens object describing the same data as the old one but with updated references.</returns>
92+
/// <returns>A new CodeLens object describing the same data as the old one but with updated references.</returns>
9393
public async Task<CodeLens> ResolveCodeLens(
9494
CodeLens codeLens,
9595
ScriptFile scriptFile,
9696
CancellationToken cancellationToken)
9797
{
98-
ScriptFile[] references = _workspaceService.ExpandScriptReferences(
99-
scriptFile);
98+
ScriptFile[] references = _workspaceService.ExpandScriptReferences(scriptFile);
10099

101100
SymbolReference foundSymbol = SymbolsService.FindSymbolDefinitionAtLocation(
102101
scriptFile,
@@ -123,7 +122,8 @@ await _symbolsService.ScanForReferencesOfSymbol(
123122
// so it's helpful to add some yields.
124123
await Task.Yield();
125124
cancellationToken.ThrowIfCancellationRequested();
126-
if (IsReferenceDefinition(foundSymbol, foundReference))
125+
126+
if (foundReference.IsDeclaration)
127127
{
128128
continue;
129129
}
@@ -165,27 +165,6 @@ await _symbolsService.ScanForReferencesOfSymbol(
165165
};
166166
}
167167

168-
/// <summary>
169-
/// Check whether a SymbolReference is the actual definition of that symbol.
170-
/// </summary>
171-
/// <param name="definition">The symbol definition that may be referenced.</param>
172-
/// <param name="reference">The reference symbol to check.</param>
173-
/// <returns>True if the reference is not a reference to the definition, false otherwise.</returns>
174-
private static bool IsReferenceDefinition(
175-
SymbolReference definition,
176-
SymbolReference reference)
177-
{
178-
// First check if we are in the same file as the definition. if we are...
179-
// check if it's on the same line number.
180-
181-
// TODO: Do we care about two symbol definitions of the same name?
182-
// if we do, how could we possibly know that a reference in one file is a reference
183-
// of a particular symbol definition?
184-
return
185-
definition.FilePath == reference.FilePath &&
186-
definition.ScriptRegion.StartLineNumber == reference.ScriptRegion.StartLineNumber;
187-
}
188-
189168
/// <summary>
190169
/// Get the code lens header for the number of references on a definition,
191170
/// given the number of references.

src/PowerShellEditorServices/Services/Symbols/ReferenceTable.cs

+4-3
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,9 @@ internal void EnsureInitialized()
7171
_parent.ScriptAst.Visit(new ReferenceVisitor(this));
7272
}
7373

74-
private void AddReference(SymbolType type, string name, IScriptExtent extent)
74+
private void AddReference(SymbolType type, string name, IScriptExtent extent, bool isDeclaration = false)
7575
{
76-
SymbolReference symbol = new(type, name, extent, _parent);
76+
SymbolReference symbol = new(type, name, extent, _parent, isDeclaration);
7777
_symbolReferences.AddOrUpdate(
7878
name,
7979
_ => new ConcurrentBag<SymbolReference> { symbol },
@@ -123,7 +123,8 @@ public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst fun
123123
_references.AddReference(
124124
SymbolType.Function,
125125
functionDefinitionAst.Name,
126-
nameExtent);
126+
nameExtent,
127+
isDeclaration: true);
127128

128129
return AstVisitAction.Continue;
129130
}

src/PowerShellEditorServices/Services/Symbols/ScriptDocumentSymbolProvider.cs

+1-22
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
// Licensed under the MIT License.
33

44
using System.Collections.Generic;
5-
using System.Linq;
6-
using System.Management.Automation.Language;
75
using Microsoft.PowerShell.EditorServices.Services.TextDocument;
86

97
namespace Microsoft.PowerShell.EditorServices.Services.Symbols
@@ -17,25 +15,6 @@ internal class ScriptDocumentSymbolProvider : IDocumentSymbolProvider
1715
string IDocumentSymbolProvider.ProviderId => nameof(ScriptDocumentSymbolProvider);
1816

1917
IEnumerable<SymbolReference> IDocumentSymbolProvider.ProvideDocumentSymbols(
20-
ScriptFile scriptFile)
21-
{
22-
// If we have an AST, then we know it's a PowerShell file
23-
// so lets try to find symbols in the document.
24-
return scriptFile?.ScriptAst != null
25-
? FindSymbolsInDocument(scriptFile.ScriptAst)
26-
: Enumerable.Empty<SymbolReference>();
27-
}
28-
29-
/// <summary>
30-
/// Finds all symbols in a script
31-
/// </summary>
32-
/// <param name="scriptAst">The abstract syntax tree of the given script</param>
33-
/// <returns>A collection of SymbolReference objects</returns>
34-
public static IEnumerable<SymbolReference> FindSymbolsInDocument(Ast scriptAst)
35-
{
36-
FindSymbolsVisitor findSymbolsVisitor = new();
37-
scriptAst.Visit(findSymbolsVisitor);
38-
return findSymbolsVisitor.SymbolReferences;
39-
}
18+
ScriptFile scriptFile) => scriptFile.References.GetAllReferences();
4019
}
4120
}

src/PowerShellEditorServices/Services/Symbols/SymbolReference.cs

+10-3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ internal record SymbolReference
2525

2626
public string FilePath { get; internal set; }
2727

28+
public bool IsDeclaration { get; }
29+
2830
/// <summary>
2931
/// Constructs and instance of a SymbolReference
3032
/// </summary>
@@ -33,26 +35,30 @@ internal record SymbolReference
3335
/// <param name="scriptExtent">The script extent of the symbol</param>
3436
/// <param name="filePath">The file path of the symbol</param>
3537
/// <param name="sourceLine">The line contents of the given symbol (defaults to empty string)</param>
38+
/// <param name="isDeclaration">True if this reference is the definition of the symbol</param>
3639
public SymbolReference(
3740
SymbolType symbolType,
3841
string symbolName,
3942
IScriptExtent scriptExtent,
4043
string filePath = "",
41-
string sourceLine = "")
44+
string sourceLine = "",
45+
bool isDeclaration = false)
4246
{
4347
// TODO: Verify params
4448
SymbolType = symbolType;
4549
SymbolName = symbolName;
4650
ScriptRegion = new(scriptExtent);
4751
FilePath = filePath;
4852
SourceLine = sourceLine;
53+
IsDeclaration = isDeclaration;
4954
}
5055

5156
public SymbolReference(
5257
SymbolType symbolType,
5358
string symbolName,
5459
IScriptExtent scriptExtent,
55-
ScriptFile file)
60+
ScriptFile file,
61+
bool isDeclaration)
5662
{
5763
SymbolType = symbolType;
5864
SymbolName = symbolName;
@@ -66,6 +72,7 @@ public SymbolReference(
6672
{
6773
SourceLine = string.Empty;
6874
}
75+
IsDeclaration = isDeclaration;
6976
}
7077

7178
/// <summary>
@@ -74,7 +81,7 @@ public SymbolReference(
7481
/// <param name="symbolType">The higher level type of the symbol</param>
7582
/// <param name="scriptExtent">The script extent of the symbol</param>
7683
public SymbolReference(SymbolType symbolType, IScriptExtent scriptExtent)
77-
: this(symbolType, scriptExtent.Text, scriptExtent, scriptExtent.File, "")
84+
: this(symbolType, scriptExtent.Text, scriptExtent, scriptExtent.File)
7885
{
7986
}
8087
}

src/PowerShellEditorServices/Services/Symbols/SymbolType.cs

+1
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ internal static SymbolKind GetSymbolKind(SymbolType symbolType)
9494
SymbolType.Method => SymbolKind.Method,
9595
SymbolType.Property => SymbolKind.Property,
9696
SymbolType.EnumMember => SymbolKind.EnumMember,
97+
SymbolType.Variable => SymbolKind.Variable,
9798
// TODO: More delicately handle the other symbol types.
9899
_ => SymbolKind.Variable,
99100
};

src/PowerShellEditorServices/Services/Symbols/SymbolsService.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ public static SymbolReference FindSymbolAtLocation(
153153
}
154154

155155
/// <summary>
156-
/// Finds all the references of a symbol
156+
/// Finds all the references of a symbol (excluding definitions)
157157
/// </summary>
158158
/// <param name="foundSymbol">The symbol to find all references for</param>
159159
/// <param name="referencedFiles">An array of scriptFiles to search for references in</param>

src/PowerShellEditorServices/Services/TextDocument/Handlers/ReferencesHandler.cs

+15-8
Original file line numberDiff line numberDiff line change
@@ -47,18 +47,25 @@ await _symbolsService.ScanForReferencesOfSymbol(
4747
_workspaceService.ExpandScriptReferences(scriptFile),
4848
cancellationToken).ConfigureAwait(false);
4949

50-
List<Location> locations = new();
50+
if (referencesResult is null)
51+
{
52+
return new LocationContainer();
53+
}
5154

52-
if (referencesResult != null)
55+
List<Location> locations = new();
56+
foreach (SymbolReference foundReference in referencesResult)
5357
{
54-
foreach (SymbolReference foundReference in referencesResult)
58+
// Respect the request's setting to include declarations.
59+
if (!request.Context.IncludeDeclaration && foundReference.IsDeclaration)
5560
{
56-
locations.Add(new Location
57-
{
58-
Uri = DocumentUri.From(foundReference.FilePath),
59-
Range = foundReference.ScriptRegion.ToRange()
60-
});
61+
continue;
6162
}
63+
64+
locations.Add(new Location
65+
{
66+
Uri = DocumentUri.From(foundReference.FilePath),
67+
Range = foundReference.ScriptRegion.ToRange()
68+
});
6269
}
6370

6471
return new LocationContainer(locations);

0 commit comments

Comments
 (0)