Skip to content

Commit d8ccf99

Browse files
CopilotT-Gro
andcommitted
Add evidence that QuickParse affects VS coloring and test for semantic classification
Co-authored-by: T-Gro <[email protected]>
1 parent 6e460cf commit d8ccf99

File tree

2 files changed

+35
-0
lines changed

2 files changed

+35
-0
lines changed

tests/FSharp.Compiler.Service.Tests/QuickParseTests.fs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ module FSharp.Compiler.Service.Tests.QuickParseTests
33
open Xunit
44
open FSharp.Compiler.EditorServices
55

6+
// QuickParse.GetCompleteIdentifierIsland is used by language service features
7+
// to extract identifier context from source text at cursor positions.
8+
// When it returns None (as it did for '?' before the fix), downstream services
9+
// like semantic classification, completion, and hover can misinterpret the context.
10+
// This impacts Visual Studio's syntax highlighting - see issue #11008753
11+
612
[<Fact>]
713
let ``QuickParse handles optional parameter identifier extraction when cursor is on question mark``() =
814
let lineStr = "member _.memb(?optional:string) = optional"

vsintegration/tests/FSharp.Editor.Tests/SemanticClassificationServiceTests.fs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,3 +240,32 @@ module ``It should still show up as a keyword even if the type parameter is inva
240240
"""
241241

242242
verifyClassificationAtEndOfMarker (sourceText, marker, classificationType)
243+
244+
[<Fact>]
245+
member _.``Optional parameters should be classified correctly``() =
246+
let sourceText =
247+
"""
248+
type TestType() =
249+
member _.memb(?optional:string) = optional
250+
member _.anotherMember(?opt1:int, ?opt2:string) = (opt1, opt2)
251+
"""
252+
let ranges = getRanges sourceText
253+
254+
// The parameter name "optional" should be classified as a parameter/local value, not as a type
255+
// After the fix, QuickParse correctly handles the ? prefix and doesn't confuse semantic classification
256+
let optionalParamRanges =
257+
ranges
258+
|> List.filter (fun item ->
259+
let text = sourceText.Substring(item.Range.StartColumn, item.Range.EndColumn - item.Range.StartColumn)
260+
text = "optional")
261+
262+
// Verify that we have classification data for "optional"
263+
Assert.True(optionalParamRanges.Length > 0, "Should have classification data for 'optional' parameter")
264+
265+
// The first occurrence should be the parameter (not incorrectly classified as a type/namespace)
266+
let firstOptional = optionalParamRanges.[0]
267+
let classificationType = FSharpClassificationTypes.getClassificationTypeName firstOptional.Type
268+
269+
// Should NOT be classified as a type or namespace
270+
Assert.NotEqual(ClassificationTypeNames.ClassName, classificationType)
271+
Assert.NotEqual(ClassificationTypeNames.NamespaceName, classificationType)

0 commit comments

Comments
 (0)