Skip to content

Commit f9fdc3e

Browse files
committed
Implementation for issue #98 - shorting file path completion list.
This commit not only addresses issue #98 but also improves completion list support overall for commands (shows resolved command or path to exe), parameters (shows parameter type) as well as .NET properties and methods (shows signature).
1 parent a5cf548 commit f9fdc3e

File tree

4 files changed

+73
-14
lines changed

4 files changed

+73
-14
lines changed

src/PowerShellEditorServices.Protocol/Server/LanguageServer.cs

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -431,10 +431,6 @@ await editorSession.LanguageService.GetCompletionsInFile(
431431

432432
if (completionResults != null)
433433
{
434-
// By default, insert the completion at the current location
435-
int startEditColumn = textDocumentPosition.Position.Character;
436-
int endEditColumn = textDocumentPosition.Position.Character;
437-
438434
completionItems =
439435
completionResults
440436
.Completions
@@ -918,7 +914,7 @@ await PublishScriptDiagnostics(
918914
Logger.Write(LogLevel.Verbose, "Analysis complete.");
919915
}
920916

921-
private async static Task PublishScriptDiagnostics(
917+
private static async Task PublishScriptDiagnostics(
922918
ScriptFile scriptFile,
923919
ScriptFileMarker[] semanticMarkers,
924920
EventContext eventContext)
@@ -989,23 +985,59 @@ private static CompletionItem CreateCompletionItem(
989985
BufferRange completionRange)
990986
{
991987
string detailString = null;
988+
string documentationString = null;
989+
string labelString = completionDetails.ListItemText;
992990

993-
if (completionDetails.CompletionType == CompletionType.Variable)
991+
if ((completionDetails.CompletionType == CompletionType.Variable) ||
992+
(completionDetails.CompletionType == CompletionType.ParameterName))
994993
{
995-
// Look for variable type encoded in the tooltip
994+
// Look for type encoded in the tooltip for parameters and variables.
995+
// Display PowerShell type names in [] to be consistent with PowerShell syntax
996+
// and now the debugger displays type names.
996997
var matches = Regex.Matches(completionDetails.ToolTipText, @"^\[(.+)\]");
998+
if ((matches.Count > 0) && (matches[0].Groups.Count > 1))
999+
{
1000+
detailString = "[" + matches[0].Groups[1].Value + "]";
1001+
}
9971002

998-
if (matches.Count > 0 && matches[0].Groups.Count > 1)
1003+
// PowerShell returns ListItemText for parameters & variables that is not prefixed
1004+
// and it needs to be or the completion will not appear for these CompletionTypes.
1005+
string prefix = (completionDetails.CompletionType == CompletionType.Variable) ? "$" : "-";
1006+
labelString = prefix + completionDetails.ListItemText;
1007+
}
1008+
else if ((completionDetails.CompletionType == CompletionType.Method) ||
1009+
(completionDetails.CompletionType == CompletionType.Property))
1010+
{
1011+
// We have a raw signature for .NET members, heck let's display it. It's
1012+
// better than nothing.
1013+
documentationString = completionDetails.ToolTipText;
1014+
}
1015+
else if (completionDetails.CompletionType == CompletionType.Command)
1016+
{
1017+
// For Commands, let's extract the resolved command or the path for an exe
1018+
// from the ToolTipText - if there is any ToolTipText.
1019+
if (completionDetails.ToolTipText != null)
9991020
{
1000-
detailString = matches[0].Groups[1].Value;
1021+
// Don't display ToolTipText if it is the same as the ListItemText.
1022+
// Reject command syntax ToolTipText - it's too much to display as a detailString.
1023+
if (!completionDetails.ListItemText.Equals(
1024+
completionDetails.ToolTipText,
1025+
StringComparison.OrdinalIgnoreCase) &&
1026+
!Regex.IsMatch(completionDetails.ToolTipText,
1027+
@"^\s*" + completionDetails.ListItemText + @"\s+\["))
1028+
{
1029+
detailString = completionDetails.ToolTipText;
1030+
}
10011031
}
10021032
}
10031033

10041034
return new CompletionItem
10051035
{
1006-
Label = completionDetails.CompletionText,
1036+
InsertText = completionDetails.CompletionText,
1037+
Label = labelString,
10071038
Kind = MapCompletionKind(completionDetails.CompletionType),
10081039
Detail = detailString,
1040+
Documentation = documentationString,
10091041
TextEdit = new TextEdit
10101042
{
10111043
NewText = completionDetails.CompletionText,

src/PowerShellEditorServices/Language/CompletionResults.cs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@ public enum CompletionType
107107
/// </summary>
108108
ParameterValue,
109109

110+
/// <summary>
111+
/// Identifies a completion for a .NET property.
112+
/// </summary>
113+
Property,
114+
110115
/// <summary>
111116
/// Identifies a completion for a variable name.
112117
/// </summary>
@@ -147,6 +152,11 @@ public sealed class CompletionDetails
147152
/// </summary>
148153
public string CompletionText { get; private set; }
149154

155+
/// <summary>
156+
/// Gets the text that should be dispayed in a drop-down completion list.
157+
/// </summary>
158+
public string ListItemText { get; private set; }
159+
150160
/// <summary>
151161
/// Gets the text that can be used to display a tooltip for
152162
/// the statement at the requested file offset.
@@ -183,6 +193,7 @@ internal static CompletionDetails Create(CompletionResult completionResult)
183193
return new CompletionDetails
184194
{
185195
CompletionText = completionResult.CompletionText,
196+
ListItemText = completionResult.ListItemText,
186197
ToolTipText = toolTipText,
187198
SymbolTypeName = ExtractSymbolTypeNameFromToolTip(completionResult.ToolTip),
188199
CompletionType =
@@ -195,12 +206,14 @@ internal static CompletionDetails Create(
195206
string completionText,
196207
CompletionType completionType,
197208
string toolTipText = null,
198-
string symbolTypeName = null)
209+
string symbolTypeName = null,
210+
string listItemText = null)
199211
{
200212
return new CompletionDetails
201213
{
202214
CompletionText = completionText,
203215
CompletionType = completionType,
216+
ListItemText = listItemText,
204217
ToolTipText = toolTipText,
205218
SymbolTypeName = symbolTypeName
206219
};
@@ -238,9 +251,10 @@ public override int GetHashCode()
238251
{
239252
return
240253
string.Format(
241-
"{0}{1}{2}{3}",
254+
"{0}{1}{2}{3}{4}",
242255
this.CompletionText,
243256
this.CompletionType,
257+
this.ListItemText,
244258
this.ToolTipText,
245259
this.SymbolTypeName).GetHashCode();
246260
}
@@ -266,6 +280,9 @@ private static CompletionType ConvertCompletionResultType(
266280
case CompletionResultType.ParameterValue:
267281
return CompletionType.ParameterValue;
268282

283+
case CompletionResultType.Property:
284+
return CompletionType.Property;
285+
269286
case CompletionResultType.Variable:
270287
return CompletionType.Variable;
271288

test/PowerShellEditorServices.Test.Host/LanguageServerTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ await this.SendRequest(
111111
c => c.Label == "$ConsoleFileName");
112112

113113
Assert.NotNull(consoleFileNameItem);
114-
Assert.Equal("string", consoleFileNameItem.Detail);
114+
Assert.Equal("[string]", consoleFileNameItem.Detail);
115115
}
116116

117117
[Fact(Skip = "Skipped until variable documentation gathering is added back.")]

test/PowerShellEditorServices.Test/Language/PowerShellVersionTests.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,23 @@ private void Compile(string project, string version)
5858
}
5959

6060
FileInfo fi = new FileInfo(project);
61+
string solutionDir = fi.Directory.Parent.Parent.FullName;
6162
var outPath = Path.GetTempPath();
6263

6364
var p = new Process();
6465
p.StartInfo.FileName = msbuild;
65-
p.StartInfo.Arguments = string.Format(@" {0} /p:Configuration=Debug /t:Build /fileLogger /flp1:logfile=errors.txt;errorsonly /p:SolutionDir={1} /p:SolutionName=PowerShellEditorServices /p:DefineConstants=PowerShellv{2} /p:OutDir={3}", project, fi.Directory.Parent.Parent.FullName, version, outPath);
66+
p.StartInfo.Arguments = string.Format(@" {0} /p:Configuration=Debug /t:Build /fileLogger " +
67+
@"/flp1:logfile=errors.txt;errorsonly /p:SolutionDir={1} " +
68+
@"/p:SolutionName=PowerShellEditorServices " +
69+
@"/p:DefineConstants=PowerShellv{2} /p:OutDir={3}",
70+
project, solutionDir, version, outPath);
6671
p.StartInfo.UseShellExecute = false;
6772
p.StartInfo.CreateNoWindow = true;
73+
74+
// On my system, the parent process (VS I guess), defines an environment variable - PLATFORM=X64 -
75+
// which breaks the build of the versioned C# project files. Removing it fixes the issue.
76+
p.StartInfo.EnvironmentVariables.Remove("Platform");
77+
6878
p.Start();
6979
p.WaitForExit(60000);
7080
if (!p.HasExited)

0 commit comments

Comments
 (0)