From 41e26b5cb9d4996304cb6799dd98743285ce895e Mon Sep 17 00:00:00 2001
From: Frode Flaten <3436158+fflaten@users.noreply.github.com>
Date: Sat, 13 Aug 2022 21:47:26 +0000
Subject: [PATCH 01/18] add symbols for classes
---
.../Services/Symbols/SymbolType.cs | 27 +++-
.../Symbols/Vistors/FindSymbolsVisitor.cs | 138 +++++++++++++++++-
.../Handlers/DocumentSymbolHandler.cs | 16 +-
.../Handlers/WorkspaceSymbolsHandler.cs | 25 +++-
4 files changed, 195 insertions(+), 11 deletions(-)
diff --git a/src/PowerShellEditorServices/Services/Symbols/SymbolType.cs b/src/PowerShellEditorServices/Services/Symbols/SymbolType.cs
index 02778b106..207038107 100644
--- a/src/PowerShellEditorServices/Services/Symbols/SymbolType.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/SymbolType.cs
@@ -41,6 +41,31 @@ internal enum SymbolType
///
/// The symbol is a hashtable key
///
- HashtableKey
+ HashtableKey,
+
+ ///
+ /// The symbol is a class
+ ///
+ Class,
+
+ ///
+ /// The symbol is a enum
+ ///
+ Enum,
+
+ ///
+ /// The symbol is a class property
+ ///
+ Property,
+
+ ///
+ /// The symbol is a class method
+ ///
+ Method,
+
+ ///
+ /// The symbol is a class constructor
+ ///
+ Constructor
}
}
diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolsVisitor.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolsVisitor.cs
index 970acb4e7..4d2d3a076 100644
--- a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolsVisitor.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolsVisitor.cs
@@ -7,12 +7,9 @@
namespace Microsoft.PowerShell.EditorServices.Services.Symbols
{
///
- /// The visitor used to find all the symbols (function and class defs) in the AST.
+ /// The visitor used to find all the symbols (variables, functions and class defs etc) in the AST.
///
- ///
- /// Requires PowerShell v3 or higher
- ///
- internal class FindSymbolsVisitor : AstVisitor
+ internal class FindSymbolsVisitor : AstVisitor2
{
public List SymbolReferences { get; }
@@ -26,6 +23,12 @@ internal class FindSymbolsVisitor : AstVisitor
/// or a decision to continue if it wasn't found
public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst)
{
+ // Extent for constructors and method trigger both this and VisitFunctionMember(). Covered in the latter.
+ // This will not exclude nested functions as they have ScriptBlockAst as parent
+ if (functionDefinitionAst.Parent is FunctionMemberAst) {
+ return AstVisitAction.Continue;
+ }
+
IScriptExtent nameExtent = new ScriptExtent()
{
Text = functionDefinitionAst.Name,
@@ -49,7 +52,7 @@ public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst fun
}
///
- /// Checks to see if this variable expression is the symbol we are looking for.
+ /// Checks to see if this variable expression is the symbol we are looking for.
///
/// A VariableExpressionAst object in the script's AST
/// A decision to stop searching if the right symbol was found,
@@ -80,6 +83,129 @@ private static bool IsAssignedAtScriptScope(VariableExpressionAst variableExpres
parent = parent.Parent;
return parent is null || parent.Parent is null || parent.Parent.Parent is null;
}
+
+ ///
+ /// Adds class and AST to symbol reference list
+ ///
+ public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst)
+ {
+ IScriptExtent nameExtent = new ScriptExtent()
+ {
+ Text = typeDefinitionAst.Name,
+ StartLineNumber = typeDefinitionAst.Extent.StartLineNumber,
+ EndLineNumber = typeDefinitionAst.Extent.EndLineNumber,
+ StartColumnNumber = typeDefinitionAst.Extent.StartColumnNumber,
+ EndColumnNumber = typeDefinitionAst.Extent.EndColumnNumber,
+ File = typeDefinitionAst.Extent.File
+ };
+
+ SymbolType symbolType =
+ typeDefinitionAst.IsEnum ?
+ SymbolType.Enum : SymbolType.Class;
+
+ SymbolReferences.Add(
+ new SymbolReference(
+ symbolType,
+ nameExtent));
+
+ return AstVisitAction.Continue;
+ }
+
+ ///
+ /// Adds class method and constructor AST to symbol reference list
+ ///
+ public override AstVisitAction VisitFunctionMember(FunctionMemberAst functionMemberAst)
+ {
+ IScriptExtent nameExtent = new ScriptExtent()
+ {
+ Text = GetMethodOverloadName(functionMemberAst),
+ StartLineNumber = functionMemberAst.Extent.StartLineNumber,
+ EndLineNumber = functionMemberAst.Extent.EndLineNumber,
+ StartColumnNumber = functionMemberAst.Extent.StartColumnNumber,
+ EndColumnNumber = functionMemberAst.Extent.EndColumnNumber,
+ File = functionMemberAst.Extent.File
+ };
+
+ SymbolType symbolType =
+ functionMemberAst.IsConstructor ?
+ SymbolType.Constructor : SymbolType.Method;
+
+ SymbolReferences.Add(
+ new SymbolReference(
+ symbolType,
+ nameExtent));
+
+ return AstVisitAction.Continue;
+ }
+
+ ///
+ /// Gets the method or constructor name with parameters for current overload.
+ ///
+ /// A FunctionMemberAst object in the script's AST
+ /// Function member name with parameter types and names
+ private static string GetMethodOverloadName(FunctionMemberAst functionMemberAst) {
+ if (functionMemberAst.Parameters.Count > 0)
+ {
+ List parameters = new(functionMemberAst.Parameters.Count);
+ foreach (ParameterAst param in functionMemberAst.Parameters)
+ {
+ parameters.Add(param.Extent.Text);
+ }
+
+ string paramString = string.Join(", ", parameters);
+ return string.Concat(functionMemberAst.Name, "(", paramString, ")");
+ }
+ else
+ {
+ return string.Concat(functionMemberAst.Name, "()");
+ }
+ }
+
+ ///
+ /// Adds class property AST to symbol reference list
+ ///
+ public override AstVisitAction VisitPropertyMember(PropertyMemberAst propertyMemberAst)
+ {
+ IScriptExtent nameExtent = new ScriptExtent()
+ {
+ Text = propertyMemberAst.Name,
+ StartLineNumber = propertyMemberAst.Extent.StartLineNumber,
+ EndLineNumber = propertyMemberAst.Extent.EndLineNumber,
+ StartColumnNumber = propertyMemberAst.Extent.StartColumnNumber,
+ EndColumnNumber = propertyMemberAst.Extent.EndColumnNumber,
+ File = propertyMemberAst.Extent.File
+ };
+
+ SymbolReferences.Add(
+ new SymbolReference(
+ SymbolType.Property,
+ nameExtent));
+
+ return AstVisitAction.Continue;
+ }
+
+ ///
+ /// Adds DSC configuration AST to symbol reference list
+ ///
+ public override AstVisitAction VisitConfigurationDefinition(ConfigurationDefinitionAst configurationDefinitionAst)
+ {
+ IScriptExtent nameExtent = new ScriptExtent()
+ {
+ Text = configurationDefinitionAst.InstanceName.Extent.Text,
+ StartLineNumber = configurationDefinitionAst.Extent.StartLineNumber,
+ EndLineNumber = configurationDefinitionAst.Extent.EndLineNumber,
+ StartColumnNumber = configurationDefinitionAst.Extent.StartColumnNumber,
+ EndColumnNumber = configurationDefinitionAst.Extent.EndColumnNumber,
+ File = configurationDefinitionAst.Extent.File
+ };
+
+ SymbolReferences.Add(
+ new SymbolReference(
+ SymbolType.Configuration,
+ nameExtent));
+
+ return AstVisitAction.Continue;
+ }
}
///
diff --git a/src/PowerShellEditorServices/Services/TextDocument/Handlers/DocumentSymbolHandler.cs b/src/PowerShellEditorServices/Services/TextDocument/Handlers/DocumentSymbolHandler.cs
index f0973a7f0..01d544f93 100644
--- a/src/PowerShellEditorServices/Services/TextDocument/Handlers/DocumentSymbolHandler.cs
+++ b/src/PowerShellEditorServices/Services/TextDocument/Handlers/DocumentSymbolHandler.cs
@@ -128,7 +128,12 @@ private static SymbolKind GetSymbolKind(SymbolType symbolType)
{
return symbolType switch
{
- SymbolType.Configuration or SymbolType.Function or SymbolType.Workflow => SymbolKind.Function,
+ SymbolType.Function or SymbolType.Configuration or SymbolType.Workflow => SymbolKind.Function,
+ SymbolType.Enum => SymbolKind.Enum,
+ SymbolType.Class => SymbolKind.Class,
+ SymbolType.Constructor => SymbolKind.Constructor,
+ SymbolType.Method => SymbolKind.Method,
+ SymbolType.Property => SymbolKind.Property,
_ => SymbolKind.Variable,
};
}
@@ -137,8 +142,15 @@ private static string GetDecoratedSymbolName(ISymbolReference symbolReference)
{
string name = symbolReference.SymbolName;
- if (symbolReference.SymbolType is SymbolType.Configuration or
+ // Append { } for symbols with scriptblock
+ // Constructors and Methods have overloaded names already
+ if (symbolReference.SymbolType is
SymbolType.Function or
+ SymbolType.Enum or
+ SymbolType.Class or
+ SymbolType.Constructor or
+ SymbolType.Method or
+ SymbolType.Configuration or
SymbolType.Workflow)
{
name += " { }";
diff --git a/src/PowerShellEditorServices/Services/Workspace/Handlers/WorkspaceSymbolsHandler.cs b/src/PowerShellEditorServices/Services/Workspace/Handlers/WorkspaceSymbolsHandler.cs
index 8a9aaa815..3fa830f99 100644
--- a/src/PowerShellEditorServices/Services/Workspace/Handlers/WorkspaceSymbolsHandler.cs
+++ b/src/PowerShellEditorServices/Services/Workspace/Handlers/WorkspaceSymbolsHandler.cs
@@ -72,7 +72,7 @@ public override async Task> Handle(WorkspaceSymbolP
symbols.Add(new SymbolInformation
{
ContainerName = containerName,
- Kind = foundOccurrence.SymbolType == SymbolType.Variable ? SymbolKind.Variable : SymbolKind.Function,
+ Kind = GetSymbolKind(foundOccurrence.SymbolType),
Location = location,
Name = GetDecoratedSymbolName(foundOccurrence)
});
@@ -107,8 +107,15 @@ private static string GetDecoratedSymbolName(SymbolReference symbolReference)
{
string name = symbolReference.SymbolName;
- if (symbolReference.SymbolType is SymbolType.Configuration or
+ // Append { } for symbols with scriptblock
+ // Constructors and Methods have overloaded names already
+ if (symbolReference.SymbolType is
SymbolType.Function or
+ SymbolType.Enum or
+ SymbolType.Class or
+ SymbolType.Constructor or
+ SymbolType.Method or
+ SymbolType.Configuration or
SymbolType.Workflow)
{
name += " { }";
@@ -117,6 +124,20 @@ SymbolType.Function or
return name;
}
+ private static SymbolKind GetSymbolKind(SymbolType symbolType)
+ {
+ return symbolType switch
+ {
+ SymbolType.Function or SymbolType.Configuration or SymbolType.Workflow => SymbolKind.Function,
+ SymbolType.Enum => SymbolKind.Enum,
+ SymbolType.Class => SymbolKind.Class,
+ SymbolType.Constructor => SymbolKind.Constructor,
+ SymbolType.Method => SymbolKind.Method,
+ SymbolType.Property => SymbolKind.Property,
+ _ => SymbolKind.Variable,
+ };
+ }
+
#endregion
}
}
From 0d6fc671c43b75d31eed825e41abf3269e478179 Mon Sep 17 00:00:00 2001
From: Frode Flaten <3436158+fflaten@users.noreply.github.com>
Date: Sat, 13 Aug 2022 22:07:33 +0000
Subject: [PATCH 02/18] remove code used for supporting PSv3 and v4
---
.../Symbols/ScriptDocumentSymbolProvider.cs | 11 ---
.../Services/Symbols/Vistors/AstOperations.cs | 12 ---
.../Symbols/Vistors/FindSymbolsVisitor2.cs | 74 -------------------
3 files changed, 97 deletions(-)
delete mode 100644 src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolsVisitor2.cs
diff --git a/src/PowerShellEditorServices/Services/Symbols/ScriptDocumentSymbolProvider.cs b/src/PowerShellEditorServices/Services/Symbols/ScriptDocumentSymbolProvider.cs
index 92b33c8de..0b40a5cc1 100644
--- a/src/PowerShellEditorServices/Services/Symbols/ScriptDocumentSymbolProvider.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/ScriptDocumentSymbolProvider.cs
@@ -33,17 +33,6 @@ IEnumerable IDocumentSymbolProvider.ProvideDocumentSymbols(
/// A collection of SymbolReference objects
public static IEnumerable FindSymbolsInDocument(Ast scriptAst)
{
- // TODO: Restore this when we figure out how to support multiple
- // PS versions in the new PSES-as-a-module world (issue #276)
- // if (powerShellVersion >= new Version(5,0))
- // {
- //#if PowerShell v5
- // FindSymbolsVisitor2 findSymbolsVisitor = new FindSymbolsVisitor2();
- // scriptAst.Visit(findSymbolsVisitor);
- // symbolReferences = findSymbolsVisitor.SymbolReferences;
- //#endif
- // }
- // else
FindSymbolsVisitor findSymbolsVisitor = new();
scriptAst.Visit(findSymbolsVisitor);
return findSymbolsVisitor.SymbolReferences;
diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/AstOperations.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/AstOperations.cs
index e14b2051a..6334b48b1 100644
--- a/src/PowerShellEditorServices/Services/Symbols/Vistors/AstOperations.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/AstOperations.cs
@@ -228,18 +228,6 @@ public static SymbolReference FindDefinitionOfSymbol(
/// A collection of SymbolReference objects
public static IEnumerable FindSymbolsInDocument(Ast scriptAst)
{
- // TODO: Restore this when we figure out how to support multiple
- // PS versions in the new PSES-as-a-module world (issue #276)
- // if (powerShellVersion >= new Version(5,0))
- // {
- //#if PowerShell v5
- // FindSymbolsVisitor2 findSymbolsVisitor = new FindSymbolsVisitor2();
- // scriptAst.Visit(findSymbolsVisitor);
- // symbolReferences = findSymbolsVisitor.SymbolReferences;
- //#endif
- // }
- // else
-
FindSymbolsVisitor findSymbolsVisitor = new();
scriptAst.Visit(findSymbolsVisitor);
return findSymbolsVisitor.SymbolReferences;
diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolsVisitor2.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolsVisitor2.cs
deleted file mode 100644
index 15f5e49db..000000000
--- a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolsVisitor2.cs
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT License.
-
-namespace Microsoft.PowerShell.EditorServices.Services.Symbols
-{
- // TODO: Restore this when we figure out how to support multiple
- // PS versions in the new PSES-as-a-module world (issue #276)
-
- /////
- ///// The visitor used to find all the symbols (function and class defs) in the AST.
- /////
- /////
- ///// Requires PowerShell v5 or higher
- /////
- /////
- //internal class FindSymbolsVisitor2 : AstVisitor2
- //{
- // private FindSymbolsVisitor findSymbolsVisitor;
-
- // public List SymbolReferences
- // {
- // get
- // {
- // return this.findSymbolsVisitor.SymbolReferences;
- // }
- // }
-
- // public FindSymbolsVisitor2()
- // {
- // this.findSymbolsVisitor = new FindSymbolsVisitor();
- // }
-
- // ///
- // /// Adds each function definition as a
- // ///
- // /// A functionDefinitionAst object in the script's AST
- // /// A decision to stop searching if the right symbol was found,
- // /// or a decision to continue if it wasn't found
- // public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst)
- // {
- // return this.findSymbolsVisitor.VisitFunctionDefinition(functionDefinitionAst);
- // }
-
- // ///
- // /// Checks to see if this variable expression is the symbol we are looking for.
- // ///
- // /// A VariableExpressionAst object in the script's AST
- // /// A decision to stop searching if the right symbol was found,
- // /// or a decision to continue if it wasn't found
- // public override AstVisitAction VisitVariableExpression(VariableExpressionAst variableExpressionAst)
- // {
- // return this.findSymbolsVisitor.VisitVariableExpression(variableExpressionAst);
- // }
-
- // public override AstVisitAction VisitConfigurationDefinition(ConfigurationDefinitionAst configurationDefinitionAst)
- // {
- // IScriptExtent nameExtent = new ScriptExtent()
- // {
- // Text = configurationDefinitionAst.InstanceName.Extent.Text,
- // StartLineNumber = configurationDefinitionAst.Extent.StartLineNumber,
- // EndLineNumber = configurationDefinitionAst.Extent.EndLineNumber,
- // StartColumnNumber = configurationDefinitionAst.Extent.StartColumnNumber,
- // EndColumnNumber = configurationDefinitionAst.Extent.EndColumnNumber
- // };
-
- // this.findSymbolsVisitor.SymbolReferences.Add(
- // new SymbolReference(
- // SymbolType.Configuration,
- // nameExtent));
-
- // return AstVisitAction.Continue;
- // }
- //}
-}
From 4974f0d70c9e7cc8ab7c872d07812057d809b98b Mon Sep 17 00:00:00 2001
From: Frode Flaten <3436158+fflaten@users.noreply.github.com>
Date: Sun, 14 Aug 2022 16:04:35 +0000
Subject: [PATCH 03/18] support hover
---
.../Services/Symbols/SymbolDetails.cs | 26 ++++
.../Symbols/Vistors/FindSymbolVisitor.cs | 143 +++++++++++++++++-
2 files changed, 167 insertions(+), 2 deletions(-)
diff --git a/src/PowerShellEditorServices/Services/Symbols/SymbolDetails.cs b/src/PowerShellEditorServices/Services/Symbols/SymbolDetails.cs
index 80a1dd8b4..fa19e0289 100644
--- a/src/PowerShellEditorServices/Services/Symbols/SymbolDetails.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/SymbolDetails.cs
@@ -82,6 +82,32 @@ await CommandHelpers.GetCommandSynopsisAsync(
symbolDetails.DisplayString = symbolReference.SymbolName;
return symbolDetails;
+ case SymbolType.Class:
+ symbolDetails.DisplayString = "class " + symbolReference.SymbolName;
+ return symbolDetails;
+
+ case SymbolType.Enum:
+ symbolDetails.DisplayString = "enum " + symbolReference.SymbolName;
+ return symbolDetails;
+
+ case SymbolType.Constructor:
+ // TODO: constructor Class(parameters)
+ symbolDetails.DisplayString = "constructor " + symbolReference.SymbolName;
+ return symbolDetails;
+
+ case SymbolType.Method:
+ // TODO: method ReturnType Class.MethodName(parameters)
+ symbolDetails.DisplayString = "method " + symbolReference.SymbolName;
+ return symbolDetails;
+
+ case SymbolType.Property:
+ symbolDetails.DisplayString = "(property) " + symbolReference.SymbolName;
+ return symbolDetails;
+
+ case SymbolType.Configuration:
+ symbolDetails.DisplayString = "configuration " + symbolReference.SymbolName;
+ return symbolDetails;
+
default:
return symbolDetails;
}
diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolVisitor.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolVisitor.cs
index bf2520a3c..adb1d6b48 100644
--- a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolVisitor.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolVisitor.cs
@@ -9,7 +9,7 @@ namespace Microsoft.PowerShell.EditorServices.Services.Symbols
///
/// The visitor used to find the symbol at a specific location in the AST
///
- internal class FindSymbolVisitor : AstVisitor
+ internal class FindSymbolVisitor : AstVisitor2
{
private readonly int lineNumber;
private readonly int columnNumber;
@@ -116,7 +116,7 @@ public override AstVisitAction VisitCommandParameter(CommandParameterAst command
}
///
- /// Checks to see if this variable expression is the symbol we are looking for.
+ /// Checks to see if this variable expression is the symbol we are looking for.
///
/// A VariableExpressionAst object in the script's AST
/// A decision to stop searching if the right symbol was found,
@@ -147,5 +147,144 @@ private bool IsPositionInExtent(IScriptExtent extent)
extent.StartColumnNumber <= columnNumber &&
extent.EndColumnNumber >= columnNumber;
}
+
+ ///
+ /// Checks to see if this function member is the symbol we are looking for.
+ ///
+ /// A FunctionMemberAst object in the script's AST
+ /// A decision to stop searching if the right symbol was found,
+ /// or a decision to continue if it wasn't found
+ public override AstVisitAction VisitFunctionMember(FunctionMemberAst functionMemberAst)
+ {
+ // Show only method/ctor name. Offset by StartColumn to include indentation etc.
+ int startColumnNumber =
+ functionMemberAst.Extent.StartColumnNumber +
+ functionMemberAst.Extent.Text.IndexOf(functionMemberAst.Name);
+
+ IScriptExtent nameExtent = new ScriptExtent()
+ {
+ Text = functionMemberAst.Name,
+ StartLineNumber = functionMemberAst.Extent.StartLineNumber,
+ EndLineNumber = functionMemberAst.Extent.StartLineNumber,
+ StartColumnNumber = startColumnNumber,
+ EndColumnNumber = startColumnNumber + functionMemberAst.Name.Length,
+ File = functionMemberAst.Extent.File
+ };
+
+ if (IsPositionInExtent(nameExtent))
+ {
+ SymbolType symbolType =
+ functionMemberAst.IsConstructor ?
+ SymbolType.Constructor : SymbolType.Method;
+
+ FoundSymbolReference =
+ new SymbolReference(
+ symbolType,
+ nameExtent);
+
+ return AstVisitAction.StopVisit;
+ }
+
+ return AstVisitAction.Continue;
+ }
+
+ ///
+ /// Checks to see if this type definition is the symbol we are looking for.
+ ///
+ /// A TypeDefinitionAst object in the script's AST
+ /// A decision to stop searching if the right symbol was found,
+ /// or a decision to continue if it wasn't found
+ public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst)
+ {
+ // Show only type name. Offset by StartColumn to include indentation etc.
+ int startColumnNumber =
+ typeDefinitionAst.Extent.StartColumnNumber +
+ typeDefinitionAst.Extent.Text.IndexOf(typeDefinitionAst.Name);
+
+ IScriptExtent nameExtent = new ScriptExtent()
+ {
+ Text = typeDefinitionAst.Name,
+ StartLineNumber = typeDefinitionAst.Extent.StartLineNumber,
+ EndLineNumber = typeDefinitionAst.Extent.StartLineNumber,
+ StartColumnNumber = startColumnNumber,
+ EndColumnNumber = startColumnNumber + typeDefinitionAst.Name.Length,
+ File = typeDefinitionAst.Extent.File
+ };
+
+ if (IsPositionInExtent(nameExtent))
+ {
+ SymbolType symbolType =
+ typeDefinitionAst.IsEnum ?
+ SymbolType.Enum : SymbolType.Class;
+
+ FoundSymbolReference =
+ new SymbolReference(
+ symbolType,
+ nameExtent);
+
+ return AstVisitAction.StopVisit;
+ }
+
+ return AstVisitAction.Continue;
+ }
+
+ ///
+ /// Checks to see if this configuration definition is the symbol we are looking for.
+ ///
+ /// A ConfigurationDefinitionAst object in the script's AST
+ /// A decision to stop searching if the right symbol was found,
+ /// or a decision to continue if it wasn't found
+ public override AstVisitAction VisitConfigurationDefinition(ConfigurationDefinitionAst configurationDefinitionAst)
+ {
+ string configurationName = configurationDefinitionAst.InstanceName.Extent.Text;
+
+ // Show only configuration name. Offset by StartColumn to include indentation etc.
+ int startColumnNumber =
+ configurationDefinitionAst.Extent.StartColumnNumber +
+ configurationDefinitionAst.Extent.Text.IndexOf(configurationName);
+
+ IScriptExtent nameExtent = new ScriptExtent()
+ {
+ Text = configurationName,
+ StartLineNumber = configurationDefinitionAst.Extent.StartLineNumber,
+ EndLineNumber = configurationDefinitionAst.Extent.StartLineNumber,
+ StartColumnNumber = startColumnNumber,
+ EndColumnNumber = startColumnNumber + configurationName.Length,
+ File = configurationDefinitionAst.Extent.File
+ };
+
+ if (IsPositionInExtent(nameExtent))
+ {
+ FoundSymbolReference =
+ new SymbolReference(
+ SymbolType.Configuration,
+ nameExtent);
+
+ return AstVisitAction.StopVisit;
+ }
+
+ return AstVisitAction.Continue;
+ }
+
+ ///
+ /// Checks to see if this variable expression is the symbol we are looking for.
+ ///
+ /// A VariableExpressionAst object in the script's AST
+ /// A decision to stop searching if the right symbol was found,
+ /// or a decision to continue if it wasn't found
+ public override AstVisitAction VisitPropertyMember(PropertyMemberAst propertyMemberAst)
+ {
+ if (IsPositionInExtent(propertyMemberAst.Extent))
+ {
+ FoundSymbolReference =
+ new SymbolReference(
+ SymbolType.Property,
+ propertyMemberAst.Extent);
+
+ return AstVisitAction.StopVisit;
+ }
+
+ return AstVisitAction.Continue;
+ }
}
}
From 221c1f771da9e497fd4afc7fe145171439f5add6 Mon Sep 17 00:00:00 2001
From: Frode Flaten <3436158+fflaten@users.noreply.github.com>
Date: Tue, 16 Aug 2022 20:14:58 +0000
Subject: [PATCH 04/18] add type reference symboltype
---
.../Services/Symbols/SymbolDetails.cs | 4 ++++
.../Services/Symbols/SymbolType.cs | 7 ++++++-
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/src/PowerShellEditorServices/Services/Symbols/SymbolDetails.cs b/src/PowerShellEditorServices/Services/Symbols/SymbolDetails.cs
index fa19e0289..fc85acd30 100644
--- a/src/PowerShellEditorServices/Services/Symbols/SymbolDetails.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/SymbolDetails.cs
@@ -90,6 +90,10 @@ await CommandHelpers.GetCommandSynopsisAsync(
symbolDetails.DisplayString = "enum " + symbolReference.SymbolName;
return symbolDetails;
+ case SymbolType.Type:
+ symbolDetails.DisplayString = "type " + symbolReference.SymbolName;
+ return symbolDetails;
+
case SymbolType.Constructor:
// TODO: constructor Class(parameters)
symbolDetails.DisplayString = "constructor " + symbolReference.SymbolName;
diff --git a/src/PowerShellEditorServices/Services/Symbols/SymbolType.cs b/src/PowerShellEditorServices/Services/Symbols/SymbolType.cs
index 207038107..84756661c 100644
--- a/src/PowerShellEditorServices/Services/Symbols/SymbolType.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/SymbolType.cs
@@ -66,6 +66,11 @@ internal enum SymbolType
///
/// The symbol is a class constructor
///
- Constructor
+ Constructor,
+
+ ///
+ /// The symbol is a type reference
+ ///
+ Type,
}
}
From b8f2c05e36e7b0e64b581566b7306f7ad8d89e5c Mon Sep 17 00:00:00 2001
From: Frode Flaten <3436158+fflaten@users.noreply.github.com>
Date: Tue, 16 Aug 2022 20:20:54 +0000
Subject: [PATCH 05/18] support references and definitions
---
.../Symbols/Vistors/FindDeclarationVisitor.cs | 153 +++++++++++++++-
.../Symbols/Vistors/FindReferencesVisitor.cs | 163 +++++++++++++++++-
.../Symbols/Vistors/FindSymbolVisitor.cs | 68 ++++++++
3 files changed, 381 insertions(+), 3 deletions(-)
diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindDeclarationVisitor.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindDeclarationVisitor.cs
index 5c3071451..60d82eeac 100644
--- a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindDeclarationVisitor.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindDeclarationVisitor.cs
@@ -9,7 +9,7 @@ namespace Microsoft.PowerShell.EditorServices.Services.Symbols
///
/// The visitor used to find the definition of a symbol
///
- internal class FindDeclarationVisitor : AstVisitor
+ internal class FindDeclarationVisitor : AstVisitor2
{
private readonly SymbolReference symbolRef;
private readonly string variableName;
@@ -68,6 +68,157 @@ public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst fun
return base.VisitFunctionDefinition(functionDefinitionAst);
}
+ ///
+ /// Decides if the current type definition is the right definition
+ /// for the symbol being searched for. The definition of the symbol will be a of type
+ /// SymbolType.Enum or SymbolType.Class and have the same name as the symbol
+ ///
+ /// A TypeDefinitionAst in the script's AST
+ /// A decision to stop searching if the right TypeDefinitionAst was found,
+ /// or a decision to continue if it wasn't found
+ public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst)
+ {
+ SymbolType symbolType =
+ typeDefinitionAst.IsEnum ?
+ SymbolType.Enum : SymbolType.Class;
+
+ if ((symbolRef.SymbolType is SymbolType.Type || symbolRef.SymbolType.Equals(symbolType)) &&
+ typeDefinitionAst.Name.Equals(symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
+ {
+ // Show only type name. Offset by StartColumn to include indentation etc.
+ int startColumnNumber =
+ typeDefinitionAst.Extent.StartColumnNumber +
+ typeDefinitionAst.Extent.Text.IndexOf(typeDefinitionAst.Name);
+
+ IScriptExtent nameExtent = new ScriptExtent()
+ {
+ Text = typeDefinitionAst.Name,
+ StartLineNumber = typeDefinitionAst.Extent.StartLineNumber,
+ EndLineNumber = typeDefinitionAst.Extent.StartLineNumber,
+ StartColumnNumber = startColumnNumber,
+ EndColumnNumber = startColumnNumber + typeDefinitionAst.Name.Length,
+ File = typeDefinitionAst.Extent.File
+ };
+
+ FoundDeclaration =
+ new SymbolReference(
+ symbolType,
+ nameExtent);
+
+ return AstVisitAction.StopVisit;
+ }
+
+ return AstVisitAction.Continue;
+ }
+
+ ///
+ /// Decides if the current function member is the right definition
+ /// for the symbol being searched for. The definition of the symbol will be a of type
+ /// SymbolType.Constructor or SymbolType.Method and have the same name as the symbol
+ ///
+ /// A FunctionMemberAst in the script's AST
+ /// A decision to stop searching if the right FunctionMemberAst was found,
+ /// or a decision to continue if it wasn't found
+ public override AstVisitAction VisitFunctionMember(FunctionMemberAst functionMemberAst)
+ {
+ SymbolType symbolType =
+ functionMemberAst.IsConstructor ?
+ SymbolType.Constructor : SymbolType.Method;
+
+ if (symbolRef.SymbolType.Equals(symbolType) &&
+ functionMemberAst.Name.Equals(symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
+ {
+ // Show only method/ctor name. Offset by StartColumn to include indentation etc.
+ int startColumnNumber =
+ functionMemberAst.Extent.StartColumnNumber +
+ functionMemberAst.Extent.Text.IndexOf(functionMemberAst.Name);
+
+ IScriptExtent nameExtent = new ScriptExtent()
+ {
+ Text = functionMemberAst.Name,
+ StartLineNumber = functionMemberAst.Extent.StartLineNumber,
+ EndLineNumber = functionMemberAst.Extent.StartLineNumber,
+ StartColumnNumber = startColumnNumber,
+ EndColumnNumber = startColumnNumber + functionMemberAst.Name.Length,
+ File = functionMemberAst.Extent.File
+ };
+
+ FoundDeclaration =
+ new SymbolReference(
+ symbolType,
+ nameExtent);
+
+ return AstVisitAction.StopVisit;
+ }
+
+ return AstVisitAction.Continue;
+ }
+
+ ///
+ /// Decides if the current property member is the right definition
+ /// for the symbol being searched for. The definition of the symbol will be a of type
+ /// SymbolType.Property and have the same name as the symbol
+ ///
+ /// A PropertyMemberAst in the script's AST
+ /// A decision to stop searching if the right PropertyMemberAst was found,
+ /// or a decision to continue if it wasn't found
+ public override AstVisitAction VisitPropertyMember(PropertyMemberAst propertyMemberAst)
+ {
+ if (symbolRef.SymbolType.Equals(SymbolType.Property) &&
+ propertyMemberAst.Name.Equals(symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
+ {
+ FoundDeclaration =
+ new SymbolReference(
+ SymbolType.Property,
+ propertyMemberAst.Extent);
+
+ return AstVisitAction.StopVisit;
+ }
+
+ return AstVisitAction.Continue;
+ }
+
+ ///
+ /// Decides if the current configuration definition is the right definition
+ /// for the symbol being searched for. The definition of the symbol will be a of type
+ /// SymbolType.Configuration and have the same name as the symbol
+ ///
+ /// A ConfigurationDefinitionAst in the script's AST
+ /// A decision to stop searching if the right ConfigurationDefinitionAst was found,
+ /// or a decision to continue if it wasn't found
+ public override AstVisitAction VisitConfigurationDefinition(ConfigurationDefinitionAst configurationDefinitionAst)
+ {
+ string configurationName = configurationDefinitionAst.InstanceName.Extent.Text;
+
+ if (symbolRef.SymbolType.Equals(SymbolType.Configuration) &&
+ configurationName.Equals(symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
+ {
+ // Show only configuration name. Offset by StartColumn to include indentation etc.
+ int startColumnNumber =
+ configurationDefinitionAst.Extent.StartColumnNumber +
+ configurationDefinitionAst.Extent.Text.IndexOf(configurationName);
+
+ IScriptExtent nameExtent = new ScriptExtent()
+ {
+ Text = configurationName,
+ StartLineNumber = configurationDefinitionAst.Extent.StartLineNumber,
+ EndLineNumber = configurationDefinitionAst.Extent.StartLineNumber,
+ StartColumnNumber = startColumnNumber,
+ EndColumnNumber = startColumnNumber + configurationName.Length,
+ File = configurationDefinitionAst.Extent.File
+ };
+
+ FoundDeclaration =
+ new SymbolReference(
+ SymbolType.Configuration,
+ nameExtent);
+
+ return AstVisitAction.StopVisit;
+ }
+
+ return AstVisitAction.Continue;
+ }
+
///
/// Check if the left hand side of an assignmentStatementAst is a VariableExpressionAst
/// with the same name as that of symbolRef.
diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs
index 44b64c8f5..bbae9ccaf 100644
--- a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Microsoft Corporation.
+// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System;
@@ -11,7 +11,7 @@ namespace Microsoft.PowerShell.EditorServices.Services.Symbols
///
/// The visitor used to find the references of a symbol in a script's AST
///
- internal class FindReferencesVisitor : AstVisitor
+ internal class FindReferencesVisitor : AstVisitor2
{
private readonly SymbolReference _symbolRef;
private readonly IDictionary> _cmdletToAliasDictionary;
@@ -168,5 +168,164 @@ public override AstVisitAction VisitVariableExpression(VariableExpressionAst var
}
return AstVisitAction.Continue;
}
+
+ ///
+ /// Decides if the current type definition is a reference of the symbol being searched for.
+ /// A reference of the symbol will be a of type SymbolType.Class or SymbolType.Enum and have the same name as the symbol
+ ///
+ /// A TypeDefinitionAst in the script's AST
+ /// A visit action that continues the search for references
+ public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst)
+ {
+ SymbolType symbolType =
+ typeDefinitionAst.IsEnum ?
+ SymbolType.Enum : SymbolType.Class;
+
+ if ((_symbolRef.SymbolType is SymbolType.Type || _symbolRef.SymbolType.Equals(symbolType)) &&
+ typeDefinitionAst.Name.Equals(_symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
+ {
+ // Show only type name. Offset by StartColumn to include indentation etc.
+ int startColumnNumber =
+ typeDefinitionAst.Extent.StartColumnNumber +
+ typeDefinitionAst.Extent.Text.IndexOf(typeDefinitionAst.Name);
+
+ IScriptExtent nameExtent = new ScriptExtent()
+ {
+ Text = typeDefinitionAst.Name,
+ StartLineNumber = typeDefinitionAst.Extent.StartLineNumber,
+ EndLineNumber = typeDefinitionAst.Extent.StartLineNumber,
+ StartColumnNumber = startColumnNumber,
+ EndColumnNumber = startColumnNumber + typeDefinitionAst.Name.Length,
+ File = typeDefinitionAst.Extent.File
+ };
+
+ FoundReferences.Add(new SymbolReference(symbolType, nameExtent));
+ }
+ return AstVisitAction.Continue;
+ }
+
+ ///
+ /// Decides if the current type expression is a reference of the symbol being searched for.
+ /// A reference of the symbol will be a of type SymbolType.Type and have the same name as the symbol
+ ///
+ /// A TypeExpressionAst in the script's AST
+ /// A visit action that continues the search for references
+ public override AstVisitAction VisitTypeExpression(TypeExpressionAst typeExpressionAst)
+ {
+ // We don't know if we're looking at a class or enum, but name is likely unique
+ if (IsTypeSymbol(_symbolRef.SymbolType) &&
+ typeExpressionAst.TypeName.Name.Equals(_symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
+ {
+ FoundReferences.Add(new SymbolReference(SymbolType.Type, typeExpressionAst.Extent));
+ }
+ return AstVisitAction.Continue;
+ }
+
+ ///
+ /// Decides if the current type constraint is a reference of the symbol being searched for.
+ /// A reference of the symbol will be a of type SymbolType.Type and have the same name as the symbol
+ ///
+ /// A TypeConstraintAst in the script's AST
+ /// A visit action that continues the search for references
+ public override AstVisitAction VisitTypeConstraint(TypeConstraintAst typeConstraintAst)
+ {
+ // We don't know if we're looking at a class or enum, but name is likely unique
+ if (IsTypeSymbol(_symbolRef.SymbolType) &&
+ typeConstraintAst.TypeName.Name.Equals(_symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
+ {
+ FoundReferences.Add(new SymbolReference(SymbolType.Type, typeConstraintAst.Extent));
+ }
+ return AstVisitAction.Continue;
+ }
+
+ ///
+ /// Decides if the current function member is a reference of the symbol being searched for.
+ /// A reference of the symbol will be a of type SymbolType.Constructor or SymbolType.Method and have the same name as the symbol
+ ///
+ /// A FunctionMemberAst in the script's AST
+ /// A visit action that continues the search for references
+ public override AstVisitAction VisitFunctionMember(FunctionMemberAst functionMemberAst)
+ {
+ SymbolType symbolType =
+ functionMemberAst.IsConstructor ?
+ SymbolType.Constructor : SymbolType.Method;
+
+ if (_symbolRef.SymbolType.Equals(symbolType) &&
+ functionMemberAst.Name.Equals(_symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
+ {
+ // Show only method/ctor name. Offset by StartColumn to include indentation etc.
+ int startColumnNumber =
+ functionMemberAst.Extent.StartColumnNumber +
+ functionMemberAst.Extent.Text.IndexOf(functionMemberAst.Name);
+
+ IScriptExtent nameExtent = new ScriptExtent()
+ {
+ Text = functionMemberAst.Name,
+ StartLineNumber = functionMemberAst.Extent.StartLineNumber,
+ EndLineNumber = functionMemberAst.Extent.StartLineNumber,
+ StartColumnNumber = startColumnNumber,
+ EndColumnNumber = startColumnNumber + functionMemberAst.Name.Length,
+ File = functionMemberAst.Extent.File
+ };
+
+ FoundReferences.Add(new SymbolReference(symbolType, nameExtent));
+ }
+ return AstVisitAction.Continue;
+ }
+
+ ///
+ /// Decides if the current property member is a reference of the symbol being searched for.
+ /// A reference of the symbol will be a of type SymbolType.Property and have the same name as the symbol
+ ///
+ /// A PropertyMemberAst in the script's AST
+ /// A visit action that continues the search for references
+ public override AstVisitAction VisitPropertyMember(PropertyMemberAst propertyMemberAst)
+ {
+ if (_symbolRef.SymbolType.Equals(SymbolType.Property) &&
+ propertyMemberAst.Name.Equals(_symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
+ {
+ FoundReferences.Add(new SymbolReference(SymbolType.Property, propertyMemberAst.Extent));
+ }
+ return AstVisitAction.Continue;
+ }
+
+ ///
+ /// Decides if the current configuration definition is a reference of the symbol being searched for.
+ /// A reference of the symbol will be a of type SymbolType.Configuration and have the same name as the symbol
+ ///
+ /// A ConfigurationDefinitionAst in the script's AST
+ /// A visit action that continues the search for references
+ public override AstVisitAction VisitConfigurationDefinition(ConfigurationDefinitionAst configurationDefinitionAst)
+ {
+ string configurationName = configurationDefinitionAst.InstanceName.Extent.Text;
+
+ if (_symbolRef.SymbolType.Equals(SymbolType.Configuration) &&
+ configurationName.Equals(_symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
+ {
+ // Show only configuration name. Offset by StartColumn to include indentation etc.
+ int startColumnNumber =
+ configurationDefinitionAst.Extent.StartColumnNumber +
+ configurationDefinitionAst.Extent.Text.IndexOf(configurationName);
+
+ IScriptExtent nameExtent = new ScriptExtent()
+ {
+ Text = configurationName,
+ StartLineNumber = configurationDefinitionAst.Extent.StartLineNumber,
+ EndLineNumber = configurationDefinitionAst.Extent.StartLineNumber,
+ StartColumnNumber = startColumnNumber,
+ EndColumnNumber = startColumnNumber + configurationName.Length,
+ File = configurationDefinitionAst.Extent.File
+ };
+
+ FoundReferences.Add(new SymbolReference(SymbolType.Configuration, nameExtent));
+ }
+ return AstVisitAction.Continue;
+ }
+
+ ///
+ /// Tests if symbol type is a type (class/enum) definition or type reference.
+ ///
+ private static bool IsTypeSymbol(SymbolType symbolType)
+ => symbolType is SymbolType.Class or SymbolType.Enum or SymbolType.Type;
}
}
diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolVisitor.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolVisitor.cs
index adb1d6b48..f40b44fd1 100644
--- a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolVisitor.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolVisitor.cs
@@ -228,6 +228,74 @@ public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinit
return AstVisitAction.Continue;
}
+ ///
+ /// Checks to see if this type expression is the symbol we are looking for.
+ ///
+ /// A TypeExpressionAst object in the script's AST
+ /// A decision to stop searching if the right symbol was found,
+ /// or a decision to continue if it wasn't found
+ public override AstVisitAction VisitTypeExpression(TypeExpressionAst typeExpressionAst)
+ {
+ // Show only type name. Offset by StartColumn to include indentation etc.
+ int startColumnNumber =
+ typeExpressionAst.Extent.StartColumnNumber +
+ typeExpressionAst.Extent.Text.IndexOf(typeExpressionAst.TypeName.Name);
+
+ IScriptExtent nameExtent = new ScriptExtent()
+ {
+ Text = typeExpressionAst.TypeName.Name,
+ StartLineNumber = typeExpressionAst.Extent.StartLineNumber,
+ EndLineNumber = typeExpressionAst.Extent.StartLineNumber,
+ StartColumnNumber = startColumnNumber,
+ EndColumnNumber = startColumnNumber + typeExpressionAst.TypeName.Name.Length,
+ File = typeExpressionAst.Extent.File
+ };
+
+ if (IsPositionInExtent(nameExtent))
+ {
+ FoundSymbolReference =
+ new SymbolReference(
+ SymbolType.Type,
+ nameExtent);
+ return AstVisitAction.StopVisit;
+ }
+ return AstVisitAction.Continue;
+ }
+
+ ///
+ /// Checks to see if this type constraint is the symbol we are looking for.
+ ///
+ /// A TypeConstraintAst object in the script's AST
+ /// A decision to stop searching if the right symbol was found,
+ /// or a decision to continue if it wasn't found
+ public override AstVisitAction VisitTypeConstraint(TypeConstraintAst typeConstraintAst)
+ {
+ // Show only type name. Offset by StartColumn to include indentation etc.
+ int startColumnNumber =
+ typeConstraintAst.Extent.StartColumnNumber +
+ typeConstraintAst.Extent.Text.IndexOf(typeConstraintAst.TypeName.Name);
+
+ IScriptExtent nameExtent = new ScriptExtent()
+ {
+ Text = typeConstraintAst.TypeName.Name,
+ StartLineNumber = typeConstraintAst.Extent.StartLineNumber,
+ EndLineNumber = typeConstraintAst.Extent.StartLineNumber,
+ StartColumnNumber = startColumnNumber,
+ EndColumnNumber = startColumnNumber + typeConstraintAst.TypeName.Name.Length,
+ File = typeConstraintAst.Extent.File
+ };
+
+ if (IsPositionInExtent(nameExtent))
+ {
+ FoundSymbolReference =
+ new SymbolReference(
+ SymbolType.Type,
+ nameExtent);
+ return AstVisitAction.StopVisit;
+ }
+ return AstVisitAction.Continue;
+ }
+
///
/// Checks to see if this configuration definition is the symbol we are looking for.
///
From 5774edc0fd852e7baeac5e8cdc974fd4bc99f971 Mon Sep 17 00:00:00 2001
From: Frode Flaten <3436158+fflaten@users.noreply.github.com>
Date: Tue, 16 Aug 2022 20:51:45 +0000
Subject: [PATCH 06/18] add codelens for class and enum
---
.../CodeLens/ReferencesCodeLensProvider.cs | 9 +++--
.../Services/Symbols/SymbolsService.cs | 6 ++--
.../Services/Symbols/Vistors/AstOperations.cs | 6 ++--
.../Symbols/Vistors/FindSymbolVisitor.cs | 33 ++++++++++++-------
4 files changed, 34 insertions(+), 20 deletions(-)
diff --git a/src/PowerShellEditorServices/Services/CodeLens/ReferencesCodeLensProvider.cs b/src/PowerShellEditorServices/Services/CodeLens/ReferencesCodeLensProvider.cs
index eb50ce2d5..5f9b6d958 100644
--- a/src/PowerShellEditorServices/Services/CodeLens/ReferencesCodeLensProvider.cs
+++ b/src/PowerShellEditorServices/Services/CodeLens/ReferencesCodeLensProvider.cs
@@ -57,14 +57,17 @@ public ReferencesCodeLensProvider(WorkspaceService workspaceService, SymbolsServ
///
/// The PowerShell script file to get code lenses for.
///
- /// An array of CodeLenses describing all functions in the given script file.
+ /// An array of CodeLenses describing all functions, classes and enums in the given script file.
public CodeLens[] ProvideCodeLenses(ScriptFile scriptFile, CancellationToken cancellationToken)
{
List acc = new();
foreach (SymbolReference sym in _symbolProvider.ProvideDocumentSymbols(scriptFile))
{
cancellationToken.ThrowIfCancellationRequested();
- if (sym.SymbolType == SymbolType.Function)
+ if (sym.SymbolType is
+ SymbolType.Function or
+ SymbolType.Class or
+ SymbolType.Enum)
{
acc.Add(new CodeLens
{
@@ -96,7 +99,7 @@ public async Task ResolveCodeLens(
ScriptFile[] references = _workspaceService.ExpandScriptReferences(
scriptFile);
- SymbolReference foundSymbol = SymbolsService.FindFunctionDefinitionAtLocation(
+ SymbolReference foundSymbol = SymbolsService.FindSymbolDefinitionAtLocation(
scriptFile,
codeLens.Range.Start.Line + 1,
codeLens.Range.Start.Character + 1);
diff --git a/src/PowerShellEditorServices/Services/Symbols/SymbolsService.cs b/src/PowerShellEditorServices/Services/Symbols/SymbolsService.cs
index f052520f0..336495bd8 100644
--- a/src/PowerShellEditorServices/Services/Symbols/SymbolsService.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/SymbolsService.cs
@@ -288,7 +288,7 @@ public static IReadOnlyList FindOccurrencesInFile(
}
///
- /// Finds a function definition in the script given a file location
+ /// Finds a function, class or enum definition in the script given a file location
///
/// The details and contents of a open script file
/// The line number of the cursor for the given script
@@ -296,7 +296,7 @@ public static IReadOnlyList FindOccurrencesInFile(
/// A SymbolReference of the symbol found at the given location
/// or null if there is no symbol at that location
///
- public static SymbolReference FindFunctionDefinitionAtLocation(
+ public static SymbolReference FindSymbolDefinitionAtLocation(
ScriptFile scriptFile,
int lineNumber,
int columnNumber)
@@ -306,7 +306,7 @@ public static SymbolReference FindFunctionDefinitionAtLocation(
scriptFile.ScriptAst,
lineNumber,
columnNumber,
- includeFunctionDefinitions: true);
+ includeDefinitions: true);
if (symbolReference != null)
{
diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/AstOperations.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/AstOperations.cs
index 6334b48b1..6fcbd62c9 100644
--- a/src/PowerShellEditorServices/Services/Symbols/Vistors/AstOperations.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/AstOperations.cs
@@ -147,19 +147,19 @@ await executionService.ExecuteDelegateAsync(
/// The abstract syntax tree of the given script
/// The line number of the cursor for the given script
/// The column number of the cursor for the given script
- /// Includes full function definition ranges in the search.
+ /// Includes full symbol definition ranges in the search.
/// SymbolReference of found symbol
public static SymbolReference FindSymbolAtPosition(
Ast scriptAst,
int lineNumber,
int columnNumber,
- bool includeFunctionDefinitions = false)
+ bool includeDefinitions = false)
{
FindSymbolVisitor symbolVisitor =
new(
lineNumber,
columnNumber,
- includeFunctionDefinitions);
+ includeDefinitions);
scriptAst.Visit(symbolVisitor);
diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolVisitor.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolVisitor.cs
index f40b44fd1..41cd2be00 100644
--- a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolVisitor.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolVisitor.cs
@@ -13,18 +13,18 @@ internal class FindSymbolVisitor : AstVisitor2
{
private readonly int lineNumber;
private readonly int columnNumber;
- private readonly bool includeFunctionDefinitions;
+ private readonly bool includeDefinitions;
public SymbolReference FoundSymbolReference { get; private set; }
public FindSymbolVisitor(
int lineNumber,
int columnNumber,
- bool includeFunctionDefinitions)
+ bool includeDefinitions)
{
this.lineNumber = lineNumber;
this.columnNumber = columnNumber;
- this.includeFunctionDefinitions = includeFunctionDefinitions;
+ this.includeDefinitions = includeDefinitions;
}
///
@@ -63,7 +63,7 @@ public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst fun
int endLineNumber = functionDefinitionAst.Extent.EndLineNumber;
int endColumnNumber = functionDefinitionAst.Extent.EndColumnNumber;
- if (!includeFunctionDefinitions)
+ if (!includeDefinitions)
{
// We only want the function name
(int startColumn, int startLine) = VisitorUtils.GetNameStartColumnAndLineNumbersFromAst(functionDefinitionAst);
@@ -196,18 +196,29 @@ public override AstVisitAction VisitFunctionMember(FunctionMemberAst functionMem
/// or a decision to continue if it wasn't found
public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst)
{
- // Show only type name. Offset by StartColumn to include indentation etc.
- int startColumnNumber =
- typeDefinitionAst.Extent.StartColumnNumber +
- typeDefinitionAst.Extent.Text.IndexOf(typeDefinitionAst.Name);
+ int startLineNumber = typeDefinitionAst.Extent.StartLineNumber;
+ int startColumnNumber = typeDefinitionAst.Extent.StartColumnNumber;
+ int endLineNumber = typeDefinitionAst.Extent.EndLineNumber;
+ int endColumnNumber = typeDefinitionAst.Extent.EndColumnNumber;
+
+ if (!includeDefinitions)
+ {
+ // We only want the function name
+ startColumnNumber =
+ typeDefinitionAst.Extent.StartColumnNumber +
+ typeDefinitionAst.Extent.Text.IndexOf(typeDefinitionAst.Name);
+ startLineNumber = typeDefinitionAst.Extent.StartLineNumber;
+ endColumnNumber = startColumnNumber + typeDefinitionAst.Name.Length;
+ endLineNumber = typeDefinitionAst.Extent.StartLineNumber;
+ }
IScriptExtent nameExtent = new ScriptExtent()
{
Text = typeDefinitionAst.Name,
- StartLineNumber = typeDefinitionAst.Extent.StartLineNumber,
- EndLineNumber = typeDefinitionAst.Extent.StartLineNumber,
+ StartLineNumber = startLineNumber,
+ EndLineNumber = endLineNumber,
StartColumnNumber = startColumnNumber,
- EndColumnNumber = startColumnNumber + typeDefinitionAst.Name.Length,
+ EndColumnNumber = endColumnNumber,
File = typeDefinitionAst.Extent.File
};
From 7bc1d3d5fe490e75bc06798298ceb2b74b21b93c Mon Sep 17 00:00:00 2001
From: Frode Flaten <3436158+fflaten@users.noreply.github.com>
Date: Tue, 16 Aug 2022 21:38:09 +0000
Subject: [PATCH 07/18] skip function ast visit for FunctionMemberAst
---
.../Services/Symbols/Vistors/FindDeclarationVisitor.cs | 7 +++++++
.../Services/Symbols/Vistors/FindReferencesVisitor.cs | 7 +++++++
.../Services/Symbols/Vistors/FindSymbolVisitor.cs | 7 +++++++
.../Services/Symbols/Vistors/FindSymbolsVisitor.cs | 3 ++-
4 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindDeclarationVisitor.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindDeclarationVisitor.cs
index 60d82eeac..aa587003d 100644
--- a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindDeclarationVisitor.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindDeclarationVisitor.cs
@@ -36,6 +36,13 @@ public FindDeclarationVisitor(SymbolReference symbolRef)
/// or a decision to continue if it wasn't found
public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst)
{
+ // Extent for constructors and method trigger both this and VisitFunctionMember(). Covered in the latter.
+ // This will not exclude nested functions as they have ScriptBlockAst as parent
+ if (functionDefinitionAst.Parent is FunctionMemberAst)
+ {
+ return AstVisitAction.Continue;
+ }
+
// Get the start column number of the function name,
// instead of the the start column of 'function' and create new extent for the functionName
int startColumnNumber =
diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs
index bbae9ccaf..7438482ce 100644
--- a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs
@@ -117,6 +117,13 @@ public override AstVisitAction VisitCommand(CommandAst commandAst)
/// A visit action that continues the search for references
public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst)
{
+ // Extent for constructors and method trigger both this and VisitFunctionMember(). Covered in the latter.
+ // This will not exclude nested functions as they have ScriptBlockAst as parent
+ if (functionDefinitionAst.Parent is FunctionMemberAst)
+ {
+ return AstVisitAction.Continue;
+ }
+
(int startColumnNumber, int startLineNumber) = VisitorUtils.GetNameStartColumnAndLineNumbersFromAst(functionDefinitionAst);
IScriptExtent nameExtent = new ScriptExtent()
diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolVisitor.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolVisitor.cs
index 41cd2be00..71a773c0e 100644
--- a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolVisitor.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolVisitor.cs
@@ -58,6 +58,13 @@ public override AstVisitAction VisitCommand(CommandAst commandAst)
/// or a decision to continue if it wasn't found
public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst)
{
+ // Extent for constructors and method trigger both this and VisitFunctionMember(). Covered in the latter.
+ // This will not exclude nested functions as they have ScriptBlockAst as parent
+ if (functionDefinitionAst.Parent is FunctionMemberAst)
+ {
+ return AstVisitAction.Continue;
+ }
+
int startLineNumber = functionDefinitionAst.Extent.StartLineNumber;
int startColumnNumber = functionDefinitionAst.Extent.StartColumnNumber;
int endLineNumber = functionDefinitionAst.Extent.EndLineNumber;
diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolsVisitor.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolsVisitor.cs
index 4d2d3a076..d7fe87db1 100644
--- a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolsVisitor.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolsVisitor.cs
@@ -25,7 +25,8 @@ public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst fun
{
// Extent for constructors and method trigger both this and VisitFunctionMember(). Covered in the latter.
// This will not exclude nested functions as they have ScriptBlockAst as parent
- if (functionDefinitionAst.Parent is FunctionMemberAst) {
+ if (functionDefinitionAst.Parent is FunctionMemberAst)
+ {
return AstVisitAction.Continue;
}
From ab34105447b590f63994be86492e9d3bfc3cab32 Mon Sep 17 00:00:00 2001
From: Frode Flaten <3436158+fflaten@users.noreply.github.com>
Date: Wed, 17 Aug 2022 19:05:10 +0000
Subject: [PATCH 08/18] drop reference-support for ConfigurationDefinition
---
.../Symbols/Vistors/FindDeclarationVisitor.cs | 41 -------------------
.../Symbols/Vistors/FindReferencesVisitor.cs | 33 ---------------
2 files changed, 74 deletions(-)
diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindDeclarationVisitor.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindDeclarationVisitor.cs
index aa587003d..18aafef21 100644
--- a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindDeclarationVisitor.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindDeclarationVisitor.cs
@@ -185,47 +185,6 @@ public override AstVisitAction VisitPropertyMember(PropertyMemberAst propertyMem
return AstVisitAction.Continue;
}
- ///
- /// Decides if the current configuration definition is the right definition
- /// for the symbol being searched for. The definition of the symbol will be a of type
- /// SymbolType.Configuration and have the same name as the symbol
- ///
- /// A ConfigurationDefinitionAst in the script's AST
- /// A decision to stop searching if the right ConfigurationDefinitionAst was found,
- /// or a decision to continue if it wasn't found
- public override AstVisitAction VisitConfigurationDefinition(ConfigurationDefinitionAst configurationDefinitionAst)
- {
- string configurationName = configurationDefinitionAst.InstanceName.Extent.Text;
-
- if (symbolRef.SymbolType.Equals(SymbolType.Configuration) &&
- configurationName.Equals(symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
- {
- // Show only configuration name. Offset by StartColumn to include indentation etc.
- int startColumnNumber =
- configurationDefinitionAst.Extent.StartColumnNumber +
- configurationDefinitionAst.Extent.Text.IndexOf(configurationName);
-
- IScriptExtent nameExtent = new ScriptExtent()
- {
- Text = configurationName,
- StartLineNumber = configurationDefinitionAst.Extent.StartLineNumber,
- EndLineNumber = configurationDefinitionAst.Extent.StartLineNumber,
- StartColumnNumber = startColumnNumber,
- EndColumnNumber = startColumnNumber + configurationName.Length,
- File = configurationDefinitionAst.Extent.File
- };
-
- FoundDeclaration =
- new SymbolReference(
- SymbolType.Configuration,
- nameExtent);
-
- return AstVisitAction.StopVisit;
- }
-
- return AstVisitAction.Continue;
- }
-
///
/// Check if the left hand side of an assignmentStatementAst is a VariableExpressionAst
/// with the same name as that of symbolRef.
diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs
index 7438482ce..858ee8479 100644
--- a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs
@@ -296,39 +296,6 @@ public override AstVisitAction VisitPropertyMember(PropertyMemberAst propertyMem
return AstVisitAction.Continue;
}
- ///
- /// Decides if the current configuration definition is a reference of the symbol being searched for.
- /// A reference of the symbol will be a of type SymbolType.Configuration and have the same name as the symbol
- ///
- /// A ConfigurationDefinitionAst in the script's AST
- /// A visit action that continues the search for references
- public override AstVisitAction VisitConfigurationDefinition(ConfigurationDefinitionAst configurationDefinitionAst)
- {
- string configurationName = configurationDefinitionAst.InstanceName.Extent.Text;
-
- if (_symbolRef.SymbolType.Equals(SymbolType.Configuration) &&
- configurationName.Equals(_symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
- {
- // Show only configuration name. Offset by StartColumn to include indentation etc.
- int startColumnNumber =
- configurationDefinitionAst.Extent.StartColumnNumber +
- configurationDefinitionAst.Extent.Text.IndexOf(configurationName);
-
- IScriptExtent nameExtent = new ScriptExtent()
- {
- Text = configurationName,
- StartLineNumber = configurationDefinitionAst.Extent.StartLineNumber,
- EndLineNumber = configurationDefinitionAst.Extent.StartLineNumber,
- StartColumnNumber = startColumnNumber,
- EndColumnNumber = startColumnNumber + configurationName.Length,
- File = configurationDefinitionAst.Extent.File
- };
-
- FoundReferences.Add(new SymbolReference(SymbolType.Configuration, nameExtent));
- }
- return AstVisitAction.Continue;
- }
-
///
/// Tests if symbol type is a type (class/enum) definition or type reference.
///
From 829480d91e84cf6a801d02644481ba9dc23bc554 Mon Sep 17 00:00:00 2001
From: Frode Flaten <3436158+fflaten@users.noreply.github.com>
Date: Wed, 17 Aug 2022 19:07:04 +0000
Subject: [PATCH 09/18] update document symbols test
---
.../Symbols/DSCFile.ps1 | 4 ++
.../Symbols/FindSymbolsInDSCFile.cs | 21 ++++++++
.../Symbols/MultipleSymbols.ps1 | 18 +++++--
.../Language/SymbolsServiceTests.cs | 51 ++++++++++++++++---
4 files changed, 85 insertions(+), 9 deletions(-)
create mode 100644 test/PowerShellEditorServices.Test.Shared/Symbols/DSCFile.ps1
create mode 100644 test/PowerShellEditorServices.Test.Shared/Symbols/FindSymbolsInDSCFile.cs
diff --git a/test/PowerShellEditorServices.Test.Shared/Symbols/DSCFile.ps1 b/test/PowerShellEditorServices.Test.Shared/Symbols/DSCFile.ps1
new file mode 100644
index 000000000..defec6863
--- /dev/null
+++ b/test/PowerShellEditorServices.Test.Shared/Symbols/DSCFile.ps1
@@ -0,0 +1,4 @@
+# This file represents a script with a DSC configuration
+configuration AConfiguration {
+ Node "TEST-PC" {}
+}
diff --git a/test/PowerShellEditorServices.Test.Shared/Symbols/FindSymbolsInDSCFile.cs b/test/PowerShellEditorServices.Test.Shared/Symbols/FindSymbolsInDSCFile.cs
new file mode 100644
index 000000000..6e3d45ff2
--- /dev/null
+++ b/test/PowerShellEditorServices.Test.Shared/Symbols/FindSymbolsInDSCFile.cs
@@ -0,0 +1,21 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Microsoft.PowerShell.EditorServices.Services.TextDocument;
+
+namespace Microsoft.PowerShell.EditorServices.Test.Shared.Symbols
+{
+ public static class FindSymbolsInDSCFile
+ {
+ public static readonly ScriptRegion SourceDetails =
+ new(
+ file: TestUtilities.NormalizePath("Symbols/DSCFile.ps1"),
+ text: string.Empty,
+ startLineNumber: 0,
+ startColumnNumber: 0,
+ startOffset: 0,
+ endLineNumber: 0,
+ endColumnNumber: 0,
+ endOffset: 0);
+ }
+}
diff --git a/test/PowerShellEditorServices.Test.Shared/Symbols/MultipleSymbols.ps1 b/test/PowerShellEditorServices.Test.Shared/Symbols/MultipleSymbols.ps1
index f234fed03..db53a6c1a 100644
--- a/test/PowerShellEditorServices.Test.Shared/Symbols/MultipleSymbols.ps1
+++ b/test/PowerShellEditorServices.Test.Shared/Symbols/MultipleSymbols.ps1
@@ -22,10 +22,22 @@ function AnAdvancedFunction {
workflow AWorkflow {}
-Configuration AConfiguration {
- Node "TEST-PC" {}
+class AClass {
+ [string]$AProperty
+
+ AClass([string]$AParameter) {
+
+ }
+
+ [void]AMethod([string]$param1, [int]$param2, $param3) {
+
+ }
+}
+
+enum AEnum {
+ AValue = 0
}
AFunction
1..3 | AFilter
-AnAdvancedFunction
\ No newline at end of file
+AnAdvancedFunction
diff --git a/test/PowerShellEditorServices.Test/Language/SymbolsServiceTests.cs b/test/PowerShellEditorServices.Test/Language/SymbolsServiceTests.cs
index e7938c287..b6552c0fb 100644
--- a/test/PowerShellEditorServices.Test/Language/SymbolsServiceTests.cs
+++ b/test/PowerShellEditorServices.Test/Language/SymbolsServiceTests.cs
@@ -6,6 +6,7 @@
using System.IO;
using System.Linq;
using System.Management.Automation;
+using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging.Abstractions;
@@ -32,6 +33,7 @@ public class SymbolsServiceTests : IDisposable
private readonly PsesInternalHost psesHost;
private readonly WorkspaceService workspace;
private readonly SymbolsService symbolsService;
+ private static readonly bool s_isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
public SymbolsServiceTests()
{
@@ -287,6 +289,11 @@ public void FindsSymbolsInFile()
Assert.Equal(4, symbolsResult.Count(symbolReference => symbolReference.SymbolType == SymbolType.Function));
Assert.Equal(3, symbolsResult.Count(symbolReference => symbolReference.SymbolType == SymbolType.Variable));
Assert.Single(symbolsResult.Where(symbolReference => symbolReference.SymbolType == SymbolType.Workflow));
+ Assert.Single(symbolsResult.Where(symbolReference => symbolReference.SymbolType == SymbolType.Class));
+ Assert.Equal(2, symbolsResult.Count(symbolReference => symbolReference.SymbolType == SymbolType.Property));
+ Assert.Single(symbolsResult.Where(symbolReference => symbolReference.SymbolType == SymbolType.Constructor));
+ Assert.Single(symbolsResult.Where(symbolReference => symbolReference.SymbolType == SymbolType.Method));
+ Assert.Single(symbolsResult.Where(symbolReference => symbolReference.SymbolType == SymbolType.Enum));
SymbolReference firstFunctionSymbol = symbolsResult.First(r => r.SymbolType == SymbolType.Function);
Assert.Equal("AFunction", firstFunctionSymbol.SymbolName);
@@ -303,12 +310,44 @@ public void FindsSymbolsInFile()
Assert.Equal(23, firstWorkflowSymbol.ScriptRegion.StartLineNumber);
Assert.Equal(1, firstWorkflowSymbol.ScriptRegion.StartColumnNumber);
- // TODO: Bring this back when we can use AstVisitor2 again (#276)
- //Assert.Equal(1, symbolsResult.FoundOccurrences.Where(r => r.SymbolType == SymbolType.Configuration).Count());
- //SymbolReference firstConfigurationSymbol = symbolsResult.FoundOccurrences.Where(r => r.SymbolType == SymbolType.Configuration).First();
- //Assert.Equal("AConfiguration", firstConfigurationSymbol.SymbolName);
- //Assert.Equal(25, firstConfigurationSymbol.ScriptRegion.StartLineNumber);
- //Assert.Equal(1, firstConfigurationSymbol.ScriptRegion.StartColumnNumber);
+ SymbolReference firstClassSymbol = symbolsResult.First(r => r.SymbolType == SymbolType.Class);
+ Assert.Equal("AClass", firstClassSymbol.SymbolName);
+ Assert.Equal(25, firstClassSymbol.ScriptRegion.StartLineNumber);
+ Assert.Equal(1, firstClassSymbol.ScriptRegion.StartColumnNumber);
+
+ SymbolReference firstPropertySymbol = symbolsResult.First(r => r.SymbolType == SymbolType.Property);
+ Assert.Equal("AProperty", firstPropertySymbol.SymbolName);
+ Assert.Equal(26, firstPropertySymbol.ScriptRegion.StartLineNumber);
+ Assert.Equal(5, firstPropertySymbol.ScriptRegion.StartColumnNumber);
+
+ SymbolReference firstConstructorSymbol = symbolsResult.First(r => r.SymbolType == SymbolType.Constructor);
+ Assert.Equal("AClass([string]$AParameter)", firstConstructorSymbol.SymbolName);
+ Assert.Equal(28, firstConstructorSymbol.ScriptRegion.StartLineNumber);
+ Assert.Equal(5, firstConstructorSymbol.ScriptRegion.StartColumnNumber);
+
+ SymbolReference firstMethodSymbol = symbolsResult.First(r => r.SymbolType == SymbolType.Method);
+ Assert.Equal("AMethod([string]$param1, [int]$param2, $param3)", firstMethodSymbol.SymbolName);
+ Assert.Equal(32, firstMethodSymbol.ScriptRegion.StartLineNumber);
+ Assert.Equal(5, firstMethodSymbol.ScriptRegion.StartColumnNumber);
+
+ SymbolReference firstEnumSymbol = symbolsResult.First(r => r.SymbolType == SymbolType.Enum);
+ Assert.Equal("AEnum", firstEnumSymbol.SymbolName);
+ Assert.Equal(37, firstEnumSymbol.ScriptRegion.StartLineNumber);
+ Assert.Equal(1, firstEnumSymbol.ScriptRegion.StartColumnNumber);
+ }
+
+ [SkippableFact]
+ public void FindsSymbolsInDSCFile()
+ {
+ Skip.If(!s_isWindows, "DSC only works properly on Windows.");
+
+ List symbolsResult = FindSymbolsInFile(FindSymbolsInDSCFile.SourceDetails);
+
+ Assert.Single(symbolsResult.Where(symbolReference => symbolReference.SymbolType == SymbolType.Configuration));
+ SymbolReference firstConfigurationSymbol = symbolsResult.First(r => r.SymbolType == SymbolType.Configuration);
+ Assert.Equal("AConfiguration", firstConfigurationSymbol.SymbolName);
+ Assert.Equal(2, firstConfigurationSymbol.ScriptRegion.StartLineNumber);
+ Assert.Equal(1, firstConfigurationSymbol.ScriptRegion.StartColumnNumber);
}
[Fact]
From 1827700e477fbea50122ab704ae0f5638b81d726 Mon Sep 17 00:00:00 2001
From: Frode Flaten <3436158+fflaten@users.noreply.github.com>
Date: Wed, 17 Aug 2022 23:24:56 +0000
Subject: [PATCH 10/18] refactor and cleanup
---
.../Symbols/Vistors/FindDeclarationVisitor.cs | 60 ++------
.../Symbols/Vistors/FindReferencesVisitor.cs | 66 +++------
.../Symbols/Vistors/FindSymbolVisitor.cs | 128 ++++++------------
.../Symbols/Vistors/FindSymbolsVisitor.cs | 95 ++++++-------
.../Utility/VisitorUtils.cs | 120 +++++++++++++++-
5 files changed, 230 insertions(+), 239 deletions(-)
diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindDeclarationVisitor.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindDeclarationVisitor.cs
index 18aafef21..71fd99905 100644
--- a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindDeclarationVisitor.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindDeclarationVisitor.cs
@@ -3,6 +3,7 @@
using System;
using System.Management.Automation.Language;
+using Microsoft.PowerShell.EditorServices.Utility;
namespace Microsoft.PowerShell.EditorServices.Services.Symbols
{
@@ -43,27 +44,15 @@ public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst fun
return AstVisitAction.Continue;
}
- // Get the start column number of the function name,
- // instead of the the start column of 'function' and create new extent for the functionName
- int startColumnNumber =
- functionDefinitionAst.Extent.Text.IndexOf(
- functionDefinitionAst.Name, StringComparison.OrdinalIgnoreCase) + 1;
-
- IScriptExtent nameExtent = new ScriptExtent()
- {
- Text = functionDefinitionAst.Name,
- StartLineNumber = functionDefinitionAst.Extent.StartLineNumber,
- StartColumnNumber = startColumnNumber,
- EndLineNumber = functionDefinitionAst.Extent.StartLineNumber,
- EndColumnNumber = startColumnNumber + functionDefinitionAst.Name.Length,
- File = functionDefinitionAst.Extent.File
- };
-
// We compare to the SymbolName instead of its text because it may have been resolved
// from an alias.
if (symbolRef.SymbolType.Equals(SymbolType.Function) &&
- nameExtent.Text.Equals(symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
+ functionDefinitionAst.Name.Equals(symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
{
+ // Get the start column number of the function name,
+ // instead of the the start column of 'function' and create new extent for the functionName
+ IScriptExtent nameExtent = VisitorUtils.GetNameExtent(functionDefinitionAst);
+
FoundDeclaration =
new SymbolReference(
SymbolType.Function,
@@ -92,20 +81,8 @@ public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinit
if ((symbolRef.SymbolType is SymbolType.Type || symbolRef.SymbolType.Equals(symbolType)) &&
typeDefinitionAst.Name.Equals(symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
{
- // Show only type name. Offset by StartColumn to include indentation etc.
- int startColumnNumber =
- typeDefinitionAst.Extent.StartColumnNumber +
- typeDefinitionAst.Extent.Text.IndexOf(typeDefinitionAst.Name);
-
- IScriptExtent nameExtent = new ScriptExtent()
- {
- Text = typeDefinitionAst.Name,
- StartLineNumber = typeDefinitionAst.Extent.StartLineNumber,
- EndLineNumber = typeDefinitionAst.Extent.StartLineNumber,
- StartColumnNumber = startColumnNumber,
- EndColumnNumber = startColumnNumber + typeDefinitionAst.Name.Length,
- File = typeDefinitionAst.Extent.File
- };
+ // We only want the type name. Get start-location for name
+ IScriptExtent nameExtent = VisitorUtils.GetNameExtent(typeDefinitionAst);
FoundDeclaration =
new SymbolReference(
@@ -135,20 +112,8 @@ public override AstVisitAction VisitFunctionMember(FunctionMemberAst functionMem
if (symbolRef.SymbolType.Equals(symbolType) &&
functionMemberAst.Name.Equals(symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
{
- // Show only method/ctor name. Offset by StartColumn to include indentation etc.
- int startColumnNumber =
- functionMemberAst.Extent.StartColumnNumber +
- functionMemberAst.Extent.Text.IndexOf(functionMemberAst.Name);
-
- IScriptExtent nameExtent = new ScriptExtent()
- {
- Text = functionMemberAst.Name,
- StartLineNumber = functionMemberAst.Extent.StartLineNumber,
- EndLineNumber = functionMemberAst.Extent.StartLineNumber,
- StartColumnNumber = startColumnNumber,
- EndColumnNumber = startColumnNumber + functionMemberAst.Name.Length,
- File = functionMemberAst.Extent.File
- };
+ // We only want the method/ctor name. Get start-location for name
+ IScriptExtent nameExtent = VisitorUtils.GetNameExtent(functionMemberAst);
FoundDeclaration =
new SymbolReference(
@@ -174,10 +139,13 @@ public override AstVisitAction VisitPropertyMember(PropertyMemberAst propertyMem
if (symbolRef.SymbolType.Equals(SymbolType.Property) &&
propertyMemberAst.Name.Equals(symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
{
+ // We only want the property name. Get start-location for name
+ IScriptExtent nameExtent = VisitorUtils.GetNameExtent(propertyMemberAst);
+
FoundDeclaration =
new SymbolReference(
SymbolType.Property,
- propertyMemberAst.Extent);
+ nameExtent);
return AstVisitAction.StopVisit;
}
diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs
index 858ee8479..81fca6331 100644
--- a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Microsoft Corporation.
+// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System;
@@ -113,7 +113,7 @@ public override AstVisitAction VisitCommand(CommandAst commandAst)
/// Decides if the current function definition is a reference of the symbol being searched for.
/// A reference of the symbol will be a of type SymbolType.Function and have the same name as the symbol
///
- /// A functionDefinitionAst in the script's AST
+ /// A FunctionDefinitionAst in the script's AST
/// A visit action that continues the search for references
public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst)
{
@@ -124,31 +124,21 @@ public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst fun
return AstVisitAction.Continue;
}
- (int startColumnNumber, int startLineNumber) = VisitorUtils.GetNameStartColumnAndLineNumbersFromAst(functionDefinitionAst);
-
- IScriptExtent nameExtent = new ScriptExtent()
- {
- Text = functionDefinitionAst.Name,
- StartLineNumber = startLineNumber,
- EndLineNumber = startLineNumber,
- StartColumnNumber = startColumnNumber,
- EndColumnNumber = startColumnNumber + functionDefinitionAst.Name.Length,
- File = functionDefinitionAst.Extent.File
- };
-
if (_symbolRef.SymbolType.Equals(SymbolType.Function) &&
- nameExtent.Text.Equals(_symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
+ functionDefinitionAst.Name.Equals(_symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
{
+ // We only want the function name
+ IScriptExtent nameExtent = VisitorUtils.GetNameExtent(functionDefinitionAst);
FoundReferences.Add(new SymbolReference(SymbolType.Function, nameExtent));
}
return base.VisitFunctionDefinition(functionDefinitionAst);
}
///
- /// Decides if the current function definition is a reference of the symbol being searched for.
+ /// Decides if the current command parameter is a reference of the symbol being searched for.
/// A reference of the symbol will be a of type SymbolType.Parameter and have the same name as the symbol
///
- /// A commandParameterAst in the script's AST
+ /// A CommandParameterAst in the script's AST
/// A visit action that continues the search for references
public override AstVisitAction VisitCommandParameter(CommandParameterAst commandParameterAst)
{
@@ -161,10 +151,10 @@ public override AstVisitAction VisitCommandParameter(CommandParameterAst command
}
///
- /// Decides if the current function definition is a reference of the symbol being searched for.
+ /// Decides if the current variable expression is a reference of the symbol being searched for.
/// A reference of the symbol will be a of type SymbolType.Variable and have the same name as the symbol
///
- /// A variableExpressionAst in the script's AST
+ /// A VariableExpressionAst in the script's AST
/// A visit action that continues the search for references
public override AstVisitAction VisitVariableExpression(VariableExpressionAst variableExpressionAst)
{
@@ -191,21 +181,8 @@ public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinit
if ((_symbolRef.SymbolType is SymbolType.Type || _symbolRef.SymbolType.Equals(symbolType)) &&
typeDefinitionAst.Name.Equals(_symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
{
- // Show only type name. Offset by StartColumn to include indentation etc.
- int startColumnNumber =
- typeDefinitionAst.Extent.StartColumnNumber +
- typeDefinitionAst.Extent.Text.IndexOf(typeDefinitionAst.Name);
-
- IScriptExtent nameExtent = new ScriptExtent()
- {
- Text = typeDefinitionAst.Name,
- StartLineNumber = typeDefinitionAst.Extent.StartLineNumber,
- EndLineNumber = typeDefinitionAst.Extent.StartLineNumber,
- StartColumnNumber = startColumnNumber,
- EndColumnNumber = startColumnNumber + typeDefinitionAst.Name.Length,
- File = typeDefinitionAst.Extent.File
- };
-
+ // We only want the type name. Get start-location for name
+ IScriptExtent nameExtent = VisitorUtils.GetNameExtent(typeDefinitionAst);
FoundReferences.Add(new SymbolReference(symbolType, nameExtent));
}
return AstVisitAction.Continue;
@@ -260,21 +237,8 @@ public override AstVisitAction VisitFunctionMember(FunctionMemberAst functionMem
if (_symbolRef.SymbolType.Equals(symbolType) &&
functionMemberAst.Name.Equals(_symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
{
- // Show only method/ctor name. Offset by StartColumn to include indentation etc.
- int startColumnNumber =
- functionMemberAst.Extent.StartColumnNumber +
- functionMemberAst.Extent.Text.IndexOf(functionMemberAst.Name);
-
- IScriptExtent nameExtent = new ScriptExtent()
- {
- Text = functionMemberAst.Name,
- StartLineNumber = functionMemberAst.Extent.StartLineNumber,
- EndLineNumber = functionMemberAst.Extent.StartLineNumber,
- StartColumnNumber = startColumnNumber,
- EndColumnNumber = startColumnNumber + functionMemberAst.Name.Length,
- File = functionMemberAst.Extent.File
- };
-
+ // We only want the method/ctor name. Get start-location for name
+ IScriptExtent nameExtent = VisitorUtils.GetNameExtent(functionMemberAst);
FoundReferences.Add(new SymbolReference(symbolType, nameExtent));
}
return AstVisitAction.Continue;
@@ -291,7 +255,9 @@ public override AstVisitAction VisitPropertyMember(PropertyMemberAst propertyMem
if (_symbolRef.SymbolType.Equals(SymbolType.Property) &&
propertyMemberAst.Name.Equals(_symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
{
- FoundReferences.Add(new SymbolReference(SymbolType.Property, propertyMemberAst.Extent));
+ // We only want the property name. Get start-location for name
+ IScriptExtent nameExtent = VisitorUtils.GetNameExtent(propertyMemberAst);
+ FoundReferences.Add(new SymbolReference(SymbolType.Property, nameExtent));
}
return AstVisitAction.Continue;
}
diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolVisitor.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolVisitor.cs
index 71a773c0e..697a92041 100644
--- a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolVisitor.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolVisitor.cs
@@ -65,30 +65,25 @@ public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst fun
return AstVisitAction.Continue;
}
- int startLineNumber = functionDefinitionAst.Extent.StartLineNumber;
- int startColumnNumber = functionDefinitionAst.Extent.StartColumnNumber;
- int endLineNumber = functionDefinitionAst.Extent.EndLineNumber;
- int endColumnNumber = functionDefinitionAst.Extent.EndColumnNumber;
+ IScriptExtent nameExtent;
- if (!includeDefinitions)
+ if (includeDefinitions)
{
- // We only want the function name
- (int startColumn, int startLine) = VisitorUtils.GetNameStartColumnAndLineNumbersFromAst(functionDefinitionAst);
- startLineNumber = startLine;
- startColumnNumber = startColumn;
- endLineNumber = startLine;
- endColumnNumber = startColumn + functionDefinitionAst.Name.Length;
+ nameExtent = new ScriptExtent()
+ {
+ Text = functionDefinitionAst.Name,
+ StartLineNumber = functionDefinitionAst.Extent.StartLineNumber,
+ EndLineNumber = functionDefinitionAst.Extent.EndLineNumber,
+ StartColumnNumber = functionDefinitionAst.Extent.StartColumnNumber,
+ EndColumnNumber = functionDefinitionAst.Extent.EndColumnNumber,
+ File = functionDefinitionAst.Extent.File
+ };
}
-
- IScriptExtent nameExtent = new ScriptExtent()
+ else
{
- Text = functionDefinitionAst.Name,
- StartLineNumber = startLineNumber,
- EndLineNumber = endLineNumber,
- StartColumnNumber = startColumnNumber,
- EndColumnNumber = endColumnNumber,
- File = functionDefinitionAst.Extent.File
- };
+ // We only want the function name
+ nameExtent = VisitorUtils.GetNameExtent(functionDefinitionAst);
+ }
if (IsPositionInExtent(nameExtent))
{
@@ -163,20 +158,8 @@ private bool IsPositionInExtent(IScriptExtent extent)
/// or a decision to continue if it wasn't found
public override AstVisitAction VisitFunctionMember(FunctionMemberAst functionMemberAst)
{
- // Show only method/ctor name. Offset by StartColumn to include indentation etc.
- int startColumnNumber =
- functionMemberAst.Extent.StartColumnNumber +
- functionMemberAst.Extent.Text.IndexOf(functionMemberAst.Name);
-
- IScriptExtent nameExtent = new ScriptExtent()
- {
- Text = functionMemberAst.Name,
- StartLineNumber = functionMemberAst.Extent.StartLineNumber,
- EndLineNumber = functionMemberAst.Extent.StartLineNumber,
- StartColumnNumber = startColumnNumber,
- EndColumnNumber = startColumnNumber + functionMemberAst.Name.Length,
- File = functionMemberAst.Extent.File
- };
+ // We only want the method/ctor name. Get start-location for name
+ IScriptExtent nameExtent = VisitorUtils.GetNameExtent(functionMemberAst);
if (IsPositionInExtent(nameExtent))
{
@@ -203,31 +186,25 @@ public override AstVisitAction VisitFunctionMember(FunctionMemberAst functionMem
/// or a decision to continue if it wasn't found
public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst)
{
- int startLineNumber = typeDefinitionAst.Extent.StartLineNumber;
- int startColumnNumber = typeDefinitionAst.Extent.StartColumnNumber;
- int endLineNumber = typeDefinitionAst.Extent.EndLineNumber;
- int endColumnNumber = typeDefinitionAst.Extent.EndColumnNumber;
+ IScriptExtent nameExtent;
- if (!includeDefinitions)
+ if (includeDefinitions)
{
- // We only want the function name
- startColumnNumber =
- typeDefinitionAst.Extent.StartColumnNumber +
- typeDefinitionAst.Extent.Text.IndexOf(typeDefinitionAst.Name);
- startLineNumber = typeDefinitionAst.Extent.StartLineNumber;
- endColumnNumber = startColumnNumber + typeDefinitionAst.Name.Length;
- endLineNumber = typeDefinitionAst.Extent.StartLineNumber;
+ nameExtent = new ScriptExtent()
+ {
+ Text = typeDefinitionAst.Name,
+ StartLineNumber = typeDefinitionAst.Extent.StartLineNumber,
+ EndLineNumber = typeDefinitionAst.Extent.EndLineNumber,
+ StartColumnNumber = typeDefinitionAst.Extent.StartColumnNumber,
+ EndColumnNumber = typeDefinitionAst.Extent.EndColumnNumber,
+ File = typeDefinitionAst.Extent.File
+ };
}
-
- IScriptExtent nameExtent = new ScriptExtent()
+ else
{
- Text = typeDefinitionAst.Name,
- StartLineNumber = startLineNumber,
- EndLineNumber = endLineNumber,
- StartColumnNumber = startColumnNumber,
- EndColumnNumber = endColumnNumber,
- File = typeDefinitionAst.Extent.File
- };
+ // We only want the type name
+ nameExtent = VisitorUtils.GetNameExtent(typeDefinitionAst);
+ }
if (IsPositionInExtent(nameExtent))
{
@@ -254,10 +231,8 @@ public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinit
/// or a decision to continue if it wasn't found
public override AstVisitAction VisitTypeExpression(TypeExpressionAst typeExpressionAst)
{
- // Show only type name. Offset by StartColumn to include indentation etc.
- int startColumnNumber =
- typeExpressionAst.Extent.StartColumnNumber +
- typeExpressionAst.Extent.Text.IndexOf(typeExpressionAst.TypeName.Name);
+ // Show only type name (skip leading '['). Offset by StartColumn to include indentation etc.
+ int startColumnNumber = typeExpressionAst.Extent.StartColumnNumber + 1;
IScriptExtent nameExtent = new ScriptExtent()
{
@@ -288,10 +263,8 @@ public override AstVisitAction VisitTypeExpression(TypeExpressionAst typeExpress
/// or a decision to continue if it wasn't found
public override AstVisitAction VisitTypeConstraint(TypeConstraintAst typeConstraintAst)
{
- // Show only type name. Offset by StartColumn to include indentation etc.
- int startColumnNumber =
- typeConstraintAst.Extent.StartColumnNumber +
- typeConstraintAst.Extent.Text.IndexOf(typeConstraintAst.TypeName.Name);
+ // Show only type name (skip leading '['). Offset by StartColumn to include indentation etc.
+ int startColumnNumber = typeConstraintAst.Extent.StartColumnNumber + 1;
IScriptExtent nameExtent = new ScriptExtent()
{
@@ -322,22 +295,8 @@ public override AstVisitAction VisitTypeConstraint(TypeConstraintAst typeConstra
/// or a decision to continue if it wasn't found
public override AstVisitAction VisitConfigurationDefinition(ConfigurationDefinitionAst configurationDefinitionAst)
{
- string configurationName = configurationDefinitionAst.InstanceName.Extent.Text;
-
- // Show only configuration name. Offset by StartColumn to include indentation etc.
- int startColumnNumber =
- configurationDefinitionAst.Extent.StartColumnNumber +
- configurationDefinitionAst.Extent.Text.IndexOf(configurationName);
-
- IScriptExtent nameExtent = new ScriptExtent()
- {
- Text = configurationName,
- StartLineNumber = configurationDefinitionAst.Extent.StartLineNumber,
- EndLineNumber = configurationDefinitionAst.Extent.StartLineNumber,
- StartColumnNumber = startColumnNumber,
- EndColumnNumber = startColumnNumber + configurationName.Length,
- File = configurationDefinitionAst.Extent.File
- };
+ // We only want the configuration name. Get start-location for name
+ IScriptExtent nameExtent = VisitorUtils.GetNameExtent(configurationDefinitionAst);
if (IsPositionInExtent(nameExtent))
{
@@ -353,19 +312,22 @@ public override AstVisitAction VisitConfigurationDefinition(ConfigurationDefinit
}
///
- /// Checks to see if this variable expression is the symbol we are looking for.
+ /// Checks to see if this property member is the symbol we are looking for.
///
- /// A VariableExpressionAst object in the script's AST
+ /// A PropertyMemberAst object in the script's AST
/// A decision to stop searching if the right symbol was found,
/// or a decision to continue if it wasn't found
public override AstVisitAction VisitPropertyMember(PropertyMemberAst propertyMemberAst)
{
- if (IsPositionInExtent(propertyMemberAst.Extent))
+ // We only want the property name. Get start-location for name
+ IScriptExtent nameExtent = VisitorUtils.GetNameExtent(propertyMemberAst);
+
+ if (IsPositionInExtent(nameExtent))
{
FoundSymbolReference =
new SymbolReference(
SymbolType.Property,
- propertyMemberAst.Extent);
+ nameExtent);
return AstVisitAction.StopVisit;
}
diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolsVisitor.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolsVisitor.cs
index d7fe87db1..b66b6f265 100644
--- a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolsVisitor.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolsVisitor.cs
@@ -16,11 +16,10 @@ internal class FindSymbolsVisitor : AstVisitor2
public FindSymbolsVisitor() => SymbolReferences = new List();
///
- /// Adds each function definition as a
+ /// Adds each function definition to symbol reference list
///
- /// A functionDefinitionAst object in the script's AST
- /// A decision to stop searching if the right symbol was found,
- /// or a decision to continue if it wasn't found
+ /// A FunctionDefinitionAst in the script's AST
+ /// A visit action that continues the search for references
public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst)
{
// Extent for constructors and method trigger both this and VisitFunctionMember(). Covered in the latter.
@@ -30,15 +29,7 @@ public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst fun
return AstVisitAction.Continue;
}
- IScriptExtent nameExtent = new ScriptExtent()
- {
- Text = functionDefinitionAst.Name,
- StartLineNumber = functionDefinitionAst.Extent.StartLineNumber,
- EndLineNumber = functionDefinitionAst.Extent.EndLineNumber,
- StartColumnNumber = functionDefinitionAst.Extent.StartColumnNumber,
- EndColumnNumber = functionDefinitionAst.Extent.EndColumnNumber,
- File = functionDefinitionAst.Extent.File
- };
+ IScriptExtent nameExtent = GetNewExtent(functionDefinitionAst, functionDefinitionAst.Name);
SymbolType symbolType =
functionDefinitionAst.IsWorkflow ?
@@ -53,11 +44,10 @@ public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst fun
}
///
- /// Checks to see if this variable expression is the symbol we are looking for.
+ /// Adds each script scoped variable assignment to symbol reference list
///
- /// A VariableExpressionAst object in the script's AST
- /// A decision to stop searching if the right symbol was found,
- /// or a decision to continue if it wasn't found
+ /// A VariableExpressionAst in the script's AST
+ /// A visit action that continues the search for references
public override AstVisitAction VisitVariableExpression(VariableExpressionAst variableExpressionAst)
{
if (!IsAssignedAtScriptScope(variableExpressionAst))
@@ -86,19 +76,13 @@ private static bool IsAssignedAtScriptScope(VariableExpressionAst variableExpres
}
///
- /// Adds class and AST to symbol reference list
+ /// Adds class and enum AST to symbol reference list
///
+ /// A TypeDefinitionAst in the script's AST
+ /// A visit action that continues the search for references
public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst)
{
- IScriptExtent nameExtent = new ScriptExtent()
- {
- Text = typeDefinitionAst.Name,
- StartLineNumber = typeDefinitionAst.Extent.StartLineNumber,
- EndLineNumber = typeDefinitionAst.Extent.EndLineNumber,
- StartColumnNumber = typeDefinitionAst.Extent.StartColumnNumber,
- EndColumnNumber = typeDefinitionAst.Extent.EndColumnNumber,
- File = typeDefinitionAst.Extent.File
- };
+ IScriptExtent nameExtent = GetNewExtent(typeDefinitionAst, typeDefinitionAst.Name);
SymbolType symbolType =
typeDefinitionAst.IsEnum ?
@@ -115,17 +99,11 @@ public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinit
///
/// Adds class method and constructor AST to symbol reference list
///
+ /// A FunctionMemberAst in the script's AST
+ /// A visit action that continues the search for references
public override AstVisitAction VisitFunctionMember(FunctionMemberAst functionMemberAst)
{
- IScriptExtent nameExtent = new ScriptExtent()
- {
- Text = GetMethodOverloadName(functionMemberAst),
- StartLineNumber = functionMemberAst.Extent.StartLineNumber,
- EndLineNumber = functionMemberAst.Extent.EndLineNumber,
- StartColumnNumber = functionMemberAst.Extent.StartColumnNumber,
- EndColumnNumber = functionMemberAst.Extent.EndColumnNumber,
- File = functionMemberAst.Extent.File
- };
+ IScriptExtent nameExtent = GetNewExtent(functionMemberAst, GetMethodOverloadName(functionMemberAst));
SymbolType symbolType =
functionMemberAst.IsConstructor ?
@@ -144,7 +122,8 @@ public override AstVisitAction VisitFunctionMember(FunctionMemberAst functionMem
///
/// A FunctionMemberAst object in the script's AST
/// Function member name with parameter types and names
- private static string GetMethodOverloadName(FunctionMemberAst functionMemberAst) {
+ private static string GetMethodOverloadName(FunctionMemberAst functionMemberAst)
+ {
if (functionMemberAst.Parameters.Count > 0)
{
List parameters = new(functionMemberAst.Parameters.Count);
@@ -165,17 +144,11 @@ private static string GetMethodOverloadName(FunctionMemberAst functionMemberAst)
///
/// Adds class property AST to symbol reference list
///
+ /// A PropertyMemberAst in the script's AST
+ /// A visit action that continues the search for references
public override AstVisitAction VisitPropertyMember(PropertyMemberAst propertyMemberAst)
{
- IScriptExtent nameExtent = new ScriptExtent()
- {
- Text = propertyMemberAst.Name,
- StartLineNumber = propertyMemberAst.Extent.StartLineNumber,
- EndLineNumber = propertyMemberAst.Extent.EndLineNumber,
- StartColumnNumber = propertyMemberAst.Extent.StartColumnNumber,
- EndColumnNumber = propertyMemberAst.Extent.EndColumnNumber,
- File = propertyMemberAst.Extent.File
- };
+ IScriptExtent nameExtent = GetNewExtent(propertyMemberAst, propertyMemberAst.Name);
SymbolReferences.Add(
new SymbolReference(
@@ -188,17 +161,11 @@ public override AstVisitAction VisitPropertyMember(PropertyMemberAst propertyMem
///
/// Adds DSC configuration AST to symbol reference list
///
+ /// A ConfigurationDefinitionAst in the script's AST
+ /// A visit action that continues the search for references
public override AstVisitAction VisitConfigurationDefinition(ConfigurationDefinitionAst configurationDefinitionAst)
{
- IScriptExtent nameExtent = new ScriptExtent()
- {
- Text = configurationDefinitionAst.InstanceName.Extent.Text,
- StartLineNumber = configurationDefinitionAst.Extent.StartLineNumber,
- EndLineNumber = configurationDefinitionAst.Extent.EndLineNumber,
- StartColumnNumber = configurationDefinitionAst.Extent.StartColumnNumber,
- EndColumnNumber = configurationDefinitionAst.Extent.EndColumnNumber,
- File = configurationDefinitionAst.Extent.File
- };
+ IScriptExtent nameExtent = GetNewExtent(configurationDefinitionAst, configurationDefinitionAst.InstanceName.Extent.Text);
SymbolReferences.Add(
new SymbolReference(
@@ -207,6 +174,22 @@ public override AstVisitAction VisitConfigurationDefinition(ConfigurationDefinit
return AstVisitAction.Continue;
}
+
+ ///
+ /// Gets a new ScriptExtent for a given Ast with same range but modified Text
+ ///
+ private static ScriptExtent GetNewExtent(Ast ast, string text)
+ {
+ return new ScriptExtent()
+ {
+ Text = text,
+ StartLineNumber = ast.Extent.StartLineNumber,
+ EndLineNumber = ast.Extent.EndLineNumber,
+ StartColumnNumber = ast.Extent.StartColumnNumber,
+ EndColumnNumber = ast.Extent.EndColumnNumber,
+ File = ast.Extent.File
+ };
+ }
}
///
@@ -227,6 +210,8 @@ internal class FindHashtableSymbolsVisitor : AstVisitor
///
/// Adds keys in the input hashtable to the symbol reference
///
+ /// A HashtableAst in the script's AST
+ /// A visit action that continues the search for references
public override AstVisitAction VisitHashtable(HashtableAst hashtableAst)
{
if (hashtableAst.KeyValuePairs == null)
diff --git a/src/PowerShellEditorServices/Utility/VisitorUtils.cs b/src/PowerShellEditorServices/Utility/VisitorUtils.cs
index 861d04acc..3456c1920 100644
--- a/src/PowerShellEditorServices/Utility/VisitorUtils.cs
+++ b/src/PowerShellEditorServices/Utility/VisitorUtils.cs
@@ -2,6 +2,7 @@
// Licensed under the MIT License.
using System.Management.Automation.Language;
+using PSESSymbols = Microsoft.PowerShell.EditorServices.Services.Symbols;
namespace Microsoft.PowerShell.EditorServices.Utility
{
@@ -11,15 +12,16 @@ namespace Microsoft.PowerShell.EditorServices.Utility
internal static class VisitorUtils
{
///
- /// Calculates the start line and column of the actual function name in a function definition AST.
+ /// Calculates the start line and column of the actual symbol name in a AST.
///
- /// A FunctionDefinitionAst object in the script's AST
- /// A tuple with start column and line for the function name
- internal static (int startColumn, int startLine) GetNameStartColumnAndLineNumbersFromAst(FunctionDefinitionAst ast)
+ /// An Ast object in the script's AST
+ /// An offset specifying where to begin searching in the first line of the AST's extent text
+ /// A tuple with start column and line of the symbol name
+ private static (int startColumn, int startLine) GetNameStartColumnAndLineNumbersFromAst(Ast ast, int firstLineColumnOffset)
{
int startColumnNumber = ast.Extent.StartColumnNumber;
int startLineNumber = ast.Extent.StartLineNumber;
- int astOffset = ast.IsFilter ? "filter".Length : ast.IsWorkflow ? "workflow".Length : "function".Length;
+ int astOffset = firstLineColumnOffset;
string astText = ast.Extent.Text;
// The line offset represents the offset on the line that we're on where as
// astOffset is the offset on the entire text of the AST.
@@ -47,5 +49,113 @@ internal static (int startColumn, int startLine) GetNameStartColumnAndLineNumber
return (startColumnNumber + lineOffset, startLineNumber);
}
+
+ ///
+ /// Gets a new ScriptExtent for a given Ast for the symbol name only (variable)
+ ///
+ /// A FunctionDefinitionAst in the script's AST
+ /// A ScriptExtent with for the symbol name only
+ internal static PSESSymbols.ScriptExtent GetNameExtent(FunctionDefinitionAst functionDefinitionAst)
+ {
+ int astOffset = functionDefinitionAst.IsFilter ? "filter".Length : functionDefinitionAst.IsWorkflow ? "workflow".Length : "function".Length;
+ (int startColumn, int startLine) = GetNameStartColumnAndLineNumbersFromAst(functionDefinitionAst, astOffset);
+
+ return new PSESSymbols.ScriptExtent()
+ {
+ Text = functionDefinitionAst.Name,
+ StartLineNumber = startLine,
+ EndLineNumber = startLine,
+ StartColumnNumber = startColumn,
+ EndColumnNumber = startColumn + functionDefinitionAst.Name.Length,
+ File = functionDefinitionAst.Extent.File
+ };
+ }
+
+ ///
+ /// Gets a new ScriptExtent for a given Ast for the symbol name only (variable)
+ ///
+ /// A TypeDefinitionAst in the script's AST
+ /// A ScriptExtent with for the symbol name only
+ internal static PSESSymbols.ScriptExtent GetNameExtent(TypeDefinitionAst typeDefinitionAst)
+ {
+ int astOffset = typeDefinitionAst.IsEnum ? "enum".Length : "class".Length;
+ (int startColumn, int startLine) = GetNameStartColumnAndLineNumbersFromAst(typeDefinitionAst, astOffset);
+
+ return new PSESSymbols.ScriptExtent()
+ {
+ Text = typeDefinitionAst.Name,
+ StartLineNumber = startLine,
+ EndLineNumber = startLine,
+ StartColumnNumber = startColumn,
+ EndColumnNumber = startColumn + typeDefinitionAst.Name.Length,
+ File = typeDefinitionAst.Extent.File
+ };
+ }
+
+ ///
+ /// Gets a new ScriptExtent for a given Ast for the symbol name only (variable)
+ ///
+ /// A FunctionMemberAst in the script's AST
+ /// A ScriptExtent with for the symbol name only
+ internal static PSESSymbols.ScriptExtent GetNameExtent(FunctionMemberAst functionMemberAst)
+ {
+ // offset by [type] if return type is specified
+ int astOffset = functionMemberAst.ReturnType?.Extent.Text.Length ?? 0;
+ (int startColumn, int startLine) = GetNameStartColumnAndLineNumbersFromAst(functionMemberAst, astOffset);
+
+ return new PSESSymbols.ScriptExtent()
+ {
+ Text = functionMemberAst.Name,
+ StartLineNumber = startLine,
+ EndLineNumber = startLine,
+ StartColumnNumber = startColumn,
+ EndColumnNumber = startColumn + functionMemberAst.Name.Length,
+ File = functionMemberAst.Extent.File
+ };
+ }
+
+ ///
+ /// Gets a new ScriptExtent for a given Ast for the property name only
+ ///
+ /// A PropertyMemberAst in the script's AST
+ /// A ScriptExtent with for the symbol name only
+ internal static PSESSymbols.ScriptExtent GetNameExtent(PropertyMemberAst propertyMemberAst)
+ {
+ // offset by [type] if type is specified
+ int astOffset = propertyMemberAst.PropertyType?.Extent.Text.Length ?? 0;
+ (int startColumn, int startLine) = GetNameStartColumnAndLineNumbersFromAst(propertyMemberAst, astOffset);
+
+ return new PSESSymbols.ScriptExtent()
+ {
+ Text = propertyMemberAst.Name,
+ StartLineNumber = startLine,
+ EndLineNumber = startLine,
+ StartColumnNumber = startColumn,
+ EndColumnNumber = startColumn + propertyMemberAst.Name.Length + 1,
+ File = propertyMemberAst.Extent.File
+ };
+ }
+
+ ///
+ /// Gets a new ScriptExtent for a given Ast for the configuration instance name only
+ ///
+ /// A ConfigurationDefinitionAst in the script's AST
+ /// A ScriptExtent with for the symbol name only
+ internal static PSESSymbols.ScriptExtent GetNameExtent(ConfigurationDefinitionAst configurationDefinitionAst)
+ {
+ string configurationName = configurationDefinitionAst.InstanceName.Extent.Text;
+ const int astOffset = 13; // "configuration".Length
+ (int startColumn, int startLine) = GetNameStartColumnAndLineNumbersFromAst(configurationDefinitionAst, astOffset);
+
+ return new PSESSymbols.ScriptExtent()
+ {
+ Text = configurationName,
+ StartLineNumber = startLine,
+ EndLineNumber = startLine,
+ StartColumnNumber = startColumn,
+ EndColumnNumber = startColumn + configurationName.Length,
+ File = configurationDefinitionAst.Extent.File
+ };
+ }
}
}
From f587eededad7b709d15141aca3f0be7ec4b78473 Mon Sep 17 00:00:00 2001
From: Frode Flaten <3436158+fflaten@users.noreply.github.com>
Date: Sat, 20 Aug 2022 02:50:17 +0000
Subject: [PATCH 11/18] fix Contains extension method for same line extent
---
.../Services/Symbols/Vistors/FindSymbolVisitor.cs | 10 ++++++----
src/PowerShellEditorServices/Utility/Extensions.cs | 9 ++++++++-
2 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolVisitor.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolVisitor.cs
index 697a92041..8269eb2d9 100644
--- a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolVisitor.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolVisitor.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Microsoft Corporation.
+// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System.Management.Automation.Language;
@@ -85,7 +85,7 @@ public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst fun
nameExtent = VisitorUtils.GetNameExtent(functionDefinitionAst);
}
- if (IsPositionInExtent(nameExtent))
+ if (nameExtent.Contains(lineNumber, columnNumber))
{
FoundSymbolReference =
new SymbolReference(
@@ -139,7 +139,9 @@ public override AstVisitAction VisitVariableExpression(VariableExpressionAst var
}
///
- /// Is the position of the given location is in the ast's extent
+ /// Is the position of the given location is in the ast's extent.
+ /// Only works with single-line extents like name extents.
+ /// Use extension for definition extents.
///
/// The script extent of the element
/// True if the given position is in the range of the element's extent
@@ -206,7 +208,7 @@ public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinit
nameExtent = VisitorUtils.GetNameExtent(typeDefinitionAst);
}
- if (IsPositionInExtent(nameExtent))
+ if (nameExtent.Contains(lineNumber, columnNumber))
{
SymbolType symbolType =
typeDefinitionAst.IsEnum ?
diff --git a/src/PowerShellEditorServices/Utility/Extensions.cs b/src/PowerShellEditorServices/Utility/Extensions.cs
index c280f1b14..22148e8b3 100644
--- a/src/PowerShellEditorServices/Utility/Extensions.cs
+++ b/src/PowerShellEditorServices/Utility/Extensions.cs
@@ -135,7 +135,14 @@ public static bool Contains(this IScriptExtent scriptExtent, int line, int colum
if (scriptExtent.StartLineNumber == line)
{
- return scriptExtent.StartColumnNumber <= column;
+ if (scriptExtent.StartLineNumber == scriptExtent.EndLineNumber)
+ {
+ return scriptExtent.StartColumnNumber <= column && scriptExtent.EndColumnNumber >= column;
+ }
+ else
+ {
+ return scriptExtent.StartColumnNumber <= column;
+ }
}
if (scriptExtent.EndLineNumber == line)
From 301258672cedc4fa751799a35e09f8b955b28370 Mon Sep 17 00:00:00 2001
From: Frode Flaten <3436158+fflaten@users.noreply.github.com>
Date: Sat, 20 Aug 2022 02:54:35 +0000
Subject: [PATCH 12/18] add EnumMember, signature and fix detection
---
.../Services/Symbols/SymbolDetails.cs | 11 +-
.../Services/Symbols/SymbolType.cs | 5 +
.../Services/Symbols/SymbolsService.cs | 3 +-
.../Services/Symbols/Vistors/AstOperations.cs | 7 +-
.../Symbols/Vistors/FindDeclarationVisitor.cs | 12 +-
.../Symbols/Vistors/FindReferencesVisitor.cs | 13 +-
.../Symbols/Vistors/FindSymbolVisitor.cs | 24 ++-
.../Symbols/Vistors/FindSymbolsVisitor.cs | 53 ++----
.../Handlers/DocumentSymbolHandler.cs | 1 +
.../Utility/VisitorUtils.cs | 179 +++++++++++++++---
10 files changed, 222 insertions(+), 86 deletions(-)
diff --git a/src/PowerShellEditorServices/Services/Symbols/SymbolDetails.cs b/src/PowerShellEditorServices/Services/Symbols/SymbolDetails.cs
index fc85acd30..84d0cef29 100644
--- a/src/PowerShellEditorServices/Services/Symbols/SymbolDetails.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/SymbolDetails.cs
@@ -95,17 +95,10 @@ await CommandHelpers.GetCommandSynopsisAsync(
return symbolDetails;
case SymbolType.Constructor:
- // TODO: constructor Class(parameters)
- symbolDetails.DisplayString = "constructor " + symbolReference.SymbolName;
- return symbolDetails;
-
case SymbolType.Method:
- // TODO: method ReturnType Class.MethodName(parameters)
- symbolDetails.DisplayString = "method " + symbolReference.SymbolName;
- return symbolDetails;
-
+ case SymbolType.EnumMember:
case SymbolType.Property:
- symbolDetails.DisplayString = "(property) " + symbolReference.SymbolName;
+ symbolDetails.DisplayString = symbolReference.SymbolName;
return symbolDetails;
case SymbolType.Configuration:
diff --git a/src/PowerShellEditorServices/Services/Symbols/SymbolType.cs b/src/PowerShellEditorServices/Services/Symbols/SymbolType.cs
index 84756661c..7f5850f45 100644
--- a/src/PowerShellEditorServices/Services/Symbols/SymbolType.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/SymbolType.cs
@@ -53,6 +53,11 @@ internal enum SymbolType
///
Enum,
+ ///
+ /// The symbol is a enum member/value
+ ///
+ EnumMember,
+
///
/// The symbol is a class property
///
diff --git a/src/PowerShellEditorServices/Services/Symbols/SymbolsService.cs b/src/PowerShellEditorServices/Services/Symbols/SymbolsService.cs
index 336495bd8..2e22ac1dc 100644
--- a/src/PowerShellEditorServices/Services/Symbols/SymbolsService.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/SymbolsService.cs
@@ -332,7 +332,8 @@ public Task FindSymbolDetailsAtLocationAsync(
AstOperations.FindSymbolAtPosition(
scriptFile.ScriptAst,
lineNumber,
- columnNumber);
+ columnNumber,
+ returnMemberSignature: true);
if (symbolReference == null)
{
diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/AstOperations.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/AstOperations.cs
index 6fcbd62c9..623fc02ba 100644
--- a/src/PowerShellEditorServices/Services/Symbols/Vistors/AstOperations.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/AstOperations.cs
@@ -148,18 +148,21 @@ await executionService.ExecuteDelegateAsync(
/// The line number of the cursor for the given script
/// The column number of the cursor for the given script
/// Includes full symbol definition ranges in the search.
+ /// Includes return type and class in symbol name.
/// SymbolReference of found symbol
public static SymbolReference FindSymbolAtPosition(
Ast scriptAst,
int lineNumber,
int columnNumber,
- bool includeDefinitions = false)
+ bool includeDefinitions = false,
+ bool returnMemberSignature = false)
{
FindSymbolVisitor symbolVisitor =
new(
lineNumber,
columnNumber,
- includeDefinitions);
+ includeDefinitions,
+ returnMemberSignature);
scriptAst.Visit(symbolVisitor);
diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindDeclarationVisitor.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindDeclarationVisitor.cs
index 71fd99905..e3d111923 100644
--- a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindDeclarationVisitor.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindDeclarationVisitor.cs
@@ -110,7 +110,7 @@ public override AstVisitAction VisitFunctionMember(FunctionMemberAst functionMem
SymbolType.Constructor : SymbolType.Method;
if (symbolRef.SymbolType.Equals(symbolType) &&
- functionMemberAst.Name.Equals(symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
+ VisitorUtils.GetMemberOverloadName(functionMemberAst).Equals(symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
{
// We only want the method/ctor name. Get start-location for name
IScriptExtent nameExtent = VisitorUtils.GetNameExtent(functionMemberAst);
@@ -129,15 +129,19 @@ public override AstVisitAction VisitFunctionMember(FunctionMemberAst functionMem
///
/// Decides if the current property member is the right definition
/// for the symbol being searched for. The definition of the symbol will be a of type
- /// SymbolType.Property and have the same name as the symbol
+ /// SymbolType.Property or SymbolType.EnumMember and have the same name as the symbol
///
/// A PropertyMemberAst in the script's AST
/// A decision to stop searching if the right PropertyMemberAst was found,
/// or a decision to continue if it wasn't found
public override AstVisitAction VisitPropertyMember(PropertyMemberAst propertyMemberAst)
{
- if (symbolRef.SymbolType.Equals(SymbolType.Property) &&
- propertyMemberAst.Name.Equals(symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
+ SymbolType symbolType =
+ propertyMemberAst.Parent is TypeDefinitionAst typeAst && typeAst.IsEnum ?
+ SymbolType.EnumMember : SymbolType.Property;
+
+ if (symbolRef.SymbolType.Equals(symbolType) &&
+ VisitorUtils.GetMemberOverloadName(propertyMemberAst).Equals(symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
{
// We only want the property name. Get start-location for name
IScriptExtent nameExtent = VisitorUtils.GetNameExtent(propertyMemberAst);
diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs
index 81fca6331..6bdab55bd 100644
--- a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs
@@ -235,7 +235,7 @@ public override AstVisitAction VisitFunctionMember(FunctionMemberAst functionMem
SymbolType.Constructor : SymbolType.Method;
if (_symbolRef.SymbolType.Equals(symbolType) &&
- functionMemberAst.Name.Equals(_symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
+ VisitorUtils.GetMemberOverloadName(functionMemberAst).Equals(_symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
{
// We only want the method/ctor name. Get start-location for name
IScriptExtent nameExtent = VisitorUtils.GetNameExtent(functionMemberAst);
@@ -246,14 +246,19 @@ public override AstVisitAction VisitFunctionMember(FunctionMemberAst functionMem
///
/// Decides if the current property member is a reference of the symbol being searched for.
- /// A reference of the symbol will be a of type SymbolType.Property and have the same name as the symbol
+ /// A reference of the symbol will be a of type SymbolType.Property or SymbolType.EnumMember
+ /// and have the same name as the symbol.
///
/// A PropertyMemberAst in the script's AST
/// A visit action that continues the search for references
public override AstVisitAction VisitPropertyMember(PropertyMemberAst propertyMemberAst)
{
- if (_symbolRef.SymbolType.Equals(SymbolType.Property) &&
- propertyMemberAst.Name.Equals(_symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
+ SymbolType symbolType =
+ propertyMemberAst.Parent is TypeDefinitionAst typeAst && typeAst.IsEnum ?
+ SymbolType.EnumMember : SymbolType.Property;
+
+ if (_symbolRef.SymbolType.Equals(symbolType) &&
+ VisitorUtils.GetMemberOverloadName(propertyMemberAst).Equals(_symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
{
// We only want the property name. Get start-location for name
IScriptExtent nameExtent = VisitorUtils.GetNameExtent(propertyMemberAst);
diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolVisitor.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolVisitor.cs
index 8269eb2d9..5442fb681 100644
--- a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolVisitor.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolVisitor.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Microsoft Corporation.
+// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System.Management.Automation.Language;
@@ -14,17 +14,20 @@ internal class FindSymbolVisitor : AstVisitor2
private readonly int lineNumber;
private readonly int columnNumber;
private readonly bool includeDefinitions;
+ private readonly bool returnMemberSignature;
public SymbolReference FoundSymbolReference { get; private set; }
public FindSymbolVisitor(
int lineNumber,
int columnNumber,
- bool includeDefinitions)
+ bool includeDefinitions,
+ bool returnMemberSignature)
{
this.lineNumber = lineNumber;
this.columnNumber = columnNumber;
this.includeDefinitions = includeDefinitions;
+ this.returnMemberSignature = returnMemberSignature;
}
///
@@ -161,7 +164,7 @@ private bool IsPositionInExtent(IScriptExtent extent)
public override AstVisitAction VisitFunctionMember(FunctionMemberAst functionMemberAst)
{
// We only want the method/ctor name. Get start-location for name
- IScriptExtent nameExtent = VisitorUtils.GetNameExtent(functionMemberAst);
+ IScriptExtent nameExtent = VisitorUtils.GetNameExtent(functionMemberAst, returnMemberSignature);
if (IsPositionInExtent(nameExtent))
{
@@ -265,8 +268,11 @@ public override AstVisitAction VisitTypeExpression(TypeExpressionAst typeExpress
/// or a decision to continue if it wasn't found
public override AstVisitAction VisitTypeConstraint(TypeConstraintAst typeConstraintAst)
{
- // Show only type name (skip leading '['). Offset by StartColumn to include indentation etc.
- int startColumnNumber = typeConstraintAst.Extent.StartColumnNumber + 1;
+ // Show only type name (skip leading '[' if present). It's not present for inherited types
+ // Offset by StartColumn to include indentation etc.
+ int startColumnNumber =
+ typeConstraintAst.Extent.Text[0] == '[' ?
+ typeConstraintAst.Extent.StartColumnNumber + 1 : typeConstraintAst.Extent.StartColumnNumber;
IScriptExtent nameExtent = new ScriptExtent()
{
@@ -322,13 +328,17 @@ public override AstVisitAction VisitConfigurationDefinition(ConfigurationDefinit
public override AstVisitAction VisitPropertyMember(PropertyMemberAst propertyMemberAst)
{
// We only want the property name. Get start-location for name
- IScriptExtent nameExtent = VisitorUtils.GetNameExtent(propertyMemberAst);
+ IScriptExtent nameExtent = VisitorUtils.GetNameExtent(propertyMemberAst, returnMemberSignature);
if (IsPositionInExtent(nameExtent))
{
+ SymbolType symbolType =
+ propertyMemberAst.Parent is TypeDefinitionAst typeAst && typeAst.IsEnum ?
+ SymbolType.EnumMember : SymbolType.Property;
+
FoundSymbolReference =
new SymbolReference(
- SymbolType.Property,
+ symbolType,
nameExtent);
return AstVisitAction.StopVisit;
diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolsVisitor.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolsVisitor.cs
index b66b6f265..f2b78abe3 100644
--- a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolsVisitor.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolsVisitor.cs
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
+using Microsoft.PowerShell.EditorServices.Utility;
using System.Collections.Generic;
using System.Management.Automation.Language;
@@ -29,7 +30,8 @@ public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst fun
return AstVisitAction.Continue;
}
- IScriptExtent nameExtent = GetNewExtent(functionDefinitionAst, functionDefinitionAst.Name);
+ (int startColumn, int startLine) = VisitorUtils.GetNameStartColumnAndLineFromAst(functionDefinitionAst);
+ IScriptExtent nameExtent = GetNewExtent(functionDefinitionAst, functionDefinitionAst.Name, startLine, startColumn);
SymbolType symbolType =
functionDefinitionAst.IsWorkflow ?
@@ -82,7 +84,8 @@ private static bool IsAssignedAtScriptScope(VariableExpressionAst variableExpres
/// A visit action that continues the search for references
public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst)
{
- IScriptExtent nameExtent = GetNewExtent(typeDefinitionAst, typeDefinitionAst.Name);
+ (int startColumn, int startLine) = VisitorUtils.GetNameStartColumnAndLineFromAst(typeDefinitionAst);
+ IScriptExtent nameExtent = GetNewExtent(typeDefinitionAst, typeDefinitionAst.Name, startLine, startColumn);
SymbolType symbolType =
typeDefinitionAst.IsEnum ?
@@ -103,7 +106,8 @@ public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinit
/// A visit action that continues the search for references
public override AstVisitAction VisitFunctionMember(FunctionMemberAst functionMemberAst)
{
- IScriptExtent nameExtent = GetNewExtent(functionMemberAst, GetMethodOverloadName(functionMemberAst));
+ (int startColumn, int startLine) = VisitorUtils.GetNameStartColumnAndLineFromAst(functionMemberAst);
+ IScriptExtent nameExtent = GetNewExtent(functionMemberAst, VisitorUtils.GetMemberOverloadName(functionMemberAst), startLine, startColumn);
SymbolType symbolType =
functionMemberAst.IsConstructor ?
@@ -117,30 +121,6 @@ public override AstVisitAction VisitFunctionMember(FunctionMemberAst functionMem
return AstVisitAction.Continue;
}
- ///
- /// Gets the method or constructor name with parameters for current overload.
- ///
- /// A FunctionMemberAst object in the script's AST
- /// Function member name with parameter types and names
- private static string GetMethodOverloadName(FunctionMemberAst functionMemberAst)
- {
- if (functionMemberAst.Parameters.Count > 0)
- {
- List parameters = new(functionMemberAst.Parameters.Count);
- foreach (ParameterAst param in functionMemberAst.Parameters)
- {
- parameters.Add(param.Extent.Text);
- }
-
- string paramString = string.Join(", ", parameters);
- return string.Concat(functionMemberAst.Name, "(", paramString, ")");
- }
- else
- {
- return string.Concat(functionMemberAst.Name, "()");
- }
- }
-
///
/// Adds class property AST to symbol reference list
///
@@ -148,11 +128,17 @@ private static string GetMethodOverloadName(FunctionMemberAst functionMemberAst)
/// A visit action that continues the search for references
public override AstVisitAction VisitPropertyMember(PropertyMemberAst propertyMemberAst)
{
- IScriptExtent nameExtent = GetNewExtent(propertyMemberAst, propertyMemberAst.Name);
+ SymbolType symbolType =
+ propertyMemberAst.Parent is TypeDefinitionAst typeAst && typeAst.IsEnum ?
+ SymbolType.EnumMember : SymbolType.Property;
+
+ bool isEnumMember = symbolType.Equals(SymbolType.EnumMember);
+ (int startColumn, int startLine) = VisitorUtils.GetNameStartColumnAndLineFromAst(propertyMemberAst, isEnumMember);
+ IScriptExtent nameExtent = GetNewExtent(propertyMemberAst, propertyMemberAst.Name, startLine, startColumn);
SymbolReferences.Add(
new SymbolReference(
- SymbolType.Property,
+ symbolType,
nameExtent));
return AstVisitAction.Continue;
@@ -165,7 +151,8 @@ public override AstVisitAction VisitPropertyMember(PropertyMemberAst propertyMem
/// A visit action that continues the search for references
public override AstVisitAction VisitConfigurationDefinition(ConfigurationDefinitionAst configurationDefinitionAst)
{
- IScriptExtent nameExtent = GetNewExtent(configurationDefinitionAst, configurationDefinitionAst.InstanceName.Extent.Text);
+ (int startColumn, int startLine) = VisitorUtils.GetNameStartColumnAndLineFromAst(configurationDefinitionAst);
+ IScriptExtent nameExtent = GetNewExtent(configurationDefinitionAst, configurationDefinitionAst.InstanceName.Extent.Text, startLine, startColumn);
SymbolReferences.Add(
new SymbolReference(
@@ -178,14 +165,14 @@ public override AstVisitAction VisitConfigurationDefinition(ConfigurationDefinit
///
/// Gets a new ScriptExtent for a given Ast with same range but modified Text
///
- private static ScriptExtent GetNewExtent(Ast ast, string text)
+ private static ScriptExtent GetNewExtent(Ast ast, string text, int startLine, int startColumn)
{
return new ScriptExtent()
{
Text = text,
- StartLineNumber = ast.Extent.StartLineNumber,
+ StartLineNumber = startLine,
EndLineNumber = ast.Extent.EndLineNumber,
- StartColumnNumber = ast.Extent.StartColumnNumber,
+ StartColumnNumber = startColumn,
EndColumnNumber = ast.Extent.EndColumnNumber,
File = ast.Extent.File
};
diff --git a/src/PowerShellEditorServices/Services/TextDocument/Handlers/DocumentSymbolHandler.cs b/src/PowerShellEditorServices/Services/TextDocument/Handlers/DocumentSymbolHandler.cs
index 01d544f93..5071cc745 100644
--- a/src/PowerShellEditorServices/Services/TextDocument/Handlers/DocumentSymbolHandler.cs
+++ b/src/PowerShellEditorServices/Services/TextDocument/Handlers/DocumentSymbolHandler.cs
@@ -134,6 +134,7 @@ private static SymbolKind GetSymbolKind(SymbolType symbolType)
SymbolType.Constructor => SymbolKind.Constructor,
SymbolType.Method => SymbolKind.Method,
SymbolType.Property => SymbolKind.Property,
+ SymbolType.EnumMember => SymbolKind.EnumMember,
_ => SymbolKind.Variable,
};
}
diff --git a/src/PowerShellEditorServices/Utility/VisitorUtils.cs b/src/PowerShellEditorServices/Utility/VisitorUtils.cs
index 3456c1920..3c959f35a 100644
--- a/src/PowerShellEditorServices/Utility/VisitorUtils.cs
+++ b/src/PowerShellEditorServices/Utility/VisitorUtils.cs
@@ -1,7 +1,10 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
+using System;
+using System.Collections.Generic;
using System.Management.Automation.Language;
+using System.Text;
using PSESSymbols = Microsoft.PowerShell.EditorServices.Services.Symbols;
namespace Microsoft.PowerShell.EditorServices.Utility
@@ -15,39 +18,94 @@ internal static class VisitorUtils
/// Calculates the start line and column of the actual symbol name in a AST.
///
/// An Ast object in the script's AST
- /// An offset specifying where to begin searching in the first line of the AST's extent text
+ /// An int specifying start index of name in the AST's extent text
/// A tuple with start column and line of the symbol name
- private static (int startColumn, int startLine) GetNameStartColumnAndLineNumbersFromAst(Ast ast, int firstLineColumnOffset)
+ private static (int startColumn, int startLine) GetNameStartColumnAndLineFromAst(Ast ast, int nameStartIndex)
{
int startColumnNumber = ast.Extent.StartColumnNumber;
int startLineNumber = ast.Extent.StartLineNumber;
- int astOffset = firstLineColumnOffset;
string astText = ast.Extent.Text;
- // The line offset represents the offset on the line that we're on where as
// astOffset is the offset on the entire text of the AST.
- int lineOffset = astOffset;
- for (; astOffset < astText.Length; astOffset++, lineOffset++)
+ for (int astOffset = 0; astOffset <= ast.Extent.Text.Length; astOffset++, startColumnNumber++)
{
if (astText[astOffset] == '\n')
{
// reset numbers since we are operating on a different line and increment the line number.
startColumnNumber = 0;
startLineNumber++;
- lineOffset = 0;
}
else if (astText[astOffset] == '\r')
{
// Do nothing with carriage returns... we only look for line feeds since those
// are used on every platform.
}
- else if (!char.IsWhiteSpace(astText[astOffset]))
+ else if (astOffset >= nameStartIndex && !char.IsWhiteSpace(astText[astOffset]))
{
// This is the start of the function name so we've found our start column and line number.
break;
}
}
- return (startColumnNumber + lineOffset, startLineNumber);
+ return (startColumnNumber, startLineNumber);
+ }
+
+ ///
+ /// Calculates the start line and column of the actual function name in a function definition AST.
+ ///
+ /// A FunctionDefinitionAst object in the script's AST
+ /// A tuple with start column and line for the function name
+ internal static (int startColumn, int startLine) GetNameStartColumnAndLineFromAst(FunctionDefinitionAst functionDefinitionAst)
+ {
+ int startOffset = functionDefinitionAst.IsFilter ? "filter".Length : functionDefinitionAst.IsWorkflow ? "workflow".Length : "function".Length;
+ return GetNameStartColumnAndLineFromAst(functionDefinitionAst, startOffset);
+ }
+
+ ///
+ /// Calculates the start line and column of the actual class/enum name in a type definition AST.
+ ///
+ /// A TypeDefinitionAst object in the script's AST
+ /// A tuple with start column and line for the type name
+ internal static (int startColumn, int startLine) GetNameStartColumnAndLineFromAst(TypeDefinitionAst typeDefinitionAst)
+ {
+ int startOffset = typeDefinitionAst.IsEnum ? "enum".Length : "class".Length;
+ return GetNameStartColumnAndLineFromAst(typeDefinitionAst, startOffset);
+ }
+
+ ///
+ /// Calculates the start line and column of the actual method/constructor name in a function member AST.
+ ///
+ /// A FunctionMemberAst object in the script's AST
+ /// A tuple with start column and line for the method/constructor name
+ internal static (int startColumn, int startLine) GetNameStartColumnAndLineFromAst(FunctionMemberAst functionMemberAst)
+ {
+ // find name index to get offset even with attributes, static, hidden ++
+ int nameStartIndex = functionMemberAst.Extent.Text.LastIndexOf(string.Concat(functionMemberAst.Name, '('), StringComparison.OrdinalIgnoreCase);
+ return GetNameStartColumnAndLineFromAst(functionMemberAst, nameStartIndex);
+ }
+
+ ///
+ /// Calculates the start line and column of the actual property name in a property member AST.
+ ///
+ /// A PropertyMemberAst object in the script's AST
+ /// A bool indicating this is a enum member
+ /// A tuple with start column and line for the property name
+ internal static (int startColumn, int startLine) GetNameStartColumnAndLineFromAst(PropertyMemberAst propertyMemberAst, bool isEnumMember)
+ {
+ // find name index to get offset even with attributes, static, hidden ++
+ string searchString = isEnumMember ? propertyMemberAst.Name : string.Concat('$', propertyMemberAst.Name);
+ int nameStartIndex = propertyMemberAst.Extent.Text.LastIndexOf(searchString, StringComparison.OrdinalIgnoreCase);
+ return GetNameStartColumnAndLineFromAst(propertyMemberAst, nameStartIndex);
+ }
+
+ ///
+ /// Calculates the start line and column of the actual configuration name in a configuration definition AST.
+ ///
+ /// A ConfigurationDefinitionAst object in the script's AST
+ /// A tuple with start column and line for the configuration name
+ internal static (int startColumn, int startLine) GetNameStartColumnAndLineFromAst(ConfigurationDefinitionAst configurationDefinitionAst)
+ {
+ const int startOffset = 13; // "configuration".Length
+ return GetNameStartColumnAndLineFromAst(configurationDefinitionAst, startOffset);
}
///
@@ -57,8 +115,7 @@ private static (int startColumn, int startLine) GetNameStartColumnAndLineNumbers
/// A ScriptExtent with for the symbol name only
internal static PSESSymbols.ScriptExtent GetNameExtent(FunctionDefinitionAst functionDefinitionAst)
{
- int astOffset = functionDefinitionAst.IsFilter ? "filter".Length : functionDefinitionAst.IsWorkflow ? "workflow".Length : "function".Length;
- (int startColumn, int startLine) = GetNameStartColumnAndLineNumbersFromAst(functionDefinitionAst, astOffset);
+ (int startColumn, int startLine) = GetNameStartColumnAndLineFromAst(functionDefinitionAst);
return new PSESSymbols.ScriptExtent()
{
@@ -78,8 +135,7 @@ internal static PSESSymbols.ScriptExtent GetNameExtent(FunctionDefinitionAst fun
/// A ScriptExtent with for the symbol name only
internal static PSESSymbols.ScriptExtent GetNameExtent(TypeDefinitionAst typeDefinitionAst)
{
- int astOffset = typeDefinitionAst.IsEnum ? "enum".Length : "class".Length;
- (int startColumn, int startLine) = GetNameStartColumnAndLineNumbersFromAst(typeDefinitionAst, astOffset);
+ (int startColumn, int startLine) = GetNameStartColumnAndLineFromAst(typeDefinitionAst);
return new PSESSymbols.ScriptExtent()
{
@@ -96,16 +152,15 @@ internal static PSESSymbols.ScriptExtent GetNameExtent(TypeDefinitionAst typeDef
/// Gets a new ScriptExtent for a given Ast for the symbol name only (variable)
///
/// A FunctionMemberAst in the script's AST
+ /// A bool indicating if return type and class should be included
/// A ScriptExtent with for the symbol name only
- internal static PSESSymbols.ScriptExtent GetNameExtent(FunctionMemberAst functionMemberAst)
+ internal static PSESSymbols.ScriptExtent GetNameExtent(FunctionMemberAst functionMemberAst, bool includeSignature = false)
{
- // offset by [type] if return type is specified
- int astOffset = functionMemberAst.ReturnType?.Extent.Text.Length ?? 0;
- (int startColumn, int startLine) = GetNameStartColumnAndLineNumbersFromAst(functionMemberAst, astOffset);
+ (int startColumn, int startLine) = GetNameStartColumnAndLineFromAst(functionMemberAst);
return new PSESSymbols.ScriptExtent()
{
- Text = functionMemberAst.Name,
+ Text = GetMemberOverloadName(functionMemberAst, includeSignature),
StartLineNumber = startLine,
EndLineNumber = startLine,
StartColumnNumber = startColumn,
@@ -118,20 +173,25 @@ internal static PSESSymbols.ScriptExtent GetNameExtent(FunctionMemberAst functio
/// Gets a new ScriptExtent for a given Ast for the property name only
///
/// A PropertyMemberAst in the script's AST
+ /// A bool indicating if property-type and name of class/enum should be included
/// A ScriptExtent with for the symbol name only
- internal static PSESSymbols.ScriptExtent GetNameExtent(PropertyMemberAst propertyMemberAst)
+ internal static PSESSymbols.ScriptExtent GetNameExtent(PropertyMemberAst propertyMemberAst, bool includeSignature = false)
{
- // offset by [type] if type is specified
- int astOffset = propertyMemberAst.PropertyType?.Extent.Text.Length ?? 0;
- (int startColumn, int startLine) = GetNameStartColumnAndLineNumbersFromAst(propertyMemberAst, astOffset);
+ bool isEnumMember = propertyMemberAst.Parent is TypeDefinitionAst typeDef && typeDef.IsEnum;
+ (int startColumn, int startLine) = GetNameStartColumnAndLineFromAst(propertyMemberAst, isEnumMember);
+
+ // +1 when class property to as start includes $
+ int endColumnNumber = isEnumMember ?
+ startColumn + propertyMemberAst.Name.Length :
+ startColumn + propertyMemberAst.Name.Length + 1;
return new PSESSymbols.ScriptExtent()
{
- Text = propertyMemberAst.Name,
+ Text = GetMemberOverloadName(propertyMemberAst, includeSignature),
StartLineNumber = startLine,
EndLineNumber = startLine,
StartColumnNumber = startColumn,
- EndColumnNumber = startColumn + propertyMemberAst.Name.Length + 1,
+ EndColumnNumber = endColumnNumber,
File = propertyMemberAst.Extent.File
};
}
@@ -144,8 +204,7 @@ internal static PSESSymbols.ScriptExtent GetNameExtent(PropertyMemberAst propert
internal static PSESSymbols.ScriptExtent GetNameExtent(ConfigurationDefinitionAst configurationDefinitionAst)
{
string configurationName = configurationDefinitionAst.InstanceName.Extent.Text;
- const int astOffset = 13; // "configuration".Length
- (int startColumn, int startLine) = GetNameStartColumnAndLineNumbersFromAst(configurationDefinitionAst, astOffset);
+ (int startColumn, int startLine) = GetNameStartColumnAndLineFromAst(configurationDefinitionAst);
return new PSESSymbols.ScriptExtent()
{
@@ -157,5 +216,73 @@ internal static PSESSymbols.ScriptExtent GetNameExtent(ConfigurationDefinitionAs
File = configurationDefinitionAst.Extent.File
};
}
+
+ ///
+ /// Gets the method or constructor name with parameters for current overload.
+ ///
+ /// A FunctionMemberAst object in the script's AST
+ /// A bool indicating if return type and class should be included
+ /// Function member name with return type (optional) and parameters
+ internal static string GetMemberOverloadName(FunctionMemberAst functionMemberAst, bool includeSignature = false)
+ {
+ StringBuilder sb = new();
+
+ // Prepend return type and class. Used for symbol details (hover)
+ if (includeSignature)
+ {
+ if (!functionMemberAst.IsConstructor)
+ {
+ sb.Append(functionMemberAst.ReturnType?.TypeName.Name ?? "void").Append(' ');
+ }
+
+ if (functionMemberAst.Parent is TypeDefinitionAst typeAst && typeAst.IsClass)
+ {
+ sb.Append(typeAst.Name).Append('.');
+ }
+ }
+
+ sb.Append(functionMemberAst.Name);
+
+ // Add parameters
+ sb.Append('(');
+ if (functionMemberAst.Parameters.Count > 0)
+ {
+ List parameters = new(functionMemberAst.Parameters.Count);
+ foreach (ParameterAst param in functionMemberAst.Parameters)
+ {
+ parameters.Add(param.Extent.Text);
+ }
+
+ sb.Append(string.Join(", ", parameters));
+ }
+ sb.Append(')');
+
+ return sb.ToString();
+ }
+
+ ///
+ /// Gets the property name with type and class/enum.
+ ///
+ /// A PropertyMemberAst object in the script's AST
+ /// A bool indicating if property-type and name of class/enum should be included
+ /// Property name with type (optional) and class/enum
+ internal static string GetMemberOverloadName(PropertyMemberAst propertyMemberAst, bool includeSignature = false)
+ {
+ StringBuilder sb = new();
+
+ // Prepend return type and class. Used for symbol details (hover)
+ if (includeSignature && propertyMemberAst.Parent is TypeDefinitionAst typeAst)
+ {
+ if (!typeAst.IsEnum)
+ {
+ sb.Append(propertyMemberAst.PropertyType?.TypeName.Name ?? "object").Append(' ');
+ }
+
+ sb.Append(typeAst.Name).Append('.');
+ }
+
+ sb.Append(propertyMemberAst.Name);
+ return sb.ToString();
+ }
}
}
From 4c0327455420499d59924d3e2c5cce3a1f7a0333 Mon Sep 17 00:00:00 2001
From: Frode Flaten <3436158+fflaten@users.noreply.github.com>
Date: Sun, 21 Aug 2022 15:00:58 +0000
Subject: [PATCH 13/18] update symbols test with name position
---
.../LanguageServerProtocolMessageTests.cs | 6 +++---
.../Language/SymbolsServiceTests.cs | 20 ++++++++++++-------
2 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/test/PowerShellEditorServices.Test.E2E/LanguageServerProtocolMessageTests.cs b/test/PowerShellEditorServices.Test.E2E/LanguageServerProtocolMessageTests.cs
index 0ca4bb2e3..5011d5245 100644
--- a/test/PowerShellEditorServices.Test.E2E/LanguageServerProtocolMessageTests.cs
+++ b/test/PowerShellEditorServices.Test.E2E/LanguageServerProtocolMessageTests.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Microsoft Corporation.
+// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System;
@@ -442,7 +442,7 @@ await PsesLanguageClient
Range range = symInfoOrDocSym.SymbolInformation.Location.Range;
Assert.Equal(1, range.Start.Line);
- Assert.Equal(0, range.Start.Character);
+ Assert.Equal(9, range.Start.Character);
Assert.Equal(3, range.End.Line);
Assert.Equal(1, range.End.Character);
});
@@ -867,7 +867,7 @@ function CanSendReferencesCodeLensRequest {
Range range = codeLens.Range;
Assert.Equal(1, range.Start.Line);
- Assert.Equal(0, range.Start.Character);
+ Assert.Equal(9, range.Start.Character);
Assert.Equal(3, range.End.Line);
Assert.Equal(1, range.End.Character);
diff --git a/test/PowerShellEditorServices.Test/Language/SymbolsServiceTests.cs b/test/PowerShellEditorServices.Test/Language/SymbolsServiceTests.cs
index b6552c0fb..27e0e8893 100644
--- a/test/PowerShellEditorServices.Test/Language/SymbolsServiceTests.cs
+++ b/test/PowerShellEditorServices.Test/Language/SymbolsServiceTests.cs
@@ -290,15 +290,16 @@ public void FindsSymbolsInFile()
Assert.Equal(3, symbolsResult.Count(symbolReference => symbolReference.SymbolType == SymbolType.Variable));
Assert.Single(symbolsResult.Where(symbolReference => symbolReference.SymbolType == SymbolType.Workflow));
Assert.Single(symbolsResult.Where(symbolReference => symbolReference.SymbolType == SymbolType.Class));
- Assert.Equal(2, symbolsResult.Count(symbolReference => symbolReference.SymbolType == SymbolType.Property));
+ Assert.Single(symbolsResult.Where(symbolReference => symbolReference.SymbolType == SymbolType.Property));
Assert.Single(symbolsResult.Where(symbolReference => symbolReference.SymbolType == SymbolType.Constructor));
Assert.Single(symbolsResult.Where(symbolReference => symbolReference.SymbolType == SymbolType.Method));
Assert.Single(symbolsResult.Where(symbolReference => symbolReference.SymbolType == SymbolType.Enum));
+ Assert.Single(symbolsResult.Where(symbolReference => symbolReference.SymbolType == SymbolType.EnumMember));
SymbolReference firstFunctionSymbol = symbolsResult.First(r => r.SymbolType == SymbolType.Function);
Assert.Equal("AFunction", firstFunctionSymbol.SymbolName);
Assert.Equal(7, firstFunctionSymbol.ScriptRegion.StartLineNumber);
- Assert.Equal(1, firstFunctionSymbol.ScriptRegion.StartColumnNumber);
+ Assert.Equal(10, firstFunctionSymbol.ScriptRegion.StartColumnNumber);
SymbolReference lastVariableSymbol = symbolsResult.Last(r => r.SymbolType == SymbolType.Variable);
Assert.Equal("$Script:ScriptVar2", lastVariableSymbol.SymbolName);
@@ -308,17 +309,17 @@ public void FindsSymbolsInFile()
SymbolReference firstWorkflowSymbol = symbolsResult.First(r => r.SymbolType == SymbolType.Workflow);
Assert.Equal("AWorkflow", firstWorkflowSymbol.SymbolName);
Assert.Equal(23, firstWorkflowSymbol.ScriptRegion.StartLineNumber);
- Assert.Equal(1, firstWorkflowSymbol.ScriptRegion.StartColumnNumber);
+ Assert.Equal(10, firstWorkflowSymbol.ScriptRegion.StartColumnNumber);
SymbolReference firstClassSymbol = symbolsResult.First(r => r.SymbolType == SymbolType.Class);
Assert.Equal("AClass", firstClassSymbol.SymbolName);
Assert.Equal(25, firstClassSymbol.ScriptRegion.StartLineNumber);
- Assert.Equal(1, firstClassSymbol.ScriptRegion.StartColumnNumber);
+ Assert.Equal(7, firstClassSymbol.ScriptRegion.StartColumnNumber);
SymbolReference firstPropertySymbol = symbolsResult.First(r => r.SymbolType == SymbolType.Property);
Assert.Equal("AProperty", firstPropertySymbol.SymbolName);
Assert.Equal(26, firstPropertySymbol.ScriptRegion.StartLineNumber);
- Assert.Equal(5, firstPropertySymbol.ScriptRegion.StartColumnNumber);
+ Assert.Equal(13, firstPropertySymbol.ScriptRegion.StartColumnNumber);
SymbolReference firstConstructorSymbol = symbolsResult.First(r => r.SymbolType == SymbolType.Constructor);
Assert.Equal("AClass([string]$AParameter)", firstConstructorSymbol.SymbolName);
@@ -328,12 +329,17 @@ public void FindsSymbolsInFile()
SymbolReference firstMethodSymbol = symbolsResult.First(r => r.SymbolType == SymbolType.Method);
Assert.Equal("AMethod([string]$param1, [int]$param2, $param3)", firstMethodSymbol.SymbolName);
Assert.Equal(32, firstMethodSymbol.ScriptRegion.StartLineNumber);
- Assert.Equal(5, firstMethodSymbol.ScriptRegion.StartColumnNumber);
+ Assert.Equal(11, firstMethodSymbol.ScriptRegion.StartColumnNumber);
SymbolReference firstEnumSymbol = symbolsResult.First(r => r.SymbolType == SymbolType.Enum);
Assert.Equal("AEnum", firstEnumSymbol.SymbolName);
Assert.Equal(37, firstEnumSymbol.ScriptRegion.StartLineNumber);
- Assert.Equal(1, firstEnumSymbol.ScriptRegion.StartColumnNumber);
+ Assert.Equal(6, firstEnumSymbol.ScriptRegion.StartColumnNumber);
+
+ SymbolReference firstEnumMemberSymbol = symbolsResult.First(r => r.SymbolType == SymbolType.EnumMember);
+ Assert.Equal("AValue", firstEnumMemberSymbol.SymbolName);
+ Assert.Equal(38, firstEnumMemberSymbol.ScriptRegion.StartLineNumber);
+ Assert.Equal(5, firstEnumMemberSymbol.ScriptRegion.StartColumnNumber);
}
[SkippableFact]
From b3eb6d69cdb4682028ab686362f5dd5266c56258 Mon Sep 17 00:00:00 2001
From: Frode Flaten <3436158+fflaten@users.noreply.github.com>
Date: Sun, 21 Aug 2022 16:47:18 +0000
Subject: [PATCH 14/18] check type for property and function members
---
.../Services/Symbols/SymbolsService.cs | 2 +-
.../Services/Symbols/Vistors/AstOperations.cs | 6 +--
.../Symbols/Vistors/FindDeclarationVisitor.cs | 8 ++--
.../Symbols/Vistors/FindReferencesVisitor.cs | 8 ++--
.../Symbols/Vistors/FindSymbolVisitor.cs | 10 ++---
.../Symbols/Vistors/FindSymbolsVisitor.cs | 2 +-
.../Utility/VisitorUtils.cs | 44 ++++++++++---------
7 files changed, 41 insertions(+), 39 deletions(-)
diff --git a/src/PowerShellEditorServices/Services/Symbols/SymbolsService.cs b/src/PowerShellEditorServices/Services/Symbols/SymbolsService.cs
index 2e22ac1dc..294cbb986 100644
--- a/src/PowerShellEditorServices/Services/Symbols/SymbolsService.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/SymbolsService.cs
@@ -333,7 +333,7 @@ public Task FindSymbolDetailsAtLocationAsync(
scriptFile.ScriptAst,
lineNumber,
columnNumber,
- returnMemberSignature: true);
+ returnFullSignature: true);
if (symbolReference == null)
{
diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/AstOperations.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/AstOperations.cs
index 623fc02ba..e843128d2 100644
--- a/src/PowerShellEditorServices/Services/Symbols/Vistors/AstOperations.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/AstOperations.cs
@@ -148,21 +148,21 @@ await executionService.ExecuteDelegateAsync(
/// The line number of the cursor for the given script
/// The column number of the cursor for the given script
/// Includes full symbol definition ranges in the search.
- /// Includes return type and class in symbol name.
+ /// Includes return or property type in symbol name.
/// SymbolReference of found symbol
public static SymbolReference FindSymbolAtPosition(
Ast scriptAst,
int lineNumber,
int columnNumber,
bool includeDefinitions = false,
- bool returnMemberSignature = false)
+ bool returnFullSignature = false)
{
FindSymbolVisitor symbolVisitor =
new(
lineNumber,
columnNumber,
includeDefinitions,
- returnMemberSignature);
+ returnFullSignature);
scriptAst.Visit(symbolVisitor);
diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindDeclarationVisitor.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindDeclarationVisitor.cs
index e3d111923..8c8e1842a 100644
--- a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindDeclarationVisitor.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindDeclarationVisitor.cs
@@ -110,10 +110,10 @@ public override AstVisitAction VisitFunctionMember(FunctionMemberAst functionMem
SymbolType.Constructor : SymbolType.Method;
if (symbolRef.SymbolType.Equals(symbolType) &&
- VisitorUtils.GetMemberOverloadName(functionMemberAst).Equals(symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
+ VisitorUtils.GetMemberOverloadName(functionMemberAst, true, false).Equals(symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
{
// We only want the method/ctor name. Get start-location for name
- IScriptExtent nameExtent = VisitorUtils.GetNameExtent(functionMemberAst);
+ IScriptExtent nameExtent = VisitorUtils.GetNameExtent(functionMemberAst, true, false);
FoundDeclaration =
new SymbolReference(
@@ -141,10 +141,10 @@ propertyMemberAst.Parent is TypeDefinitionAst typeAst && typeAst.IsEnum ?
SymbolType.EnumMember : SymbolType.Property;
if (symbolRef.SymbolType.Equals(symbolType) &&
- VisitorUtils.GetMemberOverloadName(propertyMemberAst).Equals(symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
+ VisitorUtils.GetMemberOverloadName(propertyMemberAst, false).Equals(symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
{
// We only want the property name. Get start-location for name
- IScriptExtent nameExtent = VisitorUtils.GetNameExtent(propertyMemberAst);
+ IScriptExtent nameExtent = VisitorUtils.GetNameExtent(propertyMemberAst, false);
FoundDeclaration =
new SymbolReference(
diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs
index 6bdab55bd..7f6014a2a 100644
--- a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs
@@ -235,10 +235,10 @@ public override AstVisitAction VisitFunctionMember(FunctionMemberAst functionMem
SymbolType.Constructor : SymbolType.Method;
if (_symbolRef.SymbolType.Equals(symbolType) &&
- VisitorUtils.GetMemberOverloadName(functionMemberAst).Equals(_symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
+ VisitorUtils.GetMemberOverloadName(functionMemberAst, true, false).Equals(_symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
{
// We only want the method/ctor name. Get start-location for name
- IScriptExtent nameExtent = VisitorUtils.GetNameExtent(functionMemberAst);
+ IScriptExtent nameExtent = VisitorUtils.GetNameExtent(functionMemberAst, true, false);
FoundReferences.Add(new SymbolReference(symbolType, nameExtent));
}
return AstVisitAction.Continue;
@@ -258,10 +258,10 @@ propertyMemberAst.Parent is TypeDefinitionAst typeAst && typeAst.IsEnum ?
SymbolType.EnumMember : SymbolType.Property;
if (_symbolRef.SymbolType.Equals(symbolType) &&
- VisitorUtils.GetMemberOverloadName(propertyMemberAst).Equals(_symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
+ VisitorUtils.GetMemberOverloadName(propertyMemberAst, false).Equals(_symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase))
{
// We only want the property name. Get start-location for name
- IScriptExtent nameExtent = VisitorUtils.GetNameExtent(propertyMemberAst);
+ IScriptExtent nameExtent = VisitorUtils.GetNameExtent(propertyMemberAst, false);
FoundReferences.Add(new SymbolReference(SymbolType.Property, nameExtent));
}
return AstVisitAction.Continue;
diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolVisitor.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolVisitor.cs
index 5442fb681..b45ee03eb 100644
--- a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolVisitor.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolVisitor.cs
@@ -14,7 +14,7 @@ internal class FindSymbolVisitor : AstVisitor2
private readonly int lineNumber;
private readonly int columnNumber;
private readonly bool includeDefinitions;
- private readonly bool returnMemberSignature;
+ private readonly bool returnFullSignature;
public SymbolReference FoundSymbolReference { get; private set; }
@@ -22,12 +22,12 @@ public FindSymbolVisitor(
int lineNumber,
int columnNumber,
bool includeDefinitions,
- bool returnMemberSignature)
+ bool returnFullSignature)
{
this.lineNumber = lineNumber;
this.columnNumber = columnNumber;
this.includeDefinitions = includeDefinitions;
- this.returnMemberSignature = returnMemberSignature;
+ this.returnFullSignature = returnFullSignature;
}
///
@@ -164,7 +164,7 @@ private bool IsPositionInExtent(IScriptExtent extent)
public override AstVisitAction VisitFunctionMember(FunctionMemberAst functionMemberAst)
{
// We only want the method/ctor name. Get start-location for name
- IScriptExtent nameExtent = VisitorUtils.GetNameExtent(functionMemberAst, returnMemberSignature);
+ IScriptExtent nameExtent = VisitorUtils.GetNameExtent(functionMemberAst, true, returnFullSignature);
if (IsPositionInExtent(nameExtent))
{
@@ -328,7 +328,7 @@ public override AstVisitAction VisitConfigurationDefinition(ConfigurationDefinit
public override AstVisitAction VisitPropertyMember(PropertyMemberAst propertyMemberAst)
{
// We only want the property name. Get start-location for name
- IScriptExtent nameExtent = VisitorUtils.GetNameExtent(propertyMemberAst, returnMemberSignature);
+ IScriptExtent nameExtent = VisitorUtils.GetNameExtent(propertyMemberAst, returnFullSignature);
if (IsPositionInExtent(nameExtent))
{
diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolsVisitor.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolsVisitor.cs
index f2b78abe3..55c90b4fd 100644
--- a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolsVisitor.cs
+++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindSymbolsVisitor.cs
@@ -107,7 +107,7 @@ public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinit
public override AstVisitAction VisitFunctionMember(FunctionMemberAst functionMemberAst)
{
(int startColumn, int startLine) = VisitorUtils.GetNameStartColumnAndLineFromAst(functionMemberAst);
- IScriptExtent nameExtent = GetNewExtent(functionMemberAst, VisitorUtils.GetMemberOverloadName(functionMemberAst), startLine, startColumn);
+ IScriptExtent nameExtent = GetNewExtent(functionMemberAst, VisitorUtils.GetMemberOverloadName(functionMemberAst, false, false), startLine, startColumn);
SymbolType symbolType =
functionMemberAst.IsConstructor ?
diff --git a/src/PowerShellEditorServices/Utility/VisitorUtils.cs b/src/PowerShellEditorServices/Utility/VisitorUtils.cs
index 3c959f35a..3fc3f7ea1 100644
--- a/src/PowerShellEditorServices/Utility/VisitorUtils.cs
+++ b/src/PowerShellEditorServices/Utility/VisitorUtils.cs
@@ -152,15 +152,16 @@ internal static PSESSymbols.ScriptExtent GetNameExtent(TypeDefinitionAst typeDef
/// Gets a new ScriptExtent for a given Ast for the symbol name only (variable)
///
/// A FunctionMemberAst in the script's AST
- /// A bool indicating if return type and class should be included
+ /// A bool indicating if class/enum name should be prepended
+ /// A bool indicating if return type should be included for methods
/// A ScriptExtent with for the symbol name only
- internal static PSESSymbols.ScriptExtent GetNameExtent(FunctionMemberAst functionMemberAst, bool includeSignature = false)
+ internal static PSESSymbols.ScriptExtent GetNameExtent(FunctionMemberAst functionMemberAst, bool useQualifiedName = true, bool includeReturnType = false)
{
(int startColumn, int startLine) = GetNameStartColumnAndLineFromAst(functionMemberAst);
return new PSESSymbols.ScriptExtent()
{
- Text = GetMemberOverloadName(functionMemberAst, includeSignature),
+ Text = GetMemberOverloadName(functionMemberAst, useQualifiedName, includeReturnType),
StartLineNumber = startLine,
EndLineNumber = startLine,
StartColumnNumber = startColumn,
@@ -173,9 +174,9 @@ internal static PSESSymbols.ScriptExtent GetNameExtent(FunctionMemberAst functio
/// Gets a new ScriptExtent for a given Ast for the property name only
///
/// A PropertyMemberAst in the script's AST
- /// A bool indicating if property-type and name of class/enum should be included
+ /// A bool indicating if type should be included for class property
/// A ScriptExtent with for the symbol name only
- internal static PSESSymbols.ScriptExtent GetNameExtent(PropertyMemberAst propertyMemberAst, bool includeSignature = false)
+ internal static PSESSymbols.ScriptExtent GetNameExtent(PropertyMemberAst propertyMemberAst, bool includePropertyType = false)
{
bool isEnumMember = propertyMemberAst.Parent is TypeDefinitionAst typeDef && typeDef.IsEnum;
(int startColumn, int startLine) = GetNameStartColumnAndLineFromAst(propertyMemberAst, isEnumMember);
@@ -187,7 +188,7 @@ internal static PSESSymbols.ScriptExtent GetNameExtent(PropertyMemberAst propert
return new PSESSymbols.ScriptExtent()
{
- Text = GetMemberOverloadName(propertyMemberAst, includeSignature),
+ Text = GetMemberOverloadName(propertyMemberAst, includePropertyType),
StartLineNumber = startLine,
EndLineNumber = startLine,
StartColumnNumber = startColumn,
@@ -221,24 +222,24 @@ internal static PSESSymbols.ScriptExtent GetNameExtent(ConfigurationDefinitionAs
/// Gets the method or constructor name with parameters for current overload.
///
/// A FunctionMemberAst object in the script's AST
- /// A bool indicating if return type and class should be included
+ /// A bool indicating if class/enum name should be prepended
+ /// A bool indicating if return type should be included for methods
/// Function member name with return type (optional) and parameters
- internal static string GetMemberOverloadName(FunctionMemberAst functionMemberAst, bool includeSignature = false)
+ internal static string GetMemberOverloadName(FunctionMemberAst functionMemberAst,
+ bool useQualifiedName = true,
+ bool includeReturnType = false)
{
StringBuilder sb = new();
// Prepend return type and class. Used for symbol details (hover)
- if (includeSignature)
+ if (includeReturnType && !functionMemberAst.IsConstructor)
{
- if (!functionMemberAst.IsConstructor)
- {
- sb.Append(functionMemberAst.ReturnType?.TypeName.Name ?? "void").Append(' ');
- }
+ sb.Append(functionMemberAst.ReturnType?.TypeName.Name ?? "void").Append(' ');
+ }
- if (functionMemberAst.Parent is TypeDefinitionAst typeAst && typeAst.IsClass)
- {
- sb.Append(typeAst.Name).Append('.');
- }
+ if (useQualifiedName && functionMemberAst.Parent is TypeDefinitionAst typeAst && typeAst.IsClass)
+ {
+ sb.Append(typeAst.Name).Append('.');
}
sb.Append(functionMemberAst.Name);
@@ -264,16 +265,17 @@ internal static string GetMemberOverloadName(FunctionMemberAst functionMemberAst
/// Gets the property name with type and class/enum.
///
/// A PropertyMemberAst object in the script's AST
- /// A bool indicating if property-type and name of class/enum should be included
+ /// A bool indicating if type should be included for class property
/// Property name with type (optional) and class/enum
- internal static string GetMemberOverloadName(PropertyMemberAst propertyMemberAst, bool includeSignature = false)
+ internal static string GetMemberOverloadName(PropertyMemberAst propertyMemberAst,
+ bool includePropertyType = false)
{
StringBuilder sb = new();
// Prepend return type and class. Used for symbol details (hover)
- if (includeSignature && propertyMemberAst.Parent is TypeDefinitionAst typeAst)
+ if (propertyMemberAst.Parent is TypeDefinitionAst typeAst)
{
- if (!typeAst.IsEnum)
+ if (includePropertyType && !typeAst.IsEnum)
{
sb.Append(propertyMemberAst.PropertyType?.TypeName.Name ?? "object").Append(' ');
}
From 849bd57aa7f2bdf089c0c9bf46a800c40d1a37db Mon Sep 17 00:00:00 2001
From: Frode Flaten <3436158+fflaten@users.noreply.github.com>
Date: Thu, 25 Aug 2022 19:12:04 +0000
Subject: [PATCH 15/18] add symbolsservice tests
---
.../Definition/FindsTypeSymbolsDefinition.cs | 90 ++++++
.../FindsOccurrencesOnTypeSymbols.cs | 90 ++++++
.../Occurrences/FindsOccurrencesOnVariable.cs | 20 ++
.../FindsReferencesOnTypeSymbols.cs | 90 ++++++
.../References/TypeAndClassesFile.ps1 | 46 +++
.../FindsDetailsForTypeSymbols.cs | 50 ++++
.../SymbolDetails/TypeSymbolDetails.ps1 | 23 ++
.../Language/SymbolsServiceTests.cs | 269 ++++++++++++++++++
8 files changed, 678 insertions(+)
create mode 100644 test/PowerShellEditorServices.Test.Shared/Definition/FindsTypeSymbolsDefinition.cs
create mode 100644 test/PowerShellEditorServices.Test.Shared/Occurrences/FindsOccurrencesOnTypeSymbols.cs
create mode 100644 test/PowerShellEditorServices.Test.Shared/Occurrences/FindsOccurrencesOnVariable.cs
create mode 100644 test/PowerShellEditorServices.Test.Shared/References/FindsReferencesOnTypeSymbols.cs
create mode 100644 test/PowerShellEditorServices.Test.Shared/References/TypeAndClassesFile.ps1
create mode 100644 test/PowerShellEditorServices.Test.Shared/SymbolDetails/FindsDetailsForTypeSymbols.cs
create mode 100644 test/PowerShellEditorServices.Test.Shared/SymbolDetails/TypeSymbolDetails.ps1
diff --git a/test/PowerShellEditorServices.Test.Shared/Definition/FindsTypeSymbolsDefinition.cs b/test/PowerShellEditorServices.Test.Shared/Definition/FindsTypeSymbolsDefinition.cs
new file mode 100644
index 000000000..a0b5ae61c
--- /dev/null
+++ b/test/PowerShellEditorServices.Test.Shared/Definition/FindsTypeSymbolsDefinition.cs
@@ -0,0 +1,90 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Microsoft.PowerShell.EditorServices.Services.TextDocument;
+
+namespace Microsoft.PowerShell.EditorServices.Test.Shared.Definition
+{
+ public static class FindsTypeSymbolsDefinitionData
+ {
+ public static readonly ScriptRegion ClassSourceDetails = new(
+ file: TestUtilities.NormalizePath("References/TypeAndClassesFile.ps1"),
+ text: string.Empty,
+ startLineNumber: 8,
+ startColumnNumber: 14,
+ startOffset: 0,
+ endLineNumber: 0,
+ endColumnNumber: 0,
+ endOffset: 0);
+
+ public static readonly ScriptRegion EnumSourceDetails = new(
+ file: TestUtilities.NormalizePath("References/TypeAndClassesFile.ps1"),
+ text: string.Empty,
+ startLineNumber: 39,
+ startColumnNumber: 10,
+ startOffset: 0,
+ endLineNumber: 0,
+ endColumnNumber: 0,
+ endOffset: 0);
+
+ public static readonly ScriptRegion TypeExpressionSourceDetails = new(
+ file: TestUtilities.NormalizePath("References/TypeAndClassesFile.ps1"),
+ text: string.Empty,
+ startLineNumber: 45,
+ startColumnNumber: 5,
+ startOffset: 0,
+ endLineNumber: 0,
+ endColumnNumber: 0,
+ endOffset: 0);
+
+ public static readonly ScriptRegion TypeConstraintSourceDetails = new(
+ file: TestUtilities.NormalizePath("References/TypeAndClassesFile.ps1"),
+ text: string.Empty,
+ startLineNumber: 25,
+ startColumnNumber: 24,
+ startOffset: 0,
+ endLineNumber: 0,
+ endColumnNumber: 0,
+ endOffset: 0);
+
+ public static readonly ScriptRegion ConstructorSourceDetails = new(
+ file: TestUtilities.NormalizePath("References/TypeAndClassesFile.ps1"),
+ text: string.Empty,
+ startLineNumber: 9,
+ startColumnNumber: 14,
+ startOffset: 0,
+ endLineNumber: 0,
+ endColumnNumber: 0,
+ endOffset: 0);
+
+ public static readonly ScriptRegion MethodSourceDetails = new(
+ file: TestUtilities.NormalizePath("References/TypeAndClassesFile.ps1"),
+ text: string.Empty,
+ startLineNumber: 19,
+ startColumnNumber: 25,
+ startOffset: 0,
+ endLineNumber: 0,
+ endColumnNumber: 0,
+ endOffset: 0);
+
+ public static readonly ScriptRegion PropertySourceDetails = new(
+ file: TestUtilities.NormalizePath("References/TypeAndClassesFile.ps1"),
+ text: string.Empty,
+ startLineNumber: 15,
+ startColumnNumber: 32,
+ startOffset: 0,
+ endLineNumber: 0,
+ endColumnNumber: 0,
+ endOffset: 0);
+
+ public static readonly ScriptRegion EnumMemberSourceDetails = new(
+ file: TestUtilities.NormalizePath("References/TypeAndClassesFile.ps1"),
+ text: string.Empty,
+ startLineNumber: 41,
+ startColumnNumber: 11,
+ startOffset: 0,
+ endLineNumber: 0,
+ endColumnNumber: 0,
+ endOffset: 0);
+ }
+}
diff --git a/test/PowerShellEditorServices.Test.Shared/Occurrences/FindsOccurrencesOnTypeSymbols.cs b/test/PowerShellEditorServices.Test.Shared/Occurrences/FindsOccurrencesOnTypeSymbols.cs
new file mode 100644
index 000000000..7c012bc7c
--- /dev/null
+++ b/test/PowerShellEditorServices.Test.Shared/Occurrences/FindsOccurrencesOnTypeSymbols.cs
@@ -0,0 +1,90 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Microsoft.PowerShell.EditorServices.Services.TextDocument;
+
+namespace Microsoft.PowerShell.EditorServices.Test.Shared.Occurrences
+{
+ public static class FindsOccurrencesOnTypeSymbolsData
+ {
+ public static readonly ScriptRegion ClassSourceDetails = new(
+ file: TestUtilities.NormalizePath("References/TypeAndClassesFile.ps1"),
+ text: string.Empty,
+ startLineNumber: 8,
+ startColumnNumber: 16,
+ startOffset: 0,
+ endLineNumber: 0,
+ endColumnNumber: 0,
+ endOffset: 0);
+
+ public static readonly ScriptRegion EnumSourceDetails = new(
+ file: TestUtilities.NormalizePath("References/TypeAndClassesFile.ps1"),
+ text: string.Empty,
+ startLineNumber: 39,
+ startColumnNumber: 7,
+ startOffset: 0,
+ endLineNumber: 0,
+ endColumnNumber: 0,
+ endOffset: 0);
+
+ public static readonly ScriptRegion TypeExpressionSourceDetails = new(
+ file: TestUtilities.NormalizePath("References/TypeAndClassesFile.ps1"),
+ text: string.Empty,
+ startLineNumber: 34,
+ startColumnNumber: 16,
+ startOffset: 0,
+ endLineNumber: 0,
+ endColumnNumber: 0,
+ endOffset: 0);
+
+ public static readonly ScriptRegion TypeConstraintSourceDetails = new(
+ file: TestUtilities.NormalizePath("References/TypeAndClassesFile.ps1"),
+ text: string.Empty,
+ startLineNumber: 8,
+ startColumnNumber: 24,
+ startOffset: 0,
+ endLineNumber: 0,
+ endColumnNumber: 0,
+ endOffset: 0);
+
+ public static readonly ScriptRegion ConstructorSourceDetails = new(
+ file: TestUtilities.NormalizePath("References/TypeAndClassesFile.ps1"),
+ text: string.Empty,
+ startLineNumber: 13,
+ startColumnNumber: 14,
+ startOffset: 0,
+ endLineNumber: 0,
+ endColumnNumber: 0,
+ endOffset: 0);
+
+ public static readonly ScriptRegion MethodSourceDetails = new(
+ file: TestUtilities.NormalizePath("References/TypeAndClassesFile.ps1"),
+ text: string.Empty,
+ startLineNumber: 28,
+ startColumnNumber: 22,
+ startOffset: 0,
+ endLineNumber: 0,
+ endColumnNumber: 0,
+ endOffset: 0);
+
+ public static readonly ScriptRegion PropertySourceDetails = new(
+ file: TestUtilities.NormalizePath("References/TypeAndClassesFile.ps1"),
+ text: string.Empty,
+ startLineNumber: 15,
+ startColumnNumber: 18,
+ startOffset: 0,
+ endLineNumber: 0,
+ endColumnNumber: 0,
+ endOffset: 0);
+
+ public static readonly ScriptRegion EnumMemberSourceDetails = new(
+ file: TestUtilities.NormalizePath("References/TypeAndClassesFile.ps1"),
+ text: string.Empty,
+ startLineNumber: 40,
+ startColumnNumber: 6,
+ startOffset: 0,
+ endLineNumber: 0,
+ endColumnNumber: 0,
+ endOffset: 0);
+ }
+}
diff --git a/test/PowerShellEditorServices.Test.Shared/Occurrences/FindsOccurrencesOnVariable.cs b/test/PowerShellEditorServices.Test.Shared/Occurrences/FindsOccurrencesOnVariable.cs
new file mode 100644
index 000000000..c01db0591
--- /dev/null
+++ b/test/PowerShellEditorServices.Test.Shared/Occurrences/FindsOccurrencesOnVariable.cs
@@ -0,0 +1,20 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Microsoft.PowerShell.EditorServices.Services.TextDocument;
+
+namespace Microsoft.PowerShell.EditorServices.Test.Shared.Occurrences
+{
+ public static class FindsOccurrencesOnVariableData
+ {
+ public static readonly ScriptRegion SourceDetails = new(
+ file: TestUtilities.NormalizePath("References/SimpleFile.ps1"),
+ text: string.Empty,
+ startLineNumber: 8,
+ startColumnNumber: 3,
+ startOffset: 0,
+ endLineNumber: 0,
+ endColumnNumber: 0,
+ endOffset: 0);
+ }
+}
diff --git a/test/PowerShellEditorServices.Test.Shared/References/FindsReferencesOnTypeSymbols.cs b/test/PowerShellEditorServices.Test.Shared/References/FindsReferencesOnTypeSymbols.cs
new file mode 100644
index 000000000..d9cbcf434
--- /dev/null
+++ b/test/PowerShellEditorServices.Test.Shared/References/FindsReferencesOnTypeSymbols.cs
@@ -0,0 +1,90 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Microsoft.PowerShell.EditorServices.Services.TextDocument;
+
+namespace Microsoft.PowerShell.EditorServices.Test.Shared.References
+{
+ public static class FindsReferencesOnTypeSymbolsData
+ {
+ public static readonly ScriptRegion ClassSourceDetails = new(
+ file: TestUtilities.NormalizePath("References/TypeAndClassesFile.ps1"),
+ text: string.Empty,
+ startLineNumber: 8,
+ startColumnNumber: 12,
+ startOffset: 0,
+ endLineNumber: 0,
+ endColumnNumber: 0,
+ endOffset: 0);
+
+ public static readonly ScriptRegion EnumSourceDetails = new(
+ file: TestUtilities.NormalizePath("References/TypeAndClassesFile.ps1"),
+ text: string.Empty,
+ startLineNumber: 39,
+ startColumnNumber: 8,
+ startOffset: 0,
+ endLineNumber: 0,
+ endColumnNumber: 0,
+ endOffset: 0);
+
+ public static readonly ScriptRegion ConstructorSourceDetails = new(
+ file: TestUtilities.NormalizePath("References/TypeAndClassesFile.ps1"),
+ text: string.Empty,
+ startLineNumber: 9,
+ startColumnNumber: 8,
+ startOffset: 0,
+ endLineNumber: 0,
+ endColumnNumber: 0,
+ endOffset: 0);
+
+ public static readonly ScriptRegion MethodSourceDetails = new(
+ file: TestUtilities.NormalizePath("References/TypeAndClassesFile.ps1"),
+ text: string.Empty,
+ startLineNumber: 19,
+ startColumnNumber: 20,
+ startOffset: 0,
+ endLineNumber: 0,
+ endColumnNumber: 0,
+ endOffset: 0);
+
+ public static readonly ScriptRegion PropertySourceDetails = new(
+ file: TestUtilities.NormalizePath("References/TypeAndClassesFile.ps1"),
+ text: string.Empty,
+ startLineNumber: 17,
+ startColumnNumber: 15,
+ startOffset: 0,
+ endLineNumber: 0,
+ endColumnNumber: 0,
+ endOffset: 0);
+
+ public static readonly ScriptRegion EnumMemberSourceDetails = new(
+ file: TestUtilities.NormalizePath("References/TypeAndClassesFile.ps1"),
+ text: string.Empty,
+ startLineNumber: 41,
+ startColumnNumber: 8,
+ startOffset: 0,
+ endLineNumber: 0,
+ endColumnNumber: 0,
+ endOffset: 0);
+
+ public static readonly ScriptRegion TypeExpressionSourceDetails = new(
+ file: TestUtilities.NormalizePath("References/TypeAndClassesFile.ps1"),
+ text: string.Empty,
+ startLineNumber: 34,
+ startColumnNumber: 12,
+ startOffset: 0,
+ endLineNumber: 0,
+ endColumnNumber: 0,
+ endOffset: 0);
+
+ public static readonly ScriptRegion TypeConstraintSourceDetails = new(
+ file: TestUtilities.NormalizePath("References/TypeAndClassesFile.ps1"),
+ text: string.Empty,
+ startLineNumber: 25,
+ startColumnNumber: 22,
+ startOffset: 0,
+ endLineNumber: 0,
+ endColumnNumber: 0,
+ endOffset: 0);
+ }
+}
diff --git a/test/PowerShellEditorServices.Test.Shared/References/TypeAndClassesFile.ps1 b/test/PowerShellEditorServices.Test.Shared/References/TypeAndClassesFile.ps1
new file mode 100644
index 000000000..4fe54505d
--- /dev/null
+++ b/test/PowerShellEditorServices.Test.Shared/References/TypeAndClassesFile.ps1
@@ -0,0 +1,46 @@
+Get-ChildItem ./file1.ps1
+$myScriptVar = 123
+
+class BaseClass {
+
+}
+
+class SuperClass : BaseClass {
+ SuperClass([string]$name) {
+
+ }
+
+ SuperClass() { }
+
+ [string]$SomePropWithDefault = 'this is a default value'
+
+ [int]$SomeProp
+
+ [string]MyClassMethod([string]$param1, $param2, [int]$param3) {
+ $this.SomePropWithDefault = 'something happend'
+ return 'finished'
+ }
+
+ [string]
+ MyClassMethod([MyEnum]$param1) {
+ return 'hello world'
+ }
+ [string]MyClassMethod() {
+ return 'hello world'
+ }
+}
+
+New-Object SuperClass
+$o = [SuperClass]::new()
+$o.SomeProp
+$o.MyClassMeth
+
+
+enum MyEnum {
+ First
+ Second
+ Third
+}
+
+[MyEnum]::First
+'First' -is [MyEnum]
diff --git a/test/PowerShellEditorServices.Test.Shared/SymbolDetails/FindsDetailsForTypeSymbols.cs b/test/PowerShellEditorServices.Test.Shared/SymbolDetails/FindsDetailsForTypeSymbols.cs
new file mode 100644
index 000000000..ff78a2c5a
--- /dev/null
+++ b/test/PowerShellEditorServices.Test.Shared/SymbolDetails/FindsDetailsForTypeSymbols.cs
@@ -0,0 +1,50 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Microsoft.PowerShell.EditorServices.Services.TextDocument;
+
+namespace Microsoft.PowerShell.EditorServices.Test.Shared.SymbolDetails
+{
+ public static class FindsDetailsForTypeSymbolsData
+ {
+ public static readonly ScriptRegion EnumMemberSourceDetails = new(
+ file: TestUtilities.NormalizePath("SymbolDetails/TypeSymbolDetails.ps1"),
+ text: string.Empty,
+ startLineNumber: 20,
+ startColumnNumber: 6,
+ startOffset: 0,
+ endLineNumber: 0,
+ endColumnNumber: 0,
+ endOffset: 0);
+
+ public static readonly ScriptRegion PropertySourceDetails = new(
+ file: TestUtilities.NormalizePath("SymbolDetails/TypeSymbolDetails.ps1"),
+ text: string.Empty,
+ startLineNumber: 6,
+ startColumnNumber: 18,
+ startOffset: 0,
+ endLineNumber: 0,
+ endColumnNumber: 0,
+ endOffset: 0);
+
+ public static readonly ScriptRegion ConstructorSourceDetails = new(
+ file: TestUtilities.NormalizePath("SymbolDetails/TypeSymbolDetails.ps1"),
+ text: string.Empty,
+ startLineNumber: 2,
+ startColumnNumber: 11,
+ startOffset: 0,
+ endLineNumber: 0,
+ endColumnNumber: 0,
+ endOffset: 0);
+
+ public static readonly ScriptRegion MethodSourceDetails = new(
+ file: TestUtilities.NormalizePath("SymbolDetails/TypeSymbolDetails.ps1"),
+ text: string.Empty,
+ startLineNumber: 10,
+ startColumnNumber: 20,
+ startOffset: 0,
+ endLineNumber: 0,
+ endColumnNumber: 0,
+ endOffset: 0);
+ }
+}
diff --git a/test/PowerShellEditorServices.Test.Shared/SymbolDetails/TypeSymbolDetails.ps1 b/test/PowerShellEditorServices.Test.Shared/SymbolDetails/TypeSymbolDetails.ps1
new file mode 100644
index 000000000..fd4a10a46
--- /dev/null
+++ b/test/PowerShellEditorServices.Test.Shared/SymbolDetails/TypeSymbolDetails.ps1
@@ -0,0 +1,23 @@
+class SuperClass {
+ SuperClass([string]$name) {
+
+ }
+
+ [string]$SomePropWithDefault = 'this is a default value'
+
+ [int]$SomeProp
+
+ [string]MyClassMethod([string]$param1, $param2, [int]$param3) {
+ $this.SomePropWithDefault = 'something happend'
+ return 'finished'
+ }
+}
+
+New-Object SuperClass
+$o = [SuperClass]::new()
+
+enum MyEnum {
+ First
+ Second
+ Third
+}
diff --git a/test/PowerShellEditorServices.Test/Language/SymbolsServiceTests.cs b/test/PowerShellEditorServices.Test/Language/SymbolsServiceTests.cs
index 27e0e8893..c3de81c8d 100644
--- a/test/PowerShellEditorServices.Test/Language/SymbolsServiceTests.cs
+++ b/test/PowerShellEditorServices.Test/Language/SymbolsServiceTests.cs
@@ -225,6 +225,15 @@ public async Task FindsReferencesOnVariable()
Assert.Equal(13, referencesResult[referencesResult.Count - 1].ScriptRegion.StartColumnNumber);
}
+ [Fact]
+ public void FindsOccurrencesOnVariable()
+ {
+ IReadOnlyList occurrencesResult = GetOccurrences(FindsOccurrencesOnVariableData.SourceDetails);
+ Assert.Equal(3, occurrencesResult.Count);
+ Assert.Equal(10, occurrencesResult[occurrencesResult.Count - 1].ScriptRegion.StartLineNumber);
+ Assert.Equal(13, occurrencesResult[occurrencesResult.Count - 1].ScriptRegion.StartColumnNumber);
+ }
+
[Fact]
public void FindsOccurrencesOnFunction()
{
@@ -253,6 +262,222 @@ public async Task FindsReferencesOnCommandWithAlias()
Assert.Equal("Get-ChildItem", referencesResult[referencesResult.Count - 1].SymbolName);
}
+ [Fact]
+ public async Task FindsClassDefinition()
+ {
+ SymbolReference definitionResult = await GetDefinition(FindsTypeSymbolsDefinitionData.ClassSourceDetails).ConfigureAwait(true);
+ Assert.Equal(8, definitionResult.ScriptRegion.StartLineNumber);
+ Assert.Equal(7, definitionResult.ScriptRegion.StartColumnNumber);
+ Assert.Equal("SuperClass", definitionResult.SymbolName);
+ }
+
+ [Fact]
+ public async Task FindsReferencesOnClass()
+ {
+ List referencesResult = await GetReferences(FindsReferencesOnTypeSymbolsData.ClassSourceDetails).ConfigureAwait(true);
+ Assert.Equal(2, referencesResult.Count);
+ Assert.Equal(8, referencesResult[0].ScriptRegion.StartLineNumber);
+ Assert.Equal(7, referencesResult[0].ScriptRegion.StartColumnNumber);
+ }
+
+ [Fact]
+ public void FindsOccurrencesOnClass()
+ {
+ IReadOnlyList occurrencesResult = GetOccurrences(FindsOccurrencesOnTypeSymbolsData.ClassSourceDetails);
+ Assert.Equal(2, occurrencesResult.Count);
+ Assert.Equal("[SuperClass]", occurrencesResult[occurrencesResult.Count - 1].SymbolName);
+ Assert.Equal(34, occurrencesResult[occurrencesResult.Count - 1].ScriptRegion.StartLineNumber);
+ }
+
+ [Fact]
+ public async Task FindsEnumDefinition()
+ {
+ SymbolReference definitionResult = await GetDefinition(FindsTypeSymbolsDefinitionData.EnumSourceDetails).ConfigureAwait(true);
+ Assert.Equal(39, definitionResult.ScriptRegion.StartLineNumber);
+ Assert.Equal(6, definitionResult.ScriptRegion.StartColumnNumber);
+ Assert.Equal("MyEnum", definitionResult.SymbolName);
+ }
+
+ [Fact]
+ public async Task FindsReferencesOnEnum()
+ {
+ List referencesResult = await GetReferences(FindsReferencesOnTypeSymbolsData.EnumSourceDetails).ConfigureAwait(true);
+ Assert.Equal(4, referencesResult.Count);
+ Assert.Equal(25, referencesResult[0].ScriptRegion.StartLineNumber);
+ Assert.Equal(19, referencesResult[0].ScriptRegion.StartColumnNumber);
+ }
+
+ [Fact]
+ public void FindsOccurrencesOnEnum()
+ {
+ IReadOnlyList occurrencesResult = GetOccurrences(FindsOccurrencesOnTypeSymbolsData.EnumSourceDetails);
+ Assert.Equal(4, occurrencesResult.Count);
+ Assert.Equal("[MyEnum]", occurrencesResult[occurrencesResult.Count - 1].SymbolName);
+ Assert.Equal(46, occurrencesResult[occurrencesResult.Count - 1].ScriptRegion.StartLineNumber);
+ }
+
+ [Fact]
+ public async Task FindsTypeExpressionDefinition()
+ {
+ SymbolReference definitionResult = await GetDefinition(FindsTypeSymbolsDefinitionData.TypeExpressionSourceDetails).ConfigureAwait(true);
+ Assert.Equal(39, definitionResult.ScriptRegion.StartLineNumber);
+ Assert.Equal(6, definitionResult.ScriptRegion.StartColumnNumber);
+ Assert.Equal("MyEnum", definitionResult.SymbolName);
+ }
+
+ [Fact]
+ public async Task FindsReferencesOnTypeExpression()
+ {
+ List referencesResult = await GetReferences(FindsReferencesOnTypeSymbolsData.TypeExpressionSourceDetails).ConfigureAwait(true);
+ Assert.Equal(2, referencesResult.Count);
+ Assert.Equal(8, referencesResult[0].ScriptRegion.StartLineNumber);
+ Assert.Equal(7, referencesResult[0].ScriptRegion.StartColumnNumber);
+ }
+
+ [Fact]
+ public void FindsOccurrencesOnTypeExpression()
+ {
+ IReadOnlyList occurrencesResult = GetOccurrences(FindsOccurrencesOnTypeSymbolsData.TypeExpressionSourceDetails);
+ Assert.Equal(2, occurrencesResult.Count);
+ Assert.Equal("SuperClass", occurrencesResult[0].SymbolName);
+ Assert.Equal(8, occurrencesResult[0].ScriptRegion.StartLineNumber);
+ }
+
+ [Fact]
+ public async Task FindsTypeConstraintDefinition()
+ {
+ SymbolReference definitionResult = await GetDefinition(FindsTypeSymbolsDefinitionData.TypeConstraintSourceDetails).ConfigureAwait(true);
+ Assert.Equal(39, definitionResult.ScriptRegion.StartLineNumber);
+ Assert.Equal(6, definitionResult.ScriptRegion.StartColumnNumber);
+ Assert.Equal("MyEnum", definitionResult.SymbolName);
+ }
+
+ [Fact]
+ public async Task FindsReferencesOnTypeConstraint()
+ {
+ List referencesResult = await GetReferences(FindsReferencesOnTypeSymbolsData.TypeConstraintSourceDetails).ConfigureAwait(true);
+ Assert.Equal(4, referencesResult.Count);
+ Assert.Equal(25, referencesResult[0].ScriptRegion.StartLineNumber);
+ Assert.Equal(19, referencesResult[0].ScriptRegion.StartColumnNumber);
+ }
+
+ [Fact]
+ public void FindsOccurrencesOnTypeConstraint()
+ {
+ IReadOnlyList occurrencesResult = GetOccurrences(FindsOccurrencesOnTypeSymbolsData.TypeConstraintSourceDetails);
+ Assert.Equal(2, occurrencesResult.Count);
+ Assert.Equal("BaseClass", occurrencesResult[0].SymbolName);
+ Assert.Equal(4, occurrencesResult[0].ScriptRegion.StartLineNumber);
+ }
+
+ [Fact]
+ public async Task FindsConstructorDefinition()
+ {
+ SymbolReference definitionResult = await GetDefinition(FindsTypeSymbolsDefinitionData.ConstructorSourceDetails).ConfigureAwait(true);
+ Assert.Equal(9, definitionResult.ScriptRegion.StartLineNumber);
+ Assert.Equal(5, definitionResult.ScriptRegion.StartColumnNumber);
+ Assert.Equal("SuperClass.SuperClass([string]$name)", definitionResult.SymbolName);
+ }
+
+ [Fact]
+ public async Task FindsReferencesOnConstructor()
+ {
+ List referencesResult = await GetReferences(FindsReferencesOnTypeSymbolsData.ConstructorSourceDetails).ConfigureAwait(true);
+ Assert.Single(referencesResult);
+ Assert.Equal(9, referencesResult[0].ScriptRegion.StartLineNumber);
+ Assert.Equal(5, referencesResult[0].ScriptRegion.StartColumnNumber);
+ }
+
+ [Fact]
+ public void FindsOccurrencesOnConstructor()
+ {
+ IReadOnlyList occurrencesResult = GetOccurrences(FindsOccurrencesOnTypeSymbolsData.ConstructorSourceDetails);
+ Assert.Single(occurrencesResult);
+ Assert.Equal("SuperClass.SuperClass()", occurrencesResult[occurrencesResult.Count - 1].SymbolName);
+ Assert.Equal(13, occurrencesResult[occurrencesResult.Count - 1].ScriptRegion.StartLineNumber);
+ }
+
+ [Fact]
+ public async Task FindsMethodDefinition()
+ {
+ SymbolReference definitionResult = await GetDefinition(FindsTypeSymbolsDefinitionData.MethodSourceDetails).ConfigureAwait(true);
+ Assert.Equal(19, definitionResult.ScriptRegion.StartLineNumber);
+ Assert.Equal(13, definitionResult.ScriptRegion.StartColumnNumber);
+ Assert.Equal("SuperClass.MyClassMethod([string]$param1, $param2, [int]$param3)", definitionResult.SymbolName);
+ }
+
+ [Fact]
+ public async Task FindsReferencesOnMethod()
+ {
+ List referencesResult = await GetReferences(FindsReferencesOnTypeSymbolsData.MethodSourceDetails).ConfigureAwait(true);
+ Assert.Single(referencesResult);
+ Assert.Equal(19, referencesResult[0].ScriptRegion.StartLineNumber);
+ Assert.Equal(13, referencesResult[0].ScriptRegion.StartColumnNumber);
+ }
+
+ [Fact]
+ public void FindsOccurrencesOnMethod()
+ {
+ IReadOnlyList occurrencesResult = GetOccurrences(FindsOccurrencesOnTypeSymbolsData.MethodSourceDetails);
+ Assert.Single(occurrencesResult);
+ Assert.Equal("SuperClass.MyClassMethod()", occurrencesResult[occurrencesResult.Count - 1].SymbolName);
+ Assert.Equal(28, occurrencesResult[occurrencesResult.Count - 1].ScriptRegion.StartLineNumber);
+ }
+
+ [Fact]
+ public async Task FindsPropertyDefinition()
+ {
+ SymbolReference definitionResult = await GetDefinition(FindsTypeSymbolsDefinitionData.PropertySourceDetails).ConfigureAwait(true);
+ Assert.Equal(15, definitionResult.ScriptRegion.StartLineNumber);
+ Assert.Equal(13, definitionResult.ScriptRegion.StartColumnNumber);
+ Assert.Equal("SuperClass.SomePropWithDefault", definitionResult.SymbolName);
+ }
+
+ [Fact]
+ public async Task FindsReferencesOnProperty()
+ {
+ List referencesResult = await GetReferences(FindsReferencesOnTypeSymbolsData.PropertySourceDetails).ConfigureAwait(true);
+ Assert.Single(referencesResult);
+ Assert.Equal(17, referencesResult[0].ScriptRegion.StartLineNumber);
+ Assert.Equal(10, referencesResult[0].ScriptRegion.StartColumnNumber);
+ }
+
+ [Fact]
+ public void FindsOccurrencesOnProperty()
+ {
+ IReadOnlyList occurrencesResult = GetOccurrences(FindsOccurrencesOnTypeSymbolsData.PropertySourceDetails);
+ Assert.Equal(1, occurrencesResult.Count);
+ Assert.Equal("SuperClass.SomePropWithDefault", occurrencesResult[occurrencesResult.Count - 1].SymbolName);
+ Assert.Equal(15, occurrencesResult[occurrencesResult.Count - 1].ScriptRegion.StartLineNumber);
+ }
+
+ [Fact]
+ public async Task FindsEnumMemberDefinition()
+ {
+ SymbolReference definitionResult = await GetDefinition(FindsTypeSymbolsDefinitionData.EnumMemberSourceDetails).ConfigureAwait(true);
+ Assert.Equal(41, definitionResult.ScriptRegion.StartLineNumber);
+ Assert.Equal(5, definitionResult.ScriptRegion.StartColumnNumber);
+ Assert.Equal("MyEnum.Second", definitionResult.SymbolName);
+ }
+
+ [Fact]
+ public async Task FindsReferencesOnEnumMember()
+ {
+ List referencesResult = await GetReferences(FindsReferencesOnTypeSymbolsData.EnumMemberSourceDetails).ConfigureAwait(true);
+ Assert.Single(referencesResult);
+ Assert.Equal(41, referencesResult[0].ScriptRegion.StartLineNumber);
+ Assert.Equal(5, referencesResult[0].ScriptRegion.StartColumnNumber);
+ }
+
+ [Fact]
+ public void FindsOccurrencesOnEnumMember()
+ {
+ IReadOnlyList occurrencesResult = GetOccurrences(FindsOccurrencesOnTypeSymbolsData.EnumMemberSourceDetails);
+ Assert.Single(occurrencesResult);
+ Assert.Equal("MyEnum.First", occurrencesResult[occurrencesResult.Count - 1].SymbolName);
+ Assert.Equal(40, occurrencesResult[occurrencesResult.Count - 1].ScriptRegion.StartLineNumber);
+ }
+
[Fact]
public async Task FindsReferencesOnFileWithReferencesFileB()
{
@@ -279,6 +504,50 @@ public async Task FindsDetailsForBuiltInCommand()
Assert.NotEqual("", symbolDetails.Documentation);
}
+ [Fact]
+ public async Task FindsDetailsWithSignatureForEnumMember()
+ {
+ SymbolDetails symbolDetails = await symbolsService.FindSymbolDetailsAtLocationAsync(
+ GetScriptFile(FindsDetailsForTypeSymbolsData.EnumMemberSourceDetails),
+ FindsDetailsForTypeSymbolsData.EnumMemberSourceDetails.StartLineNumber,
+ FindsDetailsForTypeSymbolsData.EnumMemberSourceDetails.StartColumnNumber).ConfigureAwait(true);
+
+ Assert.Equal("MyEnum.First", symbolDetails.DisplayString);
+ }
+
+ [Fact]
+ public async Task FindsDetailsWithSignatureForProperty()
+ {
+ SymbolDetails symbolDetails = await symbolsService.FindSymbolDetailsAtLocationAsync(
+ GetScriptFile(FindsDetailsForTypeSymbolsData.PropertySourceDetails),
+ FindsDetailsForTypeSymbolsData.PropertySourceDetails.StartLineNumber,
+ FindsDetailsForTypeSymbolsData.PropertySourceDetails.StartColumnNumber).ConfigureAwait(true);
+
+ Assert.Equal("string SuperClass.SomePropWithDefault", symbolDetails.DisplayString);
+ }
+
+ [Fact]
+ public async Task FindsDetailsWithSignatureForConstructor()
+ {
+ SymbolDetails symbolDetails = await symbolsService.FindSymbolDetailsAtLocationAsync(
+ GetScriptFile(FindsDetailsForTypeSymbolsData.ConstructorSourceDetails),
+ FindsDetailsForTypeSymbolsData.ConstructorSourceDetails.StartLineNumber,
+ FindsDetailsForTypeSymbolsData.ConstructorSourceDetails.StartColumnNumber).ConfigureAwait(true);
+
+ Assert.Equal("SuperClass.SuperClass([string]$name)", symbolDetails.DisplayString);
+ }
+
+ [Fact]
+ public async Task FindsDetailsWithSignatureForMethod()
+ {
+ SymbolDetails symbolDetails = await symbolsService.FindSymbolDetailsAtLocationAsync(
+ GetScriptFile(FindsDetailsForTypeSymbolsData.MethodSourceDetails),
+ FindsDetailsForTypeSymbolsData.MethodSourceDetails.StartLineNumber,
+ FindsDetailsForTypeSymbolsData.MethodSourceDetails.StartColumnNumber).ConfigureAwait(true);
+
+ Assert.Equal("string SuperClass.MyClassMethod([string]$param1, $param2, [int]$param3)", symbolDetails.DisplayString);
+ }
+
[Fact]
public void FindsSymbolsInFile()
{
From a20cf9945b4e404068a635de173a9fa224af4008 Mon Sep 17 00:00:00 2001
From: Frode Flaten <3436158+fflaten@users.noreply.github.com>
Date: Thu, 25 Aug 2022 19:12:50 +0000
Subject: [PATCH 16/18] add codelens tests
---
.../LanguageServerProtocolMessageTests.cs | 106 +++++++++++++++++-
1 file changed, 105 insertions(+), 1 deletion(-)
diff --git a/test/PowerShellEditorServices.Test.E2E/LanguageServerProtocolMessageTests.cs b/test/PowerShellEditorServices.Test.E2E/LanguageServerProtocolMessageTests.cs
index 5011d5245..d990ebe09 100644
--- a/test/PowerShellEditorServices.Test.E2E/LanguageServerProtocolMessageTests.cs
+++ b/test/PowerShellEditorServices.Test.E2E/LanguageServerProtocolMessageTests.cs
@@ -841,7 +841,7 @@ public async Task NoMessageIfPesterCodeLensDisabled()
}
[Fact]
- public async Task CanSendReferencesCodeLensRequestAsync()
+ public async Task CanSendFunctionReferencesCodeLensRequestAsync()
{
string filePath = NewTestFile(@"
function CanSendReferencesCodeLensRequest {
@@ -878,6 +878,110 @@ function CanSendReferencesCodeLensRequest {
Assert.Equal("1 reference", codeLensResolveResult.Command.Title);
}
+ [Fact]
+ public async Task CanSendClassReferencesCodeLensRequestAsync()
+ {
+ string filePath = NewTestFile(@"
+param(
+ [MyBaseClass]$enumValue
+)
+
+class MyBaseClass {
+
+}
+
+class ChildClass : MyBaseClass, System.IDisposable {
+
+}
+
+$o = [MyBaseClass]::new()
+$o -is [MyBaseClass]
+");
+
+ CodeLensContainer codeLenses = await PsesLanguageClient
+ .SendRequest(
+ "textDocument/codeLens",
+ new CodeLensParams
+ {
+ TextDocument = new TextDocumentIdentifier
+ {
+ Uri = new Uri(filePath)
+ }
+ })
+ .Returning(CancellationToken.None).ConfigureAwait(true);
+
+ Assert.Collection(codeLenses,
+ codeLens =>
+ {
+ Range range = codeLens.Range;
+ Assert.Equal(5, range.Start.Line);
+ Assert.Equal(6, range.Start.Character);
+ Assert.Equal(7, range.End.Line);
+ Assert.Equal(1, range.End.Character);
+ },
+ codeLens =>
+ {
+ Range range = codeLens.Range;
+ Assert.Equal(9, range.Start.Line);
+ Assert.Equal(6, range.Start.Character);
+ Assert.Equal(11, range.End.Line);
+ Assert.Equal(1, range.End.Character);
+ }
+ );
+
+ CodeLens baseClassCodeLens = codeLenses.First();
+ CodeLens codeLensResolveResult = await PsesLanguageClient
+ .SendRequest("codeLens/resolve", baseClassCodeLens)
+ .Returning(CancellationToken.None).ConfigureAwait(true);
+
+ Assert.Equal("4 references", codeLensResolveResult.Command.Title);
+ }
+
+ [Fact]
+ public async Task CanSendEnumReferencesCodeLensRequestAsync()
+ {
+ string filePath = NewTestFile(@"
+param(
+ [MyEnum]$enumValue
+)
+
+enum MyEnum {
+ First = 1
+ Second
+ Third
+}
+
+[MyEnum]::First
+'First' -is [MyEnum]
+");
+
+ CodeLensContainer codeLenses = await PsesLanguageClient
+ .SendRequest(
+ "textDocument/codeLens",
+ new CodeLensParams
+ {
+ TextDocument = new TextDocumentIdentifier
+ {
+ Uri = new Uri(filePath)
+ }
+ })
+ .Returning(CancellationToken.None).ConfigureAwait(true);
+
+ CodeLens codeLens = Assert.Single(codeLenses);
+
+ Range range = codeLens.Range;
+ Assert.Equal(5, range.Start.Line);
+ Assert.Equal(5, range.Start.Character);
+ Assert.Equal(9, range.End.Line);
+ Assert.Equal(1, range.End.Character);
+
+ CodeLens codeLensResolveResult = await PsesLanguageClient
+ .SendRequest("codeLens/resolve", codeLens)
+ .Returning(CancellationToken.None).ConfigureAwait(true);
+
+ Assert.Equal("3 references", codeLensResolveResult.Command.Title);
+ }
+
[SkippableFact]
public async Task CanSendCodeActionRequestAsync()
{
From 2aeca75f5b77adfe8f6c6ab1b79c3a77135d26d7 Mon Sep 17 00:00:00 2001
From: Frode Flaten <3436158+fflaten@users.noreply.github.com>
Date: Thu, 25 Aug 2022 19:34:02 +0000
Subject: [PATCH 17/18] add symbol tests using newline after keyword
---
.../Symbols/FindSymbolsInNewLineSymbolFile.cs | 21 ++++++++
.../Symbols/NewLineSymbols.ps1 | 28 ++++++++++
.../Language/SymbolsServiceTests.cs | 51 +++++++++++++++++++
3 files changed, 100 insertions(+)
create mode 100644 test/PowerShellEditorServices.Test.Shared/Symbols/FindSymbolsInNewLineSymbolFile.cs
create mode 100644 test/PowerShellEditorServices.Test.Shared/Symbols/NewLineSymbols.ps1
diff --git a/test/PowerShellEditorServices.Test.Shared/Symbols/FindSymbolsInNewLineSymbolFile.cs b/test/PowerShellEditorServices.Test.Shared/Symbols/FindSymbolsInNewLineSymbolFile.cs
new file mode 100644
index 000000000..0be43f8d1
--- /dev/null
+++ b/test/PowerShellEditorServices.Test.Shared/Symbols/FindSymbolsInNewLineSymbolFile.cs
@@ -0,0 +1,21 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Microsoft.PowerShell.EditorServices.Services.TextDocument;
+
+namespace Microsoft.PowerShell.EditorServices.Test.Shared.Symbols
+{
+ public static class FindSymbolsInNewLineSymbolFile
+ {
+ public static readonly ScriptRegion SourceDetails =
+ new(
+ file: TestUtilities.NormalizePath("Symbols/NewLineSymbols.ps1"),
+ text: string.Empty,
+ startLineNumber: 0,
+ startColumnNumber: 0,
+ startOffset: 0,
+ endLineNumber: 0,
+ endColumnNumber: 0,
+ endOffset: 0);
+ }
+}
diff --git a/test/PowerShellEditorServices.Test.Shared/Symbols/NewLineSymbols.ps1 b/test/PowerShellEditorServices.Test.Shared/Symbols/NewLineSymbols.ps1
new file mode 100644
index 000000000..5ca44f02a
--- /dev/null
+++ b/test/PowerShellEditorServices.Test.Shared/Symbols/NewLineSymbols.ps1
@@ -0,0 +1,28 @@
+function
+returnTrue {
+ $true
+}
+
+class
+NewLineClass {
+ NewLineClass() {
+
+ }
+
+ static
+ hidden
+ [string]
+ $SomePropWithDefault = 'some value'
+
+ static
+ hidden
+ [string]
+ MyClassMethod([MyNewLineEnum]$param1) {
+ return 'hello world $param1'
+ }
+}
+
+enum
+MyNewLineEnum {
+ First
+}
diff --git a/test/PowerShellEditorServices.Test/Language/SymbolsServiceTests.cs b/test/PowerShellEditorServices.Test/Language/SymbolsServiceTests.cs
index c3de81c8d..26754f92b 100644
--- a/test/PowerShellEditorServices.Test/Language/SymbolsServiceTests.cs
+++ b/test/PowerShellEditorServices.Test/Language/SymbolsServiceTests.cs
@@ -611,6 +611,57 @@ public void FindsSymbolsInFile()
Assert.Equal(5, firstEnumMemberSymbol.ScriptRegion.StartColumnNumber);
}
+ [Fact]
+ public void FindsSymbolsWithNewLineInFile()
+ {
+ List symbolsResult =
+ FindSymbolsInFile(
+ FindSymbolsInNewLineSymbolFile.SourceDetails);
+
+ Assert.Single(symbolsResult.Where(symbolReference => symbolReference.SymbolType == SymbolType.Function));
+ Assert.Single(symbolsResult.Where(symbolReference => symbolReference.SymbolType == SymbolType.Class));
+ Assert.Single(symbolsResult.Where(symbolReference => symbolReference.SymbolType == SymbolType.Constructor));
+ Assert.Single(symbolsResult.Where(symbolReference => symbolReference.SymbolType == SymbolType.Property));
+ Assert.Single(symbolsResult.Where(symbolReference => symbolReference.SymbolType == SymbolType.Method));
+ Assert.Single(symbolsResult.Where(symbolReference => symbolReference.SymbolType == SymbolType.Enum));
+ Assert.Single(symbolsResult.Where(symbolReference => symbolReference.SymbolType == SymbolType.EnumMember));
+
+ SymbolReference firstFunctionSymbol = symbolsResult.First(r => r.SymbolType == SymbolType.Function);
+ Assert.Equal("returnTrue", firstFunctionSymbol.SymbolName);
+ Assert.Equal(2, firstFunctionSymbol.ScriptRegion.StartLineNumber);
+ Assert.Equal(1, firstFunctionSymbol.ScriptRegion.StartColumnNumber);
+
+ SymbolReference firstClassSymbol = symbolsResult.First(r => r.SymbolType == SymbolType.Class);
+ Assert.Equal("NewLineClass", firstClassSymbol.SymbolName);
+ Assert.Equal(7, firstClassSymbol.ScriptRegion.StartLineNumber);
+ Assert.Equal(1, firstClassSymbol.ScriptRegion.StartColumnNumber);
+
+ SymbolReference firstConstructorSymbol = symbolsResult.First(r => r.SymbolType == SymbolType.Constructor);
+ Assert.Equal("NewLineClass()", firstConstructorSymbol.SymbolName);
+ Assert.Equal(8, firstConstructorSymbol.ScriptRegion.StartLineNumber);
+ Assert.Equal(5, firstConstructorSymbol.ScriptRegion.StartColumnNumber);
+
+ SymbolReference firstPropertySymbol = symbolsResult.First(r => r.SymbolType == SymbolType.Property);
+ Assert.Equal("SomePropWithDefault", firstPropertySymbol.SymbolName);
+ Assert.Equal(15, firstPropertySymbol.ScriptRegion.StartLineNumber);
+ Assert.Equal(5, firstPropertySymbol.ScriptRegion.StartColumnNumber);
+
+ SymbolReference firstMethodSymbol = symbolsResult.First(r => r.SymbolType == SymbolType.Method);
+ Assert.Equal("MyClassMethod([MyNewLineEnum]$param1)", firstMethodSymbol.SymbolName);
+ Assert.Equal(20, firstMethodSymbol.ScriptRegion.StartLineNumber);
+ Assert.Equal(5, firstMethodSymbol.ScriptRegion.StartColumnNumber);
+
+ SymbolReference firstEnumSymbol = symbolsResult.First(r => r.SymbolType == SymbolType.Enum);
+ Assert.Equal("MyNewLineEnum", firstEnumSymbol.SymbolName);
+ Assert.Equal(26, firstEnumSymbol.ScriptRegion.StartLineNumber);
+ Assert.Equal(1, firstEnumSymbol.ScriptRegion.StartColumnNumber);
+
+ SymbolReference firstEnumMemberSymbol = symbolsResult.First(r => r.SymbolType == SymbolType.EnumMember);
+ Assert.Equal("First", firstEnumMemberSymbol.SymbolName);
+ Assert.Equal(27, firstEnumMemberSymbol.ScriptRegion.StartLineNumber);
+ Assert.Equal(5, firstEnumMemberSymbol.ScriptRegion.StartColumnNumber);
+ }
+
[SkippableFact]
public void FindsSymbolsInDSCFile()
{
From 1171939a385fd53cb93e7a56420a0f338f0dd7c8 Mon Sep 17 00:00:00 2001
From: Frode Flaten <3436158+fflaten@users.noreply.github.com>
Date: Thu, 25 Aug 2022 19:45:19 +0000
Subject: [PATCH 18/18] fix DSC symbol test
---
.../Language/SymbolsServiceTests.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/test/PowerShellEditorServices.Test/Language/SymbolsServiceTests.cs b/test/PowerShellEditorServices.Test/Language/SymbolsServiceTests.cs
index 26754f92b..0f30eccde 100644
--- a/test/PowerShellEditorServices.Test/Language/SymbolsServiceTests.cs
+++ b/test/PowerShellEditorServices.Test/Language/SymbolsServiceTests.cs
@@ -673,7 +673,7 @@ public void FindsSymbolsInDSCFile()
SymbolReference firstConfigurationSymbol = symbolsResult.First(r => r.SymbolType == SymbolType.Configuration);
Assert.Equal("AConfiguration", firstConfigurationSymbol.SymbolName);
Assert.Equal(2, firstConfigurationSymbol.ScriptRegion.StartLineNumber);
- Assert.Equal(1, firstConfigurationSymbol.ScriptRegion.StartColumnNumber);
+ Assert.Equal(15, firstConfigurationSymbol.ScriptRegion.StartColumnNumber);
}
[Fact]