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)