Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 91f7e55

Browse files
T-GroCopilot
andcommitted
Fix F# editor semantic-classification issues (#19905 items 1/2/5/7)
Items 1/2/5/7 are completion-safe and shipped here: - item 1: suppress the synthesized delegate Invoke value over the `delegate of ...` RHS - item 2: classify CE builders inside list/array comprehensions as ComputationExpression - item 5: don't paint slice brackets as Method; fix open-ended slice upper-bound range - item 7: `open type T` is not unused when its static members/fields or DU cases are used Items 3/4/6 (generic `<...>` argument colorization) are deferred: narrowing the shared name-resolution range to fix colorization breaks find-all-references, completion and parameter-info, because the resolution sink matches symbol uses by exact range end. The correct fix requires separating classification ranges from symbol-use ranges in the sink. Guard tests assert the IDE features still work. Co-authored-by: Copilot <[email protected]>
1 parent d31c517 commit 91f7e55

6 files changed

Lines changed: 398 additions & 29 deletions

File tree

docs/release-notes/.FSharp.Compiler.Service/11.0.100.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
### Fixed
22

3+
* Fix several F# editor semantic-classification errors: F# delegate declarations no longer highlight the `delegate of …` syntax as a method, computation-expression builders inside list/array comprehensions are classified as `ComputationExpression`, the closing `]` of an open-ended slice (e.g. `xs[0..]`) is no longer classified as `Function`/`Method`, and `open type T` is no longer reported as unused when its imported members (static members, static fields, or DU union cases) are used. ([Issue #19905](https://github.com/dotnet/fsharp/issues/19905), [PR #19960](https://github.com/dotnet/fsharp/pull/19960))
34
* Tooltip "Full name" now shows demangled companion module names (e.g. `MyType.func` instead of `MyTypeModule.func`). ([Issue #17335](https://github.com/dotnet/fsharp/issues/17335), [PR #19867](https://github.com/dotnet/fsharp/pull/19867))
45
* Fix internal error (FS0193) when calling an indexed property setter with a named argument that matches an indexer parameter. ([Issue #16034](https://github.com/dotnet/fsharp/issues/16034), [PR #19851](https://github.com/dotnet/fsharp/pull/19851))
56
* Fix missing FS1182 ("unused binding") warning for unused `let` function bindings inside class types. ([Issue #13849](https://github.com/dotnet/fsharp/issues/13849), [PR #19805](https://github.com/dotnet/fsharp/pull/19805))

src/Compiler/Checking/Expressions/CheckExpressions.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6772,7 +6772,7 @@ and ExpandIndexArgs (cenv: cenv) (synLeftExprOpt: SynExpr option) indexArgs =
67726772
| Some (a2, isFromEnd2) ->
67736773
yield mkSynSomeExpr range2 (if isFromEnd2 then rewriteReverseExpr pos a2 range2 else a2)
67746774
| None ->
6775-
yield mkSynNoneExpr range1
6775+
yield mkSynNoneExpr range2
67766776
]
67776777
)
67786778
|> List.collect id

src/Compiler/Service/SemanticClassification.fs

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -185,22 +185,36 @@ module TcResolutionsExtensions =
185185

186186
if cnrs.Length = 1 then
187187
cnrs
188-
elif cnrs.Length = 2 then
189-
match cnrs[0].Item, cnrs[1].Item with
190-
| Item.Value _, Item.CustomBuilder _ -> [| cnrs[1] |]
191-
| Item.CustomBuilder _, Item.Value _ -> [| cnrs[0] |]
192-
| _ -> cnrs
193188
else
194-
cnrs
189+
let isCE (cnr: CapturedNameResolution) =
190+
match cnr.Item with
191+
| Item.CustomBuilder _
192+
| Item.CustomOperation _ -> true
193+
| _ -> false
194+
195+
let isPlainValue (cnr: CapturedNameResolution) =
196+
match cnr.Item with
197+
| Item.Value _ -> true
198+
| _ -> false
199+
200+
let ceCnrs = cnrs |> Array.filter isCE
201+
202+
if ceCnrs.Length > 0 && cnrs |> Array.forall (fun c -> isCE c || isPlainValue c) then
203+
ceCnrs
204+
else
205+
cnrs
195206

196207
let resolutions =
197-
match range with
198-
| Some range ->
199-
sResolutions.CapturedNameResolutions.ToArray()
200-
|> Array.filter (fun cnr -> rangeContainsPos range cnr.Range.Start || rangeContainsPos range cnr.Range.End)
201-
|> Array.groupBy (fun cnr -> cnr.Range)
202-
|> Array.collect (fun (_, cnrs) -> takeCustomBuilder cnrs)
203-
| None -> sResolutions.CapturedNameResolutions.ToArray()
208+
let baseCnrs =
209+
match range with
210+
| Some range ->
211+
sResolutions.CapturedNameResolutions.ToArray()
212+
|> Array.filter (fun cnr -> rangeContainsPos range cnr.Range.Start || rangeContainsPos range cnr.Range.End)
213+
| None -> sResolutions.CapturedNameResolutions.ToArray()
214+
215+
baseCnrs
216+
|> Array.groupBy (fun cnr -> cnr.Range)
217+
|> Array.collect (fun (_, cnrs) -> takeCustomBuilder cnrs)
204218

205219
let duplicates = HashSet<range>(comparer)
206220

@@ -210,6 +224,9 @@ module TcResolutionsExtensions =
210224
if duplicates.Add m then
211225
results.Add(SemanticClassificationItem((m, typ)))
212226

227+
let isDelegateInvokeMemberName name =
228+
name = "Invoke" || name = "BeginInvoke" || name = "EndInvoke"
229+
213230
resolutions
214231
|> Array.iter (fun cnr ->
215232
match cnr.Item, cnr.ItemOccurrence, cnr.Range with
@@ -228,7 +245,13 @@ module TcResolutionsExtensions =
228245
elif vref.IsPropertyGetterMethod || vref.IsPropertySetterMethod then
229246
add m SemanticClassificationType.Property
230247
elif vref.IsMember then
231-
add m SemanticClassificationType.Method
248+
let isSynthesizedDelegateMember =
249+
isDelegateInvokeMemberName vref.DisplayName
250+
&& vref.HasDeclaringEntity
251+
&& vref.DeclaringEntity.IsFSharpDelegateTycon
252+
253+
if not isSynthesizedDelegateMember then
254+
add m SemanticClassificationType.Method
232255
elif IsOperatorDisplayName vref.DisplayName then
233256
add m SemanticClassificationType.Operator
234257
else
@@ -296,14 +319,17 @@ module TcResolutionsExtensions =
296319
let isSynthesizedDelegateMemberInDecl =
297320
minfos
298321
|> List.forall (fun minfo ->
299-
let name = minfo.LogicalName
300-
301-
(name = "Invoke" || name = "BeginInvoke" || name = "EndInvoke")
322+
isDelegateInvokeMemberName minfo.LogicalName
302323
&& minfo.ApparentEnclosingTyconRef.IsFSharpDelegateTycon
303324
&& rangeContainsRange minfo.ApparentEnclosingTyconRef.Range m)
304325

305326
if isSynthesizedDelegateMemberInDecl then
306327
()
328+
elif
329+
minfos
330+
|> List.forall (fun minfo -> minfo.LogicalName = "GetSlice" || minfo.LogicalName = "SetSlice")
331+
then
332+
()
307333
elif
308334
minfos
309335
|> List.forall (fun minfo -> minfo.IsExtensionMember || minfo.IsCSharpStyleExtensionMember)

src/Compiler/Service/ServiceAnalysis.fs

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ module UnusedOpens =
2424
/// Compute an indexed table of the set of symbols revealed by 'open', on-demand
2525
let revealedSymbols: Lazy<HashSet<FSharpSymbol>> =
2626
lazy
27+
let unionCasesRevealedByOpen (e: FSharpEntity) =
28+
if e.IsFSharpUnion && not (e.HasAttribute<RequireQualifiedAccessAttribute>()) then
29+
e.UnionCases :> seq<_>
30+
else
31+
Seq.empty
32+
2733
let symbols: FSharpSymbol[] =
2834
[|
2935
for ent in entity.NestedEntities do
@@ -33,9 +39,8 @@ module UnusedOpens =
3339
for rf in ent.FSharpFields do
3440
rf
3541

36-
if ent.IsFSharpUnion && not (ent.HasAttribute<RequireQualifiedAccessAttribute>()) then
37-
for unionCase in ent.UnionCases do
38-
unionCase
42+
for unionCase in unionCasesRevealedByOpen ent do
43+
unionCase
3944

4045
if ent.HasAttribute<ExtensionAttribute>() then
4146
for fv in ent.MembersFunctionsAndValues do
@@ -57,6 +62,9 @@ module UnusedOpens =
5762
for field in entity.FSharpFields do
5863
if field.IsStatic && field.IsLiteral then
5964
field
65+
66+
for unionCase in unionCasesRevealedByOpen entity do
67+
unionCase
6068
|]
6169

6270
HashSet<_>(symbols, symbolHash)
@@ -278,15 +286,24 @@ module UnusedOpens =
278286
let symbolUsesRangesByDeclaringEntity =
279287
Dictionary<FSharpEntity, range list>(entityHash)
280288

281-
for symbolUse in symbolUses1 do
282-
match symbolUse.Symbol with
283-
| :? FSharpMemberOrFunctionOrValue as f ->
284-
match f.DeclaringEntity with
285-
| Some entity when entity.IsNamespace || entity.IsFSharpModule ->
286-
symbolUsesRangesByDeclaringEntity.BagAdd(entity, symbolUse.Range)
287-
| _ -> ()
289+
let recordByDeclaringEntity (symbolUse: FSharpSymbolUse) =
290+
let declaringEntity, importedByOpenType =
291+
match symbolUse.Symbol with
292+
| :? FSharpMemberOrFunctionOrValue as f -> f.DeclaringEntity, not f.IsInstanceMember
293+
| :? FSharpField as f -> f.DeclaringEntity, f.IsStatic
294+
| _ -> None, false
295+
296+
match declaringEntity with
297+
| Some entity when entity.IsNamespace || entity.IsFSharpModule || importedByOpenType ->
298+
symbolUsesRangesByDeclaringEntity.BagAdd(entity, symbolUse.Range)
288299
| _ -> ()
289300

301+
for symbolUse in symbolUses1 do
302+
recordByDeclaringEntity symbolUse
303+
304+
for symbolUse in symbolUses2 do
305+
recordByDeclaringEntity symbolUse
306+
290307
let! results =
291308
filterOpenStatementsIncremental
292309
symbolUses2

0 commit comments

Comments
 (0)