|
16 | 16 | using System.Text.RegularExpressions;
|
17 | 17 | using System.Threading;
|
18 | 18 | using System.Threading.Tasks;
|
| 19 | +using System.IO; |
19 | 20 |
|
20 | 21 | namespace Microsoft.PowerShell.EditorServices.Host
|
21 | 22 | {
|
@@ -535,29 +536,119 @@ protected async Task HandleDocumentSymbolRequest(
|
535 | 536 | EditorSession editorSession,
|
536 | 537 | RequestContext<SymbolInformation[], object> requestContext)
|
537 | 538 | {
|
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; |
539 | 548 |
|
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 | + } |
544 | 574 |
|
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; |
546 | 604 | }
|
547 | 605 |
|
548 | 606 | protected async Task HandleWorkspaceSymbolRequest(
|
549 | 607 | WorkspaceSymbolParams workspaceSymbolParams,
|
550 | 608 | EditorSession editorSession,
|
551 | 609 | RequestContext<SymbolInformation[], object> requestContext)
|
552 | 610 | {
|
553 |
| - // TODO: Implement this with Keith's changes |
| 611 | + var symbols = new List<SymbolInformation>(); |
554 | 612 |
|
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); |
559 | 618 |
|
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); |
561 | 652 | }
|
562 | 653 |
|
563 | 654 | protected async Task HandleEvaluateRequest(
|
|
0 commit comments