Skip to content

Commit bd28a73

Browse files
committed
add document symbols for #region start
1 parent ca227b5 commit bd28a73

File tree

6 files changed

+74
-1
lines changed

6 files changed

+74
-1
lines changed

src/PowerShellEditorServices/Services/Symbols/ReferenceTable.cs

+1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ internal void EnsureInitialized()
7979
}
8080

8181
_parent.ScriptAst.Visit(new SymbolVisitor(_parent, AddReference));
82+
RegionVisitor.FindRegionsInDocument(_parent, AddReference);
8283
}
8384

8485
private AstVisitAction AddReference(SymbolReference symbol)

src/PowerShellEditorServices/Services/Symbols/SymbolType.cs

+6
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ internal enum SymbolType
7979
/// The symbol is a type reference
8080
/// </summary>
8181
Type,
82+
83+
/// <summary>
84+
/// The symbol is a region
85+
/// </summary>
86+
Region
8287
}
8388

8489
internal static class SymbolTypeUtils
@@ -97,6 +102,7 @@ internal static SymbolKind GetSymbolKind(SymbolType symbolType)
97102
SymbolType.Variable or SymbolType.Parameter => SymbolKind.Variable,
98103
SymbolType.HashtableKey => SymbolKind.Key,
99104
SymbolType.Type => SymbolKind.TypeParameter,
105+
SymbolType.Region => SymbolKind.String,
100106
SymbolType.Unknown or _ => SymbolKind.Object,
101107
};
102108
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
using System;
5+
using System.Management.Automation.Language;
6+
using System.Text.RegularExpressions;
7+
using Microsoft.PowerShell.EditorServices.Services.TextDocument;
8+
9+
namespace Microsoft.PowerShell.EditorServices.Services.Symbols
10+
{
11+
internal static class RegionVisitor
12+
{
13+
// This regular expression are used to match lines which mark the start of a region comment in a script.
14+
// Based on the defaults in the VS Code Language Configuration at;
15+
// https://github.com/Microsoft/vscode/blob/64186b0a26/extensions/powershell/language-configuration.json#L26-L31
16+
// https://github.com/Microsoft/vscode/issues/49070
17+
private static readonly Regex s_startRegionTextRegex = new(
18+
@"^\s*#[rR]egion\b", RegexOptions.Compiled);
19+
20+
internal static void FindRegionsInDocument(ScriptFile file, Func<SymbolReference, AstVisitAction> action)
21+
{
22+
Token[] tokens = file.ScriptTokens;
23+
for (int i = 0; i < tokens.Length; i++)
24+
{
25+
Token token = tokens[i];
26+
27+
// Exclude everything but single-line comments
28+
if (token.Kind != TokenKind.Comment ||
29+
token.Extent.StartLineNumber != token.Extent.EndLineNumber)
30+
{
31+
continue;
32+
}
33+
34+
// Look for <newline> #region <optional name>
35+
// Document symbols only care about the symbol start and regex is expensive,
36+
// so skip checking if region is actually closed with #endregion.
37+
if (TokenOperations.IsBlockComment(i, tokens) &&
38+
s_startRegionTextRegex.IsMatch(token.Text))
39+
{
40+
action(new SymbolReference(
41+
SymbolType.Region,
42+
token.Extent.Text.TrimStart().TrimStart('#'),
43+
token.Extent.Text,
44+
token.Extent,
45+
token.Extent,
46+
file,
47+
isDeclaration: true));
48+
}
49+
}
50+
}
51+
}
52+
}

src/PowerShellEditorServices/Services/TextDocument/TokenOperations.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ private static FoldingReference CreateFoldingReference(
199199
/// - Token text must start with a '#'.false This is because comment regions
200200
/// start with '&lt;#' but have the same TokenKind
201201
/// </summary>
202-
private static bool IsBlockComment(int index, Token[] tokens)
202+
internal static bool IsBlockComment(int index, Token[] tokens)
203203
{
204204
Token thisToken = tokens[index];
205205
if (thisToken.Kind != TokenKind.Comment) { return false; }

test/PowerShellEditorServices.Test.Shared/Symbols/MultipleSymbols.ps1

+8
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,11 @@ enum AEnum {
4141
AFunction
4242
1..3 | AFilter
4343
AnAdvancedFunction
44+
45+
<#
46+
#region don't find me
47+
abc
48+
#endregion
49+
#>
50+
#region my region 123
51+
#endregion

test/PowerShellEditorServices.Test/Language/SymbolsServiceTests.cs

+6
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,12 @@ public void FindsSymbolsInFile()
821821
Assert.Equal("prop AValue", symbol.Id);
822822
Assert.Equal("AValue", symbol.Name);
823823
Assert.True(symbol.IsDeclaration);
824+
825+
symbol = Assert.Single(symbols.Where(i => i.Type == SymbolType.Region));
826+
Assert.Equal("region my region 123", symbol.Id);
827+
Assert.Equal("#region my region 123", symbol.Name);
828+
AssertIsRegion(symbol.NameRegion, 50, 1, 50, 22);
829+
Assert.True(symbol.IsDeclaration);
824830
}
825831

826832
[Fact]

0 commit comments

Comments
 (0)