Skip to content

Commit ba1c40e

Browse files
committed
Implemented HandleDocumentSymbolRequest and HandleWorkspaceSymbolRequest - the latter is not working quite right yet. @daviwil thinks it might be a bug on the VSC side.
1 parent a51da9a commit ba1c40e

File tree

2 files changed

+110
-12
lines changed

2 files changed

+110
-12
lines changed

src/PowerShellEditorServices.Host/LanguageServer.cs

+103-12
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
using System.Text.RegularExpressions;
1717
using System.Threading;
1818
using System.Threading.Tasks;
19+
using System.IO;
1920

2021
namespace Microsoft.PowerShell.EditorServices.Host
2122
{
@@ -535,29 +536,119 @@ protected async Task HandleDocumentSymbolRequest(
535536
EditorSession editorSession,
536537
RequestContext<SymbolInformation[], object> requestContext)
537538
{
538-
// TODO: Implement this with Keith's changes.
539+
ScriptFile scriptFile =
540+
editorSession.Workspace.GetFile(
541+
textDocumentIdentifier.Uri);
542+
543+
FindOccurrencesResult foundSymbols =
544+
editorSession.LanguageService.FindSymbolsInFile(
545+
scriptFile);
546+
547+
SymbolInformation[] symbols = null;
539548

540-
// NOTE SymbolInformation.Location's Start/End Position are
541-
// zero-based while the LanguageService APIs are one-based.
542-
// Make sure to subtract line/column positions by 1 when creating
543-
// the result list.
549+
string containerName = Path.GetFileNameWithoutExtension(scriptFile.FilePath);
550+
551+
if (foundSymbols != null)
552+
{
553+
symbols =
554+
foundSymbols
555+
.FoundOccurrences
556+
.Select(r =>
557+
{
558+
return new SymbolInformation {
559+
ContainerName = containerName,
560+
Kind = GetSymbolKind(r.SymbolType),
561+
Location = new Location {
562+
Uri = new Uri(r.FilePath).AbsolutePath,
563+
Range = GetRangeFromScriptRegion(r.ScriptRegion)
564+
},
565+
Name = GetDecoratedSymbolName(r)
566+
};
567+
})
568+
.ToArray();
569+
}
570+
else
571+
{
572+
symbols = new SymbolInformation[0];
573+
}
544574

545-
await requestContext.SendResult(new SymbolInformation[0]);
575+
await requestContext.SendResult(symbols);
576+
}
577+
578+
private SymbolKind GetSymbolKind(SymbolType symbolType)
579+
{
580+
switch (symbolType)
581+
{
582+
case SymbolType.Configuration:
583+
case SymbolType.Function:
584+
case SymbolType.Workflow:
585+
return SymbolKind.Function;
586+
587+
default:
588+
return SymbolKind.Variable;
589+
}
590+
}
591+
592+
private string GetDecoratedSymbolName(SymbolReference symbolReference)
593+
{
594+
string name = symbolReference.SymbolName;
595+
596+
if (symbolReference.SymbolType == SymbolType.Configuration ||
597+
symbolReference.SymbolType == SymbolType.Function ||
598+
symbolReference.SymbolType == SymbolType.Workflow)
599+
{
600+
name += " {}";
601+
}
602+
603+
return name;
546604
}
547605

548606
protected async Task HandleWorkspaceSymbolRequest(
549607
WorkspaceSymbolParams workspaceSymbolParams,
550608
EditorSession editorSession,
551609
RequestContext<SymbolInformation[], object> requestContext)
552610
{
553-
// TODO: Implement this with Keith's changes
611+
var symbols = new List<SymbolInformation>();
554612

555-
// NOTE SymbolInformation.Location's Start/End Position are
556-
// zero-based while the LanguageService APIs are one-based.
557-
// Make sure to subtract line/column positions by 1 when creating
558-
// the result list.
613+
foreach (ScriptFile scriptFile in editorSession.Workspace.GetOpenedFiles())
614+
{
615+
FindOccurrencesResult foundSymbols =
616+
editorSession.LanguageService.FindSymbolsInFile(
617+
scriptFile);
559618

560-
await requestContext.SendResult(new SymbolInformation[0]);
619+
// TODO: Need to compute a relative path that is based on common path for all workspace files
620+
string containerName = Path.GetFileNameWithoutExtension(scriptFile.FilePath);
621+
622+
if (foundSymbols != null)
623+
{
624+
var matchedSymbols =
625+
foundSymbols
626+
.FoundOccurrences
627+
.Where(r => IsQueryMatch(workspaceSymbolParams.Query, r.SymbolName))
628+
.Select(r =>
629+
{
630+
return new SymbolInformation
631+
{
632+
ContainerName = containerName,
633+
Kind = r.SymbolType == SymbolType.Variable ? SymbolKind.Variable : SymbolKind.Function,
634+
Location = new Location {
635+
Uri = new Uri(r.FilePath).AbsolutePath,
636+
Range = GetRangeFromScriptRegion(r.ScriptRegion)
637+
},
638+
Name = GetDecoratedSymbolName(r)
639+
};
640+
});
641+
642+
symbols.AddRange(matchedSymbols);
643+
}
644+
}
645+
646+
await requestContext.SendResult(symbols.ToArray());
647+
}
648+
649+
private bool IsQueryMatch(string query, string symbolName)
650+
{
651+
return symbolName.StartsWith(query, StringComparison.OrdinalIgnoreCase);
561652
}
562653

563654
protected async Task HandleEvaluateRequest(

src/PowerShellEditorServices/Workspace/Workspace.cs

+7
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,13 @@ public ScriptFile GetFileBuffer(string filePath, string initialBuffer)
9191
return scriptFile;
9292
}
9393

94+
public ScriptFile[] GetOpenedFiles()
95+
{
96+
var scriptFiles = new ScriptFile[workspaceFiles.Count];
97+
workspaceFiles.Values.CopyTo(scriptFiles, 0);
98+
return scriptFiles;
99+
}
100+
94101
/// <summary>
95102
/// Closes a currently open script file with the given file path.
96103
/// </summary>

0 commit comments

Comments
 (0)