Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Required Members for VB #66084

Merged
merged 22 commits into from May 10, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
36 changes: 34 additions & 2 deletions src/Compilers/Test/Core/CommonTestBase.cs
Expand Up @@ -14,6 +14,7 @@
using System.Text;
using System.Xml.Linq;
using Microsoft.CodeAnalysis.CodeGen;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.Operations;
Expand Down Expand Up @@ -302,9 +303,33 @@ internal static MetadataReference GetILModuleReference(string ilSource, bool pre
IEnumerable<MetadataReference> referencedAssemblies = null,
IEnumerable<Compilation> referencedCompilations = null)
{
return CreateCSharpCompilation(assemblyName, assemblyIdentity: null, code, parseOptions, compilationOptions, referencedAssemblies, referencedCompilations);
}

protected CSharp.CSharpCompilation CreateCSharpCompilation(
AssemblyIdentity assemblyIdentity,
string code,
CSharp.CSharpParseOptions parseOptions = null,
CSharp.CSharpCompilationOptions compilationOptions = null,
IEnumerable<MetadataReference> referencedAssemblies = null,
IEnumerable<Compilation> referencedCompilations = null)
{
return CreateCSharpCompilation(assemblyName: null, assemblyIdentity, code, parseOptions, compilationOptions, referencedAssemblies, referencedCompilations);
}

private CSharp.CSharpCompilation CreateCSharpCompilation(
string assemblyName,
AssemblyIdentity assemblyIdentity,
string code,
CSharp.CSharpParseOptions parseOptions = null,
CSharp.CSharpCompilationOptions compilationOptions = null,
IEnumerable<MetadataReference> referencedAssemblies = null,
IEnumerable<Compilation> referencedCompilations = null)
{
Debug.Assert(assemblyName == null || assemblyIdentity == null || assemblyIdentity.Name == assemblyName);
if (assemblyName == null)
{
assemblyName = GetUniqueName();
assemblyName = assemblyIdentity?.Name ?? GetUniqueName();
}

if (parseOptions == null)
Expand Down Expand Up @@ -336,7 +361,14 @@ internal static MetadataReference GetILModuleReference(string ilSource, bool pre

var tree = CSharp.SyntaxFactory.ParseSyntaxTree(SourceText.From(code, encoding: null, SourceHashAlgorithms.Default), options: parseOptions);

return CSharp.CSharpCompilation.Create(assemblyName, new[] { tree }, references, compilationOptions);
var compilation = CSharp.CSharpCompilation.Create(assemblyName, new[] { tree }, references, compilationOptions);

if (assemblyIdentity != null)
{
((SourceAssemblySymbol)compilation.Assembly).lazyAssemblyIdentity = assemblyIdentity;
}

return compilation;
}

protected VisualBasic.VisualBasicCompilation CreateVisualBasicCompilation(
Expand Down
Expand Up @@ -947,7 +947,7 @@ Friend Module CompilationUtils
actualLine = actualReader.ReadLine()
End While

Assert.Equal(expectedPooledBuilder.ToStringAndFree(), actualPooledBuilder.ToStringAndFree())
AssertEx.Equal(expectedPooledBuilder.ToStringAndFree(), actualPooledBuilder.ToStringAndFree())
End Sub

' There are certain cases where multiple distinct errors are
Expand Down
19 changes: 19 additions & 0 deletions src/Compilers/Test/Utilities/VisualBasic/MockSymbols.vb
Expand Up @@ -6,6 +6,7 @@ Imports System.Collections.Immutable
Imports System.Reflection
Imports System.Runtime.InteropServices
Imports System.Threading
Imports Microsoft.CodeAnalysis.Collections
333fred marked this conversation as resolved.
Show resolved Hide resolved
Imports Microsoft.CodeAnalysis.PooledObjects

Friend Interface IMockSymbol
Expand Down Expand Up @@ -378,6 +379,18 @@ Friend Class MockNamedTypeSymbol
Friend NotOverridable Overrides Function GetSynthesizedWithEventsOverrides() As IEnumerable(Of PropertySymbol)
Return SpecializedCollections.EmptyEnumerable(Of PropertySymbol)()
End Function

Friend Overrides ReadOnly Property AllRequiredMembers As ImmutableSegmentedDictionary(Of String, Symbol)
Get
Return ImmutableSegmentedDictionary(Of String, Symbol).Empty
End Get
End Property

Friend Overrides ReadOnly Property HasRequiredMembersError As Boolean
Get
Return False
End Get
End Property
End Class

Friend Class MockMethodSymbol
Expand Down Expand Up @@ -637,6 +650,12 @@ Friend Class MockMethodSymbol
Friend Overrides Function CalculateLocalSyntaxOffset(localPosition As Integer, localTree As SyntaxTree) As Integer
Throw ExceptionUtilities.Unreachable
End Function

Friend Overrides ReadOnly Property HasSetsRequiredMembers As Boolean
Get
Return False
End Get
End Property
End Class

Friend Class MockModuleSymbol
Expand Down
Expand Up @@ -347,6 +347,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End If
Next

CheckRequiredMembersInObjectInitializer(methodSym, boundNamedArguments, node.Name, diagnostics)

If Not errorsReported Then
' There should not be any used temporaries or copy back expressions because arguments must
' be constants and they cannot be passed byref.
Expand Down
Expand Up @@ -113,6 +113,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
' Emitter will just emit 'initobj' instead of constructor call instead

' create a simplified object creation expression
Dim initializerOpt As BoundObjectInitializerExpressionBase = BindObjectCollectionOrMemberInitializer(node,
type0,
asNewVariablePlaceholderOpt,
diagnostics)

CheckRequiredMembersInObjectInitializer(constructorSymbol, If(initializerOpt?.Initializers, ImmutableArray(Of BoundExpression).Empty), typeNode, diagnostics)

Return New BoundObjectCreationExpression(
node,
constructorSymbol,
Expand All @@ -123,10 +130,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
QualificationKind.QualifiedViaTypeName)),
arguments:=ImmutableArray(Of BoundExpression).Empty,
defaultArguments:=BitVector.Null,
BindObjectCollectionOrMemberInitializer(node,
type0,
asNewVariablePlaceholderOpt,
diagnostics),
initializerOpt,
type0)
End If

Expand Down Expand Up @@ -491,8 +495,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
children.ToImmutableAndFree(),
type0, hasErrors:=True)
Else
Dim constructorSymbol As MethodSymbol = DirectCast(methodResult.Candidate.UnderlyingSymbol, MethodSymbol)

CheckRequiredMembersInObjectInitializer(constructorSymbol, If(objectInitializerExpressionOpt?.Initializers, ImmutableArray(Of BoundExpression).Empty), typeNode, diagnostics)

resultExpression = New BoundObjectCreationExpression(node,
DirectCast(methodResult.Candidate.UnderlyingSymbol, MethodSymbol),
constructorSymbol,
constructorsGroup,
boundArguments,
argumentInfo.DefaultArguments,
Expand All @@ -508,6 +516,62 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return resultExpression
End Function

Private Shared Sub CheckRequiredMembersInObjectInitializer(
constructor As MethodSymbol,
initializers As ImmutableArray(Of BoundExpression),
creationSyntax As SyntaxNode,
diagnostics As BindingDiagnosticBag)

If constructor Is Nothing OrElse constructor.HasSetsRequiredMembers Then
333fred marked this conversation as resolved.
Show resolved Hide resolved
Return
End If

If constructor.ContainingType.HasRequiredMembersError Then
' A use-site diagnostic will be reported on the use, so we don't need to do any more checking here.
Return
End If

Dim requiredMembers = constructor.ContainingType.AllRequiredMembers

If requiredMembers.Count = 0 Then
Return
End If

Dim requiredMembersBuilder = requiredMembers.ToBuilder()

If Not initializers.IsDefaultOrEmpty Then
For Each initializer In initializers
Dim assignmentOperator = TryCast(initializer, BoundAssignmentOperator)
If assignmentOperator Is Nothing Then
Continue For
End If

Dim memberSymbol As Symbol = If(
DirectCast(TryCast(assignmentOperator.Left, BoundPropertyAccess)?.PropertySymbol, Symbol),
TryCast(assignmentOperator.Left, BoundFieldAccess)?.FieldSymbol)

If memberSymbol Is Nothing Then
333fred marked this conversation as resolved.
Show resolved Hide resolved
Continue For
End If

Dim requiredMember As Symbol = Nothing
If Not requiredMembersBuilder.TryGetValue(memberSymbol.Name, requiredMember) Then
Continue For
End If

If Not memberSymbol.Equals(requiredMember, TypeCompareKind.ConsiderEverything) Then
333fred marked this conversation as resolved.
Show resolved Hide resolved
Continue For
End If

requiredMembersBuilder.Remove(memberSymbol.Name)
Next
End If

For Each kvp In requiredMembersBuilder
diagnostics.Add(ERRID.ERR_RequiredMemberMustBeSet, creationSyntax.Location, kvp.Value)
Next
End Sub

Private Function BindNoPiaObjectCreationExpression(
node As SyntaxNode,
[interface] As TypeSymbol,
Expand Down
Expand Up @@ -1713,6 +1713,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Get
End Property

Public Overrides ReadOnly Property IsRequired As Boolean
Get
Return False
End Get
End Property

Private NotInheritable Class ReducedExtensionAccessorSymbol
Inherits MethodSymbol

Expand Down Expand Up @@ -1987,6 +1993,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Friend Overrides Function CalculateLocalSyntaxOffset(localPosition As Integer, localTree As SyntaxTree) As Integer
Throw ExceptionUtilities.Unreachable
End Function

Friend Overrides ReadOnly Property HasSetsRequiredMembers As Boolean
Get
Return False
End Get
End Property
End Class

Private NotInheritable Class ReducedAccessorParameterSymbol
Expand Down
4 changes: 4 additions & 0 deletions src/Compilers/VisualBasic/Portable/Errors/ErrorFacts.vb
Expand Up @@ -1355,6 +1355,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
ERRID.ERR_StdInOptionProvidedButConsoleInputIsNotRedirected,
ERRID.ERR_UnsupportedCompilerFeature,
ERRID.ERR_DoNotUseCompilerFeatureRequired,
ERRID.ERR_RequiredMemberMustBeSet,
ERRID.ERR_CannotInheritFromTypeWithRequiredMembers,
ERRID.ERR_RequiredMembersInvalid,
ERRID.ERR_NewConstraintCannotHaveRequiredMembers,
ERRID.ERR_NextAvailable,
ERRID.WRN_UseOfObsoleteSymbol2,
ERRID.WRN_InvalidOverrideDueToTupleNames2,
Expand Down
7 changes: 6 additions & 1 deletion src/Compilers/VisualBasic/Portable/Errors/Errors.vb
Expand Up @@ -1767,7 +1767,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
ERR_UnsupportedCompilerFeature = 37319
ERR_DoNotUseCompilerFeatureRequired = 37320

ERR_NextAvailable = 37321
ERR_RequiredMemberMustBeSet = 37321
ERR_CannotInheritFromTypeWithRequiredMembers = 37322
ERR_RequiredMembersInvalid = 37323
ERR_NewConstraintCannotHaveRequiredMembers = 37324

ERR_NextAvailable = 37325

'// WARNINGS BEGIN HERE
WRN_UseOfObsoleteSymbol2 = 40000
Expand Down
Expand Up @@ -321,5 +321,17 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Friend NotOverridable Overrides Function GetSynthesizedWithEventsOverrides() As IEnumerable(Of PropertySymbol)
Return SpecializedCollections.EmptyEnumerable(Of PropertySymbol)()
End Function

Friend NotOverridable Overrides ReadOnly Property AllRequiredMembers As ImmutableSegmentedDictionary(Of String, Symbol)
Get
Return ImmutableSegmentedDictionary(Of String, Symbol).Empty
End Get
End Property

Friend NotOverridable Overrides ReadOnly Property HasRequiredMembersError As Boolean
Get
Return False
End Get
End Property
End Class
End Namespace
Expand Up @@ -5,6 +5,7 @@
Imports System.Collections.Immutable
Imports System.Runtime.InteropServices
Imports System.Threading
Imports Microsoft.CodeAnalysis.Collections
333fred marked this conversation as resolved.
Show resolved Hide resolved

Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Partial Friend NotInheritable Class AnonymousTypeManager
Expand Down Expand Up @@ -328,7 +329,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Public NotOverridable Overrides Function GetHashCode() As Integer
Return Hash.Combine(Me.TypeDescriptor.GetHashCode(), TypeKind)
End Function
End Class

Friend NotOverridable Overrides ReadOnly Property AllRequiredMembers As ImmutableSegmentedDictionary(Of String, Symbol)
Get
Return ImmutableSegmentedDictionary(Of String, Symbol).Empty
End Get
End Property

Friend NotOverridable Overrides ReadOnly Property HasRequiredMembersError As Boolean
Get
Return False
End Get
End Property
End Class
End Class
End Namespace
Expand Up @@ -7,6 +7,7 @@ Imports System.Runtime.InteropServices
Imports System.Threading
Imports Microsoft.Cci
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.Collections
333fred marked this conversation as resolved.
Show resolved Hide resolved
Imports Microsoft.CodeAnalysis.Emit
Imports Microsoft.CodeAnalysis.Symbols

Expand Down Expand Up @@ -380,6 +381,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Friend NotOverridable Overrides Function GetSynthesizedWithEventsOverrides() As IEnumerable(Of PropertySymbol)
Return SpecializedCollections.EmptyEnumerable(Of PropertySymbol)()
End Function

Friend NotOverridable Overrides ReadOnly Property AllRequiredMembers As ImmutableSegmentedDictionary(Of String, Symbol)
Get
Return ImmutableSegmentedDictionary(Of String, Symbol).Empty
End Get
End Property

Friend NotOverridable Overrides ReadOnly Property HasRequiredMembersError As Boolean
Get
Return False
End Get
End Property
End Class

End Class
Expand Down
Expand Up @@ -217,6 +217,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Return False
End Get
End Property

Public Overrides ReadOnly Property IsRequired As Boolean
Get
Return False
End Get
End Property
End Class

End Class
Expand Down