Skip to content

Commit

Permalink
VB implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
jcouv committed Aug 2, 2023
1 parent 3ad6f59 commit 8a1bc25
Show file tree
Hide file tree
Showing 15 changed files with 676 additions and 26 deletions.
13 changes: 13 additions & 0 deletions src/Compilers/Test/Utilities/VisualBasic/CompilationTestUtils.vb
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
14 changes: 14 additions & 0 deletions src/Compilers/Test/Utilities/VisualBasic/MockSymbols.vb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
10 changes: 0 additions & 10 deletions src/Compilers/VisualBasic/Portable/Symbols/AssemblySymbol.vb
Original file line number Diff line number Diff line change
Expand Up @@ -238,16 +238,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
End Get
End Property

''' <summary>
''' 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.
''' </summary>
Friend NotOverridable Overrides ReadOnly Property ObsoleteAttributeData As ObsoleteAttributeData
Get
Return Nothing
End Get
End Property

''' <summary>
''' Lookup a top level type referenced from metadata, names should be
''' compared case-sensitively.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -286,5 +288,30 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE
Return MyBase.HasUnsupportedMetadata
End Get
End Property

''' <summary>
''' 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.
''' </summary>
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
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -507,5 +509,30 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE
Return MyBase.HasUnsupportedMetadata
End Get
End Property

''' <summary>
''' 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.
''' </summary>
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
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,17 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Public Overrides Function GetMetadata() As AssemblyMetadata
Return Nothing
End Function

''' <summary>
''' 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.
''' </summary>
Friend Overrides ReadOnly Property ObsoleteAttributeData As ObsoleteAttributeData
Get
Return Nothing
End Get
End Property

End Class

''' <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 0 additions & 10 deletions src/Compilers/VisualBasic/Portable/Symbols/ModuleSymbol.vb
Original file line number Diff line number Diff line change
Expand Up @@ -293,16 +293,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
''' </summary>
Friend MustOverride ReadOnly Property MightContainExtensionMethods As Boolean

''' <summary>
''' 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.
''' </summary>
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
''' </returns>
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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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

''' <summary>
''' Create a diagnostic for the given symbol. This could be an error or a warning based on
''' the ObsoleteAttribute's arguments.
''' </summary>
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,5 +268,16 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Retargeting
Public Overrides Function GetMetadata() As AssemblyMetadata
Return _underlyingAssembly.GetMetadata()
End Function

''' <summary>
''' 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.
''' </summary>
Friend Overrides ReadOnly Property ObsoleteAttributeData As ObsoleteAttributeData
Get
Return _underlyingAssembly.ObsoleteAttributeData
End Get
End Property

End Class
End Namespace
Original file line number Diff line number Diff line change
Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -1780,5 +1782,20 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Return _compilation
End Get
End Property

''' <summary>
''' 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.
''' </summary>
Friend Overrides ReadOnly Property ObsoleteAttributeData As ObsoleteAttributeData
Get
' <assembly: Experimental> 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
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -1220,5 +1222,17 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Public Overrides Function GetMetadata() As ModuleMetadata
Return Nothing
End Function

''' <summary>
''' 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.
''' </summary>
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
Loading

0 comments on commit 8a1bc25

Please sign in to comment.