diff --git a/src/Compilers/CSharp/Portable/Binder/Binder.cs b/src/Compilers/CSharp/Portable/Binder/Binder.cs index 155b3e2192ba143471061abe166379e3cef75d69..4e33198556b109193122529ee9dca7903a9a6b2f 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder.cs @@ -559,52 +559,41 @@ internal static ThreeState ReportDiagnosticsIfObsoleteInternal(DiagnosticBag dia { Debug.Assert(diagnostics != null); - if (symbol.ObsoleteState == ThreeState.False) - { - return ThreeState.False; - } - - var data = symbol.ObsoleteAttributeData; - if (data == null) - { - // Obsolete attribute has errors. - return ThreeState.False; - } - - // If we haven't cracked attributes on the symbol at all or we haven't - // cracked attribute arguments enough to be able to report diagnostics for - // ObsoleteAttribute, store the symbol so that we can report diagnostics at a - // later stage. - if (symbol.ObsoleteState == ThreeState.Unknown) - { - diagnostics.Add(new LazyObsoleteDiagnosticInfo(symbol, containingMember, location), node.GetLocation()); - return ThreeState.Unknown; - } - - // After this point, always return True. - - var inObsoleteContext = ObsoleteAttributeHelpers.GetObsoleteContextState(containingMember); - - // If we are in a context that is already obsolete, there is no point reporting - // more obsolete diagnostics. - if (inObsoleteContext == ThreeState.True) - { - return ThreeState.True; - } - // If the context is unknown, then store the symbol so that we can do this check at a - // later stage - else if (inObsoleteContext == ThreeState.Unknown) - { - diagnostics.Add(new LazyObsoleteDiagnosticInfo(symbol, containingMember, location), node.GetLocation()); - return ThreeState.True; - } - - // We have all the information we need to report diagnostics right now. So do it. - var diagInfo = ObsoleteAttributeHelpers.CreateObsoleteDiagnostic(symbol, location); - if (diagInfo != null) - { - diagnostics.Add(diagInfo, node.GetLocation()); - return ThreeState.True; + var kind = symbol.ObsoleteKind; + switch (kind) + { + case ObsoleteAttributeKind.None: + return ThreeState.False; + case ObsoleteAttributeKind.Uninitialized: + // If we haven't cracked attributes on the symbol at all or we haven't + // cracked attribute arguments enough to be able to report diagnostics for + // ObsoleteAttribute, store the symbol so that we can report diagnostics at a + // later stage. + diagnostics.Add(new LazyObsoleteDiagnosticInfo(symbol, containingMember, location), node.GetLocation()); + return ThreeState.Unknown; + } + + kind = containingMember.GetObsoleteContextKind(); + switch (kind) + { + case ObsoleteAttributeKind.None: + case ObsoleteAttributeKind.Experimental: + // We have all the information we need to report diagnostics right now. So do it. + var diagInfo = ObsoleteAttributeHelpers.CreateObsoleteDiagnostic(symbol, location); + if (diagInfo != null) + { + diagnostics.Add(diagInfo, node.GetLocation()); + } + break; + case ObsoleteAttributeKind.Uninitialized: + // If the context is unknown, then store the symbol so that we can do this check at a + // later stage + diagnostics.Add(new LazyObsoleteDiagnosticInfo(symbol, containingMember, location), node.GetLocation()); + break; + default: + // If we are in a context that is already obsolete, there is no point reporting + // more obsolete diagnostics. + break; } return ThreeState.True; diff --git a/src/Compilers/CSharp/Portable/Errors/LazyObsoleteDiagnosticInfo.cs b/src/Compilers/CSharp/Portable/Errors/LazyObsoleteDiagnosticInfo.cs index bc9aa144ea11e5a3ea8b6e80b7eb21f29184867d..4daefea7ec19096c7494e191a96619f1a3a8e4ca 100644 --- a/src/Compilers/CSharp/Portable/Errors/LazyObsoleteDiagnosticInfo.cs +++ b/src/Compilers/CSharp/Portable/Errors/LazyObsoleteDiagnosticInfo.cs @@ -33,10 +33,10 @@ internal override DiagnosticInfo GetResolvedInfo() if (_symbol.ObsoleteState == ThreeState.True) { - var inObsoleteContext = ObsoleteAttributeHelpers.GetObsoleteContextState(_containingSymbol, forceComplete: true); - Debug.Assert(inObsoleteContext != ThreeState.Unknown); + var kind = _containingSymbol.GetObsoleteContextKind(forceComplete: true); + Debug.Assert(kind != ObsoleteAttributeKind.Uninitialized); - if (inObsoleteContext == ThreeState.False) + if (kind == ObsoleteAttributeKind.None) { DiagnosticInfo info = ObsoleteAttributeHelpers.CreateObsoleteDiagnostic(_symbol, _binderFlags); if (info != null) diff --git a/src/Compilers/CSharp/Portable/Symbols/ObsoleteAttributeHelpers.cs b/src/Compilers/CSharp/Portable/Symbols/ObsoleteAttributeHelpers.cs index aea63d7cfc0aa0dc623ddbe36158480b41c32351..4f46addff3372585a207ab822b51e672cd28bb97 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ObsoleteAttributeHelpers.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ObsoleteAttributeHelpers.cs @@ -39,37 +39,42 @@ internal static ObsoleteAttributeData GetObsoleteDataFromMetadata(EntityHandle t /// This method checks to see if the given symbol is Obsolete or if any symbol in the parent hierarchy is Obsolete. /// /// - /// True if some symbol in the parent hierarchy is known to be Obsolete. Unknown if any - /// symbol's Obsoleteness is Unknown. False, if we are certain that no symbol in the parent - /// hierarchy is Obsolete. + /// Uninitialized if attributes have not been cracked yet. /// - internal static ThreeState GetObsoleteContextState(Symbol symbol, bool forceComplete = false) + internal static ObsoleteAttributeKind GetObsoleteContextKind(this Symbol symbol, bool forceComplete = false) { - if ((object)symbol == null) - return ThreeState.False; - - // For Property or Event accessors, check the associated property or event instead. - if (symbol.IsAccessor()) - { - symbol = ((MethodSymbol)symbol).AssociatedSymbol; - } - // If this is the backing field of an event, look at the event instead. - else if (symbol.Kind == SymbolKind.Field && (object)((FieldSymbol)symbol).AssociatedSymbol != null) + while ((object)symbol != null) { - symbol = ((FieldSymbol)symbol).AssociatedSymbol; - } + // For property or event accessors, check the associated property or event instead. + if (symbol.IsAccessor()) + { + symbol = ((MethodSymbol)symbol).AssociatedSymbol; + } + else if (symbol.Kind == SymbolKind.Field) + { + // If this is the backing field of an event, look at the event instead. + var associatedSymbol = ((FieldSymbol)symbol).AssociatedSymbol; + if ((object)associatedSymbol != null) + { + symbol = associatedSymbol; + } + } - if (forceComplete) - { - symbol.ForceCompleteObsoleteAttribute(); - } + if (forceComplete) + { + symbol.ForceCompleteObsoleteAttribute(); + } - if (symbol.ObsoleteState != ThreeState.False) - { - return symbol.ObsoleteState; + var kind = symbol.ObsoleteKind; + if (kind != ObsoleteAttributeKind.None) + { + return kind; + } + + symbol = symbol.ContainingSymbol; } - return GetObsoleteContextState(symbol.ContainingSymbol, forceComplete); + return ObsoleteAttributeKind.None; } /// @@ -79,10 +84,10 @@ internal static ThreeState GetObsoleteContextState(Symbol symbol, bool forceComp internal static DiagnosticInfo CreateObsoleteDiagnostic(Symbol symbol, BinderFlags location) { var data = symbol.ObsoleteAttributeData; + Debug.Assert(data != null); if (data == null) { - // ObsoleteAttribute had errors. return null; } diff --git a/src/Compilers/CSharp/Portable/Symbols/Symbol.cs b/src/Compilers/CSharp/Portable/Symbols/Symbol.cs index fffb2c5e91c8e6003f33316c1fa565ab23025de3..6723ab7d0c52c0e8fe62f907294c7df934f20a40 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Symbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Symbol.cs @@ -1018,22 +1018,28 @@ internal ThreeState ObsoleteState { get { - var data = this.ObsoleteAttributeData; - if (data == null) - { - return ThreeState.False; - } - else if (data.IsUninitialized) + switch (ObsoleteKind) { - return ThreeState.Unknown; - } - else - { - return ThreeState.True; + case ObsoleteAttributeKind.None: + return ThreeState.False; + case ObsoleteAttributeKind.Uninitialized: + return ThreeState.Unknown; + default: + return ThreeState.True; } } } + internal ObsoleteAttributeKind ObsoleteKind + { + get + { + var data = this.ObsoleteAttributeData; + return (data == null) ? ObsoleteAttributeKind.None : data.Kind; + } + } + + /// /// Returns data decoded from attribute or null if there is no attribute. /// This property returns if attribute arguments haven't been decoded yet. diff --git a/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_Experimental.cs b/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_Experimental.cs index 0907ba33ecb82f5a77a146240ca676ff67f02378..da6cac9273db4fded3f5c468d59afc23952f2b93 100644 --- a/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_Experimental.cs +++ b/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_Experimental.cs @@ -167,8 +167,6 @@ static void Main() Diagnostic(ErrorCode.WRN_Experimental, "((I)o).F()").WithArguments("I.F()").WithLocation(11, 9)); } - // [Obsolete] and [Deprecated] diagnostics are not - // suppressed inside [Experimental] type. [Fact] public void TestExperimentalTypeWithDeprecatedAndObsoleteMembers() { @@ -227,8 +225,62 @@ static void F(A a) Diagnostic(ErrorCode.WRN_Experimental, "A.B").WithArguments("A.B").WithLocation(27, 14)); } + // Diagnostics for [Obsolete] members + // are not suppressed in [Experimental] types. + [Fact] + public void TestObsoleteMembersInExperimentalType() + { + var source = +@"using System; +using Windows.Foundation.Metadata; +class A +{ + internal void F0() { } + [Deprecated("""", DeprecationType.Deprecate, 0)] + internal void F1() { } + [Deprecated("""", DeprecationType.Remove, 0)] + internal void F2() { } + [Obsolete("""", false)] + internal void F3() { } + [Obsolete("""", true)] + internal void F4() { } + [Experimental] + internal class B { } +} +[Experimental] +class C +{ + static void F(A a) + { + a.F0(); + a.F1(); + a.F2(); + a.F3(); + a.F4(); + (new A.B()).ToString(); + } +}"; + var comp = CreateCompilationWithMscorlibAndSystemCore(new[] { Parse(DeprecatedAttributeSource), Parse(ExperimentalAttributeSource), Parse(source) }); + comp.VerifyDiagnostics( + // (23,9): warning CS0618: 'A.F1()' is obsolete: '' + // a.F1(); + Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "a.F1()").WithArguments("A.F1()", "").WithLocation(23, 9), + // (24,9): error CS0619: 'A.F2()' is obsolete: '' + // a.F2(); + Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "a.F2()").WithArguments("A.F2()", "").WithLocation(24, 9), + // (25,9): warning CS0618: 'A.F3()' is obsolete: '' + // a.F3(); + Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "a.F3()").WithArguments("A.F3()", "").WithLocation(25, 9), + // (26,9): error CS0619: 'A.F4()' is obsolete: '' + // a.F4(); + Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "a.F4()").WithArguments("A.F4()", "").WithLocation(26, 9), + // (27,14): warning CS8305: 'A.B' is for evaluation purposes only and is subject to change or removal in future updates. + // (new A.B()).ToString(); + Diagnostic(ErrorCode.WRN_Experimental, "A.B").WithArguments("A.B").WithLocation(27, 14)); + } + // Diagnostics for [Experimental] types - // are suppressed in [Obsolete] members. + // are not suppressed in [Obsolete] members. [Fact] public void TestExperimentalTypeInObsoleteMember() { diff --git a/src/Compilers/Core/Portable/Symbols/Attributes/ObsoleteAttributeData.cs b/src/Compilers/Core/Portable/Symbols/Attributes/ObsoleteAttributeData.cs index 2fe284d3359e891fdfe663f503de3a5f9a76ae12..78bb4cbeb8057d1689c7b774034f1e155c4e8d88 100644 --- a/src/Compilers/Core/Portable/Symbols/Attributes/ObsoleteAttributeData.cs +++ b/src/Compilers/Core/Portable/Symbols/Attributes/ObsoleteAttributeData.cs @@ -7,6 +7,7 @@ namespace Microsoft.CodeAnalysis internal enum ObsoleteAttributeKind { None, + Uninitialized, Obsolete, Deprecated, Experimental, @@ -17,7 +18,7 @@ internal enum ObsoleteAttributeKind /// internal sealed class ObsoleteAttributeData { - public static readonly ObsoleteAttributeData Uninitialized = new ObsoleteAttributeData(ObsoleteAttributeKind.None, null, false); + public static readonly ObsoleteAttributeData Uninitialized = new ObsoleteAttributeData(ObsoleteAttributeKind.Uninitialized, null, false); public static readonly ObsoleteAttributeData Experimental = new ObsoleteAttributeData(ObsoleteAttributeKind.Experimental, null, false); public ObsoleteAttributeData(ObsoleteAttributeKind kind, string message, bool isError) diff --git a/src/Compilers/VisualBasic/Portable/Binding/Binder.vb b/src/Compilers/VisualBasic/Portable/Binding/Binder.vb index d420b2788ca5adef631a83d320803eb97e8d1049..5367ec5d8ca9ce96e7b74cbc8fd86b3437560d2b 100644 --- a/src/Compilers/VisualBasic/Portable/Binding/Binder.vb +++ b/src/Compilers/VisualBasic/Portable/Binding/Binder.vb @@ -895,43 +895,35 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Debug.Assert(context IsNot Nothing) Debug.Assert(symbol IsNot Nothing) - If symbol.ObsoleteState = ThreeState.False Then - Return - End If - - Dim data = symbol.ObsoleteAttributeData - If data Is Nothing Then - ' Obsolete attribute has errors. - Return - End If - - ' If we haven't cracked attributes on the symbol at all or we haven't - ' cracked attribute arguments enough to be able to report diagnostics for - ' ObsoleteAttribute, store the symbol so that we can report diagnostics at a - ' later stage. - If symbol.ObsoleteState = ThreeState.Unknown OrElse data.IsUninitialized Then - diagnostics.Add(New LazyObsoleteDiagnosticInfo(symbol, context), node.GetLocation()) - Return - End If - - Dim inObsoleteContext = ObsoleteAttributeHelpers.GetObsoleteContextState(context) - - ' If we are in a context that is already obsolete, there is no point reporting - ' more obsolete diagnostics. - If inObsoleteContext = ThreeState.True Then - Return - ElseIf inObsoleteContext = ThreeState.Unknown Then - ' If the context is unknown, then store the symbol so that we can do this check at a - ' later stage - diagnostics.Add(New LazyObsoleteDiagnosticInfo(symbol, context), node.GetLocation()) - Return - End If - - ' We have all the information we need to report diagnostics right now. So do it. - Dim info = ObsoleteAttributeHelpers.CreateObsoleteDiagnostic(symbol) - If info IsNot Nothing Then - diagnostics.Add(info, node.GetLocation()) - End If + Dim kind = symbol.ObsoleteKind + Select Case kind + Case ObsoleteAttributeKind.None + Return + Case ObsoleteAttributeKind.Uninitialized + ' If we haven't cracked attributes on the symbol at all or we haven't + ' cracked attribute arguments enough to be able to report diagnostics for + ' ObsoleteAttribute, store the symbol so that we can report diagnostics at a + ' later stage. + diagnostics.Add(New LazyObsoleteDiagnosticInfo(symbol, context), node.GetLocation()) + Return + End Select + + kind = ObsoleteAttributeHelpers.GetObsoleteContextKind(context) + Select Case kind + Case ObsoleteAttributeKind.None, ObsoleteAttributeKind.Experimental + ' We have all the information we need to report diagnostics right now. So do it. + Dim info = ObsoleteAttributeHelpers.CreateObsoleteDiagnostic(symbol) + If info IsNot Nothing Then + diagnostics.Add(info, node.GetLocation()) + End If + Case ObsoleteAttributeKind.Uninitialized + ' If the context is unknown, then store the symbol so that we can do this check at a + ' later stage + diagnostics.Add(New LazyObsoleteDiagnosticInfo(symbol, context), node.GetLocation()) + Case Else + ' If we are in a context that is already obsolete, there is no point reporting + ' more obsolete diagnostics. + End Select End Sub Friend Overridable ReadOnly Property SuppressObsoleteDiagnostics As Boolean diff --git a/src/Compilers/VisualBasic/Portable/Errors/LazyObsoleteDiagnosticInfo.vb b/src/Compilers/VisualBasic/Portable/Errors/LazyObsoleteDiagnosticInfo.vb index d0cd694ce2ca93deb0aee3efb2bf51be602566a2..962db9767fbb611edf540021d720d10dcb1574bf 100644 --- a/src/Compilers/VisualBasic/Portable/Errors/LazyObsoleteDiagnosticInfo.vb +++ b/src/Compilers/VisualBasic/Portable/Errors/LazyObsoleteDiagnosticInfo.vb @@ -26,10 +26,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic _symbol.ForceCompleteObsoleteAttribute() If _symbol.ObsoleteState = ThreeState.True Then - Dim inObsoleteContext = ObsoleteAttributeHelpers.GetObsoleteContextState(_containingSymbol, forceComplete:=True) - Debug.Assert(inObsoleteContext <> ThreeState.Unknown) + Dim kind = ObsoleteAttributeHelpers.GetObsoleteContextKind(_containingSymbol, forceComplete:=True) + Debug.Assert(kind <> ObsoleteAttributeKind.Uninitialized) - If inObsoleteContext = ThreeState.False Then + If kind = ObsoleteAttributeKind.None Then Dim info As DiagnosticInfo = ObsoleteAttributeHelpers.CreateObsoleteDiagnostic(_symbol) If info IsNot Nothing Then Interlocked.CompareExchange(Me._lazyActualObsoleteDiagnostic, info, Nothing) diff --git a/src/Compilers/VisualBasic/Portable/Symbols/ObsoleteAttributeHelpers.vb b/src/Compilers/VisualBasic/Portable/Symbols/ObsoleteAttributeHelpers.vb index 5fb959590f03f49febde1a8948f2f0850b534b7a..7929d7b7772384c0fe2a68293f92e06c4ea6ebea 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/ObsoleteAttributeHelpers.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/ObsoleteAttributeHelpers.vb @@ -1,8 +1,8 @@ ' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. Imports System.Diagnostics -Imports System.Threading Imports System.Reflection.Metadata +Imports System.Threading Imports Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols @@ -32,50 +32,39 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols ''' This method checks to see if the given symbol is Obsolete or if any symbol in the parent hierarchy is Obsolete. ''' ''' - ''' True if some symbol in the parent hierarchy is known to be Obsolete. Unknown if any - ''' symbol's Obsoleteness is Unknown. False, if we are certain that no symbol in the parent - ''' hierarchy is Obsolete. + ''' Uninitialized if attributes have not been cracked yet. ''' - Friend Shared Function GetObsoleteContextState(symbol As Symbol, Optional forceComplete As Boolean = False) As ThreeState - If symbol Is Nothing Then - Return ThreeState.False - End If - - If forceComplete Then - symbol.ForceCompleteObsoleteAttribute() - End If + Friend Shared Function GetObsoleteContextKind(symbol As Symbol, Optional forceComplete As Boolean = False) As ObsoleteAttributeKind + While symbol IsNot Nothing + ' For property or event accessors, check the associated property or event instead. + If symbol.IsAccessor() Then + symbol = DirectCast(symbol, MethodSymbol).AssociatedSymbol + End If - Dim associatedPropertyOrEvent = If(symbol.IsAccessor(), DirectCast(symbol, MethodSymbol).AssociatedSymbol, Nothing) + If forceComplete Then + symbol.ForceCompleteObsoleteAttribute() + End If - ' If this is an event accessor, then consider the event itself for context since - ' event accessors cannot be marked obsolete. - If associatedPropertyOrEvent IsNot Nothing AndAlso associatedPropertyOrEvent.Kind = SymbolKind.Event Then - symbol = DirectCast(symbol, MethodSymbol).AssociatedSymbol - End If + Dim kind = symbol.ObsoleteKind + If kind <> ObsoleteAttributeKind.None Then + Return kind + End If - If symbol.ObsoleteState <> ThreeState.False Then - Return symbol.ObsoleteState - End If + symbol = symbol.ContainingSymbol + End While - ' If this is a property accessor then check the property for obsoleteness as well so that we suppress - ' obsolete diagnostics anywhere inside a property. - If associatedPropertyOrEvent IsNot Nothing AndAlso associatedPropertyOrEvent.Kind = SymbolKind.Property Then - Return GetObsoleteContextState(associatedPropertyOrEvent, forceComplete) - Else - Return GetObsoleteContextState(symbol.ContainingSymbol, forceComplete) - End If + Return ObsoleteAttributeKind.None End Function - ''' ''' Create a diagnostic for the given symbol. This could be an error or a warning based on ''' the ObsoleteAttribute's arguments. ''' Friend Shared Function CreateObsoleteDiagnostic(symbol As Symbol) As DiagnosticInfo Dim data = symbol.ObsoleteAttributeData + Debug.Assert(data IsNot Nothing) If data Is Nothing Then - ' ObsoleteAttribute had errors. Return Nothing End If diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Symbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Symbol.vb index 44ca35f06fa6fcbf9d78d56db2733242fbaf6b41..c4f079418f7fa9d1fbc1e82055d1553442b48feb 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Symbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Symbol.vb @@ -423,15 +423,22 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ''' This property returns Unknown if the Obsolete Attribute hasn't been cracked yet. ''' Friend ReadOnly Property ObsoleteState As ThreeState + Get + Select Case ObsoleteKind + Case ObsoleteAttributeKind.None + Return ThreeState.False + Case ObsoleteAttributeKind.Uninitialized + Return ThreeState.Unknown + Case Else + Return ThreeState.True + End Select + End Get + End Property + + Friend ReadOnly Property ObsoleteKind As ObsoleteAttributeKind Get Dim data = Me.ObsoleteAttributeData - If data Is Nothing Then - Return ThreeState.False - ElseIf data Is ObsoleteAttributeData.Uninitialized Then - Return ThreeState.Unknown - Else - Return ThreeState.True - End If + Return If(data Is Nothing, ObsoleteAttributeKind.None, data.Kind) End Get End Property diff --git a/src/Compilers/VisualBasic/Test/Emit/Attributes/AttributeTests_Experimental.vb b/src/Compilers/VisualBasic/Test/Emit/Attributes/AttributeTests_Experimental.vb index ed3f2feede85810d9f5da495a0be305d43e51cb2..916f2539dfc5c68a919fec87677883758f4e6fe5 100644 --- a/src/Compilers/VisualBasic/Test/Emit/Attributes/AttributeTests_Experimental.vb +++ b/src/Compilers/VisualBasic/Test/Emit/Attributes/AttributeTests_Experimental.vb @@ -210,8 +210,6 @@ End Class End Sub - ' and diagnostics are not - ' suppressed inside type. Public Sub TestExperimentalTypeWithDeprecatedAndObsoleteMembers() Dim comp0 = CreateCompilationWithMscorlib(DeprecatedAndExperimentalAttributeSource) @@ -282,8 +280,74 @@ BC42380: 'A.B' is for evaluation purposes only and is subject to change or remov ) End Sub + ' Diagnostics for members + ' are not suppressed in types. + + Public Sub TestObsoleteMembersInExperimentalType() + Dim comp0 = CreateCompilationWithMscorlib(DeprecatedAndExperimentalAttributeSource) + comp0.AssertNoDiagnostics() + Dim ref0 = comp0.EmitToImageReference() + + Dim source = + + + Friend Sub F1() + End Sub + + Friend Sub F2() + End Sub + + Friend Sub F3() + End Sub + + Friend Sub F4() + End Sub + + Friend Class B + End Class +End Class + +Class C + Shared Sub F(a As A) + a.F0() + a.F1() + a.F2() + a.F3() + a.F4() + Dim b = New A.B() + End Sub +End Class +]]> + + + Dim comp = CreateCompilationWithMscorlib(source, references:={ref0}) + comp.AssertTheseDiagnostics( +BC40008: 'Friend Sub F1()' is obsolete. + a.F1() + ~~~~~~ +BC31075: 'Friend Sub F2()' is obsolete. + a.F2() + ~~~~~~ +BC40008: 'Friend Sub F3()' is obsolete. + a.F3() + ~~~~~~ +BC31075: 'Friend Sub F4()' is obsolete. + a.F4() + ~~~~~~ +BC42380: 'A.B' is for evaluation purposes only and is subject to change or removal in future updates. + Dim b = New A.B() + ~~~ + ) + End Sub + ' Diagnostics for types - ' are suppressed in [Obsolete] members. + ' are not suppressed in members. Public Sub TestExperimentalTypeInObsoleteMember() Dim comp0 = CreateCompilationWithMscorlib(DeprecatedAndExperimentalAttributeSource)