diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Initializers.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Initializers.cs
index f238992e37eb2ffab4e884802b8b79afd1298571..f766745065930ed374eb476ee984661be6319311 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Initializers.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Initializers.cs
@@ -97,7 +97,7 @@ internal struct ProcessedFieldInitializers
foreach (FieldOrPropertyInitializer initializer in siblingInitializers)
{
- FieldSymbol fieldSymbol = initializer.Field;
+ FieldSymbol fieldSymbol = initializer.FieldOpt;
Debug.Assert((object)fieldSymbol != null);
// A constant field of type decimal needs a field initializer, so
@@ -156,7 +156,7 @@ internal struct ProcessedFieldInitializers
for (int j = 0; j < siblingInitializers.Length; j++)
{
var initializer = siblingInitializers[j];
- var fieldSymbol = initializer.Field;
+ var fieldSymbol = initializer.FieldOpt;
if ((object)fieldSymbol != null && fieldSymbol.IsConst)
{
diff --git a/src/Compilers/CSharp/Portable/Symbols/FieldOrPropertyInitializer.cs b/src/Compilers/CSharp/Portable/Symbols/FieldOrPropertyInitializer.cs
index 92d80709f0c6e35adee95253ffe54894130b1cb2..efc56a5c93633652d67daf13689dd19201ae75ea 100644
--- a/src/Compilers/CSharp/Portable/Symbols/FieldOrPropertyInitializer.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/FieldOrPropertyInitializer.cs
@@ -11,20 +11,21 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols
internal struct FieldOrPropertyInitializer
{
///
- /// The field being initialized (possibly a backing field of a property), or null if this is a global statement.
+ /// The field being initialized (possibly a backing field of a property), or null if this is a top-level statement in script code.
///
- internal readonly FieldSymbol Field;
+ internal readonly FieldSymbol FieldOpt;
///
- /// A reference to or .
+ /// A reference to or top-level in script code.
///
internal readonly SyntaxReference Syntax;
- public FieldOrPropertyInitializer(FieldSymbol field, SyntaxReference syntax)
+ public FieldOrPropertyInitializer(FieldSymbol fieldOpt, SyntaxNode syntax)
{
- Debug.Assert(((object)field != null) || (syntax != null));
- Field = field;
- Syntax = syntax;
+ Debug.Assert(syntax.IsKind(SyntaxKind.EqualsValueClause) && fieldOpt != null || syntax is StatementSyntax);
+
+ FieldOpt = fieldOpt;
+ Syntax = syntax.GetReference();
}
}
}
diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs
index 19a084d62fbf937930cf97a47a893d8c47a7fffc..93ec94f3074d31a4bf3916cca242cf647b5fc584 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs
@@ -2110,10 +2110,10 @@ private static void AddNestedTypesToDictionary(Dictionary NonTypeNonIndexerMembers = ArrayBuilder.GetInstance();
- public ArrayBuilder> StaticInitializers = ArrayBuilder>.GetInstance();
- public ArrayBuilder> InstanceInitializers = ArrayBuilder>.GetInstance();
- public ArrayBuilder IndexerDeclarations = ArrayBuilder.GetInstance();
+ public readonly ArrayBuilder NonTypeNonIndexerMembers = ArrayBuilder.GetInstance();
+ public readonly ArrayBuilder> StaticInitializers = ArrayBuilder>.GetInstance();
+ public readonly ArrayBuilder> InstanceInitializers = ArrayBuilder>.GetInstance();
+ public readonly ArrayBuilder IndexerDeclarations = ArrayBuilder.GetInstance();
public MembersAndInitializers ToReadOnlyAndFree()
{
@@ -2477,8 +2477,6 @@ private static bool ParametersMatchEventAccessor(EventSymbol eventSymbol, Immuta
private void AddEnumMembers(MembersAndInitializersBuilder result, EnumDeclarationSyntax syntax, DiagnosticBag diagnostics)
{
- ArrayBuilder initializers = null;
-
// The previous enum constant used to calculate subsequent
// implicit enum constants. (This is the most recent explicit
// enum constant or the first implicit constant if no explicit values.)
@@ -2487,71 +2485,55 @@ private void AddEnumMembers(MembersAndInitializersBuilder result, EnumDeclaratio
// Offset from "otherSymbol".
int otherSymbolOffset = 0;
- foreach (var m in syntax.Members)
+ foreach (var member in syntax.Members)
{
- switch (m.Kind())
- {
- case SyntaxKind.EnumMemberDeclaration:
- {
- SourceEnumConstantSymbol symbol;
- var valueOpt = m.EqualsValue;
-
- if (valueOpt != null)
- {
- symbol = SourceEnumConstantSymbol.CreateExplicitValuedConstant(this, m, diagnostics);
- }
- else
- {
- symbol = SourceEnumConstantSymbol.CreateImplicitValuedConstant(this, m, otherSymbol, otherSymbolOffset, diagnostics);
- }
+ SourceEnumConstantSymbol symbol;
+ var valueOpt = member.EqualsValue;
- result.NonTypeNonIndexerMembers.Add(symbol);
-
- if ((valueOpt != null) || ((object)otherSymbol == null))
- {
- otherSymbol = symbol;
- otherSymbolOffset = 1;
- }
- else
- {
- otherSymbolOffset++;
- }
+ if (valueOpt != null)
+ {
+ symbol = SourceEnumConstantSymbol.CreateExplicitValuedConstant(this, member, diagnostics);
+ }
+ else
+ {
+ symbol = SourceEnumConstantSymbol.CreateImplicitValuedConstant(this, member, otherSymbol, otherSymbolOffset, diagnostics);
+ }
- // The symbol is added to the set of initializers, even for
- // implicit values since it's necessary to generate constants
- // for each member to catch errors such as overflow.
- AddInitializer(ref initializers, symbol, valueOpt);
- }
- break;
+ result.NonTypeNonIndexerMembers.Add(symbol);
- default:
- throw ExceptionUtilities.UnexpectedValue(m.Kind());
+ if (valueOpt != null || (object)otherSymbol == null)
+ {
+ otherSymbol = symbol;
+ otherSymbolOffset = 1;
+ }
+ else
+ {
+ otherSymbolOffset++;
}
}
-
- AddInitializers(ref result.StaticInitializers, initializers);
}
- private static void AddInitializer(ref ArrayBuilder initializers, FieldSymbol field, CSharpSyntaxNode node)
+ private static void AddInitializer(ref ArrayBuilder initializers, FieldSymbol fieldOpt, CSharpSyntaxNode node)
{
if (initializers == null)
{
initializers = new ArrayBuilder();
}
+ else
+ {
+ // initializers should be added in syntax order:
+ Debug.Assert(node.SyntaxTree == initializers.Last().Syntax.SyntaxTree);
+ Debug.Assert(node.SpanStart > initializers.Last().Syntax.GetSyntax().SpanStart);
+ }
- initializers.Add(new FieldOrPropertyInitializer(field, node.GetReferenceOrNull()));
+ initializers.Add(new FieldOrPropertyInitializer(fieldOpt, node));
}
- private static void AddInitializers(ref ArrayBuilder> allInitializers, ArrayBuilder siblings)
+ private static void AddInitializers(ArrayBuilder> allInitializers, ArrayBuilder siblingsOpt)
{
- if (siblings != null)
+ if (siblingsOpt != null)
{
- if (allInitializers == null)
- {
- allInitializers = new ArrayBuilder>();
- }
-
- allInitializers.Add(siblings.ToImmutableAndFree());
+ allInitializers.Add(siblingsOpt.ToImmutableAndFree());
}
}
@@ -2647,11 +2629,11 @@ private void CheckForStructBadInitializers(MembersAndInitializersBuilder builder
Debug.Assert(TypeKind == TypeKind.Struct);
foreach (var initializers in builder.InstanceInitializers)
- {
+ {
foreach (FieldOrPropertyInitializer initializer in initializers)
- {
- // '{0}': cannot have instance field initializers in structs
- diagnostics.Add(ErrorCode.ERR_FieldInitializerInStruct, (initializer.Field.AssociatedSymbol ?? initializer.Field).Locations[0], this);
+ {
+ // '{0}': cannot have instance field initializers in structs
+ diagnostics.Add(ErrorCode.ERR_FieldInitializerInStruct, (initializer.FieldOpt.AssociatedSymbol ?? initializer.FieldOpt).Locations[0], this);
}
}
}
@@ -2677,6 +2659,7 @@ private void AddSynthesizedConstructorsIfNecessary(ArrayBuilder members,
hasInstanceConstructor = true;
hasParameterlessInstanceConstructor = hasParameterlessInstanceConstructor || method.ParameterCount == 0;
break;
+
case MethodKind.StaticConstructor:
hasStaticConstructor = true;
break;
@@ -2690,27 +2673,11 @@ private void AddSynthesizedConstructorsIfNecessary(ArrayBuilder members,
}
}
- var hasStaticInitializer = false;
- if (staticInitializers != null)
- {
- foreach (var siblings in staticInitializers)
- {
- foreach (var initializer in siblings)
- {
- // constants don't count, since they do not exist as fields at runtime
- // NOTE: even for decimal constants (which require field initializers),
- // we do not create .cctor here since a static constructor implicitly created for a decimal
- // should not appear in the list returned by public API like GetMembers().
- if (!initializer.Field.IsConst)
- {
- hasStaticInitializer = true;
- goto OUTER;
- }
- }
- }
- }
-
- OUTER:
+ // constants don't count, since they do not exist as fields at runtime
+ // NOTE: even for decimal constants (which require field initializers),
+ // we do not create .cctor here since a static constructor implicitly created for a decimal
+ // should not appear in the list returned by public API like GetMembers().
+ var hasStaticInitializer = HasNonConstantInitializer(staticInitializers);
// NOTE: Per section 11.3.8 of the spec, "every struct implicitly has a parameterless instance constructor".
// We won't insert a parameterless constructor for a struct if there already is one.
@@ -2735,6 +2702,25 @@ private void AddSynthesizedConstructorsIfNecessary(ArrayBuilder members,
}
}
+ private static bool HasNonConstantInitializer(ArrayBuilder> initializers)
+ {
+ if (initializers != null)
+ {
+ foreach (var siblings in initializers)
+ {
+ foreach (var initializer in siblings)
+ {
+ if (!initializer.FieldOpt.IsConst)
+ {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
private void AddNonTypeMembers(
MembersAndInitializersBuilder result,
SyntaxList members,
@@ -3014,8 +3000,8 @@ private void AddSynthesizedConstructorsIfNecessary(ArrayBuilder members,
}
}
- AddInitializers(ref result.InstanceInitializers, instanceInitializers);
- AddInitializers(ref result.StaticInitializers, staticInitializers);
+ AddInitializers(result.InstanceInitializers, instanceInitializers);
+ AddInitializers(result.StaticInitializers, staticInitializers);
}
private static bool IsGlobalCodeAllowed(CSharpSyntaxNode parent)
diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs
index 7ec50dea5afc824a150939f52869fe7340d94c0c..d08feb917c159f32fc3c552fccbeddba32b92808 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs
@@ -990,7 +990,7 @@ internal override void PostDecodeWellKnownAttributes(ImmutableArray,
''' ,
''' ,
- ''' (top-level statement), or
- ''' Nothing (enums field with an implicit value).
+ ''' (top-level statement).
'''
Public ReadOnly Syntax As SyntaxReference
@@ -29,7 +28,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
'''
''' The initializer syntax for the statement.
Public Sub New(syntax As SyntaxReference)
- Debug.Assert(syntax IsNot Nothing)
+ Debug.Assert(TypeOf syntax.GetSyntax() Is StatementSyntax)
Me.Syntax = syntax
End Sub
@@ -40,10 +39,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
''' The initializer syntax for the field.
Public Sub New(field As FieldSymbol, syntax As SyntaxReference)
Debug.Assert(field IsNot Nothing)
- Debug.Assert(syntax Is Nothing OrElse
- syntax.GetVisualBasicSyntax.Kind = SyntaxKind.AsNewClause OrElse
- syntax.GetVisualBasicSyntax.Kind = SyntaxKind.EqualsValue OrElse
- syntax.GetVisualBasicSyntax.Kind = SyntaxKind.ModifiedIdentifier)
+ Debug.Assert(syntax.GetSyntax().IsKind(SyntaxKind.AsNewClause) OrElse
+ syntax.GetSyntax().IsKind(SyntaxKind.EqualsValue) OrElse
+ syntax.GetSyntax().IsKind(SyntaxKind.ModifiedIdentifier))
Me.FieldsOrProperty = ImmutableArray.Create(Of Symbol)(field)
Me.Syntax = syntax
@@ -54,7 +52,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
'''
Public Sub New(fieldsOrProperties As ImmutableArray(Of Symbol), syntax As SyntaxReference)
Debug.Assert(Not fieldsOrProperties.IsEmpty)
- Debug.Assert(syntax.GetSyntax.Kind = SyntaxKind.AsNewClause OrElse syntax.GetSyntax.Kind = SyntaxKind.EqualsValue)
+ Debug.Assert(syntax.GetSyntax().IsKind(SyntaxKind.AsNewClause) OrElse syntax.GetSyntax().IsKind(SyntaxKind.EqualsValue))
Me.FieldsOrProperty = fieldsOrProperties
Me.Syntax = syntax
@@ -68,7 +66,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Public Sub New([property] As PropertySymbol, syntax As SyntaxReference)
Debug.Assert([property] IsNot Nothing)
Debug.Assert(syntax IsNot Nothing)
- Debug.Assert(syntax.GetSyntax.Kind = SyntaxKind.AsNewClause OrElse syntax.GetSyntax.Kind = SyntaxKind.EqualsValue)
+ Debug.Assert(syntax.GetSyntax().IsKind(SyntaxKind.AsNewClause) OrElse syntax.GetSyntax().IsKind(SyntaxKind.EqualsValue))
Me.FieldsOrProperty = ImmutableArray.Create(Of Symbol)([property])
Me.Syntax = syntax
diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceMemberContainerTypeSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceMemberContainerTypeSymbol.vb
index d194a588625461ca214d7e73446b22118656840a..9dc7752bb44d10e4c16e547bf8d8df4534000e16 100644
--- a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceMemberContainerTypeSymbol.vb
+++ b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceMemberContainerTypeSymbol.vb
@@ -1555,13 +1555,17 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
''' Adds a field initializer for the field to list of field initializers
'''
''' All initializers.
- ''' The field initializer to add to the list of initializers.
- Friend Shared Sub AddInitializer(ByRef initializers As ArrayBuilder(Of FieldOrPropertyInitializer), fieldInitializer As FieldOrPropertyInitializer)
+ ''' The field initializer to add to the list of initializers.
+ Friend Shared Sub AddInitializer(ByRef initializers As ArrayBuilder(Of FieldOrPropertyInitializer), initializer As FieldOrPropertyInitializer)
If initializers Is Nothing Then
initializers = ArrayBuilder(Of FieldOrPropertyInitializer).GetInstance()
+ Else
+ ' initializers should be added in syntax order
+ Debug.Assert(initializer.Syntax.SyntaxTree Is initializers.Last().Syntax.SyntaxTree)
+ Debug.Assert(initializer.Syntax.Span.Start > initializers.Last().Syntax.Span.Start)
End If
- initializers.Add(fieldInitializer)
+ initializers.Add(initializer)
End Sub
'''
diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceNamedTypeSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceNamedTypeSymbol.vb
index 72b07c7325c97ab3a564683cb5fa6f2c36797510..8e8c6ca95e9951e957593963ad25e2cb30275c52 100644
--- a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceNamedTypeSymbol.vb
+++ b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceNamedTypeSymbol.vb
@@ -256,7 +256,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
ElseIf TypeKind = TypeKind.Enum Then
Dim enumBlock = DirectCast(node, EnumBlockSyntax)
- AddEnumMembers(enumBlock, binder, diagBag, members, staticInitializers)
+ AddEnumMembers(enumBlock, binder, diagBag, members)
Else
Dim typeBlock = DirectCast(node, TypeBlockSyntax)
For Each memberSyntax In typeBlock.Members
@@ -682,10 +682,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
End Sub
Private Sub AddEnumMembers(syntax As EnumBlockSyntax,
- bodyBinder As Binder,
- diagnostics As DiagnosticBag,
- members As MembersAndInitializersBuilder,
- ByRef staticInitializers As ArrayBuilder(Of FieldOrPropertyInitializer))
+ bodyBinder As Binder,
+ diagnostics As DiagnosticBag,
+ members As MembersAndInitializersBuilder)
Dim valField = New SynthesizedFieldSymbol(
Me,
@@ -705,43 +704,35 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
' Offset from "otherSymbol".
Dim otherSymbolOffset As Integer = 0
- Dim memberList = syntax.Members
-
- If memberList.Count = 0 Then
+ If syntax.Members.Count = 0 Then
Binder.ReportDiagnostic(diagnostics, syntax.EnumStatement.Identifier, ERRID.ERR_BadEmptyEnum1, syntax.EnumStatement.Identifier.ValueText)
- Else
- For Each member In syntax.Members
- If member.Kind <> SyntaxKind.EnumMemberDeclaration Then
- ' skip invalid syntax
- Continue For
- End If
-
- Dim declaration = DirectCast(member, EnumMemberDeclarationSyntax)
- Dim symbol As SourceEnumConstantSymbol
- Dim valueOpt = declaration.Initializer
- If valueOpt IsNot Nothing Then
- symbol = SourceEnumConstantSymbol.CreateExplicitValuedConstant(Me, bodyBinder, declaration, diagnostics)
- Else
- symbol = SourceEnumConstantSymbol.CreateImplicitValuedConstant(Me, bodyBinder, declaration, otherSymbol, otherSymbolOffset, diagnostics)
- End If
+ Return
+ End If
- If (valueOpt IsNot Nothing) OrElse (otherSymbol Is Nothing) Then
- otherSymbol = symbol
- otherSymbolOffset = 1
- Else
- otherSymbolOffset = otherSymbolOffset + 1
- End If
+ For Each member In syntax.Members
+ If member.Kind <> SyntaxKind.EnumMemberDeclaration Then
+ ' skip invalid syntax
+ Continue For
+ End If
- AddMember(symbol, bodyBinder, members, omitDiagnostics:=False)
+ Dim declaration = DirectCast(member, EnumMemberDeclarationSyntax)
+ Dim symbol As SourceEnumConstantSymbol
+ Dim valueOpt = declaration.Initializer
+ If valueOpt IsNot Nothing Then
+ symbol = SourceEnumConstantSymbol.CreateExplicitValuedConstant(Me, bodyBinder, declaration, diagnostics)
+ Else
+ symbol = SourceEnumConstantSymbol.CreateImplicitValuedConstant(Me, bodyBinder, declaration, otherSymbol, otherSymbolOffset, diagnostics)
+ End If
- Dim initializer = New FieldOrPropertyInitializer(symbol, If(valueOpt IsNot Nothing, bodyBinder.GetSyntaxReference(valueOpt), Nothing))
+ If (valueOpt IsNot Nothing) OrElse (otherSymbol Is Nothing) Then
+ otherSymbol = symbol
+ otherSymbolOffset = 1
+ Else
+ otherSymbolOffset = otherSymbolOffset + 1
+ End If
- ' The symbol is added to the set of initializers, even for
- ' implicit values since it's necessary to generate constants
- ' for each member to catch errors such as overflow.
- SourceNamedTypeSymbol.AddInitializer(staticInitializers, initializer)
- Next
- End If
+ AddMember(symbol, bodyBinder, members, omitDiagnostics:=False)
+ Next
End Sub
#End Region