Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -338,14 +338,25 @@ static bool TryWriteToken(
int deltaStart;
if (!isFirstRange && previousRange.StartLine == currentRange.StartLine)
{
deltaStart = currentRange.StartCharacter - previousRange.StartCharacter;
// If the current range overlaps the previous one, we assume the sort order was
// correct, and prefer the previous range. We have a check for the start character first
// just in case there is a C# range that extends past a Razor range. There is no known case
// for this, but we need to make sure we don't report bad data.
if (previousRange.StartCharacter == currentRange.StartCharacter)
{
return false;
}

// If there is no line delta, no char delta, and this isn't the first range
// then it means this range overlaps the previous, so we skip it.
if (deltaStart == 0)
// Razor ranges are allowed to extend past C# ranges though, so we need to check for that too.
if (previousRange.StartCharacter <= currentRange.StartCharacter &&
(previousRange.EndCharacter >= currentRange.EndCharacter || previousRange.EndLine > currentRange.EndLine))
{
return false;
}

deltaStart = currentRange.StartCharacter - previousRange.StartCharacter;

Debug.Assert(deltaStart > 0, "There is no char delta which means this span overlaps the previous. This should have been filtered out!");
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,18 @@ public int CompareTo(SemanticRange other)
return result;
}

// If the start positions are the same, and one is Razor and one isn't, we prefer Razor. This allows a Razor
// produced token to win over multiple C# tokens, for example the tag name in "<My.Cool.Component>" is one
// Razor classification (for component) but multiple C# classifications (2 namespaces and a type name)
if (FromRazor && !other.FromRazor)
{
return -1;
}
else if (other.FromRazor && !FromRazor)
{
return 1;
}

result = EndLine.CompareTo(other.EndLine);
if (result != 0)
{
Expand All @@ -82,16 +94,6 @@ public int CompareTo(SemanticRange other)
return result;
}

// If we have ranges that are the same, we want a Razor produced token to win over a non-Razor produced token
if (FromRazor && !other.FromRazor)
{
return -1;
}
else if (other.FromRazor && !FromRazor)
{
return 1;
}

return 0;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
Line Δ, Char Δ, Length, Type, Modifier(s), Text
0 0 1 markupTagDelimiter [] [<]
0 1 9 razorComponentElement [] [InputText]
0 10 5 razorComponentAttribute [] [Value]
0 5 1 markupOperator [] [=]
0 1 1 markupAttributeQuote [] ["]
0 1 9 markupAttributeValue [] [someValue]
0 9 1 markupAttributeQuote [] ["]
0 2 1 markupTagDelimiter [] [/]
0 1 1 markupTagDelimiter [] [>]
1 0 1 markupTagDelimiter [] [<]
0 1 9 razorComponentElement [] [InputText]
0 10 5 razorComponentAttribute [] [Value]
0 5 1 markupOperator [] [=]
0 1 1 markupAttributeQuote [] ["]
0 1 9 markupAttributeValue [] [someValue]
0 9 1 markupAttributeQuote [] ["]
0 1 1 markupTagDelimiter [] [>]
0 1 1 markupTagDelimiter [] [<]
0 1 1 markupTagDelimiter [] [/]
0 1 9 razorComponentElement [] [InputText]
0 9 1 markupTagDelimiter [] [>]
1 0 1 markupTagDelimiter [] [<]
0 1 47 razorComponentElement [] [Microsoft.AspNetCore.Components.Forms.InputText]
0 48 5 razorComponentAttribute [] [Value]
0 5 1 markupOperator [] [=]
0 1 1 markupAttributeQuote [] ["]
0 1 9 markupAttributeValue [] [someValue]
0 9 1 markupAttributeQuote [] ["]
0 2 1 markupTagDelimiter [] [/]
0 1 1 markupTagDelimiter [] [>]
1 0 1 markupTagDelimiter [] [<]
0 1 47 razorComponentElement [] [Microsoft.AspNetCore.Components.Forms.InputText]
0 48 5 razorComponentAttribute [] [Value]
0 5 1 markupOperator [] [=]
0 1 1 markupAttributeQuote [] ["]
0 1 9 markupAttributeValue [] [someValue]
0 9 1 markupAttributeQuote [] ["]
0 1 1 markupTagDelimiter [] [>]
0 1 1 markupTagDelimiter [] [<]
0 1 1 markupTagDelimiter [] [/]
0 1 47 razorComponentElement [] [Microsoft.AspNetCore.Components.Forms.InputText]
0 47 1 markupTagDelimiter [] [>]
2 0 1 razorTransition [] [@]
0 1 6 keyword [] [typeof]
0 6 1 punctuation [] [(]
0 1 9 class name [] [InputText]
0 9 1 punctuation [] [)]
0 1 1 operator [] [.]
0 1 8 method name [] [ToString]
0 8 1 punctuation [] [(]
0 1 1 punctuation [] [)]
1 0 1 razorTransition [] [@]
0 1 6 keyword [] [typeof]
0 6 1 punctuation [] [(]
0 1 9 namespace name [] [Microsoft]
0 9 1 operator [] [.]
0 1 10 namespace name [] [AspNetCore]
0 10 1 operator [] [.]
0 1 10 namespace name [] [Components]
0 10 1 operator [] [.]
0 1 5 namespace name [] [Forms]
0 5 1 operator [] [.]
0 1 9 class name [] [InputText]
0 9 1 punctuation [] [)]
0 1 1 operator [] [.]
0 1 8 method name [] [ToString]
0 8 1 punctuation [] [(]
0 1 1 punctuation [] [)]
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
Line Δ, Char Δ, Length, Type, Modifier(s), Text
0 0 1 markupTagDelimiter [] [<]
0 1 9 markupElement [] [InputText]
0 10 5 markupAttribute [] [Value]
0 5 1 markupOperator [] [=]
0 1 1 markupAttributeQuote [] ["]
0 1 9 markupAttributeValue [] [someValue]
0 9 1 markupAttributeQuote [] ["]
0 2 1 markupTagDelimiter [] [/]
0 1 1 markupTagDelimiter [] [>]
1 0 1 markupTagDelimiter [] [<]
0 1 9 markupElement [] [InputText]
0 10 5 markupAttribute [] [Value]
0 5 1 markupOperator [] [=]
0 1 1 markupAttributeQuote [] ["]
0 1 9 markupAttributeValue [] [someValue]
0 9 1 markupAttributeQuote [] ["]
0 1 1 markupTagDelimiter [] [>]
0 1 1 markupTagDelimiter [] [<]
0 1 1 markupTagDelimiter [] [/]
0 1 9 markupElement [] [InputText]
0 9 1 markupTagDelimiter [] [>]
1 0 1 markupTagDelimiter [] [<]
0 1 47 markupElement [] [Microsoft.AspNetCore.Components.Forms.InputText]
0 48 5 markupAttribute [] [Value]
0 5 1 markupOperator [] [=]
0 1 1 markupAttributeQuote [] ["]
0 1 9 markupAttributeValue [] [someValue]
0 9 1 markupAttributeQuote [] ["]
0 2 1 markupTagDelimiter [] [/]
0 1 1 markupTagDelimiter [] [>]
1 0 1 markupTagDelimiter [] [<]
0 1 47 markupElement [] [Microsoft.AspNetCore.Components.Forms.InputText]
0 48 5 markupAttribute [] [Value]
0 5 1 markupOperator [] [=]
0 1 1 markupAttributeQuote [] ["]
0 1 9 markupAttributeValue [] [someValue]
0 9 1 markupAttributeQuote [] ["]
0 1 1 markupTagDelimiter [] [>]
0 1 1 markupTagDelimiter [] [<]
0 1 1 markupTagDelimiter [] [/]
0 1 47 markupElement [] [Microsoft.AspNetCore.Components.Forms.InputText]
0 47 1 markupTagDelimiter [] [>]
2 0 1 razorTransition [] [@]
0 1 6 keyword [] [typeof]
0 6 1 punctuation [] [(]
0 1 9 variable [] [InputText]
0 9 1 punctuation [] [)]
0 1 1 operator [] [.]
0 1 8 method name [] [ToString]
0 8 1 punctuation [] [(]
0 1 1 punctuation [] [)]
1 0 1 razorTransition [] [@]
0 1 6 keyword [] [typeof]
0 6 1 punctuation [] [(]
0 1 9 namespace name [] [Microsoft]
0 9 1 operator [] [.]
0 1 10 variable [] [AspNetCore]
0 10 1 operator [] [.]
0 1 10 variable [] [Components]
0 10 1 operator [] [.]
0 1 5 variable [] [Forms]
0 5 1 operator [] [.]
0 1 9 variable [] [InputText]
0 9 1 punctuation [] [)]
0 1 1 operator [] [.]
0 1 8 method name [] [ToString]
0 8 1 punctuation [] [(]
0 1 1 punctuation [] [)]
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
Line Δ, Char Δ, Length, Type, Modifier(s), Text
0 0 1 markupTagDelimiter [] [<]
0 1 9 razorComponentElement [] [InputText]
0 10 5 razorComponentAttribute [] [Value]
0 5 1 markupOperator [] [=]
0 1 1 markupAttributeQuote [] ["]
0 1 9 markupAttributeValue [] [someValue]
0 9 1 markupAttributeQuote [] ["]
0 2 1 markupTagDelimiter [] [/]
0 1 1 markupTagDelimiter [] [>]
1 0 1 markupTagDelimiter [] [<]
0 1 9 razorComponentElement [] [InputText]
0 10 5 razorComponentAttribute [] [Value]
0 5 1 markupOperator [] [=]
0 1 1 markupAttributeQuote [] ["]
0 1 9 markupAttributeValue [] [someValue]
0 9 1 markupAttributeQuote [] ["]
0 1 1 markupTagDelimiter [] [>]
0 1 1 markupTagDelimiter [] [<]
0 1 1 markupTagDelimiter [] [/]
0 1 9 razorComponentElement [] [InputText]
0 9 1 markupTagDelimiter [] [>]
1 0 1 markupTagDelimiter [] [<]
0 1 47 razorComponentElement [] [Microsoft.AspNetCore.Components.Forms.InputText]
0 48 5 razorComponentAttribute [] [Value]
0 5 1 markupOperator [] [=]
0 1 1 markupAttributeQuote [] ["]
0 1 9 markupAttributeValue [] [someValue]
0 9 1 markupAttributeQuote [] ["]
0 2 1 markupTagDelimiter [] [/]
0 1 1 markupTagDelimiter [] [>]
1 0 1 markupTagDelimiter [] [<]
0 1 47 razorComponentElement [] [Microsoft.AspNetCore.Components.Forms.InputText]
0 48 5 razorComponentAttribute [] [Value]
0 5 1 markupOperator [] [=]
0 1 1 markupAttributeQuote [] ["]
0 1 9 markupAttributeValue [] [someValue]
0 9 1 markupAttributeQuote [] ["]
0 1 1 markupTagDelimiter [] [>]
0 1 1 markupTagDelimiter [] [<]
0 1 1 markupTagDelimiter [] [/]
0 1 47 razorComponentElement [] [Microsoft.AspNetCore.Components.Forms.InputText]
0 47 1 markupTagDelimiter [] [>]
2 0 1 razorTransition [razorCode] [@]
0 1 6 keyword [razorCode] [typeof]
0 6 1 punctuation [razorCode] [(]
0 1 9 class name [razorCode] [InputText]
0 9 1 punctuation [razorCode] [)]
0 1 1 operator [razorCode] [.]
0 1 8 method name [razorCode] [ToString]
0 8 1 punctuation [razorCode] [(]
0 1 1 punctuation [razorCode] [)]
1 0 1 razorTransition [razorCode] [@]
0 1 6 keyword [razorCode] [typeof]
0 6 1 punctuation [razorCode] [(]
0 1 9 namespace name [razorCode] [Microsoft]
0 9 1 operator [razorCode] [.]
0 1 10 namespace name [razorCode] [AspNetCore]
0 10 1 operator [razorCode] [.]
0 1 10 namespace name [razorCode] [Components]
0 10 1 operator [razorCode] [.]
0 1 5 namespace name [razorCode] [Forms]
0 5 1 operator [razorCode] [.]
0 1 9 class name [razorCode] [InputText]
0 9 1 punctuation [razorCode] [)]
0 1 1 operator [razorCode] [.]
0 1 8 method name [razorCode] [ToString]
0 8 1 punctuation [razorCode] [(]
0 1 1 punctuation [razorCode] [)]
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
Line Δ, Char Δ, Length, Type, Modifier(s), Text
0 0 1 markupTagDelimiter [] [<]
0 1 9 markupElement [] [InputText]
0 10 5 markupAttribute [] [Value]
0 5 1 markupOperator [] [=]
0 1 1 markupAttributeQuote [] ["]
0 1 9 markupAttributeValue [] [someValue]
0 9 1 markupAttributeQuote [] ["]
0 2 1 markupTagDelimiter [] [/]
0 1 1 markupTagDelimiter [] [>]
1 0 1 markupTagDelimiter [] [<]
0 1 9 markupElement [] [InputText]
0 10 5 markupAttribute [] [Value]
0 5 1 markupOperator [] [=]
0 1 1 markupAttributeQuote [] ["]
0 1 9 markupAttributeValue [] [someValue]
0 9 1 markupAttributeQuote [] ["]
0 1 1 markupTagDelimiter [] [>]
0 1 1 markupTagDelimiter [] [<]
0 1 1 markupTagDelimiter [] [/]
0 1 9 markupElement [] [InputText]
0 9 1 markupTagDelimiter [] [>]
1 0 1 markupTagDelimiter [] [<]
0 1 47 markupElement [] [Microsoft.AspNetCore.Components.Forms.InputText]
0 48 5 markupAttribute [] [Value]
0 5 1 markupOperator [] [=]
0 1 1 markupAttributeQuote [] ["]
0 1 9 markupAttributeValue [] [someValue]
0 9 1 markupAttributeQuote [] ["]
0 2 1 markupTagDelimiter [] [/]
0 1 1 markupTagDelimiter [] [>]
1 0 1 markupTagDelimiter [] [<]
0 1 47 markupElement [] [Microsoft.AspNetCore.Components.Forms.InputText]
0 48 5 markupAttribute [] [Value]
0 5 1 markupOperator [] [=]
0 1 1 markupAttributeQuote [] ["]
0 1 9 markupAttributeValue [] [someValue]
0 9 1 markupAttributeQuote [] ["]
0 1 1 markupTagDelimiter [] [>]
0 1 1 markupTagDelimiter [] [<]
0 1 1 markupTagDelimiter [] [/]
0 1 47 markupElement [] [Microsoft.AspNetCore.Components.Forms.InputText]
0 47 1 markupTagDelimiter [] [>]
2 0 1 razorTransition [razorCode] [@]
0 1 6 keyword [razorCode] [typeof]
0 6 1 punctuation [razorCode] [(]
0 1 9 variable [razorCode] [InputText]
0 9 1 punctuation [razorCode] [)]
0 1 1 operator [razorCode] [.]
0 1 8 method name [razorCode] [ToString]
0 8 1 punctuation [razorCode] [(]
0 1 1 punctuation [razorCode] [)]
1 0 1 razorTransition [razorCode] [@]
0 1 6 keyword [razorCode] [typeof]
0 6 1 punctuation [razorCode] [(]
0 1 9 namespace name [razorCode] [Microsoft]
0 9 1 operator [razorCode] [.]
0 1 10 variable [razorCode] [AspNetCore]
0 10 1 operator [razorCode] [.]
0 1 10 variable [razorCode] [Components]
0 10 1 operator [razorCode] [.]
0 1 5 variable [razorCode] [Forms]
0 5 1 operator [razorCode] [.]
0 1 9 variable [razorCode] [InputText]
0 9 1 punctuation [razorCode] [)]
0 1 1 operator [razorCode] [.]
0 1 8 method name [razorCode] [ToString]
0 8 1 punctuation [razorCode] [(]
0 1 1 punctuation [razorCode] [)]
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,23 @@ namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost;

public class CohostSemanticTokensRangeEndpointTest(ITestOutputHelper testOutputHelper) : CohostEndpointTestBase(testOutputHelper)
{
[Theory]
[CombinatorialData]
public async Task RazorComponents(bool colorBackground, bool miscellaneousFile)
{
var input = """
<InputText Value="someValue" />
<InputText Value="someValue"></InputText>
<Microsoft.AspNetCore.Components.Forms.InputText Value="someValue" />
<Microsoft.AspNetCore.Components.Forms.InputText Value="someValue"></Microsoft.AspNetCore.Components.Forms.InputText>

@typeof(InputText).ToString()
@typeof(Microsoft.AspNetCore.Components.Forms.InputText).ToString()
""";

await VerifySemanticTokensAsync(input, colorBackground, miscellaneousFile);
}

[Theory]
[CombinatorialData]
public async Task Razor(bool colorBackground, bool miscellaneousFile)
Expand Down
Loading