diff --git a/src/PowerShellEditorServices.Hosting/BuildInfo.cs b/src/PowerShellEditorServices.Hosting/BuildInfo.cs index f516c8a8e..3a1b393b9 100644 --- a/src/PowerShellEditorServices.Hosting/BuildInfo.cs +++ b/src/PowerShellEditorServices.Hosting/BuildInfo.cs @@ -5,7 +5,7 @@ namespace Microsoft.PowerShell.EditorServices.Hosting public static class BuildInfo { public static readonly string BuildVersion = ""; - public static readonly string BuildOrigin = ""; - public static readonly System.DateTime? BuildTime = System.DateTime.Parse("2019-12-06T21:43:41", CultureInfo.InvariantCulture.DateTimeFormat); + public static readonly string BuildOrigin = "Development"; + public static readonly System.DateTime? BuildTime = System.DateTime.Parse("2020-10-07T03:34:58", CultureInfo.InvariantCulture.DateTimeFormat); } } diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/AstOperations.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/AstOperations.cs index 1ed34dc96..2a83b0853 100644 --- a/src/PowerShellEditorServices/Services/Symbols/Vistors/AstOperations.cs +++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/AstOperations.cs @@ -153,16 +153,35 @@ public static SymbolReference FindSymbolAtPosition( int columnNumber, bool includeFunctionDefinitions = false) { - FindSymbolVisitor symbolVisitor = - new FindSymbolVisitor( - lineNumber, - columnNumber, - includeFunctionDefinitions); - - scriptAst.Visit(symbolVisitor); - - return symbolVisitor.FoundSymbolReference; - } + var condition = new Func ( x => (x.Extent.StartLineNumber == lineNumber && x.Extent.EndLineNumber == lineNumber && x.Extent.StartColumnNumber <= columnNumber && x.Extent.EndColumnNumber >= columnNumber)); + List lAst = scriptAst.FindAll(condition, true)?.OrderBy(x => x.Extent.Text.Length).Take(1).ToList(); + if (lAst.Count == 0) { + condition = new Func(x => (x.Extent.StartLineNumber == lineNumber && x.Extent.EndLineNumber > lineNumber && x.Extent.StartColumnNumber <= columnNumber)); + lAst = scriptAst.FindAll(condition, true)?.OrderBy(x => x.Extent.Text.Length).Take(1).ToList(); + } + if (lAst.Count == 0) return null; + Ast ast = lAst[0]; + string name = null; + name = (ast is PropertyMemberAst) ? (ast as PropertyMemberAst).Name : + (ast is FunctionDefinitionAst) ? (ast as FunctionDefinitionAst).Name : + (ast is FunctionMemberAst) ? (ast as FunctionMemberAst).Name : + //(ast is NamedBlockAst) ? (ast as NamedBlockAst).BlockKind.ToString() : + (ast is TypeExpressionAst) ? (ast as TypeExpressionAst).TypeName.ToString() : null; + + if (name!=null) { + int startColumnNumber = ast.Extent.Text.IndexOf(name) + 1; + IScriptExtent nameExtent = new ScriptExtent() { + Text = name, + StartLineNumber = ast.Extent.StartLineNumber, + EndLineNumber = ast.Extent.EndLineNumber, + StartColumnNumber = ast.Extent.StartColumnNumber + startColumnNumber, + EndColumnNumber = ast.Extent.StartColumnNumber + name.Length, + File = ast.Extent.File + }; + return new SymbolReference(SymbolType.Function, nameExtent); + } + return new SymbolReference(SymbolType.Function, ast.Extent); + } /// /// Finds the symbol (always Command type) at a given file location @@ -194,15 +213,13 @@ public static IEnumerable FindReferencesOfSymbol( Dictionary AliasToCmdletDictionary) { // find the symbol evaluators for the node types we are handling - FindReferencesVisitor referencesVisitor = - new FindReferencesVisitor( - symbolReference, - CmdletToAliasDictionary, - AliasToCmdletDictionary); + FindReferencesVisitor referencesVisitor = new FindReferencesVisitor(symbolReference, CmdletToAliasDictionary, AliasToCmdletDictionary); scriptAst.Visit(referencesVisitor); - return referencesVisitor.FoundReferences; - } + FindReferencesVisitor2 declarationVisitor2 = new FindReferencesVisitor2(symbolReference); + scriptAst.Visit(declarationVisitor2); + return referencesVisitor.FoundReferences.Concat(declarationVisitor2.FoundReferences).ToList(); + } /// /// Finds all references (not including aliases) in a script for the given symbol @@ -218,11 +235,12 @@ public static IEnumerable FindReferencesOfSymbol( SymbolReference foundSymbol, bool needsAliases) { - FindReferencesVisitor referencesVisitor = - new FindReferencesVisitor(foundSymbol); + FindReferencesVisitor referencesVisitor = new FindReferencesVisitor(foundSymbol); scriptAst.Visit(referencesVisitor); - return referencesVisitor.FoundReferences; + FindReferencesVisitor2 declarationVisitor2 = new FindReferencesVisitor2(foundSymbol); + scriptAst.Visit(declarationVisitor2); + return referencesVisitor.FoundReferences.Concat(declarationVisitor2.FoundReferences).ToList(); } /// @@ -235,13 +253,14 @@ public static SymbolReference FindDefinitionOfSymbol( Ast scriptAst, SymbolReference symbolReference) { - FindDeclarationVisitor declarationVisitor = - new FindDeclarationVisitor( - symbolReference); + FindDeclarationVisitor declarationVisitor = new FindDeclarationVisitor(symbolReference); scriptAst.Visit(declarationVisitor); + if (declarationVisitor.FoundDeclaration != null) return declarationVisitor.FoundDeclaration; - return declarationVisitor.FoundDeclaration; - } + FindDeclarationVisitor2 declarationVisitor2 = new FindDeclarationVisitor2(symbolReference); + scriptAst.Visit(declarationVisitor2); + return declarationVisitor2.FoundDeclaration; + } /// /// Finds all symbols in a script diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindDeclarationVisitor.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindDeclarationVisitor.cs index 3ef4fc1ed..c8a86e6dd 100644 --- a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindDeclarationVisitor.cs +++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindDeclarationVisitor.cs @@ -8,6 +8,43 @@ namespace Microsoft.PowerShell.EditorServices.Services.Symbols { + internal class FindDeclarationVisitor2 : AstVisitor2 { + private SymbolReference symbolRef; + private string variableName; + + public SymbolReference FoundDeclaration { get; private set; } + + public FindDeclarationVisitor2(SymbolReference symbolRef) { + this.symbolRef = symbolRef; + if (this.symbolRef.SymbolType == SymbolType.Variable) { + // converts `$varName` to `varName` or of the form ${varName} to varName + variableName = symbolRef.SymbolName.TrimStart('$').Trim('{', '}'); + } + } + private bool ValidateExtend(string searchName, string foundName, Ast ast) { + if (!(symbolRef.SymbolType.Equals(SymbolType.Function) && foundName.Equals(searchName, StringComparison.CurrentCultureIgnoreCase))) return false; + int startColumnNumber = ast.Extent.StartScriptPosition.ColumnNumber + ast.Extent.Text.IndexOf(foundName, StringComparison.OrdinalIgnoreCase); + IScriptExtent nameExtent = new ScriptExtent() { Text = foundName, StartLineNumber = ast.Extent.StartLineNumber, StartColumnNumber = startColumnNumber, EndLineNumber = ast.Extent.StartLineNumber, EndColumnNumber = startColumnNumber + foundName.Length, File = ast.Extent.File }; + this.FoundDeclaration = new SymbolReference(SymbolType.Function, nameExtent); + return true; + } + public override AstVisitAction VisitMemberExpression(MemberExpressionAst memberExpressionAst) { + if (!ValidateExtend(symbolRef.ScriptRegion.Text, memberExpressionAst.Member.ToString(), memberExpressionAst)) return AstVisitAction.Continue; + return AstVisitAction.StopVisit; + } + public override AstVisitAction VisitFunctionMember(FunctionMemberAst functionMemberAst) { + if (!ValidateExtend(symbolRef.ScriptRegion.Text, functionMemberAst.Name, functionMemberAst)) return AstVisitAction.Continue; + return AstVisitAction.StopVisit; + } + public override AstVisitAction VisitPropertyMember(PropertyMemberAst propertyMemberAst) { + if (!ValidateExtend(symbolRef.ScriptRegion.Text, propertyMemberAst.Name, propertyMemberAst)) return AstVisitAction.Continue; + return AstVisitAction.StopVisit; + } + public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst) { + if (!ValidateExtend(symbolRef.ScriptRegion.Text, typeDefinitionAst.Name, typeDefinitionAst)) return AstVisitAction.Continue; + return AstVisitAction.StopVisit; + } + } /// /// The visitor used to find the definition of a symbol /// diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs index 256cfe559..964db3abb 100644 --- a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs +++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs @@ -9,6 +9,93 @@ namespace Microsoft.PowerShell.EditorServices.Services.Symbols { + internal class FindReferencesVisitor2 : AstVisitor2 { + private SymbolReference symbolRef; + private Dictionary> CmdletToAliasDictionary; + private Dictionary AliasToCmdletDictionary; + private string symbolRefCommandName; + private bool needsAliases; + + public List FoundReferences { get; set; } + public FindReferencesVisitor2( + SymbolReference symbolReference, + Dictionary> CmdletToAliasDictionary, + Dictionary AliasToCmdletDictionary) { + this.symbolRef = symbolReference; + this.FoundReferences = new List(); + this.needsAliases = true; + this.CmdletToAliasDictionary = CmdletToAliasDictionary; + this.AliasToCmdletDictionary = AliasToCmdletDictionary; + + // Try to get the symbolReference's command name of an alias, + // if a command name does not exists (if the symbol isn't an alias to a command) + // set symbolRefCommandName to and empty string value + AliasToCmdletDictionary.TryGetValue(symbolReference.ScriptRegion.Text, out symbolRefCommandName); + if (symbolRefCommandName == null) { symbolRefCommandName = string.Empty; } + + } + public FindReferencesVisitor2(SymbolReference foundSymbol) { + this.symbolRef = foundSymbol; + this.FoundReferences = new List(); + this.needsAliases = false; + } + private void ValidateExtend(string searchName, string foundName, Ast ast) { + if (!foundName.Equals(searchName, StringComparison.CurrentCultureIgnoreCase)) return; + int startColumnNumber = ast.Extent.StartScriptPosition.ColumnNumber + ast.Extent.Text.IndexOf(foundName, StringComparison.OrdinalIgnoreCase); + IScriptExtent nameExtent = new ScriptExtent() {Text = foundName, StartLineNumber = ast.Extent.StartLineNumber, StartColumnNumber = startColumnNumber, EndLineNumber = ast.Extent.StartLineNumber, EndColumnNumber = startColumnNumber + foundName.Length, File = ast.Extent.File }; + this.FoundReferences.Add(new SymbolReference(SymbolType.Function, nameExtent)); + } + public override AstVisitAction VisitCommandExpression(CommandExpressionAst commandExpressionAst) {//confirmed + if (commandExpressionAst.ToString().Contains(symbolRef.ScriptRegion.Text)) + ValidateExtend(symbolRef.ScriptRegion.Text, commandExpressionAst.Expression.ToString(), commandExpressionAst); + return base.VisitCommandExpression(commandExpressionAst); + } + public override AstVisitAction VisitCommandParameter(CommandParameterAst commandParameterAst) { + if (commandParameterAst.ToString().Contains(symbolRef.ScriptRegion.Text)) + ValidateExtend(symbolRef.ScriptRegion.Text, commandParameterAst.ParameterName, commandParameterAst); + return base.VisitCommandParameter(commandParameterAst); + } + public override AstVisitAction VisitCommand(CommandAst commandAst) {//confirmed + if (commandAst.ToString().Contains(symbolRef.ScriptRegion.Text)) + ValidateExtend(symbolRef.ScriptRegion.Text, commandAst.GetCommandName(), commandAst); + return base.VisitCommand(commandAst); + } + public override AstVisitAction VisitConfigurationDefinition(ConfigurationDefinitionAst configurationDefinitionAst) { + if (configurationDefinitionAst.ToString().Contains(symbolRef.ScriptRegion.Text)) + ValidateExtend(symbolRef.ScriptRegion.Text, configurationDefinitionAst.InstanceName.ToString(), configurationDefinitionAst); + return base.VisitConfigurationDefinition(configurationDefinitionAst); + } + public override AstVisitAction VisitInvokeMemberExpression(InvokeMemberExpressionAst methodCallAst) {//confirmed + if (methodCallAst.ToString().Contains(symbolRef.ScriptRegion.Text)) + ValidateExtend(symbolRef.ScriptRegion.Text, methodCallAst.Member.ToString(), methodCallAst); + return base.VisitInvokeMemberExpression(methodCallAst); + } + public override AstVisitAction VisitMemberExpression(MemberExpressionAst memberExpressionAst) {//confirmed + if(memberExpressionAst.ToString().Contains(symbolRef.ScriptRegion.Text)) + ValidateExtend(symbolRef.ScriptRegion.Text, memberExpressionAst.Member.ToString(), memberExpressionAst); + return base.VisitMemberExpression(memberExpressionAst); + } + public override AstVisitAction VisitFunctionMember(FunctionMemberAst functionMemberAst) {//confirmed + if (functionMemberAst.ToString().Contains(symbolRef.ScriptRegion.Text)) + ValidateExtend(symbolRef.ScriptRegion.Text, functionMemberAst.Name, functionMemberAst); + return base.VisitFunctionMember(functionMemberAst); + } + public override AstVisitAction VisitPropertyMember(PropertyMemberAst propertyMemberAst) {//confirmed + if (propertyMemberAst.ToString().Contains(symbolRef.ScriptRegion.Text)) + ValidateExtend(symbolRef.ScriptRegion.Text, propertyMemberAst.Name, propertyMemberAst); + return base.VisitPropertyMember(propertyMemberAst); + } + public override AstVisitAction VisitStringConstantExpression(StringConstantExpressionAst stringConstantExpressionAst) {//confirmed + if (stringConstantExpressionAst.ToString().Contains(symbolRef.ScriptRegion.Text)) + ValidateExtend(symbolRef.ScriptRegion.Text, stringConstantExpressionAst.Value, stringConstantExpressionAst); + return base.VisitStringConstantExpression(stringConstantExpressionAst); + } + public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst) { + if (typeDefinitionAst.ToString().Contains(symbolRef.ScriptRegion.Text)) + ValidateExtend(symbolRef.ScriptRegion.Text, typeDefinitionAst.Name, typeDefinitionAst); + return base.VisitTypeDefinition(typeDefinitionAst); + } + } /// /// The visitor used to find the references of a symbol in a script's AST ///