@@ -24,13 +24,6 @@ open FSharp.Compiler.TypeProviders
2424open FSharp.Core .CompilerServices
2525#endif
2626
27- exception ObsoleteDiagnostic of
28- isError: bool *
29- diagnosticId: string *
30- message: string *
31- urlFormat: string *
32- range: range
33-
3427let fail () = failwith " This custom attribute has an argument that cannot yet be converted using this API"
3528
3629let rec private evalILAttribElem elem =
@@ -247,44 +240,68 @@ let private CheckCompilerFeatureRequiredAttribute (g: TcGlobals) cattrs msg m =
247240 | Some([ ILAttribElem.String ( Some featureName) ], _) when featureName = " RequiredMembers" ->
248241 CompleteD
249242 | _ ->
250- ErrorD ( ObsoleteDiagnostic( true , " " , msg, " " , m))
243+ ErrorD ( ObsoleteDiagnostic( true , None, msg, None, m))
244+
245+ let private extractILAttribValueFrom name namedArgs =
246+ match namedArgs with
247+ | ExtractILAttributeNamedArg name ( AttribElemStringArg v) -> Some v
248+ | _ -> None
251249
252- let private extractILObsoleteAttributeInfo namedArgs =
253- let extractILAttribValueFrom name namedArgs =
254- match namedArgs with
255- | ExtractILAttributeNamedArg name ( AttribElemStringArg v) -> v
256- | _ -> " "
250+ let private extractILAttributeInfo namedArgs =
257251 let diagnosticId = extractILAttribValueFrom " DiagnosticId" namedArgs
258252 let urlFormat = extractILAttribValueFrom " UrlFormat" namedArgs
259253 ( diagnosticId, urlFormat)
260254
255+ let private CheckILExperimentalAttributes ( g : TcGlobals ) cattrs m =
256+ let ( AttribInfo ( tref , _ )) = g.attrib_ IlExperimentalAttribute
257+ match TryDecodeILAttribute tref cattrs with
258+ // [Experimental("DiagnosticId")]
259+ // [Experimental(diagnosticId: "DiagnosticId")]
260+ // [Experimental("DiagnosticId", UrlFormat = "UrlFormat")]
261+ // [Experimental(diagnosticId = "DiagnosticId", UrlFormat = "UrlFormat")]
262+ // Constructors deciding on DiagnosticId and UrlFormat properties.
263+ | Some ([ attribElement ], namedArgs) ->
264+ let diagnosticId =
265+ match attribElement with
266+ | ILAttribElem.String ( Some msg) -> Some msg
267+ | ILAttribElem.String None
268+ | _ -> None
269+
270+ let message = extractILAttribValueFrom " Message" namedArgs
271+ let urlFormat = extractILAttribValueFrom " UrlFormat" namedArgs
272+
273+ WarnD( Experimental( message, diagnosticId, urlFormat, m))
274+ // Empty constructor or only UrlFormat property are not allowed.
275+ | Some _
276+ | None -> CompleteD
277+
261278let private CheckILObsoleteAttributes ( g : TcGlobals ) isByrefLikeTyconRef cattrs m =
262279 if isByrefLikeTyconRef then
263280 CompleteD
264281 else
265282 let ( AttribInfo ( tref , _ )) = g.attrib_ SystemObsolete
266283 match TryDecodeILAttribute tref cattrs with
267- // [< Obsolete> ]
268- // [< Obsolete("Message")> ]
269- // [< Obsolete("Message", true)> ]
270- // [< Obsolete("Message", DiagnosticId = "DiagnosticId")> ]
271- // [< Obsolete("Message", DiagnosticId = "DiagnosticId", UrlFormat = "UrlFormat")> ]
272- // [< Obsolete(DiagnosticId = "DiagnosticId")> ]
273- // [< Obsolete(DiagnosticId = "DiagnosticId", UrlFormat = "UrlFormat")> ]
274- // [< Obsolete("Message", true, DiagnosticId = "DiagnosticId")> ]
275- // [< Obsolete("Message", true, DiagnosticId = "DiagnosticId", UrlFormat = "UrlFormat")> ]
284+ // [Obsolete]
285+ // [Obsolete("Message")]
286+ // [Obsolete("Message", true)]
287+ // [Obsolete("Message", DiagnosticId = "DiagnosticId")]
288+ // [Obsolete("Message", DiagnosticId = "DiagnosticId", UrlFormat = "UrlFormat")]
289+ // [Obsolete(DiagnosticId = "DiagnosticId")]
290+ // [Obsolete(DiagnosticId = "DiagnosticId", UrlFormat = "UrlFormat")]
291+ // [Obsolete("Message", true, DiagnosticId = "DiagnosticId")]
292+ // [Obsolete("Message", true, DiagnosticId = "DiagnosticId", UrlFormat = "UrlFormat")]
276293 // Constructors deciding on IsError and Message properties.
277294 | Some ([ attribElement ], namedArgs) ->
278- let diagnosticId , urlFormat = extractILObsoleteAttributeInfo namedArgs
295+ let diagnosticId , urlFormat = extractILAttributeInfo namedArgs
279296 let msg =
280297 match attribElement with
281- | ILAttribElem.String ( Some msg) -> msg
298+ | ILAttribElem.String ( Some msg) -> Some msg
282299 | ILAttribElem.String None
283- | _ -> " "
300+ | _ -> None
284301
285302 WarnD ( ObsoleteDiagnostic( false , diagnosticId, msg, urlFormat, m))
286- | Some ([ ILAttribElem.String ( Some msg) ; ILAttribElem.Bool isError ], namedArgs) ->
287- let diagnosticId , urlFormat = extractILObsoleteAttributeInfo namedArgs
303+ | Some ([ ILAttribElem.String msg; ILAttribElem.Bool isError ], namedArgs) ->
304+ let diagnosticId , urlFormat = extractILAttributeInfo namedArgs
288305 if isError then
289306 if g.langVersion.SupportsFeature( LanguageFeature.RequiredPropertiesSupport) then
290307 CheckCompilerFeatureRequiredAttribute g cattrs msg m
@@ -294,24 +311,23 @@ let private CheckILObsoleteAttributes (g: TcGlobals) isByrefLikeTyconRef cattrs
294311 WarnD ( ObsoleteDiagnostic( false , diagnosticId, msg, urlFormat, m))
295312 // Only DiagnosticId, UrlFormat
296313 | Some (_, namedArgs) ->
297- let diagnosticId , urlFormat = extractILObsoleteAttributeInfo namedArgs
298- WarnD( ObsoleteDiagnostic( false , diagnosticId, " " , urlFormat, m))
314+ let diagnosticId , urlFormat = extractILAttributeInfo namedArgs
315+ WarnD( ObsoleteDiagnostic( false , diagnosticId, None , urlFormat, m))
299316 // No arguments
300317 | None -> CompleteD
301318
302- /// Check IL attributes for 'ObsoleteAttribute', returning errors and warnings as data
319+ /// Check IL attributes for Experimental, warnings as data
303320let private CheckILAttributes ( g : TcGlobals ) isByrefLikeTyconRef cattrs m =
304321 trackErrors {
305322 do ! CheckILObsoleteAttributes g isByrefLikeTyconRef cattrs m
323+ do ! CheckILExperimentalAttributes g cattrs m
306324 }
307325
308- let langVersionPrefix = " --langversion:preview"
309-
310326let private extractObsoleteAttributeInfo namedArgs =
311327 let extractILAttribValueFrom name namedArgs =
312328 match namedArgs with
313- | ExtractAttribNamedArg name ( AttribStringArg v) -> v
314- | _ -> " "
329+ | ExtractAttribNamedArg name ( AttribStringArg v) -> Some v
330+ | _ -> None
315331 let diagnosticId = extractILAttribValueFrom " DiagnosticId" namedArgs
316332 let urlFormat = extractILAttribValueFrom " UrlFormat" namedArgs
317333 ( diagnosticId, urlFormat)
@@ -331,17 +347,17 @@ let private CheckObsoleteAttributes g attribs m =
331347 // Constructors deciding on IsError and Message properties.
332348 | Some( Attrib( unnamedArgs= [ AttribStringArg s ]; propVal= namedArgs)) ->
333349 let diagnosticId , urlFormat = extractObsoleteAttributeInfo namedArgs
334- do ! WarnD( ObsoleteDiagnostic( false , diagnosticId, s, urlFormat, m))
350+ do ! WarnD( ObsoleteDiagnostic( false , diagnosticId, Some s, urlFormat, m))
335351 | Some( Attrib( unnamedArgs= [ AttribStringArg s; AttribBoolArg( isError) ]; propVal= namedArgs)) ->
336352 let diagnosticId , urlFormat = extractObsoleteAttributeInfo namedArgs
337353 if isError then
338- do ! ErrorD ( ObsoleteDiagnostic( true , diagnosticId, s, urlFormat, m))
354+ do ! ErrorD ( ObsoleteDiagnostic( true , diagnosticId, Some s, urlFormat, m))
339355 else
340- do ! WarnD ( ObsoleteDiagnostic( false , diagnosticId, s, urlFormat, m))
356+ do ! WarnD ( ObsoleteDiagnostic( false , diagnosticId, Some s, urlFormat, m))
341357 // Only DiagnosticId, UrlFormat
342358 | Some( Attrib( propVal= namedArgs)) ->
343359 let diagnosticId , urlFormat = extractObsoleteAttributeInfo namedArgs
344- do ! WarnD( ObsoleteDiagnostic( false , diagnosticId, " " , urlFormat, m))
360+ do ! WarnD( ObsoleteDiagnostic( false , diagnosticId, None , urlFormat, m))
345361 | None -> ()
346362 }
347363
@@ -366,21 +382,21 @@ let private CheckCompilerMessageAttribute g attribs m =
366382 ()
367383 }
368384
369- let private CheckExperimentalAttribute g attribs m =
385+ let private CheckFSharpExperimentalAttribute g attribs m =
370386 trackErrors {
371387 match TryFindFSharpAttribute g g.attrib_ ExperimentalAttribute attribs with
388+ // [<Experimental("Message")>]
372389 | Some( Attrib( unnamedArgs= [ AttribStringArg( s) ])) ->
373390 let isExperimentalAttributeDisabled ( s : string ) =
374391 if g.compilingFSharpCore then
375392 true
376393 else
377- g.langVersion.IsPreviewEnabled && ( s.IndexOf( langVersionPrefix , StringComparison.OrdinalIgnoreCase) >= 0 )
394+ g.langVersion.IsPreviewEnabled && ( s.IndexOf( " --langversion:preview " , StringComparison.OrdinalIgnoreCase) >= 0 )
378395 if not ( isExperimentalAttributeDisabled s) then
379- do ! WarnD( Experimental( s, m))
380- | Some _ ->
381- do ! WarnD( Experimental( FSComp.SR.experimentalConstruct (), m))
382- | _ ->
383- ()
396+ do ! WarnD( Experimental( Some s, None, None, m))
397+ // Empty constructor is not allowed.
398+ | Some _
399+ | _ -> ()
384400 }
385401
386402let private CheckUnverifiableAttribute g attribs m =
@@ -399,7 +415,7 @@ let CheckFSharpAttributes (g:TcGlobals) attribs m =
399415 trackErrors {
400416 do ! CheckObsoleteAttributes g attribs m
401417 do ! CheckCompilerMessageAttribute g attribs m
402- do ! CheckExperimentalAttribute g attribs m
418+ do ! CheckFSharpExperimentalAttribute g attribs m
403419 do ! CheckUnverifiableAttribute g attribs m
404420 }
405421
@@ -408,16 +424,16 @@ let CheckFSharpAttributes (g:TcGlobals) attribs m =
408424let private CheckProvidedAttributes ( g : TcGlobals ) m ( provAttribs : Tainted < IProvidedCustomAttributeProvider >) =
409425 let ( AttribInfo ( tref , _ )) = g.attrib_ SystemObsolete
410426 match provAttribs.PUntaint(( fun a -> a.GetAttributeConstructorArgs( provAttribs.TypeProvider.PUntaintNoFailure( id), tref.FullName)), m) with
411- | Some ([ Some (:? string as msg) ], _) -> WarnD( ObsoleteDiagnostic( false , " " , msg, " " , m))
427+ | Some ([ Some (:? string as msg) ], _) -> WarnD( ObsoleteDiagnostic( false , None , Some msg, None , m))
412428 | Some ([ Some (:? string as msg); Some (:? bool as isError) ], _) ->
413429 if isError then
414- ErrorD ( ObsoleteDiagnostic( true , " " , msg, " " , m))
430+ ErrorD ( ObsoleteDiagnostic( true , None , Some msg, None , m))
415431 else
416- WarnD ( ObsoleteDiagnostic( false , " " , msg, " " , m))
432+ WarnD ( ObsoleteDiagnostic( false , None , Some msg, None , m))
417433 | Some ([ None ], _) ->
418- WarnD( ObsoleteDiagnostic( false , " " , " " , " " , m))
434+ WarnD( ObsoleteDiagnostic( false , None , None , None , m))
419435 | Some _ ->
420- WarnD( ObsoleteDiagnostic( false , " " , " " , " " , m))
436+ WarnD( ObsoleteDiagnostic( false , None , None , None , m))
421437 | None ->
422438 CompleteD
423439#endif
0 commit comments