-
Notifications
You must be signed in to change notification settings - Fork 222
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added Handler for Semantic Tokenization #1328
Changes from 21 commits
2790655
04458e4
2e46016
b3077cc
f68e4e3
6f28dc5
d960ac7
2853580
a55108c
75b6386
01bde39
ea0fab2
ccf1028
170fb6b
4764d2e
5572a16
f8411cc
4b7db57
a20241b
bebc507
5550780
3fb9abe
73bda8d
4703804
c013b1d
5ab13c4
62566a8
bafff92
5a631dd
7df4e67
b2e43b1
4a6955f
f4562c0
6264c0b
ae5a498
9ae83aa
b4d558c
874db6e
bec8bd6
9848c71
855790c
514012c
5294cf4
9aed66b
b4024e7
4908752
2e4f098
8f5db93
42714b5
1657fdf
ebae357
f109d71
c9b858d
d8f0a36
3fba85f
8592540
d4a86ac
e86c5b8
6c21195
09d632c
7c4b3b7
99c1c0b
725e8eb
1aedd88
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,160 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Copyright (c) Microsoft. All rights reserved. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using System; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using System.Collections.Generic; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using System.Management.Automation.Language; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using System.Threading; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using System.Threading.Tasks; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Microsoft.Extensions.Logging; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Microsoft.PowerShell.EditorServices.Services; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Microsoft.PowerShell.EditorServices.Services.TextDocument; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Microsoft.PowerShell.EditorServices.Utility; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using OmniSharp.Extensions.LanguageServer.Protocol; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using OmniSharp.Extensions.LanguageServer.Protocol.Document.Proposals; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using OmniSharp.Extensions.LanguageServer.Protocol.Models; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
namespace Microsoft.PowerShell.EditorServices.Handlers | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
internal class PsesSemanticTokens : SemanticTokensHandler | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private readonly ILogger _logger; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private readonly WorkspaceService _workspaceService; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private static readonly SemanticTokensRegistrationOptions s_registrationOptions = new SemanticTokensRegistrationOptions() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
DocumentSelector = LspUtils.PowerShellDocumentSelector, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Legend = new SemanticTokensLegend(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
DocumentProvider = new Supports<SemanticTokensDocumentProviderOptions>(isSupported: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
new SemanticTokensDocumentProviderOptions { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Edits = true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
RangeProvider = true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this but with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed above |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public PsesSemanticTokens(ILogger<PsesSemanticTokens> logger, WorkspaceService workspaceService) : base(s_registrationOptions) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_logger = logger; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_workspaceService = workspaceService; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
protected override Task Tokenize(SemanticTokensBuilder builder, ITextDocumentIdentifierParams identifier, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
CancellationToken cancellationToken) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ScriptFile file = _workspaceService.GetFile(DocumentUri.GetFileSystemPath(identifier)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
foreach (var token in file.ScriptTokens){ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
rjmholt marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PushToken(token, builder); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return Task.CompletedTask; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private static void PushToken(Token token, SemanticTokensBuilder builder) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
foreach(SemanticToken sToken in ConvertToSemanticTokens(token)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
builder.Push( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
sToken.Line, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
sToken.Index, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
length: sToken.Text.Length, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
sToken.Type, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tokenModifiers: sToken.TokenModifiers); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
internal static IEnumerable<SemanticToken> ConvertToSemanticTokens(Token token) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (token is StringExpandableToken stringExpandableToken) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Try parsing tokens within the string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (stringExpandableToken.NestedTokens != null) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
foreach (Token t in stringExpandableToken.NestedTokens) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
foreach (SemanticToken subToken in ConvertToSemanticTokens(t)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
yield return subToken; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
yield break; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
SemanticTokenType mappedType = MapSemanticTokenType(token); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
rjmholt marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (mappedType == null){ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
rjmholt marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
yield break; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
//Tokens line and col numbers indexed starting from 1, expecting indexing from 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
int line = token.Extent.StartLineNumber - 1; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
int index = token.Extent.StartColumnNumber - 1; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
SemanticToken sToken = new SemanticToken(token.Text, mappedType, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
line, index, Array.Empty<string>()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
yield return sToken; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private static SemanticTokenType MapSemanticTokenType(Token token) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// First check token flags | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if ((token.TokenFlags & TokenFlags.Keyword) != 0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return SemanticTokenType.Keyword; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if ((token.TokenFlags & TokenFlags.CommandName) != 0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return SemanticTokenType.Function; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (token.Kind != TokenKind.Generic && (token.TokenFlags & | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
(TokenFlags.BinaryOperator | TokenFlags.UnaryOperator | TokenFlags.AssignmentOperator)) != 0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return SemanticTokenType.Operator; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if ((token.TokenFlags & TokenFlags.TypeName) != 0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return SemanticTokenType.Type; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if ((token.TokenFlags & TokenFlags.MemberName) != 0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return SemanticTokenType.Member; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Only check token kind after checking flags | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
switch (token.Kind) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case TokenKind.Comment: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return SemanticTokenType.Comment; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case TokenKind.Parameter: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case TokenKind.Generic when token is StringLiteralToken slt && slt.Text.StartsWith("--"): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return SemanticTokenType.Parameter; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case TokenKind.Variable: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case TokenKind.SplattedVariable: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return SemanticTokenType.Variable; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case TokenKind.StringExpandable: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case TokenKind.StringLiteral: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case TokenKind.HereStringExpandable: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case TokenKind.HereStringLiteral: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return SemanticTokenType.String; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case TokenKind.Number: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return SemanticTokenType.Number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case TokenKind.Generic: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return SemanticTokenType.Function; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
protected override Task<SemanticTokensDocument> GetSemanticTokensDocument( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ITextDocumentIdentifierParams @params, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
CancellationToken cancellationToken) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return Task.FromResult(new SemanticTokensDocument(GetRegistrationOptions().Legend)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
using System.Collections.Generic; | ||
using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; | ||
|
||
namespace Microsoft.PowerShell.EditorServices.Services.TextDocument | ||
{ | ||
class SemanticToken | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't there an Omnisharp type for this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, never made one because it adds extra allocations. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can add one if you'd like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do have
rjmholt marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
public SemanticToken(string text, SemanticTokenType type, int line, int index, IEnumerable<string> tokenModifiers) | ||
TylerLeonhardt marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
Line = line; | ||
Text = text; | ||
Index = index; | ||
Type = type; | ||
TokenModifiers = tokenModifiers; | ||
} | ||
public string Text {get; set;} | ||
public int Line {get; set;} | ||
public int Index {get; set;} | ||
public SemanticTokenType Type {get; set;} | ||
public IEnumerable<string> TokenModifiers {get; set;} | ||
rjmholt marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
// | ||
// Copyright (c) Microsoft. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
// | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Management.Automation.Language; | ||
using System.Threading.Tasks; | ||
using Microsoft.PowerShell.EditorServices.Services.TextDocument; | ||
using Microsoft.PowerShell.EditorServices.Handlers; | ||
using OmniSharp.Extensions.LanguageServer.Protocol; | ||
using OmniSharp.Extensions.LanguageServer.Protocol.Document.Proposals; | ||
using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; | ||
using Xunit; | ||
|
||
namespace Microsoft.PowerShell.EditorServices.Test.Language | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The tests here look good. One extra thing I would do is include tests for the less conspicuous tokens like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Those tokens aren't mapped to SemanticTokenTypes and are handled by EditorSyntax There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, I didn't realise that. That seems a bit strange, and maybe like we're doing more work than we should... We should maybe discuss at some point There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I map the tokens that can be recognized as one of these https://github.com/OmniSharp/csharp-language-server-protocol/blob/f93f973ec96d895c0c6056f5f5942c4646071ab9/src/Protocol/Models/Proposals/SemanticTokenTypes.cs |
||
{ | ||
public class SemanticTokenTest | ||
{ | ||
[Fact] | ||
public async Task TokenizesFunctionElements() | ||
{ | ||
string text = @" | ||
function Get-Sum { | ||
param( [int]$a, [int]$b ) | ||
return $a + $b | ||
} | ||
"; | ||
ScriptFile scriptFile = new ScriptFile( | ||
// Use any absolute path. Even if it doesn't exist. | ||
DocumentUri.FromFileSystemPath(Path.Combine(Path.GetTempPath(), "TestFile.ps1")), | ||
text, | ||
Version.Parse("5.0")); | ||
|
||
foreach(Token t in scriptFile.ScriptTokens) | ||
{ | ||
List<SemanticToken> mappedTokens = new List<SemanticToken>(PsesSemanticTokens.ConvertToSemanticTokens(t)); | ||
switch(t.Text) | ||
{ | ||
case "function": | ||
case "param": | ||
case "return": | ||
Assert.Collection(mappedTokens, sToken => Assert.Equal(SemanticTokenType.Keyword, mappedTokens[0].Type)); | ||
diego-alvarez-by marked this conversation as resolved.
Show resolved
Hide resolved
|
||
break; | ||
case "Get-Sum": | ||
Assert.Collection(mappedTokens, sToken => Assert.Equal(SemanticTokenType.Function, mappedTokens[0].Type)); | ||
break; | ||
case "$a": | ||
case "$b": | ||
Assert.Collection(mappedTokens, sToken => Assert.Equal(SemanticTokenType.Variable, mappedTokens[0].Type)); | ||
break; | ||
case "[int]": | ||
Assert.Collection(mappedTokens, sToken => Assert.Equal(SemanticTokenType.Type, mappedTokens[0].Type)); | ||
break; | ||
case "+": | ||
Assert.Collection(mappedTokens, sToken => Assert.Equal(SemanticTokenType.Operator, mappedTokens[0].Type)); | ||
break; | ||
} | ||
} | ||
} | ||
|
||
[Fact] | ||
public async Task TokenizesStringExpansion() | ||
{ | ||
string text = "Write-Host \"$(Test-Property Get-Whatever) $(Get-Whatever)\""; | ||
ScriptFile scriptFile = new ScriptFile( | ||
// Use any absolute path. Even if it doesn't exist. | ||
DocumentUri.FromFileSystemPath(Path.Combine(Path.GetTempPath(), "TestFile.ps1")), | ||
text, | ||
Version.Parse("5.0")); | ||
|
||
Token commandToken = scriptFile.ScriptTokens[0]; | ||
List<SemanticToken> mappedTokens = new List<SemanticToken>(PsesSemanticTokens.ConvertToSemanticTokens(commandToken)); | ||
Assert.Single(mappedTokens); | ||
Assert.Equal(SemanticTokenType.Function, mappedTokens[0].Type); | ||
|
||
Token stringExpandableToken = scriptFile.ScriptTokens[1]; | ||
mappedTokens = new List<SemanticToken>(PsesSemanticTokens.ConvertToSemanticTokens(stringExpandableToken)); | ||
Assert.Collection(mappedTokens, | ||
sToken => Assert.Equal(SemanticTokenType.Function, sToken.Type), | ||
sToken => Assert.Equal(SemanticTokenType.Function, sToken.Type), | ||
sToken => Assert.Equal(SemanticTokenType.Function, sToken.Type) | ||
); | ||
} | ||
|
||
[Fact] | ||
public async Task RecognizesTokensWithAsterisk() | ||
{ | ||
string text = @" | ||
function Get-A*A { | ||
} | ||
Get-A*A | ||
"; | ||
ScriptFile scriptFile = new ScriptFile( | ||
// Use any absolute path. Even if it doesn't exist. | ||
DocumentUri.FromFileSystemPath(Path.Combine(Path.GetTempPath(), "TestFile.ps1")), | ||
text, | ||
Version.Parse("5.0")); | ||
|
||
foreach(Token t in scriptFile.ScriptTokens) | ||
{ | ||
List<SemanticToken> mappedTokens = new List<SemanticToken>(PsesSemanticTokens.ConvertToSemanticTokens(t)); | ||
switch(t.Text) | ||
{ | ||
case "function": | ||
Assert.Collection(mappedTokens, sToken => Assert.Equal(SemanticTokenType.Keyword, mappedTokens[0].Type)); | ||
break; | ||
case "Get-A*A": | ||
Assert.Collection(mappedTokens, sToken => Assert.Equal(SemanticTokenType.Function, mappedTokens[0].Type)); | ||
break; | ||
TylerLeonhardt marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
} | ||
|
||
[Fact] | ||
public async Task RecognizesArrayMemberInExpandableString() | ||
{ | ||
string text = "\"$(@($Array).Count) OtherText\""; | ||
ScriptFile scriptFile = new ScriptFile( | ||
// Use any absolute path. Even if it doesn't exist. | ||
DocumentUri.FromFileSystemPath(Path.Combine(Path.GetTempPath(), "TestFile.ps1")), | ||
text, | ||
Version.Parse("5.0")); | ||
|
||
foreach(Token t in scriptFile.ScriptTokens) | ||
{ | ||
List<SemanticToken> mappedTokens = new List<SemanticToken>(PsesSemanticTokens.ConvertToSemanticTokens(t)); | ||
switch(t.Text) | ||
{ | ||
case "$Array": | ||
Assert.Collection(mappedTokens, sToken => Assert.Equal(SemanticTokenType.Variable, mappedTokens[0].Type)); | ||
break; | ||
case "Count": | ||
Assert.Collection(mappedTokens, sToken => Assert.Equal(SemanticTokenType.Member, mappedTokens[0].Type)); | ||
break; | ||
} | ||
} | ||
} | ||
|
||
[Fact] | ||
public async Task RecognizesCurlyQuotedString() | ||
{ | ||
string text = "“^[-'a-z]*”"; | ||
ScriptFile scriptFile = new ScriptFile( | ||
// Use any absolute path. Even if it doesn't exist. | ||
DocumentUri.FromFileSystemPath(Path.Combine(Path.GetTempPath(), "TestFile.ps1")), | ||
text, | ||
Version.Parse("5.0")); | ||
|
||
List<SemanticToken> mappedTokens = new List<SemanticToken>(PsesSemanticTokens.ConvertToSemanticTokens(scriptFile.ScriptTokens[0])); | ||
Assert.Collection(mappedTokens, sToken => Assert.Equal(SemanticTokenType.String, mappedTokens[0].Type)); | ||
TylerLeonhardt marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tokens*
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Fixed in my suggestion)