in src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs [2928:3280]
private void AddNonTypeMembers(
MembersAndInitializersBuilder builder,
SyntaxList<MemberDeclarationSyntax> members,
DiagnosticBag diagnostics)
{
if (members.Count == 0)
{
return;
}
var firstMember = members[0];
var bodyBinder = this.GetBinder(firstMember);
ArrayBuilder<FieldOrPropertyInitializer> staticInitializers = null;
ArrayBuilder<FieldOrPropertyInitializer> instanceInitializers = null;
foreach (var m in members)
{
if (_lazyMembersAndInitializers != null)
{
// membersAndInitializers is already computed. no point to continue.
return;
}
bool reportMisplacedGlobalCode = !m.HasErrors;
switch (m.Kind())
{
case SyntaxKind.FieldDeclaration:
{
var fieldSyntax = (FieldDeclarationSyntax)m;
if (IsImplicitClass && reportMisplacedGlobalCode)
{
diagnostics.Add(ErrorCode.ERR_NamespaceUnexpected,
new SourceLocation(fieldSyntax.Declaration.Variables.First().Identifier));
}
bool modifierErrors;
var modifiers = SourceMemberFieldSymbol.MakeModifiers(this, fieldSyntax.Declaration.Variables[0].Identifier, fieldSyntax.Modifiers, diagnostics, out modifierErrors);
foreach (var variable in fieldSyntax.Declaration.Variables)
{
var fieldSymbol = (modifiers & DeclarationModifiers.Fixed) == 0
? new SourceMemberFieldSymbolFromDeclarator(this, variable, modifiers, modifierErrors, diagnostics)
: new SourceFixedFieldSymbol(this, variable, modifiers, modifierErrors, diagnostics);
builder.NonTypeNonIndexerMembers.Add(fieldSymbol);
if (IsScriptClass)
{
// also gather expression-declared variables from the bracketed argument lists and the initializers
ExpressionFieldFinder.FindExpressionVariables(builder.NonTypeNonIndexerMembers, variable, this,
DeclarationModifiers.Private | (modifiers & DeclarationModifiers.Static),
fieldSymbol);
}
if (variable.Initializer != null)
{
if (fieldSymbol.IsStatic)
{
AddInitializer(ref staticInitializers, ref builder.StaticSyntaxLength, fieldSymbol, variable.Initializer);
}
else
{
AddInitializer(ref instanceInitializers, ref builder.InstanceSyntaxLength, fieldSymbol, variable.Initializer);
}
}
}
}
break;
case SyntaxKind.MethodDeclaration:
{
var methodSyntax = (MethodDeclarationSyntax)m;
if (IsImplicitClass && reportMisplacedGlobalCode)
{
diagnostics.Add(ErrorCode.ERR_NamespaceUnexpected,
new SourceLocation(methodSyntax.Identifier));
}
var method = SourceOrdinaryMethodSymbol.CreateMethodSymbol(this, bodyBinder, methodSyntax, diagnostics);
builder.NonTypeNonIndexerMembers.Add(method);
}
break;
case SyntaxKind.ConstructorDeclaration:
{
var constructorSyntax = (ConstructorDeclarationSyntax)m;
if (IsImplicitClass && reportMisplacedGlobalCode)
{
diagnostics.Add(ErrorCode.ERR_NamespaceUnexpected,
new SourceLocation(constructorSyntax.Identifier));
}
var constructor = SourceConstructorSymbol.CreateConstructorSymbol(this, constructorSyntax, diagnostics);
builder.NonTypeNonIndexerMembers.Add(constructor);
}
break;
case SyntaxKind.DestructorDeclaration:
{
var destructorSyntax = (DestructorDeclarationSyntax)m;
if (IsImplicitClass && reportMisplacedGlobalCode)
{
diagnostics.Add(ErrorCode.ERR_NamespaceUnexpected,
new SourceLocation(destructorSyntax.Identifier));
}
// CONSIDER: if this doesn't (directly or indirectly) override object.Finalize, the
// runtime won't consider it a finalizer and it will not be marked as a destructor
// when it is loaded from metadata. Perhaps we should just treat it as an Ordinary
// method in such cases?
var destructor = new SourceDestructorSymbol(this, destructorSyntax, diagnostics);
builder.NonTypeNonIndexerMembers.Add(destructor);
}
break;
case SyntaxKind.PropertyDeclaration:
{
var propertySyntax = (PropertyDeclarationSyntax)m;
if (IsImplicitClass && reportMisplacedGlobalCode)
{
diagnostics.Add(ErrorCode.ERR_NamespaceUnexpected,
new SourceLocation(propertySyntax.Identifier));
}
var property = SourcePropertySymbol.Create(this, bodyBinder, propertySyntax, diagnostics);
builder.NonTypeNonIndexerMembers.Add(property);
AddAccessorIfAvailable(builder.NonTypeNonIndexerMembers, property.GetMethod, diagnostics);
AddAccessorIfAvailable(builder.NonTypeNonIndexerMembers, property.SetMethod, diagnostics);
FieldSymbol backingField = property.BackingField;
// TODO: can we leave this out of the member list?
// From the 10/12/11 design notes:
// In addition, we will change autoproperties to behavior in
// a similar manner and make the autoproperty fields private.
if ((object)backingField != null)
{
builder.NonTypeNonIndexerMembers.Add(backingField);
var initializer = propertySyntax.Initializer;
if (initializer != null)
{
if (IsScriptClass)
{
// also gather expression-declared variables from the initializer
ExpressionFieldFinder.FindExpressionVariables(builder.NonTypeNonIndexerMembers,
initializer,
this,
DeclarationModifiers.Private | (property.IsStatic ? DeclarationModifiers.Static : 0),
backingField);
}
if (property.IsStatic)
{
AddInitializer(ref staticInitializers, ref builder.StaticSyntaxLength, backingField, initializer);
}
else
{
AddInitializer(ref instanceInitializers, ref builder.InstanceSyntaxLength, backingField, initializer);
}
}
}
}
break;
case SyntaxKind.EventFieldDeclaration:
{
var eventFieldSyntax = (EventFieldDeclarationSyntax)m;
if (IsImplicitClass && reportMisplacedGlobalCode)
{
diagnostics.Add(
ErrorCode.ERR_NamespaceUnexpected,
new SourceLocation(eventFieldSyntax.Declaration.Variables.First().Identifier));
}
foreach (VariableDeclaratorSyntax declarator in eventFieldSyntax.Declaration.Variables)
{
SourceFieldLikeEventSymbol @event = new SourceFieldLikeEventSymbol(this, bodyBinder, eventFieldSyntax.Modifiers, declarator, diagnostics);
builder.NonTypeNonIndexerMembers.Add(@event);
FieldSymbol associatedField = @event.AssociatedField;
if (IsScriptClass)
{
// also gather expression-declared variables from the bracketed argument lists and the initializers
ExpressionFieldFinder.FindExpressionVariables(builder.NonTypeNonIndexerMembers, declarator, this,
DeclarationModifiers.Private | (@event.IsStatic ? DeclarationModifiers.Static : 0),
associatedField);
}
if ((object)associatedField != null)
{
// NOTE: specifically don't add the associated field to the members list
// (regard it as an implementation detail).
if (declarator.Initializer != null)
{
if (associatedField.IsStatic)
{
AddInitializer(ref staticInitializers, ref builder.StaticSyntaxLength, associatedField, declarator.Initializer);
}
else
{
AddInitializer(ref instanceInitializers, ref builder.InstanceSyntaxLength, associatedField, declarator.Initializer);
}
}
}
Debug.Assert((object)@event.AddMethod != null);
Debug.Assert((object)@event.RemoveMethod != null);
AddAccessorIfAvailable(builder.NonTypeNonIndexerMembers, @event.AddMethod, diagnostics);
AddAccessorIfAvailable(builder.NonTypeNonIndexerMembers, @event.RemoveMethod, diagnostics);
}
}
break;
case SyntaxKind.EventDeclaration:
{
var eventSyntax = (EventDeclarationSyntax)m;
if (IsImplicitClass && reportMisplacedGlobalCode)
{
diagnostics.Add(ErrorCode.ERR_NamespaceUnexpected,
new SourceLocation(eventSyntax.Identifier));
}
var @event = new SourceCustomEventSymbol(this, bodyBinder, eventSyntax, diagnostics);
builder.NonTypeNonIndexerMembers.Add(@event);
AddAccessorIfAvailable(builder.NonTypeNonIndexerMembers, @event.AddMethod, diagnostics);
AddAccessorIfAvailable(builder.NonTypeNonIndexerMembers, @event.RemoveMethod, diagnostics);
Debug.Assert((object)@event.AssociatedField == null);
}
break;
case SyntaxKind.IndexerDeclaration:
{
var indexerSyntax = (IndexerDeclarationSyntax)m;
if (IsImplicitClass && reportMisplacedGlobalCode)
{
diagnostics.Add(ErrorCode.ERR_NamespaceUnexpected,
new SourceLocation(indexerSyntax.ThisKeyword));
}
// We can't create the indexer symbol yet, because we don't know
// what name it will have after attribute binding (because of
// IndexerNameAttribute). Instead, we'll keep a (weak) reference
// to the syntax and bind it again after early attribute decoding.
builder.IndexerDeclarations.Add(indexerSyntax.GetReference());
}
break;
case SyntaxKind.ConversionOperatorDeclaration:
{
var conversionOperatorSyntax = (ConversionOperatorDeclarationSyntax)m;
if (IsImplicitClass && reportMisplacedGlobalCode)
{
diagnostics.Add(ErrorCode.ERR_NamespaceUnexpected,
new SourceLocation(conversionOperatorSyntax.OperatorKeyword));
}
var method = SourceUserDefinedConversionSymbol.CreateUserDefinedConversionSymbol
(this, conversionOperatorSyntax, diagnostics);
builder.NonTypeNonIndexerMembers.Add(method);
}
break;
case SyntaxKind.OperatorDeclaration:
{
var operatorSyntax = (OperatorDeclarationSyntax)m;
if (IsImplicitClass && reportMisplacedGlobalCode)
{
diagnostics.Add(ErrorCode.ERR_NamespaceUnexpected,
new SourceLocation(operatorSyntax.OperatorKeyword));
}
var method = SourceUserDefinedOperatorSymbol.CreateUserDefinedOperatorSymbol
(this, operatorSyntax, diagnostics);
builder.NonTypeNonIndexerMembers.Add(method);
}
break;
case SyntaxKind.GlobalStatement:
{
var globalStatement = ((GlobalStatementSyntax)m).Statement;
if (IsScriptClass)
{
var innerStatement = globalStatement;
// drill into any LabeledStatements
while (innerStatement.Kind() == SyntaxKind.LabeledStatement)
{
innerStatement = ((LabeledStatementSyntax)innerStatement).Statement;
}
switch (innerStatement.Kind())
{
case SyntaxKind.LocalDeclarationStatement:
// We shouldn't reach this place, but field declarations preceded with a label end up here.
// This is tracked by https://github.com/dotnet/roslyn/issues/13712. Let's do our best for now.
var decl = (LocalDeclarationStatementSyntax)innerStatement;
foreach (var vdecl in decl.Declaration.Variables)
{
// also gather expression-declared variables from the bracketed argument lists and the initializers
ExpressionFieldFinder.FindExpressionVariables(builder.NonTypeNonIndexerMembers, vdecl, this, DeclarationModifiers.Private,
containingFieldOpt: null);
}
break;
case SyntaxKind.ExpressionStatement:
case SyntaxKind.IfStatement:
case SyntaxKind.YieldReturnStatement:
case SyntaxKind.ReturnStatement:
case SyntaxKind.ThrowStatement:
case SyntaxKind.SwitchStatement:
case SyntaxKind.LockStatement:
ExpressionFieldFinder.FindExpressionVariables(builder.NonTypeNonIndexerMembers,
innerStatement,
this,
DeclarationModifiers.Private,
containingFieldOpt: null);
break;
default:
// no other statement introduces variables into the enclosing scope
break;
}
AddInitializer(ref instanceInitializers, ref builder.InstanceSyntaxLength, null, globalStatement);
}
else if (reportMisplacedGlobalCode)
{
diagnostics.Add(ErrorCode.ERR_GlobalStatement, new SourceLocation(globalStatement));
}
}
break;
default:
Debug.Assert(
SyntaxFacts.IsTypeDeclaration(m.Kind()) ||
m.Kind() == SyntaxKind.NamespaceDeclaration ||
m.Kind() == SyntaxKind.IncompleteMember);
break;
}
}
AddInitializers(builder.InstanceInitializers, instanceInitializers);
AddInitializers(builder.StaticInitializers, staticInitializers);
}