From dc23f53e501c2c577ae2cca922b441fd8ae33b42 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 31 Mar 2026 14:23:58 +0000 Subject: [PATCH 1/3] Fix completion inconsistently filtering obsolete fields and events Add ILFieldInfoIsUnseen and EventInfoIsUnseen functions to filter obsolete IL fields and events from completion, matching existing behavior for methods and properties. Also update ItemIsUnseen to handle ILField and Event items. Fixes #13693 Agent-Logs-Url: https://github.com/dotnet/fsharp/sessions/1d21d452-3f55-4d56-898c-0b50980050b5 Co-authored-by: abonie <20281641+abonie@users.noreply.github.com> --- .../.FSharp.Compiler.Service/11.0.100.md | 1 + src/Compiler/Checking/AttributeChecking.fs | 21 ++++++++++++++++++ src/Compiler/Checking/AttributeChecking.fsi | 4 ++++ src/Compiler/Checking/NameResolution.fs | 8 +++++-- .../CompletionTests.fs | 22 +++++++++++++++++++ 5 files changed, 54 insertions(+), 2 deletions(-) diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md index d5c2087765e..e67fd15e9ab 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -17,6 +17,7 @@ * Fix `YieldFromFinal`/`ReturnFromFinal` being incorrectly called in non-tail positions (`for`, `use`, `use!`, `try/with` handler). ([Issue #19402](https://github.com/dotnet/fsharp/issues/19402), [PR #19403](https://github.com/dotnet/fsharp/pull/19403)) * Fixed how the source ranges of warn directives are reported (as trivia) in the parser output (by not reporting leading spaces). ([Issue #19405](https://github.com/dotnet/fsharp/issues/19405), [PR #19408]((https://github.com/dotnet/fsharp/pull/19408))) * Fix UoM value type `ToString()` returning garbage values when `--checknulls+` is enabled, caused by double address-taking in codegen. ([Issue #19435](https://github.com/dotnet/fsharp/issues/19435), [PR #19440](https://github.com/dotnet/fsharp/pull/19440)) +* Fix completion inconsistently showing some obsolete members (fields and events) while hiding others (methods and properties). All obsolete members are now consistently hidden by default. ([Issue #13693](https://github.com/dotnet/fsharp/issues/13693), [PR #19506](https://github.com/dotnet/fsharp/pull/19506)) ### Added diff --git a/src/Compiler/Checking/AttributeChecking.fs b/src/Compiler/Checking/AttributeChecking.fs index ba62a69e4be..a7352914720 100755 --- a/src/Compiler/Checking/AttributeChecking.fs +++ b/src/Compiler/Checking/AttributeChecking.fs @@ -639,6 +639,27 @@ let PropInfoIsUnseen _m allowObsolete pinfo = CheckProvidedAttributesForUnseen (pi.PApply((fun st -> (st :> IProvidedCustomAttributeProvider)), m)) m #endif +/// Indicate if an ILFieldInfo has 'Obsolete' attribute. +/// Used to suppress the item in intellisense. +let ILFieldInfoIsUnseen (finfo: ILFieldInfo) = + match finfo with + | ILFieldInfo(_, fdef) -> CheckILAttributesForUnseen fdef.CustomAttrs +#if !NO_TYPEPROVIDERS + | ProvidedField(_amap, fi, m) -> + CheckProvidedAttributesForUnseen (fi.PApply((fun st -> (st :> IProvidedCustomAttributeProvider)), m)) m +#endif + +/// Indicate if an EventInfo has 'Obsolete' or 'CompilerMessageAttribute'. +/// Used to suppress the item in intellisense. +let EventInfoIsUnseen allowObsolete (einfo: EventInfo) = + match einfo with + | ILEvent(ILEventInfo(_, ilEventDef)) -> CheckILAttributesForUnseen ilEventDef.CustomAttrs + | FSEvent(g, _, addValRef, _) -> CheckFSharpAttributesForUnseen g addValRef.Attribs allowObsolete +#if !NO_TYPEPROVIDERS + | ProvidedEvent(_amap, ei, m) -> + CheckProvidedAttributesForUnseen (ei.PApply((fun st -> (st :> IProvidedCustomAttributeProvider)), m)) m +#endif + /// Check the attributes on a union case, returning errors and warnings as data. let CheckUnionCaseAttributes g (x:UnionCaseRef) m = trackErrors { diff --git a/src/Compiler/Checking/AttributeChecking.fsi b/src/Compiler/Checking/AttributeChecking.fsi index c8198e4a985..564957e1bd7 100644 --- a/src/Compiler/Checking/AttributeChecking.fsi +++ b/src/Compiler/Checking/AttributeChecking.fsi @@ -101,6 +101,10 @@ val MethInfoIsUnseen: g: TcGlobals -> m: range -> ty: TType -> minfo: MethInfo - val PropInfoIsUnseen: _m: 'a -> allowObsolete: bool -> pinfo: PropInfo -> bool +val ILFieldInfoIsUnseen: finfo: ILFieldInfo -> bool + +val EventInfoIsUnseen: allowObsolete: bool -> einfo: EventInfo -> bool + val CheckEntityAttributes: g: TcGlobals -> tcref: TyconRef -> m: range -> OperationResult val CheckUnionCaseAttributes: g: TcGlobals -> x: UnionCaseRef -> m: range -> OperationResult diff --git a/src/Compiler/Checking/NameResolution.fs b/src/Compiler/Checking/NameResolution.fs index 55ab3c9219b..07d0ea4743b 100644 --- a/src/Compiler/Checking/NameResolution.fs +++ b/src/Compiler/Checking/NameResolution.fs @@ -4393,6 +4393,8 @@ let ItemIsUnseen ad g amap m allowObsolete item = isUnseenNameOfOperator || IsValUnseen ad g m allowObsolete x | Item.UnionCase(x, _) -> IsUnionCaseUnseen ad g amap m allowObsolete x.UnionCaseRef | Item.ExnCase x -> IsTyconUnseen ad g amap m allowObsolete x + | Item.ILField finfo -> not allowObsolete && ILFieldInfoIsUnseen finfo + | Item.Event einfo -> not allowObsolete && EventInfoIsUnseen allowObsolete einfo | _ -> false let ItemOfTyconRef ncenv m (x: TyconRef) = @@ -4467,7 +4469,8 @@ let ResolveCompletionsInType (ncenv: NameResolver) nenv (completionTargets: Reso ncenv.InfoReader.GetEventInfosOfType(None, ad, m, ty) |> List.filter (fun x -> IsStandardEventInfo ncenv.InfoReader m ad x && - x.IsStatic = statics) + x.IsStatic = statics && + (allowObsolete || not (EventInfoIsUnseen allowObsolete x))) else [] let nestedTypes = @@ -4482,7 +4485,8 @@ let ResolveCompletionsInType (ncenv: NameResolver) nenv (completionTargets: Reso |> List.filter (fun x -> not x.IsSpecialName && x.IsStatic = statics && - IsILFieldInfoAccessible g amap m ad x) + IsILFieldInfoAccessible g amap m ad x && + (allowObsolete || not (ILFieldInfoIsUnseen x))) let qinfos = ncenv.InfoReader.GetTraitInfosInType None ty diff --git a/tests/FSharp.Compiler.Service.Tests/CompletionTests.fs b/tests/FSharp.Compiler.Service.Tests/CompletionTests.fs index 43ee08b4ee3..717e8b519f6 100644 --- a/tests/FSharp.Compiler.Service.Tests/CompletionTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/CompletionTests.fs @@ -691,6 +691,28 @@ exception E try () with E{caret} """ + // https://github.com/dotnet/fsharp/issues/13693 + [] + let ``Event - Instance 01`` () = + assertItem "Ev" """ +type T() = + [] + member _.Ev = Event().Publish + +T().{caret} +""" + + // https://github.com/dotnet/fsharp/issues/13693 + [] + let ``Event - Static 01`` () = + assertItem "Ev" """ +type T() = + [] + static member Ev = Event().Publish + +T.{caret} +""" + module PatternNameSuggestions = let private suggestPatternNames = { FSharpCodeCompletionOptions.Default with SuggestPatternNames = true } From 8552ec49f03f95144dee1204811f4e0a5f825172 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 31 Mar 2026 14:46:14 +0000 Subject: [PATCH 2/3] Add C# interop tests for obsolete field/event/method/property filtering Fix issue number to #13512. Add ObsoleteMembersClass to CSharp_Analysis with obsolete and non-obsolete members. Add 6 C# interop completion tests verifying all obsolete member types are consistently hidden. Agent-Logs-Url: https://github.com/dotnet/fsharp/sessions/1d21d452-3f55-4d56-898c-0b50980050b5 Co-authored-by: abonie <20281641+abonie@users.noreply.github.com> --- .../.FSharp.Compiler.Service/11.0.100.md | 2 +- .../FSharp.Compiler.Service.Tests/Checker.fs | 5 ++ .../CompletionTests.fs | 62 ++++++++++++++++++- .../data/CSharp_Analysis/CSharpClass.cs | 21 +++++++ 4 files changed, 87 insertions(+), 3 deletions(-) diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md index e67fd15e9ab..28d4f0050dc 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -17,7 +17,7 @@ * Fix `YieldFromFinal`/`ReturnFromFinal` being incorrectly called in non-tail positions (`for`, `use`, `use!`, `try/with` handler). ([Issue #19402](https://github.com/dotnet/fsharp/issues/19402), [PR #19403](https://github.com/dotnet/fsharp/pull/19403)) * Fixed how the source ranges of warn directives are reported (as trivia) in the parser output (by not reporting leading spaces). ([Issue #19405](https://github.com/dotnet/fsharp/issues/19405), [PR #19408]((https://github.com/dotnet/fsharp/pull/19408))) * Fix UoM value type `ToString()` returning garbage values when `--checknulls+` is enabled, caused by double address-taking in codegen. ([Issue #19435](https://github.com/dotnet/fsharp/issues/19435), [PR #19440](https://github.com/dotnet/fsharp/pull/19440)) -* Fix completion inconsistently showing some obsolete members (fields and events) while hiding others (methods and properties). All obsolete members are now consistently hidden by default. ([Issue #13693](https://github.com/dotnet/fsharp/issues/13693), [PR #19506](https://github.com/dotnet/fsharp/pull/19506)) +* Fix completion inconsistently showing some obsolete members (fields and events) while hiding others (methods and properties). All obsolete members are now consistently hidden by default. ([Issue #13512](https://github.com/dotnet/fsharp/issues/13512), [PR #19506](https://github.com/dotnet/fsharp/pull/19506)) ### Added diff --git a/tests/FSharp.Compiler.Service.Tests/Checker.fs b/tests/FSharp.Compiler.Service.Tests/Checker.fs index 5d16f87783d..22dcf2ad502 100644 --- a/tests/FSharp.Compiler.Service.Tests/Checker.fs +++ b/tests/FSharp.Compiler.Service.Tests/Checker.fs @@ -162,6 +162,11 @@ module Checker = let parseResults, checkResults = getParseAndCheckResults context.Source checkResults.GetCodeCompletionSuggestions(context, parseResults, options) + let getCompletionInfoWithCompilerAndCompletionOptions (compilerOptions: string array) (completionOptions: FSharpCodeCompletionOptions) (markedSource: string) = + let context = getCompletionContext markedSource + let parseResults, checkResults = getParseAndCheckResultsWithOptions compilerOptions context.Source + checkResults.GetCodeCompletionSuggestions(context, parseResults, completionOptions) + let getCompletionInfo markedSource = getCompletionInfoWithOptions FSharpCodeCompletionOptions.Default markedSource diff --git a/tests/FSharp.Compiler.Service.Tests/CompletionTests.fs b/tests/FSharp.Compiler.Service.Tests/CompletionTests.fs index 717e8b519f6..e229a6f2b34 100644 --- a/tests/FSharp.Compiler.Service.Tests/CompletionTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/CompletionTests.fs @@ -691,7 +691,7 @@ exception E try () with E{caret} """ - // https://github.com/dotnet/fsharp/issues/13693 + // https://github.com/dotnet/fsharp/issues/13512 [] let ``Event - Instance 01`` () = assertItem "Ev" """ @@ -702,7 +702,7 @@ type T() = T().{caret} """ - // https://github.com/dotnet/fsharp/issues/13693 + // https://github.com/dotnet/fsharp/issues/13512 [] let ``Event - Static 01`` () = assertItem "Ev" """ @@ -713,6 +713,64 @@ type T() = T.{caret} """ + /// Helper to assert completion with a reference to the CSharp_Analysis assembly + let private assertCSharpInteropItem name source = + let csharpAssembly = PathRelativeToTestAssembly "CSharp_Analysis.dll" + let compilerOptions = [| $"-r:{csharpAssembly}" |] + [allowObsoleteOptions; disallowObsoleteOptions] + |> List.iter (fun completionOptions -> + let contains = completionOptions.SuggestObsoleteSymbols + let info = Checker.getCompletionInfoWithCompilerAndCompletionOptions compilerOptions completionOptions source + assertItemsWithNames contains [name] info + ) + + // https://github.com/dotnet/fsharp/issues/13512 + [] + let ``CSharp - Obsolete field is hidden`` () = + assertCSharpInteropItem "ObsoleteField" """ +open FSharp.Compiler.Service.Tests +ObsoleteMembersClass.{caret} +""" + + // https://github.com/dotnet/fsharp/issues/13512 + [] + let ``CSharp - Obsolete method is hidden`` () = + assertCSharpInteropItem "ObsoleteMethod" """ +open FSharp.Compiler.Service.Tests +ObsoleteMembersClass.{caret} +""" + + // https://github.com/dotnet/fsharp/issues/13512 + [] + let ``CSharp - Obsolete property is hidden`` () = + assertCSharpInteropItem "ObsoleteProperty" """ +open FSharp.Compiler.Service.Tests +ObsoleteMembersClass.{caret} +""" + + // https://github.com/dotnet/fsharp/issues/13512 + [] + let ``CSharp - Obsolete event is hidden`` () = + assertCSharpInteropItem "ObsoleteEvent" """ +open FSharp.Compiler.Service.Tests +ObsoleteMembersClass.{caret} +""" + + // https://github.com/dotnet/fsharp/issues/13512 + [] + let ``CSharp - Non-obsolete members are always shown`` () = + let csharpAssembly = PathRelativeToTestAssembly "CSharp_Analysis.dll" + let compilerOptions = [| $"-r:{csharpAssembly}" |] + let source = """ +open FSharp.Compiler.Service.Tests +ObsoleteMembersClass.{caret} +""" + [allowObsoleteOptions; disallowObsoleteOptions] + |> List.iter (fun completionOptions -> + let info = Checker.getCompletionInfoWithCompilerAndCompletionOptions compilerOptions completionOptions source + assertItemsWithNames true ["NonObsoleteField"; "NonObsoleteMethod"; "NonObsoleteProperty"; "NonObsoleteEvent"] info + ) + module PatternNameSuggestions = let private suggestPatternNames = { FSharpCodeCompletionOptions.Default with SuggestPatternNames = true } diff --git a/tests/service/data/CSharp_Analysis/CSharpClass.cs b/tests/service/data/CSharp_Analysis/CSharpClass.cs index a8131651b50..e8afc869dc2 100644 --- a/tests/service/data/CSharp_Analysis/CSharpClass.cs +++ b/tests/service/data/CSharp_Analysis/CSharpClass.cs @@ -155,4 +155,25 @@ public class DummyClass { } } + + /// + /// Class with obsolete members for testing completion filtering (issue #13512). + /// + public class ObsoleteMembersClass + { + [Obsolete("Field is obsolete")] public static readonly int ObsoleteField = 1; + + [Obsolete("Method is obsolete")] + public static void ObsoleteMethod() + { + } + + [Obsolete("Property is obsolete")] public static int ObsoleteProperty => 1; + [Obsolete("Event is obsolete")] public static event EventHandler ObsoleteEvent; + + public static readonly int NonObsoleteField = 2; + public static void NonObsoleteMethod() { } + public static int NonObsoleteProperty => 2; + public static event EventHandler NonObsoleteEvent; + } } From 96ad01901fe1645c5bc830c6023151e72ade5f56 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 9 Apr 2026 15:18:07 +0200 Subject: [PATCH 3/3] Bump FSBuildVersion to 101 to fix Check_Published_Package_Versions CI failure FSharp.Core 11.0.100 and FSharp.Compiler.Service 43.12.100 have already been published to NuGet, causing the version check to fail on all PRs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- eng/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index b96d89e5c09..054f4320ef3 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -19,7 +19,7 @@ 11 0 - 100 + 101 0