diff --git a/src/Compilers/Test/Utilities/VisualBasic/CompilationTestUtils.vb b/src/Compilers/Test/Utilities/VisualBasic/CompilationTestUtils.vb
index a39b2dd93158a..410cdd9e098b7 100644
--- a/src/Compilers/Test/Utilities/VisualBasic/CompilationTestUtils.vb
+++ b/src/Compilers/Test/Utilities/VisualBasic/CompilationTestUtils.vb
@@ -33,6 +33,19 @@ Friend Module CompilationUtils
Return CreateEmptyCompilation(source, references, options, parseOptions, assemblyName)
End Function
+ Public Function CreateCompilationWithIdentity(
+ identity As AssemblyIdentity,
+ source As BasicTestSource,
+ Optional references As IEnumerable(Of MetadataReference) = Nothing,
+ Optional targetFramework As TargetFramework = TargetFramework.StandardAndVBRuntime) As VisualBasicCompilation
+
+ Dim c = CreateCompilation(source, references, assemblyName:=identity.Name)
+ Assert.NotNull(c.Assembly) ' force creation Of SourceAssemblySymbol
+ DirectCast(c.Assembly, SourceAssemblySymbol).m_lazyIdentity = identity
+
+ Return c
+ End Function
+
Public Function CreateEmptyCompilation(
source As BasicTestSource,
Optional references As IEnumerable(Of MetadataReference) = Nothing,
diff --git a/src/Compilers/Test/Utilities/VisualBasic/MockSymbols.vb b/src/Compilers/Test/Utilities/VisualBasic/MockSymbols.vb
index 28cdd322f7cec..ebbfcf124a727 100644
--- a/src/Compilers/Test/Utilities/VisualBasic/MockSymbols.vb
+++ b/src/Compilers/Test/Utilities/VisualBasic/MockSymbols.vb
@@ -747,6 +747,13 @@ Friend Class MockModuleSymbol
Public Overrides Function GetMetadata() As ModuleMetadata
Return Nothing
End Function
+
+ Friend NotOverridable Overrides ReadOnly Property ObsoleteAttributeData As ObsoleteAttributeData
+ Get
+ Return Nothing
+ End Get
+ End Property
+
End Class
Friend Class MockAssemblySymbol
@@ -861,4 +868,11 @@ Friend Class MockAssemblySymbol
Public Overrides Function GetMetadata() As AssemblyMetadata
Return Nothing
End Function
+
+ Friend Overrides ReadOnly Property ObsoleteAttributeData As ObsoleteAttributeData
+ Get
+ Return Nothing
+ End Get
+ End Property
+
End Class
diff --git a/src/Compilers/VisualBasic/Portable/Symbols/AssemblySymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/AssemblySymbol.vb
index 09e42621e0c18..74da0a0cb68e4 100644
--- a/src/Compilers/VisualBasic/Portable/Symbols/AssemblySymbol.vb
+++ b/src/Compilers/VisualBasic/Portable/Symbols/AssemblySymbol.vb
@@ -238,16 +238,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
End Get
End Property
- '''
- ''' Returns data decoded from Obsolete attribute or null if there is no Obsolete attribute.
- ''' This property returns ObsoleteAttributeData.Uninitialized if attribute arguments haven't been decoded yet.
- '''
- Friend NotOverridable Overrides ReadOnly Property ObsoleteAttributeData As ObsoleteAttributeData
- Get
- Return Nothing
- End Get
- End Property
-
'''
''' Lookup a top level type referenced from metadata, names should be
''' compared case-sensitively.
diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEAssemblySymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEAssemblySymbol.vb
index 9306bafa7931c..9afeb9cc2a8cd 100644
--- a/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEAssemblySymbol.vb
+++ b/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEAssemblySymbol.vb
@@ -68,6 +68,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE
Private _lazyCachedCompilerFeatureRequiredDiagnosticInfo As DiagnosticInfo = ErrorFactory.EmptyDiagnosticInfo
+ Private _lazyObsoleteAttributeData As ObsoleteAttributeData = ObsoleteAttributeData.Uninitialized
+
Friend Sub New(assembly As PEAssembly, documentationProvider As DocumentationProvider,
isLinked As Boolean, importOptions As MetadataImportOptions)
Debug.Assert(assembly IsNot Nothing)
@@ -286,5 +288,30 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE
Return MyBase.HasUnsupportedMetadata
End Get
End Property
+
+ '''
+ ''' Returns data decoded from Obsolete attribute or null if there is no Obsolete/Experimental/... attribute.
+ ''' This property returns ObsoleteAttributeData.Uninitialized if attribute arguments haven't been decoded yet.
+ '''
+ Friend Overrides ReadOnly Property ObsoleteAttributeData As ObsoleteAttributeData
+ Get
+ If _lazyObsoleteAttributeData Is ObsoleteAttributeData.Uninitialized Then
+ Interlocked.CompareExchange(_lazyObsoleteAttributeData, ComputeObsoleteAttributeData(), ObsoleteAttributeData.Uninitialized)
+ End If
+
+ Return _lazyObsoleteAttributeData
+ End Get
+ End Property
+
+ Private Function ComputeObsoleteAttributeData() As ObsoleteAttributeData
+ For Each attrData In GetAttributes()
+ If attrData.IsTargetAttribute(Me, AttributeDescription.ExperimentalAttribute) Then
+ Return attrData.DecodeExperimentalAttribute()
+ End If
+ Next
+
+ Return Nothing
+ End Function
+
End Class
End Namespace
diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEModuleSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEModuleSymbol.vb
index e6af8729c47d5..5045e4a594d9c 100644
--- a/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEModuleSymbol.vb
+++ b/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEModuleSymbol.vb
@@ -81,6 +81,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE
Private _lazyCachedCompilerFeatureRequiredDiagnosticInfo As DiagnosticInfo = ErrorFactory.EmptyDiagnosticInfo
+ Private _lazyObsoleteAttributeData As ObsoleteAttributeData = ObsoleteAttributeData.Uninitialized
+
Friend Sub New(assemblySymbol As PEAssemblySymbol, [module] As PEModule, importOptions As MetadataImportOptions, ordinal As Integer)
Me.New(DirectCast(assemblySymbol, AssemblySymbol), [module], importOptions, ordinal)
Debug.Assert(ordinal >= 0)
@@ -507,5 +509,30 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE
Return MyBase.HasUnsupportedMetadata
End Get
End Property
+
+ '''
+ ''' Returns data decoded from Obsolete attribute or null if there is no Obsolete/Experimental/... attribute.
+ ''' This property returns ObsoleteAttributeData.Uninitialized if attribute arguments haven't been decoded yet.
+ '''
+ Friend Overrides ReadOnly Property ObsoleteAttributeData As ObsoleteAttributeData
+ Get
+ If _lazyObsoleteAttributeData Is ObsoleteAttributeData.Uninitialized Then
+ Interlocked.CompareExchange(_lazyObsoleteAttributeData, ComputeObsoleteAttributeData(), ObsoleteAttributeData.Uninitialized)
+ End If
+
+ Return _lazyObsoleteAttributeData
+ End Get
+ End Property
+
+ Private Function ComputeObsoleteAttributeData() As ObsoleteAttributeData
+ For Each attrData In GetAttributes()
+ If attrData.IsTargetAttribute(Me, AttributeDescription.ExperimentalAttribute) Then
+ Return attrData.DecodeExperimentalAttribute()
+ End If
+ Next
+
+ Return Nothing
+ End Function
+
End Class
End Namespace
diff --git a/src/Compilers/VisualBasic/Portable/Symbols/MissingAssemblySymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/MissingAssemblySymbol.vb
index c6a1d7d5a4936..36fd9b018e4cb 100644
--- a/src/Compilers/VisualBasic/Portable/Symbols/MissingAssemblySymbol.vb
+++ b/src/Compilers/VisualBasic/Portable/Symbols/MissingAssemblySymbol.vb
@@ -165,6 +165,17 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Public Overrides Function GetMetadata() As AssemblyMetadata
Return Nothing
End Function
+
+ '''
+ ''' Returns data decoded from Obsolete attribute or null if there is no Obsolete/Experimental/... attribute.
+ ''' This property returns ObsoleteAttributeData.Uninitialized if attribute arguments haven't been decoded yet.
+ '''
+ Friend Overrides ReadOnly Property ObsoleteAttributeData As ObsoleteAttributeData
+ Get
+ Return Nothing
+ End Get
+ End Property
+
End Class
'''
diff --git a/src/Compilers/VisualBasic/Portable/Symbols/MissingModuleSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/MissingModuleSymbol.vb
index 5c62aa12a50db..1d88e088a130b 100644
--- a/src/Compilers/VisualBasic/Portable/Symbols/MissingModuleSymbol.vb
+++ b/src/Compilers/VisualBasic/Portable/Symbols/MissingModuleSymbol.vb
@@ -171,6 +171,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Public Overrides Function GetMetadata() As ModuleMetadata
Return Nothing
End Function
+
+ Friend NotOverridable Overrides ReadOnly Property ObsoleteAttributeData As ObsoleteAttributeData
+ Get
+ Return Nothing
+ End Get
+ End Property
+
End Class
Friend Class MissingModuleSymbolWithName
diff --git a/src/Compilers/VisualBasic/Portable/Symbols/ModuleSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/ModuleSymbol.vb
index 2753e72de51d0..3dcb5d16caef4 100644
--- a/src/Compilers/VisualBasic/Portable/Symbols/ModuleSymbol.vb
+++ b/src/Compilers/VisualBasic/Portable/Symbols/ModuleSymbol.vb
@@ -293,16 +293,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
'''
Friend MustOverride ReadOnly Property MightContainExtensionMethods As Boolean
- '''
- ''' Returns data decoded from Obsolete attribute or null if there is no Obsolete attribute.
- ''' This property returns ObsoleteAttributeData.Uninitialized if attribute arguments haven't been decoded yet.
- '''
- Friend NotOverridable Overrides ReadOnly Property ObsoleteAttributeData As ObsoleteAttributeData
- Get
- Return Nothing
- End Get
- End Property
-
#Region "IModuleSymbol"
Private ReadOnly Property IModuleSymbol_GlobalNamespace As INamespaceSymbol Implements IModuleSymbol.GlobalNamespace
Get
diff --git a/src/Compilers/VisualBasic/Portable/Symbols/ObsoleteAttributeHelpers.vb b/src/Compilers/VisualBasic/Portable/Symbols/ObsoleteAttributeHelpers.vb
index e8367ab52beb4..c248a2875a39e 100644
--- a/src/Compilers/VisualBasic/Portable/Symbols/ObsoleteAttributeHelpers.vb
+++ b/src/Compilers/VisualBasic/Portable/Symbols/ObsoleteAttributeHelpers.vb
@@ -46,13 +46,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
''' symbol's Obsoleteness is Unknown. False, if we are certain that no symbol in the parent
''' hierarchy is Obsolete.
'''
- Private Shared Function GetObsoleteContextState(symbol As Symbol, forceComplete As Boolean) As ThreeState
+ Private Shared Function GetObsoleteContextState(symbol As Symbol, forceComplete As Boolean, getStateFromSymbol As Func(Of Symbol, ThreeState)) As ThreeState
While symbol IsNot Nothing
If forceComplete Then
symbol.ForceCompleteObsoleteAttribute()
End If
- Dim state = symbol.ObsoleteState
+ Dim state = getStateFromSymbol(symbol)
If state <> ThreeState.False Then
Return state
End If
@@ -72,11 +72,39 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Debug.Assert(context IsNot Nothing)
Debug.Assert(symbol IsNot Nothing)
+ Dim namedType = TryCast(symbol, NamedTypeSymbol)
+ If namedType IsNot Nothing AndAlso
+ IsExperimentalSymbol(namedType) Then
+
+ ' Skip for System.Diagnostics.CodeAnalysis.ExperimentalAttribute to mitigate cycles
+ Return ObsoleteDiagnosticKind.NotObsolete
+ End If
+
+ Dim method = TryCast(symbol, MethodSymbol)
+ If method IsNot Nothing AndAlso
+ method.MethodKind = MethodKind.Constructor AndAlso
+ IsExperimentalSymbol(method.ContainingType) Then
+
+ ' Skip for constructors of System.Diagnostics.CodeAnalysis.ExperimentalAttribute to mitigate cycles
+ Return ObsoleteDiagnosticKind.NotObsolete
+ End If
+
+ Debug.Assert(symbol.ContainingModule Is Nothing OrElse symbol.ContainingModule.ObsoleteKind <> ObsoleteAttributeKind.Uninitialized)
+ Debug.Assert(symbol.ContainingAssembly Is Nothing OrElse symbol.ContainingAssembly.ObsoleteKind <> ObsoleteAttributeKind.Uninitialized)
+
+ If symbol.ContainingModule?.ObsoleteKind = ObsoleteAttributeKind.Experimental OrElse
+ symbol.ContainingAssembly?.ObsoleteKind = ObsoleteAttributeKind.Experimental Then
+
+ Return GetExperimentalDiagnosticKind(context, forceComplete)
+ End If
+
Select Case symbol.ObsoleteKind
Case ObsoleteAttributeKind.None
Return ObsoleteDiagnosticKind.NotObsolete
- Case ObsoleteAttributeKind.WindowsExperimental, ObsoleteAttributeKind.Experimental
+ Case ObsoleteAttributeKind.WindowsExperimental
Return ObsoleteDiagnosticKind.Diagnostic
+ Case ObsoleteAttributeKind.Experimental
+ Return GetExperimentalDiagnosticKind(context, forceComplete)
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
@@ -85,7 +113,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Return ObsoleteDiagnosticKind.Lazy
End Select
- Select Case GetObsoleteContextState(context, forceComplete)
+ Select Case GetObsoleteContextState(context, forceComplete, getStateFromSymbol:=Function(s) s.ObsoleteState)
Case ThreeState.False
Return ObsoleteDiagnosticKind.Diagnostic
Case ThreeState.True
@@ -99,12 +127,36 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
End Select
End Function
+ Private Shared Function IsExperimentalSymbol(namedType As NamedTypeSymbol) As Boolean
+ Return namedType IsNot Nothing AndAlso
+ namedType.Arity = 0 AndAlso
+ namedType.HasNameQualifier("System.Diagnostics.CodeAnalysis", StringComparison.Ordinal) AndAlso
+ namedType.Name.Equals("ExperimentalAttribute", StringComparison.Ordinal)
+ End Function
+
+ Private Shared Function GetExperimentalDiagnosticKind(containingMember As Symbol, forceComplete As Boolean) As ObsoleteDiagnosticKind
+
+ Select Case GetObsoleteContextState(containingMember, forceComplete, getStateFromSymbol:=Function(s) s.ExperimentalState)
+ Case ThreeState.False
+ Return ObsoleteDiagnosticKind.Diagnostic
+ Case ThreeState.True
+ ' If we are in a context that is already experimental, there is no point reporting
+ ' more experimental diagnostics.
+ Return ObsoleteDiagnosticKind.Suppressed
+ Case Else
+ ' If the context is unknown, then store the symbol so that we can do this check at a
+ ' later stage
+ Return ObsoleteDiagnosticKind.LazyPotentiallySuppressed
+ End Select
+ 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
+ Dim data = If(If(symbol.ObsoleteAttributeData, symbol.ContainingModule.ObsoleteAttributeData), symbol.ContainingAssembly.ObsoleteAttributeData)
+
Debug.Assert(data IsNot Nothing)
If data Is Nothing Then
diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Retargeting/RetargetingAssemblySymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Retargeting/RetargetingAssemblySymbol.vb
index 00d063d90fb91..6722cf79b2e9f 100644
--- a/src/Compilers/VisualBasic/Portable/Symbols/Retargeting/RetargetingAssemblySymbol.vb
+++ b/src/Compilers/VisualBasic/Portable/Symbols/Retargeting/RetargetingAssemblySymbol.vb
@@ -268,5 +268,16 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Retargeting
Public Overrides Function GetMetadata() As AssemblyMetadata
Return _underlyingAssembly.GetMetadata()
End Function
+
+ '''
+ ''' Returns data decoded from Obsolete attribute or null if there is no Obsolete/Experimental/... attribute.
+ ''' This property returns ObsoleteAttributeData.Uninitialized if attribute arguments haven't been decoded yet.
+ '''
+ Friend Overrides ReadOnly Property ObsoleteAttributeData As ObsoleteAttributeData
+ Get
+ Return _underlyingAssembly.ObsoleteAttributeData
+ End Get
+ End Property
+
End Class
End Namespace
diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Retargeting/RetargetingModuleSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Retargeting/RetargetingModuleSymbol.vb
index ed1cd2fc52464..99987031c11fc 100644
--- a/src/Compilers/VisualBasic/Portable/Symbols/Retargeting/RetargetingModuleSymbol.vb
+++ b/src/Compilers/VisualBasic/Portable/Symbols/Retargeting/RetargetingModuleSymbol.vb
@@ -290,5 +290,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Retargeting
Public Overrides Function GetMetadata() As ModuleMetadata
Return _underlyingModule.GetMetadata()
End Function
+
+ Friend Overrides ReadOnly Property ObsoleteAttributeData As ObsoleteAttributeData
+ Get
+ Return _underlyingModule.ObsoleteAttributeData
+ End Get
+ End Property
+
End Class
End Namespace
diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceAssemblySymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceAssemblySymbol.vb
index 7e522d31b6a95..346648b033b7b 100644
--- a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceAssemblySymbol.vb
+++ b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceAssemblySymbol.vb
@@ -1092,6 +1092,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
arguments.GetOrCreateData(Of CommonAssemblyWellKnownAttributeData)().RuntimeCompatibilityWrapNonExceptionThrows = True
ElseIf attrData.IsTargetAttribute(Me, AttributeDescription.DebuggableAttribute) Then
arguments.GetOrCreateData(Of CommonAssemblyWellKnownAttributeData)().HasDebuggableAttribute = True
+ ElseIf attrData.IsTargetAttribute(Me, AttributeDescription.ExperimentalAttribute) Then
+ arguments.GetOrCreateData(Of CommonAssemblyWellKnownAttributeData)().ObsoleteAttributeData = attrData.DecodeExperimentalAttribute()
Else
Dim signature As Integer = attrData.GetTargetAttributeSignatureIndex(Me, AttributeDescription.AssemblyAlgorithmIdAttribute)
@@ -1780,5 +1782,20 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Return _compilation
End Get
End Property
+
+ '''
+ ''' Returns data decoded from Obsolete attribute or null if there is no Obsolete attribute.
+ ''' This property returns ObsoleteAttributeData.Uninitialized if attribute arguments haven't been decoded yet.
+ '''
+ Friend Overrides ReadOnly Property ObsoleteAttributeData As ObsoleteAttributeData
+ Get
+ ' may have been specified in the assembly or one of the modules
+ Dim result = If(GetSourceDecodedWellKnownAttributeData()?.ObsoleteAttributeData, GetNetModuleDecodedWellKnownAttributeData()?.ObsoleteAttributeData)
+
+ Debug.Assert(result Is Nothing OrElse result.Kind = ObsoleteAttributeKind.Experimental)
+ Return result
+ End Get
+ End Property
+
End Class
End Namespace
diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceModuleSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceModuleSymbol.vb
index e208ec8ce966b..65645885f2e34 100644
--- a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceModuleSymbol.vb
+++ b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceModuleSymbol.vb
@@ -1116,6 +1116,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
End If
ElseIf attrData.IsTargetAttribute(Me, AttributeDescription.DebuggableAttribute) Then
arguments.GetOrCreateData(Of CommonModuleWellKnownAttributeData).HasDebuggableAttribute = True
+ ElseIf attrData.IsTargetAttribute(Me, AttributeDescription.ExperimentalAttribute) Then
+ arguments.GetOrCreateData(Of CommonModuleWellKnownAttributeData).ObsoleteAttributeData = attrData.DecodeObsoleteAttribute(ObsoleteAttributeKind.Experimental)
End If
MyBase.DecodeWellKnownAttribute(arguments)
@@ -1220,5 +1222,17 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Public Overrides Function GetMetadata() As ModuleMetadata
Return Nothing
End Function
+
+ '''
+ ''' Returns data decoded from Obsolete attribute or null if there is no Obsolete/Experimental/... attribute.
+ ''' This property returns ObsoleteAttributeData.Uninitialized if attribute arguments haven't been decoded yet.
+ '''
+ Friend Overrides ReadOnly Property ObsoleteAttributeData As ObsoleteAttributeData
+ Get
+ Dim data = GetDecodedWellKnownAttributeData()
+ Return If(data IsNot Nothing, data.ObsoleteAttributeData, Nothing)
+ End Get
+ End Property
+
End Class
End Namespace
diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Symbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Symbol.vb
index 9771862391d5d..49e052acacd84 100644
--- a/src/Compilers/VisualBasic/Portable/Symbols/Symbol.vb
+++ b/src/Compilers/VisualBasic/Portable/Symbols/Symbol.vb
@@ -456,6 +456,23 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Get
End Property
+ '''
+ ''' True if this symbol has been marked with the Experimental attribute.
+ ''' This property returns Unknown if the Experimental attribute hasn't been cracked yet.
+ '''
+ Friend ReadOnly Property ExperimentalState As ThreeState
+ Get
+ Select Case ObsoleteKind
+ Case ObsoleteAttributeKind.Experimental
+ Return ThreeState.True
+ Case ObsoleteAttributeKind.Uninitialized
+ Return ThreeState.Unknown
+ Case Else
+ Return ThreeState.False
+ End Select
+ End Get
+ End Property
+
Friend ReadOnly Property ObsoleteKind As ObsoleteAttributeKind
Get
Dim data = Me.ObsoleteAttributeData
diff --git a/src/Compilers/VisualBasic/Test/Emit/Attributes/AttributeTests.vb b/src/Compilers/VisualBasic/Test/Emit/Attributes/AttributeTests.vb
index a41614fd8878e..a48d45ea8c780 100644
--- a/src/Compilers/VisualBasic/Test/Emit/Attributes/AttributeTests.vb
+++ b/src/Compilers/VisualBasic/Test/Emit/Attributes/AttributeTests.vb
@@ -5,12 +5,14 @@
Imports System.Collections.Immutable
Imports System.IO
Imports System.Reflection
+Imports System.Resources
Imports System.Runtime.InteropServices
Imports Microsoft.CodeAnalysis.Emit
Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.CodeAnalysis.VisualBasic
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE
+Imports Microsoft.CodeAnalysis.VisualBasic.Symbols.Retargeting
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports Roslyn.Test.Utilities
@@ -5067,7 +5069,7 @@ DiagID1: 'C' is for evaluation purposes only and is subject to change or removal
~
]]>)
- Dim diag = Comp.GetDiagnostics().Single()
+ Dim diag = comp.GetDiagnostics().Single()
Assert.Equal("DiagID1", diag.Id)
Assert.Equal(ERRID.WRN_Experimental, diag.Code)
Assert.Equal("https://example.org/DiagID1", diag.Descriptor.HelpLinkUri)
@@ -5111,5 +5113,456 @@ DiagID1: 'C' is for evaluation purposes only and is subject to change or removal
Assert.Equal("https://example.org/DiagID1", diag.Descriptor.HelpLinkUri)
End Sub
+
+ Public Sub OnAssembly_UsedFromSource()
+ Dim attrComp = CreateCSharpCompilation(experimentalAttributeCSharpSrc)
+
+ Dim src =
+
+
+
+Class C
+End Class
+
+Class D
+ Sub M(c As C)
+ End Sub
+End Class
+]]>
+
+
+
+ Dim comp = CreateCompilation(src, references:={attrComp.EmitToImageReference()})
+ comp.AssertNoDiagnostics()
+
+ Assert.Equal(ObsoleteAttributeKind.None, comp.GetTypeByMetadataName("C").ContainingModule.ObsoleteKind)
+ Assert.Equal(ObsoleteAttributeKind.Experimental, comp.GetTypeByMetadataName("C").ContainingAssembly.ObsoleteKind)
+ End Sub
+
+
+ Public Sub OnAssembly_UsedFromMetadata()
+ Dim attrComp = CreateCSharpCompilation(experimentalAttributeCSharpSrc)
+ Dim attrRef = attrComp.EmitToImageReference()
+
+ Dim libSrc =
+
+
+
+Public Class C
+End Class
+]]>
+
+
+ Dim libComp = CreateCompilation(libSrc, references:={attrRef})
+ Dim libRef = libComp.EmitToImageReference()
+
+ Dim src =
+
+
+
+
+
+ Dim comp = CreateCompilation(src, references:={libRef, attrRef})
+
+ comp.AssertTheseDiagnostics(
+)
+
+ Assert.Equal(ObsoleteAttributeKind.None, comp.GetTypeByMetadataName("C").ContainingModule.ObsoleteKind)
+ Assert.Equal(ObsoleteAttributeKind.Experimental, comp.GetTypeByMetadataName("C").ContainingAssembly.ObsoleteKind)
+
+ Dim diag = comp.GetDiagnostics().Single()
+ Assert.Equal("DiagID1", diag.Id)
+ Assert.Equal(ERRID.WRN_Experimental, diag.Code)
+ Assert.Equal("https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(BC42380)", diag.Descriptor.HelpLinkUri)
+ End Sub
+
+
+ Public Sub OnAssembly_CompiledIntoModule()
+ Dim attrComp = CreateCSharpCompilation(experimentalAttributeCSharpSrc)
+ Dim attrRef = attrComp.EmitToImageReference()
+
+ Dim libSrc =
+
+
+
+Public Class C
+ Public Shared Sub M()
+ End Sub
+End Class
+]]>
+
+
+
+ Dim moduleComp = CreateCompilation(libSrc, options:=TestOptions.ReleaseModule, references:={attrRef})
+ moduleComp.VerifyDiagnostics()
+ Dim moduleRef = moduleComp.EmitToImageReference()
+
+ Dim libSrc2 =
+
+
+
+
+
+ Dim assemblyComp = CreateCompilation(libSrc2, references:={moduleRef, attrRef})
+ assemblyComp.VerifyDiagnostics()
+ Dim assemblyRef = assemblyComp.EmitToImageReference()
+
+ Dim src =
+
+
+
+
+
+ ' Since the module is referenced but not linked, we also need it here, but as
+ ' a result the diagnostics are suppressed
+ Dim comp = CreateCompilation(src, references:={assemblyRef, moduleRef, attrRef})
+ comp.VerifyDiagnostics()
+
+ Assert.Equal(ObsoleteAttributeKind.None, comp.GetTypeByMetadataName("C").ContainingModule.ObsoleteKind)
+ Assert.Equal(ObsoleteAttributeKind.Experimental, comp.GetTypeByMetadataName("C").ContainingAssembly.ObsoleteKind)
+
+ Assert.Equal(ObsoleteAttributeKind.None, comp.GetTypeByMetadataName("D").ContainingModule.ObsoleteKind)
+ Assert.Equal(ObsoleteAttributeKind.Experimental, comp.GetTypeByMetadataName("D").ContainingAssembly.ObsoleteKind)
+ End Sub
+
+
+ Public Sub RetargetingAssembly_Experimental()
+ Dim attrComp = CreateCSharpCompilation(experimentalAttributeCSharpSrc)
+ Dim attrRef = attrComp.EmitToImageReference()
+
+ Dim retargetedCode =
+
+
+
+
+
+ Dim originalC = CreateCompilationWithIdentity(New AssemblyIdentity("Ret", New Version(1, 0, 0, 0), isRetargetable:=True), retargetedCode)
+ Dim retargetedC = CreateCompilationWithIdentity(New AssemblyIdentity("Ret", New Version(2, 0, 0, 0), isRetargetable:=True), retargetedCode)
+
+ Dim derivedSrc =
+
+
+
+Class Derived
+ Inherits C
+End Class
+]]>
+
+
+
+ Dim derivedComp = CreateCompilation(derivedSrc, references:={originalC.ToMetadataReference(), attrRef})
+ derivedComp.AssertNoDiagnostics()
+
+ Dim comp = CreateCompilation("", references:={derivedComp.ToMetadataReference(), retargetedC.ToMetadataReference(), attrRef})
+ derivedComp.AssertNoDiagnostics()
+
+ Dim derivedType = comp.GetTypeByMetadataName("Derived")
+ Assert.IsType(Of RetargetingNamedTypeSymbol)(derivedType)
+ Assert.IsType(Of RetargetingAssemblySymbol)(derivedType.ContainingAssembly)
+ Assert.Equal(ObsoleteAttributeKind.Experimental, derivedType.ContainingAssembly.ObsoleteKind)
+ End Sub
+
+
+ Public Sub RetargetingAssembly_NotExperimental()
+ Dim attrComp = CreateCSharpCompilation(experimentalAttributeCSharpSrc)
+ Dim attrRef = attrComp.EmitToImageReference()
+
+ Dim retargetedCode =
+
+
+
+
+
+ Dim originalC = CreateCompilationWithIdentity(New AssemblyIdentity("Ret", New Version(1, 0, 0, 0), isRetargetable:=True), retargetedCode)
+ Dim retargetedC = CreateCompilationWithIdentity(New AssemblyIdentity("Ret", New Version(2, 0, 0, 0), isRetargetable:=True), retargetedCode)
+
+ Dim derivedSrc =
+
+
+
+
+
+ Dim derivedComp = CreateCompilation(derivedSrc, references:={originalC.ToMetadataReference(), attrRef})
+ derivedComp.AssertNoDiagnostics()
+
+ Dim comp = CreateCompilation("", references:={derivedComp.ToMetadataReference(), retargetedC.ToMetadataReference(), attrRef})
+ derivedComp.AssertNoDiagnostics()
+
+ Dim derivedType = comp.GetTypeByMetadataName("Derived")
+ Assert.IsType(Of RetargetingNamedTypeSymbol)(derivedType)
+ Assert.IsType(Of RetargetingAssemblySymbol)(derivedType.ContainingAssembly)
+ Assert.Equal(ObsoleteAttributeKind.None, derivedType.ContainingAssembly.ObsoleteKind)
+ End Sub
+
+
+ Public Sub RetargetingModule_Experimental()
+ Dim attrComp = CreateCSharpCompilation(experimentalAttributeCSharpSrc)
+ Dim attrRef = attrComp.EmitToImageReference()
+
+ Dim retargetedCode =
+
+
+
+
+
+ Dim originalC = CreateCompilationWithIdentity(New AssemblyIdentity("Ret", New Version(1, 0, 0, 0), isRetargetable:=True), retargetedCode)
+ Dim retargetedC = CreateCompilationWithIdentity(New AssemblyIdentity("Ret", New Version(2, 0, 0, 0), isRetargetable:=True), retargetedCode)
+
+ Dim derivedSrc =
+
+
+
+Class Derived
+ Inherits C
+End Class
+]]>
+
+
+
+ Dim derivedComp = CreateCompilation(derivedSrc, references:={originalC.ToMetadataReference(), attrRef})
+ derivedComp.AssertNoDiagnostics()
+
+ Dim comp = CreateCompilation("", references:={derivedComp.ToMetadataReference(), retargetedC.ToMetadataReference(), attrRef})
+ derivedComp.AssertNoDiagnostics()
+
+ Dim derivedType = comp.GetTypeByMetadataName("Derived")
+ Assert.IsType(Of RetargetingNamedTypeSymbol)(derivedType)
+ Assert.IsType(Of RetargetingModuleSymbol)(derivedType.ContainingModule)
+ Assert.Equal(ObsoleteAttributeKind.Experimental, derivedType.ContainingModule.ObsoleteKind)
+ End Sub
+
+
+ Public Sub MissingAssemblyAndModule()
+
+ Dim missingSrc =
+
+
+
+
+
+ Dim missingRef = CreateCompilation(missingSrc, assemblyName:="missing").EmitToImageReference()
+
+ Dim libSrc =
+
+
+
+
+
+ Dim libRef = CreateCompilation(libSrc, references:={missingRef}).EmitToImageReference()
+
+ Dim src =
+
+
+
+
+
+ Dim comp = CreateCompilation(src, references:={libRef})
+
+ comp.AssertTheseDiagnostics()
+
+ Dim missingType = comp.GlobalNamespace.GetTypeMember("C").BaseTypeNoUseSiteDiagnostics
+ Assert.True(TypeOf missingType.ContainingAssembly Is MissingAssemblySymbol)
+ Assert.Equal(ObsoleteAttributeKind.None, missingType.ContainingAssembly.ObsoleteKind)
+ Assert.True(TypeOf missingType.ContainingModule Is MissingModuleSymbol)
+ Assert.Equal(ObsoleteAttributeKind.None, missingType.ContainingModule.ObsoleteKind)
+ End Sub
+
+
+ Public Sub Cycle()
+
+ Dim src =
+
+
+
+Namespace System.Diagnostics.CodeAnalysis
+
+ Public Class ExperimentalAttribute
+ Inherits System.Attribute
+
+ Public Sub New(diagnosticId As String)
+ End Sub
+
+ Public Property UrlFormat As String
+ End Class
+End Namespace
+]]>
+
+
+
+ Dim comp = CreateCompilation(src)
+ comp.AssertNoDiagnostics()
+ End Sub
+
+
+ Public Sub OnModule_UsedFromMetadata()
+ Dim attrComp = CreateCSharpCompilation(experimentalAttributeCSharpSrc)
+ Dim attrRef = attrComp.EmitToImageReference()
+
+ Dim libSrc =
+
+
+
+Public Class C
+ Public Shared Sub M()
+ End Sub
+End Class
+]]>
+
+
+
+ Dim libComp = CreateCompilation(libSrc, references:={attrRef})
+ Dim libRef = libComp.EmitToImageReference()
+
+ Dim src =
+
+
+
+
+
+ Dim comp = CreateCompilation(src, references:={libRef, attrRef})
+
+ comp.AssertTheseDiagnostics(
+)
+
+ Assert.Equal(ObsoleteAttributeKind.Experimental, comp.GetTypeByMetadataName("C").ContainingModule.ObsoleteKind)
+ Assert.Equal(ObsoleteAttributeKind.None, comp.GetTypeByMetadataName("C").ContainingAssembly.ObsoleteKind)
+
+ For Each diag In comp.GetDiagnostics()
+ Assert.Equal("DiagID1", diag.Id)
+ Assert.Equal(ERRID.WRN_Experimental, diag.Code)
+ Assert.Equal("https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(BC42380)", diag.Descriptor.HelpLinkUri)
+ Next
+ End Sub
+
+
+ Public Sub OnModuleAndAssembly()
+ ' Prefer reporting the module-level diagnostic
+ Dim attrComp = CreateCSharpCompilation(experimentalAttributeCSharpSrc)
+ Dim attrRef = attrComp.EmitToImageReference()
+
+ Dim libSrc =
+
+
+
+
+Public Class C
+ Public Shared Sub M()
+ End Sub
+End Class
+]]>
+
+
+
+ Dim libComp = CreateCompilation(libSrc, references:={attrRef})
+ Dim libRef = libComp.EmitToImageReference()
+
+ Dim src =
+
+
+
+
+
+ Dim comp = CreateCompilation(src, references:={libRef, attrRef})
+
+ comp.AssertTheseDiagnostics(
+)
+
+ Assert.Equal(ObsoleteAttributeKind.Experimental, comp.GetTypeByMetadataName("C").ContainingModule.ObsoleteKind)
+ Assert.Equal(ObsoleteAttributeKind.Experimental, comp.GetTypeByMetadataName("C").ContainingAssembly.ObsoleteKind)
+
+ For Each diag In comp.GetDiagnostics()
+ Assert.Equal("DiagModule", diag.Id)
+ Next
+ End Sub
+
End Class
End Namespace