diff --git a/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md b/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md index 5997ca29bd4..2c2971c9c1c 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md +++ b/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md @@ -1,14 +1,11 @@ ### Fixed - * Fix Realsig+ generates nested closures with incorrect Generic ([Issue #17797](https://github.com/dotnet/fsharp/issues/17797), [PR #17877](https://github.com/dotnet/fsharp/pull/17877)) * Set `Cancellable.token` from async computation ([Issue #18235](https://github.com/dotnet/fsharp/issues/18235), [PR #18238](https://github.com/dotnet/fsharp/pull/18238)) ### Added - * Added missing type constraints in FCS. ([PR #18241](https://github.com/dotnet/fsharp/pull/18241)) ### Changed - +* Update `Obsolete` attribute checking to account for `DiagnosticId` and `UrlFormat` properties. ([PR #18224](https://github.com/dotnet/fsharp/pull/18224)) ### Breaking Changes - diff --git a/src/Compiler/Checking/AttributeChecking.fs b/src/Compiler/Checking/AttributeChecking.fs old mode 100644 new mode 100755 index 563af942829..8c317ad5f31 --- a/src/Compiler/Checking/AttributeChecking.fs +++ b/src/Compiler/Checking/AttributeChecking.fs @@ -24,8 +24,12 @@ open FSharp.Compiler.TypeProviders open FSharp.Core.CompilerServices #endif -exception ObsoleteWarning of string * range -exception ObsoleteError of string * range +exception ObsoleteDiagnostic of + isError: bool * + diagnosticId: string * + message: string * + urlFormat: string * + range: range let fail() = failwith "This custom attribute has an argument that cannot yet be converted using this API" @@ -234,7 +238,6 @@ let MethInfoHasAttribute g m attribSpec minfo = (fun _ -> Some ()) |> Option.isSome - let private CheckCompilerFeatureRequiredAttribute (g: TcGlobals) cattrs msg m = // In some cases C# will generate both ObsoleteAttribute and CompilerFeatureRequiredAttribute. // Specifically, when default constructor is generated for class with any required members in them. @@ -244,87 +247,160 @@ let private CheckCompilerFeatureRequiredAttribute (g: TcGlobals) cattrs msg m = | Some([ILAttribElem.String (Some featureName) ], _) when featureName = "RequiredMembers" -> CompleteD | _ -> - ErrorD (ObsoleteError(msg, m)) + ErrorD (ObsoleteDiagnostic(true, "", msg, "", m)) + +let private extractILObsoleteAttributeInfo namedArgs = + let extractILAttribValueFrom name namedArgs = + match namedArgs with + | ExtractILAttributeNamedArg name (AttribElemStringArg v) -> v + | _ -> "" + let diagnosticId = extractILAttribValueFrom "DiagnosticId" namedArgs + let urlFormat = extractILAttribValueFrom "UrlFormat" namedArgs + (diagnosticId, urlFormat) + +let private CheckILObsoleteAttributes (g: TcGlobals) isByrefLikeTyconRef cattrs m = + if isByrefLikeTyconRef then + CompleteD + else + let (AttribInfo(tref,_)) = g.attrib_SystemObsolete + match TryDecodeILAttribute tref cattrs with + // [] + // [] + // [] + // [] + // [] + // [] + // [] + // [] + // [] + // Constructors deciding on IsError and Message properties. + | Some ([ attribElement ], namedArgs) -> + let diagnosticId, urlFormat = extractILObsoleteAttributeInfo namedArgs + let msg = + match attribElement with + | ILAttribElem.String (Some msg) -> msg + | ILAttribElem.String None + | _ -> "" + + WarnD (ObsoleteDiagnostic(false, diagnosticId, msg, urlFormat, m)) + | Some ([ILAttribElem.String (Some msg); ILAttribElem.Bool isError ], namedArgs) -> + let diagnosticId, urlFormat = extractILObsoleteAttributeInfo namedArgs + if isError then + if g.langVersion.SupportsFeature(LanguageFeature.RequiredPropertiesSupport) then + CheckCompilerFeatureRequiredAttribute g cattrs msg m + else + ErrorD (ObsoleteDiagnostic(true, diagnosticId, msg, urlFormat, m)) + else + WarnD (ObsoleteDiagnostic(false, diagnosticId, msg, urlFormat, m)) + // Only DiagnosticId, UrlFormat + | Some (_, namedArgs) -> + let diagnosticId, urlFormat = extractILObsoleteAttributeInfo namedArgs + WarnD(ObsoleteDiagnostic(false, diagnosticId, "", urlFormat, m)) + // No arguments + | None -> CompleteD /// Check IL attributes for 'ObsoleteAttribute', returning errors and warnings as data let private CheckILAttributes (g: TcGlobals) isByrefLikeTyconRef cattrs m = - let (AttribInfo(tref,_)) = g.attrib_SystemObsolete - match TryDecodeILAttribute tref cattrs with - | Some ([ILAttribElem.String (Some msg) ], _) when not isByrefLikeTyconRef -> - WarnD(ObsoleteWarning(msg, m)) - | Some ([ILAttribElem.String (Some msg); ILAttribElem.Bool isError ], _) when not isByrefLikeTyconRef -> - if isError then - if g.langVersion.SupportsFeature(LanguageFeature.RequiredPropertiesSupport) then - CheckCompilerFeatureRequiredAttribute g cattrs msg m - else - ErrorD (ObsoleteError(msg, m)) - else - WarnD (ObsoleteWarning(msg, m)) - | Some ([ILAttribElem.String None ], _) when not isByrefLikeTyconRef -> - WarnD(ObsoleteWarning("", m)) - | Some _ when not isByrefLikeTyconRef -> - WarnD(ObsoleteWarning("", m)) - | _ -> - CompleteD + trackErrors { + do! CheckILObsoleteAttributes g isByrefLikeTyconRef cattrs m + } let langVersionPrefix = "--langversion:preview" +let private extractObsoleteAttributeInfo namedArgs = + let extractILAttribValueFrom name namedArgs = + match namedArgs with + | ExtractAttribNamedArg name (AttribStringArg v) -> v + | _ -> "" + let diagnosticId = extractILAttribValueFrom "DiagnosticId" namedArgs + let urlFormat = extractILAttribValueFrom "UrlFormat" namedArgs + (diagnosticId, urlFormat) + +let private CheckObsoleteAttributes g attribs m = + trackErrors { + match TryFindFSharpAttribute g g.attrib_SystemObsolete attribs with + // [] + // [] + // [] + // [] + // [] + // [] + // [] + // [] + // [] + // Constructors deciding on IsError and Message properties. + | Some(Attrib(unnamedArgs= [ AttribStringArg s ]; propVal= namedArgs)) -> + let diagnosticId, urlFormat = extractObsoleteAttributeInfo namedArgs + do! WarnD(ObsoleteDiagnostic(false, diagnosticId, s, urlFormat, m)) + | Some(Attrib(unnamedArgs= [ AttribStringArg s; AttribBoolArg(isError) ]; propVal= namedArgs)) -> + let diagnosticId, urlFormat = extractObsoleteAttributeInfo namedArgs + if isError then + do! ErrorD (ObsoleteDiagnostic(true, diagnosticId, s, urlFormat, m)) + else + do! WarnD (ObsoleteDiagnostic(false, diagnosticId, s, urlFormat, m)) + // Only DiagnosticId, UrlFormat + | Some(Attrib(propVal= namedArgs)) -> + let diagnosticId, urlFormat = extractObsoleteAttributeInfo namedArgs + do! WarnD(ObsoleteDiagnostic(false, diagnosticId, "", urlFormat, m)) + | None -> () + } + +let private CheckCompilerMessageAttribute g attribs m = + trackErrors { + match TryFindFSharpAttribute g g.attrib_CompilerMessageAttribute attribs with + | Some(Attrib(unnamedArgs= [ AttribStringArg s ; AttribInt32Arg n ]; propVal= namedArgs)) -> + let msg = UserCompilerMessage(s, n, m) + let isError = + match namedArgs with + | ExtractAttribNamedArg "IsError" (AttribBoolArg v) -> v + | _ -> false + // If we are using a compiler that supports nameof then error 3501 is always suppressed. + // See attribute on FSharp.Core 'nameof' + if n = 3501 then + () + elif isError && (not g.compilingFSharpCore || n <> 1204) then + do! ErrorD msg + else + do! WarnD msg + | _ -> + () + } + +let private CheckExperimentalAttribute g attribs m = + trackErrors { + match TryFindFSharpAttribute g g.attrib_ExperimentalAttribute attribs with + | Some(Attrib(unnamedArgs= [ AttribStringArg(s) ])) -> + let isExperimentalAttributeDisabled (s:string) = + if g.compilingFSharpCore then + true + else + g.langVersion.IsPreviewEnabled && (s.IndexOf(langVersionPrefix, StringComparison.OrdinalIgnoreCase) >= 0) + if not (isExperimentalAttributeDisabled s) then + do! WarnD(Experimental(s, m)) + | Some _ -> + do! WarnD(Experimental(FSComp.SR.experimentalConstruct (), m)) + | _ -> + () + } + +let private CheckUnverifiableAttribute g attribs m = + trackErrors { + match TryFindFSharpAttribute g g.attrib_UnverifiableAttribute attribs with + | Some _ -> + do! WarnD(PossibleUnverifiableCode(m)) + | _ -> () + } + /// Check F# attributes for 'ObsoleteAttribute', 'CompilerMessageAttribute' and 'ExperimentalAttribute', /// returning errors and warnings as data let CheckFSharpAttributes (g:TcGlobals) attribs m = if isNil attribs then CompleteD else trackErrors { - match TryFindFSharpAttribute g g.attrib_SystemObsolete attribs with - | Some(Attrib(_, _, [ AttribStringArg s ], _, _, _, _)) -> - do! WarnD(ObsoleteWarning(s, m)) - | Some(Attrib(_, _, [ AttribStringArg s; AttribBoolArg(isError) ], _, _, _, _)) -> - if isError then - do! ErrorD (ObsoleteError(s, m)) - else - do! WarnD (ObsoleteWarning(s, m)) - | Some _ -> - do! WarnD(ObsoleteWarning("", m)) - | None -> - () - - match TryFindFSharpAttribute g g.attrib_CompilerMessageAttribute attribs with - | Some(Attrib(_, _, [ AttribStringArg s ; AttribInt32Arg n ], namedArgs, _, _, _)) -> - let msg = UserCompilerMessage(s, n, m) - let isError = - match namedArgs with - | ExtractAttribNamedArg "IsError" (AttribBoolArg v) -> v - | _ -> false - // If we are using a compiler that supports nameof then error 3501 is always suppressed. - // See attribute on FSharp.Core 'nameof' - if n = 3501 then - () - elif isError && (not g.compilingFSharpCore || n <> 1204) then - do! ErrorD msg - else - do! WarnD msg - | _ -> - () - - match TryFindFSharpAttribute g g.attrib_ExperimentalAttribute attribs with - | Some(Attrib(_, _, [ AttribStringArg(s) ], _, _, _, _)) -> - let isExperimentalAttributeDisabled (s:string) = - if g.compilingFSharpCore then - true - else - g.langVersion.IsPreviewEnabled && (s.IndexOf(langVersionPrefix, StringComparison.OrdinalIgnoreCase) >= 0) - if not (isExperimentalAttributeDisabled s) then - do! WarnD(Experimental(s, m)) - | Some _ -> - do! WarnD(Experimental(FSComp.SR.experimentalConstruct (), m)) - | _ -> - () - - match TryFindFSharpAttribute g g.attrib_UnverifiableAttribute attribs with - | Some _ -> - do! WarnD(PossibleUnverifiableCode(m)) - | _ -> - () + do! CheckObsoleteAttributes g attribs m + do! CheckCompilerMessageAttribute g attribs m + do! CheckExperimentalAttribute g attribs m + do! CheckUnverifiableAttribute g attribs m } #if !NO_TYPEPROVIDERS @@ -332,16 +408,16 @@ let CheckFSharpAttributes (g:TcGlobals) attribs m = let private CheckProvidedAttributes (g: TcGlobals) m (provAttribs: Tainted) = let (AttribInfo(tref, _)) = g.attrib_SystemObsolete match provAttribs.PUntaint((fun a -> a.GetAttributeConstructorArgs(provAttribs.TypeProvider.PUntaintNoFailure(id), tref.FullName)), m) with - | Some ([ Some (:? string as msg) ], _) -> WarnD(ObsoleteWarning(msg, m)) + | Some ([ Some (:? string as msg) ], _) -> WarnD(ObsoleteDiagnostic(false, "", msg, "", m)) | Some ([ Some (:? string as msg); Some (:?bool as isError) ], _) -> if isError then - ErrorD (ObsoleteError(msg, m)) + ErrorD (ObsoleteDiagnostic(true, "", msg, "", m)) else - WarnD (ObsoleteWarning(msg, m)) + WarnD (ObsoleteDiagnostic(false, "", msg, "", m)) | Some ([ None ], _) -> - WarnD(ObsoleteWarning("", m)) + WarnD(ObsoleteDiagnostic(false, "", "", "", m)) | Some _ -> - WarnD(ObsoleteWarning("", m)) + WarnD(ObsoleteDiagnostic(false, "", "", "", m)) | None -> CompleteD #endif diff --git a/src/Compiler/Checking/AttributeChecking.fsi b/src/Compiler/Checking/AttributeChecking.fsi index 663198f9247..5885c1b39e9 100644 --- a/src/Compiler/Checking/AttributeChecking.fsi +++ b/src/Compiler/Checking/AttributeChecking.fsi @@ -13,9 +13,12 @@ open FSharp.Compiler.TcGlobals open FSharp.Compiler.Text open FSharp.Compiler.TypedTree -exception ObsoleteWarning of string * range - -exception ObsoleteError of string * range +exception ObsoleteDiagnostic of + isError: bool * + diagnosticId: string * + message: string * + urlFormat: string * + range: range type AttribInfo = | FSAttribInfo of TcGlobals * Attrib diff --git a/src/Compiler/Checking/PostInferenceChecks.fs b/src/Compiler/Checking/PostInferenceChecks.fs index 645f43fe3cb..e8d6f5a5af0 100644 --- a/src/Compiler/Checking/PostInferenceChecks.fs +++ b/src/Compiler/Checking/PostInferenceChecks.fs @@ -551,7 +551,7 @@ let WarnOnWrongTypeForAccess (cenv: cenv) env objName valAcc m ty = if isLessAccessible tyconAcc valAcc then let errorText = FSComp.SR.chkTypeLessAccessibleThanType(tcref.DisplayName, (objName())) |> snd let warningText = errorText + Environment.NewLine + FSComp.SR.tcTypeAbbreviationsCheckedAtCompileTime() - warning(AttributeChecking.ObsoleteWarning(warningText, m)) + warning(AttributeChecking.ObsoleteDiagnostic(false, "", warningText, "", m)) CheckTypeDeep cenv (visitType, None, None, None, None) cenv.g env NoInfo ty diff --git a/src/Compiler/Driver/CompilerDiagnostics.fs b/src/Compiler/Driver/CompilerDiagnostics.fs index 9dcf0b72ea3..019226f46e4 100644 --- a/src/Compiler/Driver/CompilerDiagnostics.fs +++ b/src/Compiler/Driver/CompilerDiagnostics.fs @@ -148,8 +148,7 @@ type Exception with | IntfImplInExtrinsicAugmentation m | ValueRestriction(_, _, _, _, m) | LetRecUnsound(_, _, m) - | ObsoleteError(_, m) - | ObsoleteWarning(_, m) + | ObsoleteDiagnostic(_, _, _, _, m) | Experimental(_, m) | PossibleUnverifiableCode m | UserCompilerMessage(_, _, m) @@ -266,7 +265,7 @@ type Exception with | UnresolvedOverloading _ -> 41 | LibraryUseOnly _ -> 42 | ErrorFromAddingConstraint _ -> 43 - | ObsoleteWarning _ -> 44 + | ObsoleteDiagnostic(isError = false) -> 44 | ReservedKeyword _ -> 46 | SelfRefObjCtor _ -> 47 | VirtualAugmentationOnNullValuedType _ -> 48 @@ -327,7 +326,7 @@ type Exception with | UnresolvedConversionOperator _ -> 93 // avoid 94-100 for safety - | ObsoleteError _ -> 101 + | ObsoleteDiagnostic(isError = true) -> 101 #if !NO_TYPEPROVIDERS | TypeProviders.ProvidedTypeResolutionNoRange _ | TypeProviders.ProvidedTypeResolution _ -> 103 @@ -1790,9 +1789,7 @@ type Exception with | ValNotLocal _ -> os.AppendString(ValNotLocalE().Format) - | ObsoleteError(s, _) - - | ObsoleteWarning(s, _) -> + | ObsoleteDiagnostic(message = s) -> os.AppendString(Obsolete1E().Format) if s <> "" then diff --git a/src/Compiler/Symbols/FSharpDiagnostic.fs b/src/Compiler/Symbols/FSharpDiagnostic.fs index 31ec0536c3e..581b51ab8c7 100644 --- a/src/Compiler/Symbols/FSharpDiagnostic.fs +++ b/src/Compiler/Symbols/FSharpDiagnostic.fs @@ -9,6 +9,7 @@ namespace FSharp.Compiler.Diagnostics open System +open FSharp.Compiler.AttributeChecking open FSharp.Compiler.CheckExpressions open FSharp.Compiler.ConstraintSolver open FSharp.Compiler.SignatureConformance @@ -18,7 +19,6 @@ open FSharp.Compiler.TypedTree open FSharp.Compiler.TypedTreeBasics open FSharp.Compiler.TypedTreeOps open Internal.Utilities.Library -open Internal.Utilities.Library.Extras open FSharp.Core.Printf open FSharp.Compiler @@ -67,6 +67,17 @@ module ExtendedData = [] type IFSharpDiagnosticExtendedData = interface end + /// Additional data for diagnostics about obsolete attributes. + [] + type ObsoleteDiagnosticExtendedData + internal (diagnosticId: string, urlFormat: string) = + interface IFSharpDiagnosticExtendedData + /// Represents the DiagnosticId of the diagnostic + member this.DiagnosticId: string = diagnosticId + + /// Represents the URL format of the diagnostic + member this.UrlFormat: string = urlFormat + [] type TypeMismatchDiagnosticExtendedData internal (symbolEnv: SymbolEnv, dispEnv: DisplayEnv, expectedType: TType, actualType: TType, context: DiagnosticContextInfo) = @@ -201,6 +212,8 @@ type FSharpDiagnostic(m: range, severity: FSharpDiagnosticSeverity, message: str | DefinitionsInSigAndImplNotCompatibleAbbreviationsDiffer(implTycon = implTycon; sigTycon = sigTycon) -> Some(DefinitionsInSigAndImplNotCompatibleAbbreviationsDifferExtendedData(sigTycon, implTycon)) + | ObsoleteDiagnostic(diagnosticId= diagnosticId; urlFormat= urlFormat) -> + Some(ObsoleteDiagnosticExtendedData(diagnosticId, urlFormat)) | _ -> None let msg = diff --git a/src/Compiler/Symbols/FSharpDiagnostic.fsi b/src/Compiler/Symbols/FSharpDiagnostic.fsi index 6c941bdd84d..ecee4c0540b 100644 --- a/src/Compiler/Symbols/FSharpDiagnostic.fsi +++ b/src/Compiler/Symbols/FSharpDiagnostic.fsi @@ -50,6 +50,17 @@ module public ExtendedData = interface end + /// Additional data for diagnostics about obsolete attributes. + [] + type public ObsoleteDiagnosticExtendedData = + interface IFSharpDiagnosticExtendedData + + /// Represents the DiagnosticId of the diagnostic + member DiagnosticId: string + + /// Represents the URL format of the diagnostic + member UrlFormat: string + /// Additional data for type-mismatch-like (usually with ErrorNumber = 1) diagnostics [] type public TypeMismatchDiagnosticExtendedData = diff --git a/src/Compiler/TypedTree/TypedTreeOps.fs b/src/Compiler/TypedTree/TypedTreeOps.fs index e2bc362c784..d2964bb8dfc 100644 --- a/src/Compiler/TypedTree/TypedTreeOps.fs +++ b/src/Compiler/TypedTree/TypedTreeOps.fs @@ -3524,6 +3524,10 @@ let IsMatchingFSharpAttributeOpt g attrOpt (Attrib(tcref2, _, _, _, _, _, _)) = [] let (|ExtractAttribNamedArg|_|) nm args = args |> List.tryPick (function AttribNamedArg(nm2, _, _, v) when nm = nm2 -> Some v | _ -> None) |> ValueOptionInternal.ofOption + +[] +let (|ExtractILAttributeNamedArg|_|) nm (args: ILAttributeNamedArg list) = + args |> List.tryPick (function nm2, _, _, v when nm = nm2 -> Some v | _ -> None) |> ValueOptionInternal.ofOption [] let (|StringExpr|_|) = function Expr.Const (Const.String n, _, _) -> ValueSome n | _ -> ValueNone @@ -3540,6 +3544,8 @@ let (|AttribBoolArg|_|) = function AttribExpr(_, Expr.Const (Const.Bool n, _, _) [] let (|AttribStringArg|_|) = function AttribExpr(_, Expr.Const (Const.String n, _, _)) -> ValueSome n | _ -> ValueNone +let (|AttribElemStringArg|_|) = function ILAttribElem.String(n) -> n | _ -> None + let TryFindFSharpBoolAttributeWithDefault dflt g nm attrs = match TryFindFSharpAttribute g nm attrs with | Some(Attrib(_, _, [ ], _, _, _, _)) -> Some dflt diff --git a/src/Compiler/TypedTree/TypedTreeOps.fsi b/src/Compiler/TypedTree/TypedTreeOps.fsi index 10f66bf63bf..3bca5cdb21e 100755 --- a/src/Compiler/TypedTree/TypedTreeOps.fsi +++ b/src/Compiler/TypedTree/TypedTreeOps.fsi @@ -2601,6 +2601,9 @@ val (|ConstToILFieldInit|_|): Const -> ILFieldInit voption [] val (|ExtractAttribNamedArg|_|): string -> AttribNamedArg list -> AttribExpr voption +[] +val (|ExtractILAttributeNamedArg|_|): string -> ILAttributeNamedArg list -> ILAttribElem voption + [] val (|AttribInt32Arg|_|): (AttribExpr -> int32 voption) @@ -2613,6 +2616,8 @@ val (|AttribBoolArg|_|): (AttribExpr -> bool voption) [] val (|AttribStringArg|_|): (AttribExpr -> string voption) +val (|AttribElemStringArg|_|): (ILAttribElem -> string option) + [] val (|Int32Expr|_|): Expr -> int32 voption diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/ExtendedDiagnosticDataTests.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/ExtendedDiagnosticDataTests.fs index 65a1cceb43d..23e4a9b9440 100644 --- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/ExtendedDiagnosticDataTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/ExtendedDiagnosticDataTests.fs @@ -241,3 +241,304 @@ type Foo = {| bar: int; x: int |} (fun (fieldsData: DefinitionsInSigAndImplNotCompatibleAbbreviationsDifferExtendedData) -> assertRange (4,5) (4,8) fieldsData.SignatureRange assertRange (4,6) (4,9) fieldsData.ImplementationRange) + + +[] +let ``Warning - ObsoleteDiagnosticExtendedData 01`` () = + FSharp """ +open System +[] +type MyClass() = class end + +let x = MyClass() +""" + |> typecheckResults + |> checkDiagnostic + (44, "This construct is deprecated. Message") + (fun (obsoleteDiagnostic: ObsoleteDiagnosticExtendedData) -> + Assert.Equal("FS222", obsoleteDiagnostic.DiagnosticId) + Assert.Equal("https://example.com", obsoleteDiagnostic.UrlFormat)) + +[] +let ``Warning - ObsoleteDiagnosticExtendedData 02`` () = + FSharp """ +open System +[] +type MyClass() = class end + +let x = MyClass() +""" + |> typecheckResults + |> checkDiagnostic + (44, "This construct is deprecated. Message") + (fun (obsoleteDiagnostic: ObsoleteDiagnosticExtendedData) -> + Assert.Equal("FS222", obsoleteDiagnostic.DiagnosticId) + Assert.Equal("", obsoleteDiagnostic.UrlFormat)) + +[] +let ``Warning - ObsoleteDiagnosticExtendedData 03`` () = + FSharp """ +open System +[] +type MyClass() = class end + +let x = MyClass() +""" + |> typecheckResults + |> checkDiagnostic + (44, "This construct is deprecated. Message") + (fun (obsoleteDiagnostic: ObsoleteDiagnosticExtendedData) -> + Assert.Equal("", obsoleteDiagnostic.DiagnosticId) + Assert.Equal("", obsoleteDiagnostic.UrlFormat)) + +[] +let ``Warning - ObsoleteDiagnosticExtendedData 04`` () = + FSharp """ +open System +[] +type MyClass() = class end + +let x = MyClass() +""" + |> typecheckResults + |> checkDiagnostic + (44, "This construct is deprecated") + (fun (obsoleteDiagnostic: ObsoleteDiagnosticExtendedData) -> + Assert.Equal("FS222", obsoleteDiagnostic.DiagnosticId) + Assert.Equal("https://example.com", obsoleteDiagnostic.UrlFormat)) + + +[] +let ``Warning - ObsoleteDiagnosticExtendedData 05`` () = + let CSLib = + CSharp """ +using System; +[Obsolete("Use something else", false, DiagnosticId = "FS222")] +public static class Class1 +{ + public static string Test() + { + return "Hello"; + } +} + """ + |> withName "CSLib" + + let app = + FSharp """ +open MyLib + +let text = Class1.Test(); + """ |> withReferences [CSLib] + + app + |> typecheckResults + |> checkDiagnostic + (44, "This construct is deprecated. Use something else") + (fun (obsoleteDiagnostic: ObsoleteDiagnosticExtendedData) -> + Assert.Equal("FS222", obsoleteDiagnostic.DiagnosticId) + Assert.Equal("", obsoleteDiagnostic.UrlFormat)) + +[] +let ``Warning - ObsoleteDiagnosticExtendedData 06`` () = + let CSLib = + CSharp """ +using System; +[Obsolete("Use something else", false, DiagnosticId = "FS222", UrlFormat = "https://example.com")] +public static class Class1 +{ + public static string Test() + { + return "Hello"; + } +} + """ + |> withName "CSLib" + + let app = + FSharp """ +open MyLib + +let text = Class1.Test(); + """ |> withReferences [CSLib] + + app + |> typecheckResults + |> checkDiagnostic + (44, "This construct is deprecated. Use something else") + (fun (obsoleteDiagnostic: ObsoleteDiagnosticExtendedData) -> + Assert.Equal("FS222", obsoleteDiagnostic.DiagnosticId) + Assert.Equal("https://example.com", obsoleteDiagnostic.UrlFormat)) + +[] +let ``Warning - ObsoleteDiagnosticExtendedData 07`` () = + let CSLib = + CSharp """ +using System; +[Obsolete("Use something else", false)] +public static class Class1 +{ + public static string Test() + { + return "Hello"; + } +} + """ + |> withName "CSLib" + + let app = + FSharp """ +open MyLib + +let text = Class1.Test(); + """ |> withReferences [CSLib] + + app + |> typecheckResults + |> checkDiagnostic + (44, "This construct is deprecated. Use something else") + (fun (obsoleteDiagnostic: ObsoleteDiagnosticExtendedData) -> + Assert.Equal("", obsoleteDiagnostic.DiagnosticId) + Assert.Equal("", obsoleteDiagnostic.UrlFormat)) + +[] +let ``Warning - ObsoleteDiagnosticExtendedData 08`` () = + let CSLib = + CSharp """ +using System; +[Obsolete(DiagnosticId = "FS222", UrlFormat = "https://example.com")] +public static class Class1 +{ + public static string Test() + { + return "Hello"; + } +} + """ + |> withName "CSLib" + + let app = + FSharp """ +open MyLib + +let text = Class1.Test(); + """ |> withReferences [CSLib] + + app + |> typecheckResults + |> checkDiagnostic + (44, "This construct is deprecated") + (fun (obsoleteDiagnostic: ObsoleteDiagnosticExtendedData) -> + Assert.Equal("FS222", obsoleteDiagnostic.DiagnosticId) + Assert.Equal("https://example.com", obsoleteDiagnostic.UrlFormat)) + +[] +let ``Warning - ObsoleteDiagnosticExtendedData 09`` () = + FSharp """ +open System +[] +type MyClass() = class end + +let x = MyClass() +""" + |> typecheckResults + |> checkDiagnostic + (44, "This construct is deprecated") + (fun (obsoleteDiagnostic: ObsoleteDiagnosticExtendedData) -> + Assert.Equal("", obsoleteDiagnostic.DiagnosticId) + Assert.Equal("", obsoleteDiagnostic.UrlFormat)) + +[] +let ``Warning - ObsoleteDiagnosticExtendedData 10`` () = + let CSLib = + CSharp """ +using System; +[Obsolete] +public static class Class1 +{ + public static string Test() + { + return "Hello"; + } +} + """ + |> withName "CSLib" + + let app = + FSharp """ +open MyLib + +let text = Class1.Test(); + """ |> withReferences [CSLib] + + app + |> typecheckResults + |> checkDiagnostic + (44, "This construct is deprecated") + (fun (obsoleteDiagnostic: ObsoleteDiagnosticExtendedData) -> + Assert.Equal("", obsoleteDiagnostic.DiagnosticId) + Assert.Equal("", obsoleteDiagnostic.UrlFormat)) + +[] +let ``Error - ObsoleteDiagnosticExtendedData 01`` () = + FSharp """ +open System +[] +type MyClass() = class end + +let x = MyClass() +""" + |> typecheckResults + |> checkDiagnostic + (101, "This construct is deprecated. Message") + (fun (obsoleteDiagnostic: ObsoleteDiagnosticExtendedData) -> + Assert.Equal("FS222", obsoleteDiagnostic.DiagnosticId) + Assert.Equal("https://example.com", obsoleteDiagnostic.UrlFormat)) + +[] +let ``Error - ObsoleteDiagnosticExtendedData 02`` () = + FSharp """ +open System +[] +type MyClass() = class end + +let x = MyClass() +""" + |> typecheckResults + |> checkDiagnostic + (101, "This construct is deprecated. Message") + (fun (obsoleteDiagnostic: ObsoleteDiagnosticExtendedData) -> + Assert.Equal("FS222", obsoleteDiagnostic.DiagnosticId) + Assert.Equal("", obsoleteDiagnostic.UrlFormat)) + +[] +let ``Error - ObsoleteDiagnosticExtendedData 03`` () = + FSharp """ +open System +[] +type MyClass() = class end + +let x = MyClass() +""" + |> typecheckResults + |> checkDiagnostic + (101, "This construct is deprecated. Message") + (fun (obsoleteDiagnostic: ObsoleteDiagnosticExtendedData) -> + Assert.Equal("", obsoleteDiagnostic.DiagnosticId) + Assert.Equal("", obsoleteDiagnostic.UrlFormat)) + +[] +let ``Error - ObsoleteDiagnosticExtendedData 04`` () = + FSharp """ +open System +[] +type MyClass() = class end + +let x = MyClass() +""" + |> typecheckResults + |> checkDiagnostic + (101, "This construct is deprecated") + (fun (obsoleteDiagnostic: ObsoleteDiagnosticExtendedData) -> + Assert.Equal("FS222", obsoleteDiagnostic.DiagnosticId) + Assert.Equal("https://example.com", obsoleteDiagnostic.UrlFormat)) \ No newline at end of file diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl index 13180c3b649..e85b3022c96 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl @@ -2856,6 +2856,11 @@ FSharp.Compiler.Diagnostics.ExtendedData: FSharp.Compiler.Diagnostics.ExtendedDa FSharp.Compiler.Diagnostics.ExtendedData: FSharp.Compiler.Diagnostics.ExtendedData+IFSharpDiagnosticExtendedData FSharp.Compiler.Diagnostics.ExtendedData: FSharp.Compiler.Diagnostics.ExtendedData+TypeMismatchDiagnosticExtendedData FSharp.Compiler.Diagnostics.ExtendedData: FSharp.Compiler.Diagnostics.ExtendedData+ValueNotContainedDiagnosticExtendedData +FSharp.Compiler.Diagnostics.ExtendedData+ObsoleteDiagnosticExtendedData: System.String DiagnosticId +FSharp.Compiler.Diagnostics.ExtendedData+ObsoleteDiagnosticExtendedData: System.String UrlFormat +FSharp.Compiler.Diagnostics.ExtendedData+ObsoleteDiagnosticExtendedData: System.String get_DiagnosticId() +FSharp.Compiler.Diagnostics.ExtendedData+ObsoleteDiagnosticExtendedData: System.String get_UrlFormat() +FSharp.Compiler.Diagnostics.ExtendedData: FSharp.Compiler.Diagnostics.ExtendedData+ObsoleteDiagnosticExtendedData FSharp.Compiler.Diagnostics.FSharpDiagnostic: FSharp.Compiler.Diagnostics.FSharpDiagnostic Create(FSharp.Compiler.Diagnostics.FSharpDiagnosticSeverity, System.String, Int32, FSharp.Compiler.Text.Range, Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.Diagnostics.FSharpDiagnostic: FSharp.Compiler.Diagnostics.FSharpDiagnosticSeverity Severity FSharp.Compiler.Diagnostics.FSharpDiagnostic: FSharp.Compiler.Diagnostics.FSharpDiagnosticSeverity get_Severity() diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl index 13180c3b649..e85b3022c96 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl @@ -2856,6 +2856,11 @@ FSharp.Compiler.Diagnostics.ExtendedData: FSharp.Compiler.Diagnostics.ExtendedDa FSharp.Compiler.Diagnostics.ExtendedData: FSharp.Compiler.Diagnostics.ExtendedData+IFSharpDiagnosticExtendedData FSharp.Compiler.Diagnostics.ExtendedData: FSharp.Compiler.Diagnostics.ExtendedData+TypeMismatchDiagnosticExtendedData FSharp.Compiler.Diagnostics.ExtendedData: FSharp.Compiler.Diagnostics.ExtendedData+ValueNotContainedDiagnosticExtendedData +FSharp.Compiler.Diagnostics.ExtendedData+ObsoleteDiagnosticExtendedData: System.String DiagnosticId +FSharp.Compiler.Diagnostics.ExtendedData+ObsoleteDiagnosticExtendedData: System.String UrlFormat +FSharp.Compiler.Diagnostics.ExtendedData+ObsoleteDiagnosticExtendedData: System.String get_DiagnosticId() +FSharp.Compiler.Diagnostics.ExtendedData+ObsoleteDiagnosticExtendedData: System.String get_UrlFormat() +FSharp.Compiler.Diagnostics.ExtendedData: FSharp.Compiler.Diagnostics.ExtendedData+ObsoleteDiagnosticExtendedData FSharp.Compiler.Diagnostics.FSharpDiagnostic: FSharp.Compiler.Diagnostics.FSharpDiagnostic Create(FSharp.Compiler.Diagnostics.FSharpDiagnosticSeverity, System.String, Int32, FSharp.Compiler.Text.Range, Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.Diagnostics.FSharpDiagnostic: FSharp.Compiler.Diagnostics.FSharpDiagnosticSeverity Severity FSharp.Compiler.Diagnostics.FSharpDiagnostic: FSharp.Compiler.Diagnostics.FSharpDiagnosticSeverity get_Severity()