diff --git a/.gitignore b/.gitignore
index ed6903bd0..4e31936dd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -43,9 +43,10 @@ ClientBin/
*.build.csdef
csx/
-# Temporarily exclude files generated by Script Analyzer build
-PSLanguageService/Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules.dll
-PSLanguageService/Microsoft.Windows.PowerShell.ScriptAnalyzer.dll
-PSLanguageService/PSScriptAnalyzer.psd1
-PSLanguageService/ScriptAnalyzer.format.ps1xml
-PSLanguageService/ScriptAnalyzer.types.ps1xml
+# Don't include ScriptAnalyzer binaries
+PowerShellEditorServices/Microsoft.Windows.PowerShell.ScriptAnalyzer.dll
+PowerShellEditorServices/Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules.dll
+PowerShellEditorServices/PSScriptAnalyzer.psd1
+PowerShellEditorServices/ScriptAnalyzer.format.ps1xml
+PowerShellEditorServices/ScriptAnalyzer.types.ps1xml
+
diff --git a/src/PowerShellEditorServices.Transport.Stdio/Message/MessageParser.cs b/src/PowerShellEditorServices.Transport.Stdio/Message/MessageParser.cs
index 477e3a39f..6cdc3a616 100644
--- a/src/PowerShellEditorServices.Transport.Stdio/Message/MessageParser.cs
+++ b/src/PowerShellEditorServices.Transport.Stdio/Message/MessageParser.cs
@@ -3,6 +3,7 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
+
using Microsoft.PowerShell.EditorServices.Utility;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
diff --git a/src/PowerShellEditorServices.Transport.Stdio/PowerShellEditorServices.Transport.Stdio.csproj b/src/PowerShellEditorServices.Transport.Stdio/PowerShellEditorServices.Transport.Stdio.csproj
index 7ca31e292..efe3c8b42 100644
--- a/src/PowerShellEditorServices.Transport.Stdio/PowerShellEditorServices.Transport.Stdio.csproj
+++ b/src/PowerShellEditorServices.Transport.Stdio/PowerShellEditorServices.Transport.Stdio.csproj
@@ -79,12 +79,23 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/PowerShellEditorServices.Transport.Stdio/Request/CompletionDetailsRequest.cs b/src/PowerShellEditorServices.Transport.Stdio/Request/CompletionDetailsRequest.cs
new file mode 100644
index 000000000..020b93de0
--- /dev/null
+++ b/src/PowerShellEditorServices.Transport.Stdio/Request/CompletionDetailsRequest.cs
@@ -0,0 +1,59 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using Microsoft.PowerShell.EditorServices.Language;
+using Microsoft.PowerShell.EditorServices.Session;
+using Microsoft.PowerShell.EditorServices.Transport.Stdio.Message;
+using Microsoft.PowerShell.EditorServices.Transport.Stdio.Response;
+using System.Collections.Generic;
+
+namespace Microsoft.PowerShell.EditorServices.Transport.Stdio.Request
+{
+ [MessageTypeName("completionEntryDetails")]
+ public class CompletionDetailsRequest : FileRequest
+ {
+ public override void ProcessMessage(
+ EditorSession editorSession,
+ MessageWriter messageWriter)
+ {
+ ScriptFile scriptFile = this.GetScriptFile(editorSession);
+
+ CompletionDetails completionDetails =
+ editorSession.LanguageService.GetCompletionDetailsInFile(
+ scriptFile,
+ this.Arguments.Line,
+ this.Arguments.Offset,
+ this.Arguments.EntryNames[0]);
+
+ var details = new List();
+ if (completionDetails != null)
+ {
+ details.Add(
+ new CompletionEntryDetails(completionDetails, this.Arguments.EntryNames[0]
+ ));
+ messageWriter.WriteMessage(
+ this.PrepareResponse(
+ new CompletionDetailsResponse
+ {
+ Body = details.ToArray()
+ }));
+ }
+ else
+ {
+ messageWriter.WriteMessage(
+ this.PrepareResponse(
+ new CompletionDetailsResponse{
+ Body = details.ToArray()
+ }));
+ }
+ }
+ }
+
+ public class CompletionDetailsRequestArgs : FileLocationRequestArgs
+ {
+ public string[] EntryNames { get; set; }
+ }
+
+}
diff --git a/src/PowerShellEditorServices.Transport.Stdio/Request/CompletionsRequest.cs b/src/PowerShellEditorServices.Transport.Stdio/Request/CompletionsRequest.cs
index a829ca545..c7b0f6d89 100644
--- a/src/PowerShellEditorServices.Transport.Stdio/Request/CompletionsRequest.cs
+++ b/src/PowerShellEditorServices.Transport.Stdio/Request/CompletionsRequest.cs
@@ -31,7 +31,6 @@ public override void ProcessMessage(
completions)));
}
}
-
public class CompletionsRequestArgs : FileLocationRequestArgs
{
public string Prefix { get; set; }
diff --git a/src/PowerShellEditorServices.Transport.Stdio/Request/DeclarationRequest.cs b/src/PowerShellEditorServices.Transport.Stdio/Request/DeclarationRequest.cs
new file mode 100644
index 000000000..900de6419
--- /dev/null
+++ b/src/PowerShellEditorServices.Transport.Stdio/Request/DeclarationRequest.cs
@@ -0,0 +1,38 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using Microsoft.PowerShell.EditorServices.Language;
+using Microsoft.PowerShell.EditorServices.Session;
+using Microsoft.PowerShell.EditorServices.Transport.Stdio.Message;
+using Microsoft.PowerShell.EditorServices.Transport.Stdio.Response;
+
+namespace Microsoft.PowerShell.EditorServices.Transport.Stdio.Request
+{
+ [MessageTypeName("definition")]
+ public class DeclarationRequest : FileRequest
+ {
+ public override void ProcessMessage(
+ EditorSession editorSession,
+ MessageWriter messageWriter)
+ {
+ ScriptFile scriptFile = this.GetScriptFile(editorSession);
+
+ GetDefinitionResult definition =
+ editorSession.LanguageService.GetDefinitionInFile(
+ scriptFile,
+ this.Arguments.Line,
+ this.Arguments.Offset);
+
+ if (definition != null)
+ {
+ DefinitionResponse defResponse =
+ DefinitionResponse.Create(definition.FoundDefinition, this.Arguments.File);
+
+ messageWriter.WriteMessage(
+ this.PrepareResponse(defResponse));
+ }
+ }
+ }
+}
diff --git a/src/PowerShellEditorServices.Transport.Stdio/Request/OccurrencesRequest.cs b/src/PowerShellEditorServices.Transport.Stdio/Request/OccurrencesRequest.cs
new file mode 100644
index 000000000..d8fe52a8f
--- /dev/null
+++ b/src/PowerShellEditorServices.Transport.Stdio/Request/OccurrencesRequest.cs
@@ -0,0 +1,36 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using Microsoft.PowerShell.EditorServices.Language;
+using Microsoft.PowerShell.EditorServices.Session;
+using Microsoft.PowerShell.EditorServices.Transport.Stdio.Message;
+using Microsoft.PowerShell.EditorServices.Transport.Stdio.Response;
+
+namespace Microsoft.PowerShell.EditorServices.Transport.Stdio.Request
+{
+ [MessageTypeName("occurrences")]
+ public class OccurrencesRequest : FileRequest
+ {
+ public override void ProcessMessage(
+ EditorSession editorSession,
+ MessageWriter messageWriter)
+ {
+ ScriptFile scriptFile = this.GetScriptFile(editorSession);
+
+ FindOccurrencesResult occurrencesResult =
+ editorSession.LanguageService.FindOccurrencesInFile(
+ scriptFile,
+ this.Arguments.Line,
+ this.Arguments.Offset);
+
+ OccurrencesResponse occurrencesResponce =
+ OccurrencesResponse.Create(occurrencesResult, this.Arguments.File);
+
+ messageWriter.WriteMessage(
+ this.PrepareResponse(
+ occurrencesResponce));
+ }
+ }
+}
diff --git a/src/PowerShellEditorServices.Transport.Stdio/Request/OpenFileRequest.cs b/src/PowerShellEditorServices.Transport.Stdio/Request/OpenFileRequest.cs
index 98a40552d..4fd581994 100644
--- a/src/PowerShellEditorServices.Transport.Stdio/Request/OpenFileRequest.cs
+++ b/src/PowerShellEditorServices.Transport.Stdio/Request/OpenFileRequest.cs
@@ -1,10 +1,10 @@
-using Microsoft.PowerShell.EditorServices.Session;
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using Microsoft.PowerShell.EditorServices.Session;
using Microsoft.PowerShell.EditorServices.Transport.Stdio.Message;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace Microsoft.PowerShell.EditorServices.Transport.Stdio.Request
{
diff --git a/src/PowerShellEditorServices.Transport.Stdio/Request/ReferencesRequest.cs b/src/PowerShellEditorServices.Transport.Stdio/Request/ReferencesRequest.cs
new file mode 100644
index 000000000..0f175db7d
--- /dev/null
+++ b/src/PowerShellEditorServices.Transport.Stdio/Request/ReferencesRequest.cs
@@ -0,0 +1,36 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using Microsoft.PowerShell.EditorServices.Language;
+using Microsoft.PowerShell.EditorServices.Session;
+using Microsoft.PowerShell.EditorServices.Transport.Stdio.Message;
+using Microsoft.PowerShell.EditorServices.Transport.Stdio.Response;
+
+namespace Microsoft.PowerShell.EditorServices.Transport.Stdio.Request
+{
+ [MessageTypeName("references")]
+ public class ReferencesRequest : FileRequest
+ {
+ public override void ProcessMessage(
+ EditorSession editorSession,
+ MessageWriter messageWriter)
+ {
+ ScriptFile scriptFile = this.GetScriptFile(editorSession);
+
+ FindReferencesResult referencesResult =
+ editorSession.LanguageService.FindReferencesInFile(
+ scriptFile,
+ this.Arguments.Line,
+ this.Arguments.Offset);
+
+ ReferencesResponse referencesResponse =
+ ReferencesResponse.Create(referencesResult, this.Arguments.File);
+
+ messageWriter.WriteMessage(
+ this.PrepareResponse(
+ referencesResponse));
+ }
+ }
+}
diff --git a/src/PowerShellEditorServices.Transport.Stdio/Request/SignatureHelpRequest.cs b/src/PowerShellEditorServices.Transport.Stdio/Request/SignatureHelpRequest.cs
new file mode 100644
index 000000000..7313e5fef
--- /dev/null
+++ b/src/PowerShellEditorServices.Transport.Stdio/Request/SignatureHelpRequest.cs
@@ -0,0 +1,40 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using Microsoft.PowerShell.EditorServices.Language;
+using Microsoft.PowerShell.EditorServices.Session;
+using Microsoft.PowerShell.EditorServices.Transport.Stdio.Message;
+using Microsoft.PowerShell.EditorServices.Transport.Stdio.Response;
+
+namespace Microsoft.PowerShell.EditorServices.Transport.Stdio.Request
+{
+ [MessageTypeName("signatureHelp")]
+ public class SignatureHelpRequest : FileRequest
+ {
+ public override void ProcessMessage(
+ EditorSession editorSession,
+ MessageWriter messageWriter)
+ {
+ ScriptFile scriptFile = this.GetScriptFile(editorSession);
+
+ ParameterSetSignatures parameterSetSigs =
+ editorSession.LanguageService.FindParameterSetsInFile(
+ scriptFile,
+ this.Arguments.Line,
+ this.Arguments.Offset);
+
+ SignatureHelpResponse sigHelpResponce =
+ SignatureHelpResponse.Create(parameterSetSigs);
+
+ messageWriter.WriteMessage(
+ this.PrepareResponse(
+ sigHelpResponce));
+ }
+ }
+
+ public class SignatureHelpRequestArgs : FileLocationRequestArgs
+ {
+ }
+}
diff --git a/src/PowerShellEditorServices.Transport.Stdio/Response/CompletionDetailsResponse.cs b/src/PowerShellEditorServices.Transport.Stdio/Response/CompletionDetailsResponse.cs
new file mode 100644
index 000000000..d64dca7ae
--- /dev/null
+++ b/src/PowerShellEditorServices.Transport.Stdio/Response/CompletionDetailsResponse.cs
@@ -0,0 +1,76 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using Microsoft.PowerShell.EditorServices.Language;
+using Microsoft.PowerShell.EditorServices.Transport.Stdio.Message;
+using System.Text.RegularExpressions;
+
+namespace Microsoft.PowerShell.EditorServices.Transport.Stdio.Response
+{
+ [MessageTypeName("completionEntryDetails")]
+ public class CompletionDetailsResponse : ResponseBase
+ {
+ }
+
+ public class CompletionEntryDetails
+ {
+ public CompletionEntryDetails(CompletionDetails completionResult, string entryName)
+ {
+
+ Kind = null;
+ KindModifiers = null;
+ DisplayParts = null;
+ Documentation = null;
+ DocString = null;
+
+ // if the result type is a command return null
+ if (completionResult != null &&
+ !(completionResult.CompletionType.Equals(CompletionType.Command)))
+ {
+ //find matches on square brackets in the the tool tip
+ var matches =
+ Regex.Matches(completionResult.ToolTipText, @"^\[(.+)\]");
+ string strippedEntryName =
+ Regex.Replace(entryName, @"^[$_-]", "").Replace("{", "").Replace("}", "");
+
+ if (matches.Count > 0 && matches[0].Groups.Count > 1)
+ {
+ Name = matches[0].Groups[1].Value;
+ }
+ // if there are nobracets and the only content is the completion name
+ else if (completionResult.ToolTipText.Equals(strippedEntryName))
+ {
+ Name = null;
+ }
+ else
+ {
+ Name = null;
+ DocString = completionResult.ToolTipText;
+ }
+ }
+
+ else { Name = null; }
+ }
+ public string Name { get; set; }
+
+ public string Kind { get; set; }
+
+ public string KindModifiers { get; set; }
+
+ public SymbolDisplayPart[] DisplayParts { get; set; }
+
+ public SymbolDisplayPart[] Documentation { get; set; }
+
+ public string DocString { get; set; }
+
+ }
+
+ public class SymbolDisplayPart
+ {
+ public string Text { get; set; }
+
+ public string Kind { get; set; }
+ }
+}
diff --git a/src/PowerShellEditorServices.Transport.Stdio/Response/CompletionsResponse.cs b/src/PowerShellEditorServices.Transport.Stdio/Response/CompletionsResponse.cs
index 2aa9810df..313faab30 100644
--- a/src/PowerShellEditorServices.Transport.Stdio/Response/CompletionsResponse.cs
+++ b/src/PowerShellEditorServices.Transport.Stdio/Response/CompletionsResponse.cs
@@ -45,4 +45,15 @@ private static string GetCompletionKind(CompletionType completionType)
}
}
}
+ public class CompletionEntry
+ {
+ public string Name { get; set; }
+
+ public string Kind { get; set; }
+
+ public string KindModifiers { get; set; }
+
+ public string SortText { get; set; }
+ }
+
}
diff --git a/src/PowerShellEditorServices.Transport.Stdio/Response/DefinitionResponse.cs b/src/PowerShellEditorServices.Transport.Stdio/Response/DefinitionResponse.cs
new file mode 100644
index 000000000..a3b315e2f
--- /dev/null
+++ b/src/PowerShellEditorServices.Transport.Stdio/Response/DefinitionResponse.cs
@@ -0,0 +1,50 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using Microsoft.PowerShell.EditorServices.Language;
+using Microsoft.PowerShell.EditorServices.Transport.Stdio.Message;
+using System.Collections.Generic;
+
+namespace Microsoft.PowerShell.EditorServices.Transport.Stdio.Response
+{
+ [MessageTypeName("definition")]
+ public class DefinitionResponse : ResponseBase
+ {
+ public static DefinitionResponse Create(SymbolReference result, string thisFile)
+ {
+ if (result != null)
+ {
+ //The protocol expects a filespan when there whould only be one definition
+ List declarResult = new List();
+ declarResult.Add(
+ new FileSpan()
+ {
+ Start = new Location
+ {
+ Line = result.ScriptRegion.StartLineNumber,
+ Offset = result.ScriptRegion.StartColumnNumber
+ },
+ End = new Location
+ {
+ Line = result.ScriptRegion.EndLineNumber,
+ Offset = result.ScriptRegion.EndColumnNumber
+ },
+ File = thisFile,
+ });
+ return new DefinitionResponse
+ {
+ Body = declarResult.ToArray()
+ };
+ }
+ else
+ {
+ return new DefinitionResponse
+ {
+ Body = null
+ };
+ }
+ }
+ }
+}
diff --git a/src/PowerShellEditorServices.Transport.Stdio/Response/LocationResponseElements.cs b/src/PowerShellEditorServices.Transport.Stdio/Response/LocationResponseElements.cs
new file mode 100644
index 000000000..deea5b67b
--- /dev/null
+++ b/src/PowerShellEditorServices.Transport.Stdio/Response/LocationResponseElements.cs
@@ -0,0 +1,26 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+namespace Microsoft.PowerShell.EditorServices.Transport.Stdio.Response
+{
+ public class TextSpan
+ {
+ public Location Start { get; set; }
+ public Location End { get; set; }
+ }
+
+ public class FileSpan : TextSpan
+ {
+ public string File { get; set; }
+ }
+
+ public class Location
+ {
+ public int Line { get; set; }
+
+ public int Offset { get; set; }
+ }
+
+}
diff --git a/src/PowerShellEditorServices.Transport.Stdio/Response/OccurrencesResponse.cs b/src/PowerShellEditorServices.Transport.Stdio/Response/OccurrencesResponse.cs
new file mode 100644
index 000000000..07e57de3e
--- /dev/null
+++ b/src/PowerShellEditorServices.Transport.Stdio/Response/OccurrencesResponse.cs
@@ -0,0 +1,60 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using Microsoft.PowerShell.EditorServices.Language;
+using Microsoft.PowerShell.EditorServices.Transport.Stdio.Message;
+using System.Collections.Generic;
+
+namespace Microsoft.PowerShell.EditorServices.Transport.Stdio.Response
+{
+ [MessageTypeName("occurrences")]
+ public class OccurrencesResponse : ResponseBase
+ {
+ public static OccurrencesResponse Create(FindOccurrencesResult occurrencesResult, string thisFile)
+ {
+ if (occurrencesResult != null)
+ {
+ List occurrenceItems =
+ new List();
+
+ foreach (SymbolReference reference in occurrencesResult.FoundOccurrences)
+ {
+ occurrenceItems.Add(
+ new OccurrencesResponseItem()
+ {
+ IsWriteAccess = true,
+ File = thisFile,
+ Start = new Location
+ {
+ Line = reference.ScriptRegion.StartLineNumber,
+ Offset = reference.ScriptRegion.StartColumnNumber
+ },
+ End = new Location
+ {
+ Line = reference.ScriptRegion.EndLineNumber,
+ Offset = reference.ScriptRegion.EndColumnNumber
+ },
+ });
+ }
+ return new OccurrencesResponse
+ {
+ Body = occurrenceItems.ToArray()
+ };
+ }
+ else
+ {
+ return new OccurrencesResponse
+ {
+ Body = null
+ };
+ }
+ }
+ }
+
+ public class OccurrencesResponseItem : FileSpan
+ {
+ public bool IsWriteAccess { get; set; }
+ }
+}
diff --git a/src/PowerShellEditorServices.Transport.Stdio/Response/ReferencesResponse.cs b/src/PowerShellEditorServices.Transport.Stdio/Response/ReferencesResponse.cs
new file mode 100644
index 000000000..788ced37e
--- /dev/null
+++ b/src/PowerShellEditorServices.Transport.Stdio/Response/ReferencesResponse.cs
@@ -0,0 +1,76 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using Microsoft.PowerShell.EditorServices.Language;
+using Microsoft.PowerShell.EditorServices.Transport.Stdio.Message;
+using System.Collections.Generic;
+
+namespace Microsoft.PowerShell.EditorServices.Transport.Stdio.Response
+{
+ [MessageTypeName("references")]
+ public class ReferencesResponse : ResponseBase
+ {
+ public static ReferencesResponse Create(FindReferencesResult referencesResult, string thisFile)
+ {
+ if (referencesResult != null && referencesResult.FoundReferences != null)
+ {
+ List referenceItems
+ = new List();
+
+ foreach (SymbolReference reference in referencesResult.FoundReferences)
+ {
+ referenceItems.Add(
+ new ReferencesResponseItem()
+ {
+ Start = new Location
+ {
+ Line = reference.ScriptRegion.StartLineNumber,
+ Offset = reference.ScriptRegion.StartColumnNumber
+ },
+ End = new Location
+ {
+ Line = reference.ScriptRegion.EndLineNumber,
+ Offset = reference.ScriptRegion.EndColumnNumber
+ },
+ IsWriteAccess = true,
+ File = thisFile,
+ LineText = reference.SourceLine
+ });
+ }
+ return new ReferencesResponse
+ {
+ Body = new ReferencesResponseBody
+ {
+ Refs = referenceItems.ToArray(),
+ SymbolName = referencesResult.SymbolName,
+ SymbolDisplayString = referencesResult.SymbolName,
+ SymbolStartOffest = referencesResult.SymbolFileOffset
+ }
+ };
+ }
+ else
+ {
+ return new ReferencesResponse
+ {
+ Body = null
+ };
+ }
+ }
+ }
+
+ public class ReferencesResponseBody
+ {
+ public ReferencesResponseItem[] Refs { get; set; }
+ public string SymbolName { get; set; }
+ public int SymbolStartOffest { get; set; }
+ public string SymbolDisplayString { get; set; }
+ }
+
+ public class ReferencesResponseItem : FileSpan
+ {
+ public string LineText { get; set; }
+ public bool IsWriteAccess { get; set; }
+ }
+}
diff --git a/src/PowerShellEditorServices.Transport.Stdio/Response/ResponseBase.cs b/src/PowerShellEditorServices.Transport.Stdio/Response/ResponseBase.cs
index bcb4c5f29..e646bfc41 100644
--- a/src/PowerShellEditorServices.Transport.Stdio/Response/ResponseBase.cs
+++ b/src/PowerShellEditorServices.Transport.Stdio/Response/ResponseBase.cs
@@ -3,10 +3,8 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
-using Microsoft.PowerShell.EditorServices.Language;
using Microsoft.PowerShell.EditorServices.Transport.Stdio.Message;
using Newtonsoft.Json;
-using System.Text.RegularExpressions;
namespace Microsoft.PowerShell.EditorServices.Transport.Stdio.Response
{
@@ -34,71 +32,4 @@ public ResponseBase()
this.Type = MessageType.Response;
}
}
-
- public class CompletionEntry
- {
- public string Name { get; set; }
-
- public string Kind { get; set; }
-
- public string KindModifiers { get; set; }
-
- public string SortText { get; set; }
- }
-
- public class CompletionEntryDetails
- {
- public CompletionEntryDetails(CompletionDetails completionDetails, string entryName)
- {
- Kind = null;
- KindModifiers = null;
- DisplayParts = null;
- Documentation = null;
- DocString = null;
-
- // if the result type is a command return null
- if (!(completionDetails.CompletionType.Equals(CompletionType.Command)))
- {
- //find matches on square brackets in the the tool tip
- var matches = Regex.Matches(completionDetails.ToolTipText, @"^\[(.+)\]");
- string strippedEntryName = Regex.Replace(entryName, @"^[$_-]","").Replace("{","").Replace("}","");
-
- if (matches.Count > 0 && matches[0].Groups.Count > 1)
- {
- Name = matches[0].Groups[1].Value;
- }
- // if there are nobracets and the only content is the completion name
- else if (completionDetails.ToolTipText.Equals(strippedEntryName))
- {
- Name = null;
- }
- else
- {
- Name = null;
- DocString = completionDetails.ToolTipText;
- }
- }
-
- else { Name = null; }
- }
- public string Name { get; set; }
-
- public string Kind { get; set; }
-
- public string KindModifiers { get; set; }
-
- public SymbolDisplayPart[] DisplayParts { get; set; }
-
- public SymbolDisplayPart[] Documentation { get; set; }
-
- public string DocString { get; set; }
-
- }
-
- public class SymbolDisplayPart
- {
- public string Text { get; set; }
-
- public string Kind { get; set; }
- }
}
diff --git a/src/PowerShellEditorServices.Transport.Stdio/Response/SignatureHelpResponse.cs b/src/PowerShellEditorServices.Transport.Stdio/Response/SignatureHelpResponse.cs
new file mode 100644
index 000000000..c3ada431a
--- /dev/null
+++ b/src/PowerShellEditorServices.Transport.Stdio/Response/SignatureHelpResponse.cs
@@ -0,0 +1,135 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using Microsoft.PowerShell.EditorServices.Language;
+using Microsoft.PowerShell.EditorServices.Transport.Stdio.Message;
+using System.Collections.Generic;
+
+namespace Microsoft.PowerShell.EditorServices.Transport.Stdio.Response
+{
+ [MessageTypeName("signatureHelp")]
+ public class SignatureHelpResponse : ResponseBase
+ {
+ public static SignatureHelpResponse Create(ParameterSetSignatures parameterSets)
+ {
+ if (parameterSets != null && parameterSets.Signatures != null)
+ {
+ return new SignatureHelpResponse
+ {
+ Body = SignatureHelpItems.Create(parameterSets)
+ };
+ }
+ else
+ {
+ return new SignatureHelpResponse
+ {
+ Body = null
+ };
+ }
+ }
+ }
+
+ public class SignatureHelpItems
+ {
+ public IEnumerable Items { get; set; }
+ public TextSpan ApplicableSpan { get; set; }
+ public int SelectedItemIndex { get; set; }
+ public int ArgumentIndex { get; set; }
+ public int ArgumentCount { get; set; }
+ public string CommandName { get; set; }
+
+ public static SignatureHelpItems Create(ParameterSetSignatures parameterSets)
+ {
+ List itemsList = new List();
+ foreach (ParameterSetSignature item in parameterSets.Signatures)
+ {
+ itemsList.Add(SignatureHelpItem.Create(item));
+ }
+
+ TextSpan textSpan =
+ new TextSpan
+ {
+ Start = new Location
+ {
+ Line = parameterSets.ScriptRegion.StartLineNumber,
+ Offset = parameterSets.ScriptRegion.StartColumnNumber
+ },
+ End = new Location
+ {
+ Line = parameterSets.ScriptRegion.EndLineNumber,
+ Offset = parameterSets.ScriptRegion.EndColumnNumber
+ }
+ };
+
+ return new SignatureHelpItems
+ {
+ ArgumentCount = parameterSets.Signatures.Length,
+ ArgumentIndex = 0,
+ SelectedItemIndex = 0,
+ CommandName = parameterSets.CommandName,
+ ApplicableSpan = textSpan,
+ Items = itemsList
+ };
+ }
+ }
+
+ /**
+ * Represents a single signature to show in signature help.
+ * */
+ public class SignatureHelpItem
+ {
+ public bool IsVariadic { get; set; }
+ public IEnumerable PrefixDisplayParts { get; set; }
+ public IEnumerable SuffixDisplayParts { get; set; }
+ public IEnumerable SeparatorDisplayParts { get; set; }
+ public IEnumerable Parameters { get; set; }
+ public IEnumerable Documentation { get; set; }
+ public string SignatureText { get; set; }
+
+ public static SignatureHelpItem Create(ParameterSetSignature paramSetSignature)
+ {
+ List parameterList =
+ new List();
+ foreach (ParameterInfo paramInfo in paramSetSignature.Parameters)
+ {
+ parameterList.Add(SignatureHelpParameter.Create(paramInfo));
+ }
+
+ return new SignatureHelpItem
+ {
+ IsVariadic = false,
+ PrefixDisplayParts = new List(),
+ SuffixDisplayParts = new List(),
+ SeparatorDisplayParts = new List(),
+ Parameters = parameterList,
+ Documentation = new List(),
+ SignatureText = paramSetSignature.SignatureText
+ };
+ }
+ }
+
+
+ /**
+ * Signature help information for a single parameter
+ * */
+ public class SignatureHelpParameter
+ {
+ public string Name { get; set; }
+ public IEnumerable Documentation { get; set; }
+ public IEnumerable DisplayParts { get; set; }
+ public bool IsOptional { get; set; }
+
+ public static SignatureHelpParameter Create(ParameterInfo paramInfo)
+ {
+ return new SignatureHelpParameter
+ {
+ Name = paramInfo.Name,
+ Documentation = new List(),
+ DisplayParts = new List(),
+ IsOptional = false
+ };
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/PowerShellEditorServices/Language/AstOperations.cs b/src/PowerShellEditorServices/Language/AstOperations.cs
index 62996047d..d44100759 100644
--- a/src/PowerShellEditorServices/Language/AstOperations.cs
+++ b/src/PowerShellEditorServices/Language/AstOperations.cs
@@ -3,6 +3,7 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
+using System.Collections.Generic;
using System.Management.Automation;
using System.Management.Automation.Language;
using System.Management.Automation.Runspaces;
@@ -74,5 +75,65 @@ static public CompletionResults GetCompletions(
return CompletionResults.Create(commandCompletion);
}
+
+ ///
+ /// Finds the symbol at a given file location
+ ///
+ /// The abstract syntax tree of the given script
+ /// The line number of the cursor for the given script
+ /// The coulumn number of the cursor for the given script
+ /// SymbolReference of found symbol
+ static public SymbolReference FindSymbolAtPosition(Ast scriptAst, int lineNumber, int columnNumber)
+ {
+ FindSymbolVisitor symbolVisitor = new FindSymbolVisitor(lineNumber, columnNumber);
+ scriptAst.Visit(symbolVisitor);
+
+ return symbolVisitor.FoundSymbolReference;
+ }
+
+ ///
+ /// Finds the symbol (always Command type) at a given file location
+ ///
+ /// 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
+ /// SymbolReference of found command
+ static public SymbolReference FindCommandAtPosition(Ast scriptAst, int lineNumber, int columnNumber)
+ {
+ FindCommandVisitor commandVisitor = new FindCommandVisitor(lineNumber, columnNumber);
+ scriptAst.Visit(commandVisitor);
+
+ return commandVisitor.FoundCommandReference;
+ }
+
+ ///
+ /// Finds all references in a script of the given symbol
+ ///
+ /// The abstract syntax tree of the given script
+ /// The symbol that we are looking for referneces of
+ /// A collection of SymbolReference objects that are refrences to the symbolRefrence
+ static public IEnumerable FindReferencesOfSymbol(Ast scriptAst, SymbolReference symbolReference)
+ {
+ // find the symbol evaluators for the node types we are handling
+ FindReferencesVisitor referencesVisitor = new FindReferencesVisitor(symbolReference);
+ scriptAst.Visit(referencesVisitor);
+
+ return referencesVisitor.FoundReferences;
+
+ }
+
+ ///
+ /// Finds the definition of the symbol
+ ///
+ /// The abstract syntax tree of the given script
+ /// The symbol that we are looking for the definition of
+ /// A SymbolReference of the definition of the symbolReference
+ static public SymbolReference FindDefinitionOfSymbol(Ast scriptAst, SymbolReference symbolReference)
+ {
+ FindDeclartionVisitor declarationVisitor = new FindDeclartionVisitor(symbolReference);
+ scriptAst.Visit(declarationVisitor);
+
+ return declarationVisitor.FoundDeclartion;
+ }
}
}
diff --git a/src/PowerShellEditorServices/Language/FindCommandVisitor.cs b/src/PowerShellEditorServices/Language/FindCommandVisitor.cs
new file mode 100644
index 000000000..349081f15
--- /dev/null
+++ b/src/PowerShellEditorServices/Language/FindCommandVisitor.cs
@@ -0,0 +1,74 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using System.Management.Automation.Language;
+
+namespace Microsoft.PowerShell.EditorServices.Language
+{
+ ///
+ /// The vistior used to find the commandAst of a specific location in an AST
+ ///
+ internal class FindCommandVisitor : AstVisitor
+ {
+ private int lineNumber;
+ private int columnNumber;
+
+ public SymbolReference FoundCommandReference { get; private set; }
+
+ public FindCommandVisitor(int lineNumber, int columnNumber)
+ {
+ this.lineNumber = lineNumber;
+ this.columnNumber = columnNumber;
+ }
+
+ ///
+ /// Checks to see if this command ast is the symbol we are looking for.
+ /// Assumes the commandAst will have two elements to be considered the correct command.
+ ///
+ /// A CommandAst object in the script's AST
+ /// A descion to stop searching if the right commandAst was found,
+ /// or a decision to continue if it wasn't found
+ public override AstVisitAction VisitCommand(CommandAst commandAst)
+ {
+ Ast commandNameAst = commandAst.CommandElements[0];
+ if (!(commandAst.CommandElements.Count > 1))
+ {
+ return base.VisitCommand(commandAst);
+ }
+ else
+ {
+ Ast secondCommandElementAst = commandAst.CommandElements[1];
+
+ if (this.IsPositionInExtent(commandNameAst.Extent, secondCommandElementAst.Extent))
+ {
+ this.FoundCommandReference =
+ new SymbolReference(
+ SymbolType.Function,
+ commandNameAst.Extent,
+ string.Empty);
+
+ return AstVisitAction.StopVisit;
+ }
+ }
+
+ return base.VisitCommand(commandAst);
+ }
+
+ ///
+ /// Is the position of the given location is in the range of the start
+ /// of the first element to the character before the second element
+ ///
+ /// The script extent of the first element of the command ast
+ /// The script extent of the second element of the command ast
+ /// True if the given position is in the range of the start of
+ /// the first element to the character before the second element
+ private bool IsPositionInExtent(IScriptExtent firstExtent, IScriptExtent secondExtent)
+ {
+ return (firstExtent.StartLineNumber == lineNumber &&
+ firstExtent.StartColumnNumber <= columnNumber &&
+ secondExtent.StartColumnNumber >= columnNumber - 1);
+ }
+ }
+}
diff --git a/src/PowerShellEditorServices/Language/FindDeclartionVisitor.cs b/src/PowerShellEditorServices/Language/FindDeclartionVisitor.cs
new file mode 100644
index 000000000..af15b0f70
--- /dev/null
+++ b/src/PowerShellEditorServices/Language/FindDeclartionVisitor.cs
@@ -0,0 +1,86 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using System.Management.Automation.Language;
+
+namespace Microsoft.PowerShell.EditorServices.Language
+{
+ ///
+ /// The vistor used to find the defintion of a symbol
+ ///
+ internal class FindDeclartionVisitor : AstVisitor
+ {
+ private SymbolReference symbolRef;
+
+ public SymbolReference FoundDeclartion{ get; private set; }
+
+ public FindDeclartionVisitor(SymbolReference symbolRef)
+ {
+ this.symbolRef = symbolRef;
+ }
+
+ ///
+ /// Decides if the current function defintion is the right defition
+ /// for the symbol being searched for. The defintion 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 descion to stop searching if the right FunctionDefinitionAst was found,
+ /// or a decision to continue if it wasn't found
+ public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst)
+ {
+ int startColumnNumber =
+ functionDefinitionAst.Extent.Text.IndexOf(
+ functionDefinitionAst.Name) + 1;
+
+ IScriptExtent nameExtent = new ScriptExtent()
+ {
+ Text = functionDefinitionAst.Name,
+ StartLineNumber = functionDefinitionAst.Extent.StartLineNumber,
+ StartColumnNumber = startColumnNumber,
+ EndColumnNumber = startColumnNumber + functionDefinitionAst.Name.Length
+ };
+
+ if (symbolRef.SymbolType.Equals(SymbolType.Function) &&
+ nameExtent.Text.Equals(symbolRef.ScriptRegion.Text))
+ {
+ this.FoundDeclartion =
+ new SymbolReference(
+ SymbolType.Function,
+ nameExtent,
+ string.Empty);
+
+ return AstVisitAction.StopVisit;
+ }
+
+ return base.VisitFunctionDefinition(functionDefinitionAst);
+ }
+
+ ///
+ /// Decides if the current variable expression is the right defition for
+ /// the symbol being searched for. The defintion of the symbol will be a of type
+ /// SymbolType.Variable and have the same name as the symbol
+ ///
+ /// A FunctionDefinitionAst in the script's AST
+ /// A descion to stop searching if the right VariableExpressionAst was found,
+ /// or a decision to continue if it wasn't found
+ public override AstVisitAction VisitVariableExpression(VariableExpressionAst variableExpressionAst)
+ {
+ if(symbolRef.SymbolType.Equals(SymbolType.Variable) &&
+ variableExpressionAst.Extent.Text.Equals(symbolRef.SymbolName))
+ {
+ this.FoundDeclartion =
+ new SymbolReference(
+ SymbolType.Variable,
+ variableExpressionAst.Extent,
+ string.Empty);
+
+ return AstVisitAction.StopVisit;
+ }
+
+ return AstVisitAction.Continue;
+ }
+ }
+}
diff --git a/src/PowerShellEditorServices/Language/FindOccurrencesResult.cs b/src/PowerShellEditorServices/Language/FindOccurrencesResult.cs
new file mode 100644
index 000000000..9dc617145
--- /dev/null
+++ b/src/PowerShellEditorServices/Language/FindOccurrencesResult.cs
@@ -0,0 +1,23 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using System.Collections.Generic;
+
+namespace Microsoft.PowerShell.EditorServices.Language
+{
+ ///
+ /// A class for the found occurences of a symbol.
+ /// It contains a collection of symbol references.
+ ///
+ public class FindOccurrencesResult
+ {
+ #region Properties
+ ///
+ /// Gets the collection of SymboleReferences for the all occurences of the symbol
+ ///
+ public IEnumerable FoundOccurrences { get; internal set; }
+ #endregion
+ }
+}
diff --git a/src/PowerShellEditorServices/Language/FindReferencesResult.cs b/src/PowerShellEditorServices/Language/FindReferencesResult.cs
new file mode 100644
index 000000000..4bff3db5b
--- /dev/null
+++ b/src/PowerShellEditorServices/Language/FindReferencesResult.cs
@@ -0,0 +1,33 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using System.Collections.Generic;
+
+namespace Microsoft.PowerShell.EditorServices.Language
+{
+ ///
+ /// A class to contain the found references of a symbol.
+ /// It contains a collection of symbol references, the symbol name, and the symbol's file offset
+ ///
+ public class FindReferencesResult
+ {
+ #region Properties
+ ///
+ /// Gets the name of the symbol
+ ///
+ public string SymbolName { get; internal set; }
+
+ ///
+ /// Gets the file offset (location based on line and column number) of the symbol
+ ///
+ public int SymbolFileOffset { get; internal set; }
+
+ ///
+ /// Gets the collection of SymboleReferences for the all references to the symbol
+ ///
+ public IEnumerable FoundReferences { get; internal set; }
+ #endregion
+ }
+}
diff --git a/src/PowerShellEditorServices/Language/FindReferencesVisitor.cs b/src/PowerShellEditorServices/Language/FindReferencesVisitor.cs
new file mode 100644
index 000000000..fa1f13b1f
--- /dev/null
+++ b/src/PowerShellEditorServices/Language/FindReferencesVisitor.cs
@@ -0,0 +1,116 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using System.Collections.Generic;
+using System.Management.Automation.Language;
+
+namespace Microsoft.PowerShell.EditorServices.Language
+{
+ ///
+ /// The visitor used to find the references of a symbol in a script's AST
+ ///
+ internal class FindReferencesVisitor : AstVisitor
+ {
+ private SymbolReference symbolRef;
+
+ public List FoundReferences { get; set; }
+
+ public FindReferencesVisitor(SymbolReference symbolRef)
+ {
+ this.symbolRef = symbolRef;
+ this.FoundReferences = new List();
+ }
+
+ ///
+ /// Decides if the current command 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 CommandAst in the script's AST
+ /// A visit action that continues the search for references
+ public override AstVisitAction VisitCommand(CommandAst commandAst)
+ {
+ Ast commandNameAst = commandAst.CommandElements[0];
+ if(symbolRef.SymbolType.Equals(SymbolType.Function) &&
+ commandNameAst.Extent.Text.Equals(symbolRef.ScriptRegion.Text))
+ {
+ this.FoundReferences.Add(new SymbolReference(
+ SymbolType.Function,
+ commandNameAst.Extent,
+ string.Empty));
+ }
+ return base.VisitCommand(commandAst);
+ }
+
+ ///
+ /// Decides if the current function defintion 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 visit action that continues the search for references
+ public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst)
+ {
+ int startColumnNumber =
+ functionDefinitionAst.Extent.Text.IndexOf(
+ functionDefinitionAst.Name) + 1;
+
+ IScriptExtent nameExtent = new ScriptExtent()
+ {
+ Text = functionDefinitionAst.Name,
+ StartLineNumber = functionDefinitionAst.Extent.StartLineNumber,
+ StartColumnNumber = startColumnNumber,
+ EndColumnNumber = startColumnNumber + functionDefinitionAst.Name.Length
+ };
+
+ if (symbolRef.SymbolType.Equals(SymbolType.Function) &&
+ nameExtent.Text.Equals(symbolRef.SymbolName))
+ {
+ this.FoundReferences.Add(new SymbolReference(
+ SymbolType.Function,
+ nameExtent,
+ string.Empty));
+ }
+ return base.VisitFunctionDefinition(functionDefinitionAst);
+ }
+
+ ///
+ /// Decides if the current function defintion 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 visit action that continues the search for references
+ public override AstVisitAction VisitCommandParameter(CommandParameterAst commandParameterAst)
+ {
+ if (symbolRef.SymbolType.Equals(SymbolType.Parameter) &&
+ commandParameterAst.Extent.Text.Equals(symbolRef.SymbolName))
+ {
+ this.FoundReferences.Add(new SymbolReference(
+ SymbolType.Parameter,
+ commandParameterAst.Extent,
+ string.Empty));
+ }
+ return AstVisitAction.Continue;
+ }
+
+ ///
+ /// Decides if the current function defintion 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 visit action that continues the search for references
+ public override AstVisitAction VisitVariableExpression(VariableExpressionAst variableExpressionAst)
+ {
+ if(symbolRef.SymbolType.Equals(SymbolType.Variable) &&
+ variableExpressionAst.Extent.Text.Equals(symbolRef.SymbolName))
+ {
+ this.FoundReferences.Add(new SymbolReference(
+ SymbolType.Variable,
+ variableExpressionAst.Extent,
+ string.Empty));
+ }
+ return AstVisitAction.Continue;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/PowerShellEditorServices/Language/FindSymbolVisitor.cs b/src/PowerShellEditorServices/Language/FindSymbolVisitor.cs
new file mode 100644
index 000000000..b8e003fee
--- /dev/null
+++ b/src/PowerShellEditorServices/Language/FindSymbolVisitor.cs
@@ -0,0 +1,138 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using System.Management.Automation.Language;
+
+namespace Microsoft.PowerShell.EditorServices.Language
+{
+ ///
+ /// The visitor used to find the the symbol at a specfic location in the AST
+ ///
+ internal class FindSymbolVisitor : AstVisitor
+ {
+ private int lineNumber;
+ private int columnNumber;
+
+ public SymbolReference FoundSymbolReference { get; private set; }
+
+ public FindSymbolVisitor(int lineNumber, int columnNumber)
+ {
+ this.lineNumber = lineNumber;
+ this.columnNumber = columnNumber;
+ }
+
+ ///
+ /// Checks to see if this command ast is the symbol we are looking for.
+ ///
+ /// A CommandAst object in the script's AST
+ /// A descion to stop searching if the right symbol was found,
+ /// or a decision to continue if it wasn't found
+ public override AstVisitAction VisitCommand(CommandAst commandAst)
+ {
+ Ast commandNameAst = commandAst.CommandElements[0];
+
+ if (this.IsPositionInExtent(commandNameAst.Extent))
+ {
+ this.FoundSymbolReference =
+ new SymbolReference(
+ SymbolType.Function,
+ commandNameAst.Extent,
+ string.Empty);
+
+ return AstVisitAction.StopVisit;
+ }
+
+ return base.VisitCommand(commandAst);
+ }
+
+ ///
+ /// Checks to see if this function definition is the symbol we are looking for.
+ ///
+ /// A functionDefinitionAst object in the script's AST
+ /// A descion 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)
+ {
+ int startColumnNumber =
+ functionDefinitionAst.Extent.Text.IndexOf(
+ functionDefinitionAst.Name) + 1;
+
+ IScriptExtent nameExtent = new ScriptExtent()
+ {
+ Text = functionDefinitionAst.Name,
+ StartLineNumber = functionDefinitionAst.Extent.StartLineNumber,
+ StartColumnNumber = startColumnNumber,
+ EndColumnNumber = startColumnNumber + functionDefinitionAst.Name.Length
+ };
+
+ if (this.IsPositionInExtent(nameExtent))
+ {
+ this.FoundSymbolReference =
+ new SymbolReference(
+ SymbolType.Function,
+ nameExtent,
+ string.Empty);
+
+ return AstVisitAction.StopVisit;
+ }
+
+ return base.VisitFunctionDefinition(functionDefinitionAst);
+ }
+
+ ///
+ /// Checks to see if this command parameter is the symbol we are looking for.
+ ///
+ /// A CommandParameterAst object in the script's AST
+ /// A descion to stop searching if the right symbol was found,
+ /// or a decision to continue if it wasn't found
+ public override AstVisitAction VisitCommandParameter(CommandParameterAst commandParameterAst)
+ {
+ if (this.IsPositionInExtent(commandParameterAst.Extent))
+ {
+ this.FoundSymbolReference =
+ new SymbolReference(
+ SymbolType.Parameter,
+ commandParameterAst.Extent,
+ string.Empty);
+ 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 descion 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)
+ {
+ if (this.IsPositionInExtent(variableExpressionAst.Extent))
+ {
+ this.FoundSymbolReference =
+ new SymbolReference(
+ SymbolType.Variable,
+ variableExpressionAst.Extent,
+ string.Empty);
+
+ return AstVisitAction.StopVisit;
+ }
+
+ return AstVisitAction.Continue;
+ }
+
+ ///
+ /// Is the position of the given location is in the ast's extent
+ ///
+ /// The script extent of the element
+ /// True if the given position is in the range of the element's extent
+ private bool IsPositionInExtent(IScriptExtent extent)
+ {
+ return (extent.StartLineNumber == lineNumber &&
+ extent.StartColumnNumber <= columnNumber &&
+ extent.EndColumnNumber >= columnNumber);
+ }
+ }
+}
diff --git a/src/PowerShellEditorServices/Language/GetDefinitionResult.cs b/src/PowerShellEditorServices/Language/GetDefinitionResult.cs
new file mode 100644
index 000000000..6feb831c2
--- /dev/null
+++ b/src/PowerShellEditorServices/Language/GetDefinitionResult.cs
@@ -0,0 +1,30 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+namespace Microsoft.PowerShell.EditorServices.Language
+{
+ ///
+ /// A class to contain the found defintion of a symbol.
+ /// It contains the symbol reference of the defintion
+ ///
+ public class GetDefinitionResult
+ {
+ #region Properties
+ ///
+ /// Gets the symbolReference of the found definition
+ ///
+ public SymbolReference FoundDefinition { get; internal set; }
+ #endregion
+
+ ///
+ /// Constructs an instance of a GetDefinitionResut
+ ///
+ /// The symbolRefernece for the found definition
+ public GetDefinitionResult(SymbolReference symRef)
+ {
+ FoundDefinition = symRef;
+ }
+ }
+}
diff --git a/src/PowerShellEditorServices/Language/LanguageService.cs b/src/PowerShellEditorServices/Language/LanguageService.cs
index 3b4d57125..f53ea1d6f 100644
--- a/src/PowerShellEditorServices/Language/LanguageService.cs
+++ b/src/PowerShellEditorServices/Language/LanguageService.cs
@@ -22,6 +22,10 @@ public class LanguageService
#region Private Fields
private Runspace runspace;
+ private CompletionResults mostRecentCompletions;
+ private int mostRecentRequestLine;
+ private int mostRecentRequestOffest;
+ private string mostRecentRequestFile;
#endregion
@@ -75,14 +79,205 @@ public CompletionResults GetCompletionsInFile(
lineNumber,
columnNumber);
- return
+ CompletionResults completionResults =
AstOperations.GetCompletions(
scriptFile.ScriptAst,
scriptFile.ScriptTokens,
fileOffset,
this.runspace);
+
+ // save state of most recent completion
+ mostRecentCompletions = completionResults;
+ mostRecentRequestFile = scriptFile.FilePath;
+ mostRecentRequestLine = lineNumber;
+ mostRecentRequestOffest = columnNumber;
+
+ return completionResults;
+ }
+
+ ///
+ /// Finds command completion details for 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
+ /// The coulumn number of the cursor for the given script
+ /// The name of the suggestion that needs details
+ /// CompletionResult object (contains information about the command completion)
+ public CompletionDetails GetCompletionDetailsInFile(
+ ScriptFile file,
+ int lineNumber,
+ int columnNumber,
+ string entryName)
+ {
+ if (file.FilePath.Equals(mostRecentRequestFile) &&
+ lineNumber == mostRecentRequestLine &&
+ columnNumber == mostRecentRequestOffest)
+ {
+ CompletionDetails completionResult =
+ mostRecentCompletions.Completions.First(
+ result => result.CompletionText.Equals(entryName));
+ return completionResult;
+ }
+ else { return null; }
+ }
+
+ ///
+ /// Finds all the references of a symbol 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
+ /// The coulumn number of the cursor for the given script
+ /// FindReferencesResult
+ public FindReferencesResult FindReferencesInFile(
+ ScriptFile file,
+ int lineNumber,
+ int columnNumber)
+ {
+ SymbolReference foundSymbol =
+ AstOperations.FindSymbolAtPosition(
+ file.ScriptAst,
+ lineNumber,
+ columnNumber);
+
+ if (foundSymbol != null)
+ {
+ IEnumerable symbolReferences =
+ AstOperations
+ .FindReferencesOfSymbol(
+ file.ScriptAst,
+ foundSymbol)
+ .Select(
+ reference =>
+ {
+ reference.SourceLine =
+ file.GetLine(reference.ScriptRegion.StartLineNumber);
+ return reference;
+ });
+
+ return
+ new FindReferencesResult
+ {
+ SymbolFileOffset = file.GetOffsetAtPosition(lineNumber, columnNumber),
+ SymbolName = foundSymbol.SymbolName,
+ FoundReferences = symbolReferences
+ };
+ }
+ else { return null; }
+ }
+
+ ///
+ /// Finds the definition of a symbol 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
+ /// The coulumn number of the cursor for the given script
+ /// GetDefinitionResult
+ public GetDefinitionResult GetDefinitionInFile(
+ ScriptFile file,
+ int lineNumber,
+ int columnNumber)
+ {
+ SymbolReference foundSymbol =
+ AstOperations.FindSymbolAtPosition(
+ file.ScriptAst,
+ lineNumber,
+ columnNumber);
+
+ if (foundSymbol != null)
+ {
+ SymbolReference foundDefinition =
+ AstOperations.FindDefinitionOfSymbol(
+ file.ScriptAst,
+ foundSymbol);
+
+ return new GetDefinitionResult(foundDefinition);
+ }
+ else { return null; }
+ }
+
+ ///
+ /// Finds all the occurences of a symbol 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
+ /// The coulumn number of the cursor for the given script
+ /// FindOccurrencesResult
+ public FindOccurrencesResult FindOccurrencesInFile(
+ ScriptFile file,
+ int lineNumber,
+ int columnNumber)
+ {
+ SymbolReference foundSymbol =
+ AstOperations.FindSymbolAtPosition(
+ file.ScriptAst,
+ lineNumber,
+ columnNumber);
+ if (foundSymbol != null)
+ {
+ IEnumerable symbolOccurrences =
+ AstOperations
+ .FindReferencesOfSymbol(
+ file.ScriptAst,
+ foundSymbol);
+
+ return
+ new FindOccurrencesResult
+ {
+ FoundOccurrences = symbolOccurrences
+ };
+ }
+ else { return null; }
}
+ ///
+ /// Finds the parameter set hints of a specific command (determined by a given file location)
+ ///
+ /// The details and contents of a open script file
+ /// The line number of the cursor for the given script
+ /// The coulumn number of the cursor for the given script
+ /// ParameterSetSignatures
+ public ParameterSetSignatures FindParameterSetsInFile(
+ ScriptFile file,
+ int lineNumber,
+ int columnNumber)
+ {
+ SymbolReference foundSymbol =
+ AstOperations.FindCommandAtPosition(
+ file.ScriptAst,
+ lineNumber,
+ columnNumber);
+
+ if (foundSymbol != null)
+ {
+ if (GetCommandInfo(foundSymbol.SymbolName) != null)
+ {
+ IEnumerable commandInfo =
+ GetCommandInfo(foundSymbol.SymbolName).ParameterSets;
+ List commandInfoSet =
+ new List(commandInfo);
+
+ return new ParameterSetSignatures(commandInfoSet, foundSymbol);
+ }
+ else { return null; }
+ }
+ else { return null; }
+ }
+
#endregion
+
+ private CommandInfo GetCommandInfo(string commandName)
+ {
+ CommandInfo commandInfo = null;
+
+ using (PowerShell powerShell = PowerShell.Create())
+ {
+ powerShell.Runspace = this.runspace;
+ powerShell.AddCommand("Get-Command");
+ powerShell.AddArgument(commandName);
+ commandInfo = powerShell.Invoke().FirstOrDefault();
+ }
+
+ return commandInfo;
+ }
}
}
diff --git a/src/PowerShellEditorServices/Language/ParameterSetSignatures.cs b/src/PowerShellEditorServices/Language/ParameterSetSignatures.cs
new file mode 100644
index 000000000..a7c7b7acc
--- /dev/null
+++ b/src/PowerShellEditorServices/Language/ParameterSetSignatures.cs
@@ -0,0 +1,131 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using Microsoft.PowerShell.EditorServices.Session;
+using System.Collections.Generic;
+using System.Management.Automation;
+
+namespace Microsoft.PowerShell.EditorServices.Language
+{
+ ///
+ /// A class for containing the commandName, the command's
+ /// possible signatures, and the script extent of the command
+ ///
+ public class ParameterSetSignatures
+ {
+ #region Properties
+ ///
+ /// Gets the name of the command
+ ///
+ public string CommandName { get; internal set; }
+
+ ///
+ /// Gets the collection of signatures for the command
+ ///
+ public ParameterSetSignature[] Signatures { get; internal set; }
+
+ ///
+ /// Gets the script extent of the command
+ ///
+ public ScriptRegion ScriptRegion { get; internal set; }
+ #endregion
+
+ ///
+ /// Constructs an instance of a ParameterSetSignatures object
+ ///
+ /// Collection of parameter set info
+ /// The SymbolReference of the command
+ public ParameterSetSignatures(List commandInfoSet, SymbolReference foundSymbol)
+ {
+ List paramSetSignatures = new List();
+ foreach (CommandParameterSetInfo setInfo in commandInfoSet)
+ {
+ paramSetSignatures.Add(new ParameterSetSignature(setInfo));
+ }
+ Signatures = paramSetSignatures.ToArray();
+ CommandName = foundSymbol.ScriptRegion.Text;
+ ScriptRegion = foundSymbol.ScriptRegion;
+ }
+ }
+
+ ///
+ /// A class for containing the signature text and the collection of parameters for a signature
+ ///
+ public class ParameterSetSignature
+ {
+ #region Properties
+ ///
+ /// Gets the signature text
+ ///
+ public string SignatureText { get; internal set; }
+
+ ///
+ /// Gets the collection of parameters for the signature
+ ///
+ public IEnumerable Parameters { get; internal set; }
+ #endregion
+
+ ///
+ /// Constructs an instance of a ParameterSetSignature
+ ///
+ /// Collection of parameter info
+ public ParameterSetSignature(CommandParameterSetInfo commandParamInfoSet)
+ {
+ List parameterInfo = new List();
+ foreach (CommandParameterInfo commandParameterInfo in commandParamInfoSet.Parameters)
+ {
+ parameterInfo.Add(new ParameterInfo(commandParameterInfo));
+ }
+ SignatureText = commandParamInfoSet.ToString();
+ Parameters = parameterInfo.ToArray();
+ }
+ }
+
+ ///
+ /// A class for containing the parameter info of a parameter
+ ///
+ public class ParameterInfo
+ {
+ #region Properties
+ ///
+ /// Gets the name of the parameter
+ ///
+ public string Name { get; internal set; }
+
+ ///
+ /// Gets the type of the parameter
+ ///
+ public string ParameterType { get; internal set; }
+
+ ///
+ /// Gets the position of the parameter
+ ///
+ public int Position { get; internal set; }
+
+ ///
+ /// Gets a boolean for whetheer or not the parameter is required
+ ///
+ public bool IsMandatory { get; internal set; }
+
+ ///
+ /// Gets the help message of the parameter
+ ///
+ public string HelpMessage { get; internal set; }
+ #endregion
+
+ ///
+ /// Constructs an instance of a ParameterInfo object
+ ///
+ /// Parameter info of the parameter
+ public ParameterInfo(CommandParameterInfo parameterInfo)
+ {
+ this.Name = parameterInfo.Name;
+ this.ParameterType = parameterInfo.ParameterType.FullName;
+ this.Position = parameterInfo.Position;
+ this.IsMandatory = parameterInfo.IsMandatory;
+ this.HelpMessage = parameterInfo.HelpMessage;
+ }
+ }
+}
diff --git a/src/PowerShellEditorServices/Language/ScriptExtent.cs b/src/PowerShellEditorServices/Language/ScriptExtent.cs
index f7395b012..d166952b2 100644
--- a/src/PowerShellEditorServices/Language/ScriptExtent.cs
+++ b/src/PowerShellEditorServices/Language/ScriptExtent.cs
@@ -4,11 +4,7 @@
//
using System;
-using System.Collections.Generic;
-using System.Linq;
using System.Management.Automation.Language;
-using System.Text;
-using System.Threading.Tasks;
namespace Microsoft.PowerShell.EditorServices.Language
{
@@ -26,7 +22,8 @@ public class ScriptExtent : IScriptExtent
///
public string File
{
- get { throw new NotImplementedException(); }
+ get;
+ set;
}
///
diff --git a/src/PowerShellEditorServices/Language/SymbolReference.cs b/src/PowerShellEditorServices/Language/SymbolReference.cs
new file mode 100644
index 000000000..84e1609b3
--- /dev/null
+++ b/src/PowerShellEditorServices/Language/SymbolReference.cs
@@ -0,0 +1,81 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using Microsoft.PowerShell.EditorServices.Session;
+using System.Management.Automation.Language;
+
+namespace Microsoft.PowerShell.EditorServices.Language
+{
+ ///
+ /// A way to define symbols on a higher level
+ ///
+ public enum SymbolType
+ {
+ ///
+ /// The symbol type is unknown
+ ///
+ Unknown = 0,
+
+ ///
+ /// The symbol is a vairable
+ ///
+ Variable,
+
+ ///
+ /// The symbol is a function
+ ///
+ Function,
+
+ ///
+ /// The symbol is a parameter
+ ///
+ Parameter
+ }
+
+ ///
+ /// A class that holds the type, name, script extent, and source line of a symbol
+ ///
+ public class SymbolReference
+ {
+ #region Properties
+ ///
+ /// Gets the symbol's type
+ ///
+ public SymbolType SymbolType { get; private set; }
+
+ ///
+ /// Gets the name of the symbol
+ ///
+ public string SymbolName { get; private set; }
+
+ ///
+ /// Gets the script extent of the symbol
+ ///
+ public ScriptRegion ScriptRegion { get; private set; }
+
+ ///
+ /// Gets the contents of the line the given symbol is on
+ ///
+ public string SourceLine { get; internal set; }
+ #endregion
+
+ ///
+ /// Constructs and instance of a SymbolReference
+ ///
+ /// The higher level type of the symbol
+ /// The script extent of the symbol
+ /// The line contents of the given symbol (defaults to empty string)
+ public SymbolReference(SymbolType symbolType, IScriptExtent scriptExtent, string sourceLine = "")
+ {
+ // TODO: Verify params
+ this.SymbolType = symbolType;
+ this.SymbolName = scriptExtent.Text;
+ this.ScriptRegion = ScriptRegion.Create(scriptExtent);
+ this.SourceLine = sourceLine;
+
+ // TODO: Make sure end column number usage is correct
+ }
+ }
+}
diff --git a/src/PowerShellEditorServices/PowerShellEditorServices.csproj b/src/PowerShellEditorServices/PowerShellEditorServices.csproj
index e3a2af44f..7771791c2 100644
--- a/src/PowerShellEditorServices/PowerShellEditorServices.csproj
+++ b/src/PowerShellEditorServices/PowerShellEditorServices.csproj
@@ -70,8 +70,17 @@
+
+
+
+
+
+
+
+
+
diff --git a/submodules/PSScriptAnalyzer b/submodules/PSScriptAnalyzer
index 96652e225..297140f0d 160000
--- a/submodules/PSScriptAnalyzer
+++ b/submodules/PSScriptAnalyzer
@@ -1 +1 @@
-Subproject commit 96652e2259048336a68d93db72a10a10165bd39d
+Subproject commit 297140f0d3f1205da010073cd2ad8ab8cd43b665
diff --git a/test/PowerShellEditorServices.Test.Host/ScenarioTests.cs b/test/PowerShellEditorServices.Test.Host/ScenarioTests.cs
index e722ee159..976cf7d22 100644
--- a/test/PowerShellEditorServices.Test.Host/ScenarioTests.cs
+++ b/test/PowerShellEditorServices.Test.Host/ScenarioTests.cs
@@ -3,11 +3,14 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
+using Microsoft.PowerShell.EditorServices.Language;
+using Microsoft.PowerShell.EditorServices.Transport.Stdio;
using Microsoft.PowerShell.EditorServices.Transport.Stdio.Event;
using Microsoft.PowerShell.EditorServices.Transport.Stdio.Message;
using Microsoft.PowerShell.EditorServices.Transport.Stdio.Request;
using Microsoft.PowerShell.EditorServices.Transport.Stdio.Response;
using System;
+using System.Collections.Generic;
using Xunit;
namespace Microsoft.PowerShell.EditorServices.Test.Host
@@ -81,6 +84,291 @@ public void ServiceCompletesFunctionName()
// TODO: Add more asserts
}
+ [Fact]
+ public void CompletesDetailOnVariableSuggestion()
+ {
+ this.SendOpenFileRequest("TestFiles\\CompleteFunctionName.ps1");
+ this.MessageWriter.WriteMessage(
+ new CompletionsRequest
+ {
+ Arguments = new CompletionsRequestArgs
+ {
+ File = "TestFiles\\CompleteFunctionName.ps1",
+ Line = 4,
+ Offset = 6,
+ Prefix = ""
+ }
+ });
+ CompletionsResponse completion = this.WaitForMessage();
+ List entryName = new List();
+ entryName.Add("$ConsoleFileName");
+ this.MessageWriter.WriteMessage(
+ new CompletionDetailsRequest
+ {
+ Arguments = new CompletionDetailsRequestArgs
+ {
+ File = "TestFiles\\CompleteFunctionName.ps1",
+ Line = 4,
+ Offset = 6,
+ EntryNames = entryName.ToArray()
+ }
+ });
+ CompletionDetailsResponse completionDetail = this.WaitForMessage();
+ Assert.NotNull(completionDetail.Body[0]);
+ Assert.Equal("string", completionDetail.Body[0].Name);
+ }
+
+ [Fact]
+ public void CompletesDetailOnVariableDocSuggestion()
+ {
+ this.SendOpenFileRequest("TestFiles\\CompleteFunctionName.ps1");
+ this.MessageWriter.WriteMessage(
+ new CompletionsRequest
+ {
+ Arguments = new CompletionsRequestArgs
+ {
+ File = "TestFiles\\CompleteFunctionName.ps1",
+ Line = 7,
+ Offset = 5,
+ Prefix = ""
+ }
+ });
+ CompletionsResponse completion = this.WaitForMessage();
+ List entryName = new List();
+ entryName.Add("$HKCU:");
+ this.MessageWriter.WriteMessage(
+ new CompletionDetailsRequest
+ {
+ Arguments = new CompletionDetailsRequestArgs
+ {
+ File = "TestFiles\\CompleteFunctionName.ps1",
+ Line = 7,
+ Offset = 5,
+ EntryNames = entryName.ToArray()
+ }
+ });
+ CompletionDetailsResponse completionDetail = this.WaitForMessage();
+ Assert.NotNull(completionDetail.Body[0]);
+ Assert.Equal("The software settings for the current user", completionDetail.Body[0].DocString);
+ }
+
+ [Fact]
+ public void CompletesDetailOnCommandSuggestion()
+ {
+ this.SendOpenFileRequest("TestFiles\\CompleteFunctionName.ps1");
+ this.MessageWriter.WriteMessage(
+ new CompletionsRequest
+ {
+ Arguments = new CompletionsRequestArgs
+ {
+ File = "TestFiles\\CompleteFunctionName.ps1",
+ Line = 6,
+ Offset = 9,
+ Prefix = ""
+ }
+ });
+ CompletionsResponse completion = this.WaitForMessage();
+ List entryName = new List();
+ entryName.Add("Get-Process");
+ this.MessageWriter.WriteMessage(
+ new CompletionDetailsRequest
+ {
+ Arguments = new CompletionDetailsRequestArgs
+ {
+ File = "TestFiles\\CompleteFunctionName.ps1",
+ Line = 6,
+ Offset = 9,
+ EntryNames = entryName.ToArray()
+ }
+ });
+ CompletionDetailsResponse completionDetail = this.WaitForMessage();
+ Assert.Null(completionDetail.Body[0].Name);
+ }
+
+ [Fact]
+ public void FindsReferencesOfVariable()
+ {
+ this.SendOpenFileRequest("TestFiles\\FindReferences.ps1");
+ this.MessageWriter.WriteMessage(
+ new ReferencesRequest
+ {
+ Arguments = new FileLocationRequestArgs
+ {
+ File = "TestFiles\\FindReferences.ps1",
+ Line = 8,
+ Offset = 5,
+ }
+ });
+
+ ReferencesResponse references = this.WaitForMessage();
+ Assert.NotNull(references);
+ Assert.Equal(references.Body.Refs.Length, 3);
+ Assert.Equal(references.Body.Refs[0].LineText, "$things = 4");
+ }
+
+ [Fact]
+ public void FindsNoReferencesOfEmptyLine()
+ {
+ this.SendOpenFileRequest("TestFiles\\FindReferences.ps1");
+ this.MessageWriter.WriteMessage(
+ new ReferencesRequest
+ {
+ Arguments = new FileLocationRequestArgs
+ {
+ File = "TestFiles\\FindReferences.ps1",
+ Line = 9,
+ Offset = 1,
+ }
+ });
+
+ ReferencesResponse references = this.WaitForMessage();
+ Assert.Null(references.Body);
+ }
+
+ [Fact]
+ public void FindsReferencesOnFunctionDefinition()
+ {
+ this.SendOpenFileRequest("TestFiles\\FindReferences.ps1");
+ this.MessageWriter.WriteMessage(
+ new ReferencesRequest
+ {
+ Arguments = new FileLocationRequestArgs
+ {
+ File = "TestFiles\\FindReferences.ps1",
+ Line = 1,
+ Offset = 18,
+ }
+ });
+
+ ReferencesResponse references = this.WaitForMessage();
+ Assert.NotNull(references);
+ Assert.Equal(references.Body.Refs.Length, 3);
+ Assert.Equal(references.Body.SymbolName, "My-Function");
+ }
+
+ [Fact]
+ public void FindsReferencesOnCommand()
+ {
+ this.SendOpenFileRequest("TestFiles\\FindReferences.ps1");
+ this.MessageWriter.WriteMessage(
+ new ReferencesRequest
+ {
+ Arguments = new FileLocationRequestArgs
+ {
+ File = "TestFiles\\FindReferences.ps1",
+ Line = 10,
+ Offset = 2,
+ }
+ });
+
+ ReferencesResponse references = this.WaitForMessage();
+ Assert.NotNull(references);
+ Assert.Equal(references.Body.Refs.Length, 3);
+ Assert.Equal(references.Body.SymbolName, "My-Function");
+ }
+
+ [Fact]
+ public void FindsDefinitionOfCommand()
+ {
+ this.SendOpenFileRequest("TestFiles\\FindReferences.ps1");
+ this.MessageWriter.WriteMessage(
+ new DeclarationRequest
+ {
+ Arguments = new FileLocationRequestArgs
+ {
+ File = "TestFiles\\FindReferences.ps1",
+ Line = 3,
+ Offset = 12,
+ }
+ });
+ DefinitionResponse definition = this.WaitForMessage();
+ Assert.NotNull(definition);
+ Assert.Equal(1, definition.Body[0].Start.Line);
+ Assert.Equal(10, definition.Body[0].Start.Offset);
+ }
+
+ [Fact]
+ public void FindsNoDefinitionOfBuiltinCommand()
+ {
+ this.SendOpenFileRequest("TestFiles\\FindReferences.ps1");
+ this.MessageWriter.WriteMessage(
+ new DeclarationRequest
+ {
+ Arguments = new FileLocationRequestArgs
+ {
+ File = "TestFiles\\FindReferences.ps1",
+ Line = 12,
+ Offset = 10,
+ }
+ });
+ DefinitionResponse definition = this.WaitForMessage();
+ Assert.Null(definition.Body);
+ }
+
+ [Fact]
+ public void FindsDefintionOfVariable()
+ {
+ this.SendOpenFileRequest("TestFiles\\FindReferences.ps1");
+ this.MessageWriter.WriteMessage(
+ new DeclarationRequest
+ {
+ Arguments = new FileLocationRequestArgs
+ {
+ File = "TestFiles\\FindReferences.ps1",
+ Line = 10,
+ Offset = 14,
+ }
+ });
+ DefinitionResponse definition = this.WaitForMessage();
+ Assert.NotNull(definition);
+ Assert.Equal(6, definition.Body[0].Start.Line);
+ Assert.Equal(1, definition.Body[0].Start.Offset);
+ Assert.Equal(6, definition.Body[0].End.Line);
+ Assert.Equal(8, definition.Body[0].End.Offset);
+ }
+
+ [Fact]
+ public void FindsOccurencesOnFunctionDefinition()
+ {
+ this.SendOpenFileRequest("TestFiles\\FindReferences.ps1");
+ this.MessageWriter.WriteMessage(
+ new OccurrencesRequest
+ {
+ Arguments = new FileLocationRequestArgs
+ {
+ File = "TestFiles\\FindReferences.ps1",
+ Line = 1,
+ Offset = 18,
+ }
+ });
+
+ OccurrencesResponse occurences = this.WaitForMessage();
+ Assert.NotNull(occurences);
+ Assert.Equal(occurences.Body.Length, 3);
+ Assert.Equal(occurences.Body[1].Start.Line, 3);
+ }
+
+ [Fact]
+ public void GetsParameterHintsOnCommand()
+ {
+ this.SendOpenFileRequest("TestFiles\\FindReferences.ps1");
+ this.MessageWriter.WriteMessage(
+ new SignatureHelpRequest
+ {
+ Arguments = new SignatureHelpRequestArgs
+ {
+ File = "TestFiles\\FindReferences.ps1",
+ Line = 14,
+ Offset = 15,
+ }
+ });
+
+ SignatureHelpResponse sigHelp = this.WaitForMessage();
+ Assert.NotNull(sigHelp);
+ Assert.Equal(sigHelp.Body.CommandName, "Write-Output");
+ Assert.Equal(sigHelp.Body.ArgumentCount, 1);
+ }
+
[Fact]
public void ServiceExecutesReplCommandAndReceivesOutput()
{
diff --git a/test/PowerShellEditorServices.Test.Host/TestFiles/CompleteFunctionName.ps1 b/test/PowerShellEditorServices.Test.Host/TestFiles/CompleteFunctionName.ps1
index d7c7e7c8f..a049b2845 100644
--- a/test/PowerShellEditorServices.Test.Host/TestFiles/CompleteFunctionName.ps1
+++ b/test/PowerShellEditorServices.Test.Host/TestFiles/CompleteFunctionName.ps1
@@ -1,5 +1,7 @@
function My-Function
{
}
-
-My-
\ No newline at end of file
+$Cons
+My-
+Get-Proc
+$HKC
\ No newline at end of file
diff --git a/test/PowerShellEditorServices.Test.Host/TestFiles/FindReferences.ps1 b/test/PowerShellEditorServices.Test.Host/TestFiles/FindReferences.ps1
index 0468c9f27..9373c10f4 100644
--- a/test/PowerShellEditorServices.Test.Host/TestFiles/FindReferences.ps1
+++ b/test/PowerShellEditorServices.Test.Host/TestFiles/FindReferences.ps1
@@ -8,3 +8,7 @@ $things = 4
$things
My-Function $things
+
+Write-Output "Hi";
+
+Write-Output ""
\ No newline at end of file
diff --git a/test/PowerShellEditorServices.Test.Shared/Definition/FindsFunctionDefinition.cs b/test/PowerShellEditorServices.Test.Shared/Definition/FindsFunctionDefinition.cs
new file mode 100644
index 000000000..877145fae
--- /dev/null
+++ b/test/PowerShellEditorServices.Test.Shared/Definition/FindsFunctionDefinition.cs
@@ -0,0 +1,20 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using Microsoft.PowerShell.EditorServices.Language;
+using Microsoft.PowerShell.EditorServices.Session;
+
+namespace Microsoft.PowerShell.EditorServices.Test.Shared.Definition
+{
+ public class FindsFunctionDefinition
+ {
+ public static readonly ScriptRegion SourceDetails =
+ new ScriptRegion
+ {
+ File = @"References\SimpleFile.ps1",
+ StartLineNumber = 3,
+ StartColumnNumber = 12
+ };
+ }
+}
diff --git a/test/PowerShellEditorServices.Test.Shared/Definition/FindsVariableDefinition.cs b/test/PowerShellEditorServices.Test.Shared/Definition/FindsVariableDefinition.cs
new file mode 100644
index 000000000..de337e6b7
--- /dev/null
+++ b/test/PowerShellEditorServices.Test.Shared/Definition/FindsVariableDefinition.cs
@@ -0,0 +1,20 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using Microsoft.PowerShell.EditorServices.Language;
+using Microsoft.PowerShell.EditorServices.Session;
+
+namespace Microsoft.PowerShell.EditorServices.Test.Shared.Definition
+{
+ public class FindsVariableDefinition
+ {
+ public static readonly ScriptRegion SourceDetails =
+ new ScriptRegion
+ {
+ File = @"References\SimpleFile.ps1",
+ StartLineNumber = 8,
+ StartColumnNumber = 3
+ };
+ }
+}
diff --git a/test/PowerShellEditorServices.Test.Shared/Occurrences/FindOccurrencesOnParameter.cs b/test/PowerShellEditorServices.Test.Shared/Occurrences/FindOccurrencesOnParameter.cs
new file mode 100644
index 000000000..28bbefd52
--- /dev/null
+++ b/test/PowerShellEditorServices.Test.Shared/Occurrences/FindOccurrencesOnParameter.cs
@@ -0,0 +1,20 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using Microsoft.PowerShell.EditorServices.Language;
+using Microsoft.PowerShell.EditorServices.Session;
+
+namespace Microsoft.PowerShell.EditorServices.Test.Shared.Occurrences
+{
+ public class FindOccurrencesOnParameter
+ {
+ public static readonly ScriptRegion SourceDetails =
+ new ScriptRegion
+ {
+ File = @"References\SimpleFile.ps1",
+ StartLineNumber = 1,
+ StartColumnNumber = 31
+ };
+ }
+}
diff --git a/test/PowerShellEditorServices.Test.Shared/Occurrences/FindsOccurrencesOnFunction.cs b/test/PowerShellEditorServices.Test.Shared/Occurrences/FindsOccurrencesOnFunction.cs
new file mode 100644
index 000000000..b5658603b
--- /dev/null
+++ b/test/PowerShellEditorServices.Test.Shared/Occurrences/FindsOccurrencesOnFunction.cs
@@ -0,0 +1,20 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using Microsoft.PowerShell.EditorServices.Language;
+using Microsoft.PowerShell.EditorServices.Session;
+
+namespace Microsoft.PowerShell.EditorServices.Test.Shared.Occurrences
+{
+ public class FindsOccurrencesOnFunction
+ {
+ public static readonly ScriptRegion SourceDetails =
+ new ScriptRegion
+ {
+ File = @"References\SimpleFile.ps1",
+ StartLineNumber = 1,
+ StartColumnNumber = 17
+ };
+ }
+}
diff --git a/test/PowerShellEditorServices.Test.Shared/ParameterHints/FindsParameterSetsOnCommand.cs b/test/PowerShellEditorServices.Test.Shared/ParameterHints/FindsParameterSetsOnCommand.cs
new file mode 100644
index 000000000..24c805238
--- /dev/null
+++ b/test/PowerShellEditorServices.Test.Shared/ParameterHints/FindsParameterSetsOnCommand.cs
@@ -0,0 +1,20 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using Microsoft.PowerShell.EditorServices.Language;
+using Microsoft.PowerShell.EditorServices.Session;
+
+namespace Microsoft.PowerShell.EditorServices.Test.Shared.ParameterHint
+{
+ public class FindsParameterSetsOnCommand
+ {
+ public static readonly ScriptRegion SourceDetails =
+ new ScriptRegion
+ {
+ File = @"ParameterHints\ParamHints.ps1",
+ StartLineNumber = 1,
+ StartColumnNumber = 14
+ };
+ }
+}
\ No newline at end of file
diff --git a/test/PowerShellEditorServices.Test.Shared/ParameterHints/FindsParameterSetsOnCommandWithSpaces.cs b/test/PowerShellEditorServices.Test.Shared/ParameterHints/FindsParameterSetsOnCommandWithSpaces.cs
new file mode 100644
index 000000000..0ebbc19aa
--- /dev/null
+++ b/test/PowerShellEditorServices.Test.Shared/ParameterHints/FindsParameterSetsOnCommandWithSpaces.cs
@@ -0,0 +1,20 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using Microsoft.PowerShell.EditorServices.Language;
+using Microsoft.PowerShell.EditorServices.Session;
+
+namespace Microsoft.PowerShell.EditorServices.Test.Shared.ParameterHint
+{
+ public class FindsParameterSetsOnCommandWithSpaces
+ {
+ public static readonly ScriptRegion SourceDetails =
+ new ScriptRegion
+ {
+ File = @"ParameterHints\ParamHints.ps1",
+ StartLineNumber = 9,
+ StartColumnNumber = 31
+ };
+ }
+}
diff --git a/test/PowerShellEditorServices.Test.Shared/ParameterHints/ParamHints.ps1 b/test/PowerShellEditorServices.Test.Shared/ParameterHints/ParamHints.ps1
new file mode 100644
index 000000000..b04da2374
--- /dev/null
+++ b/test/PowerShellEditorServices.Test.Shared/ParameterHints/ParamHints.ps1
@@ -0,0 +1,9 @@
+Get-Process -
+
+function Do-Stuff($things){
+
+}
+
+Write-Output ""
+
+Write-Host ()
\ No newline at end of file
diff --git a/test/PowerShellEditorServices.Test.Shared/PowerShellEditorServices.Test.Shared.csproj b/test/PowerShellEditorServices.Test.Shared/PowerShellEditorServices.Test.Shared.csproj
index c24baf51b..ae967bbcd 100644
--- a/test/PowerShellEditorServices.Test.Shared/PowerShellEditorServices.Test.Shared.csproj
+++ b/test/PowerShellEditorServices.Test.Shared/PowerShellEditorServices.Test.Shared.csproj
@@ -42,7 +42,15 @@
+
+
+
+
+
+
+
+
@@ -54,6 +62,17 @@
PowerShellEditorServices
+
+
+ PreserveNewest
+
+
+
+
+ PreserveNewest
+
+
+