diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
index 276a331f9a7b9..b26e85c09bb00 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
@@ -3777,9 +3777,8 @@ private static bool IsNegativeConstantForArraySize(BoundExpression expression)
///
///
/// Null for implicit,
- /// BaseConstructorInitializerSyntax.ArgumentList, or
- /// ThisConstructorInitializerSyntax.ArgumentList, or
- /// SimpleBaseTypeSyntax.ArgumentList for explicit.
+ /// , or
+ /// for explicit.
/// Constructor containing the initializer.
/// Accumulates errors (e.g. unable to find constructor to invoke).
/// A bound expression for the constructor initializer call.
@@ -3921,9 +3920,8 @@ private BoundExpression BindConstructorInitializerCore(
errorLocation = initializerSyntax.ThisOrBaseKeyword.GetLocation();
break;
- case SimpleBaseTypeSyntax baseWithArguments:
- Debug.Assert(baseWithArguments.Parent?.Parent is RecordDeclarationSyntax recordDecl && recordDecl.BaseList.Types.FirstOrDefault() == baseWithArguments);
- nonNullSyntax = initializerArgumentListOpt;
+ case PrimaryConstructorBaseTypeSyntax baseWithArguments:
+ nonNullSyntax = baseWithArguments;
errorLocation = initializerArgumentListOpt.GetLocation();
break;
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
index be2802ac4751e..ea2cf793cc199 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
@@ -3322,7 +3322,7 @@ private BoundNode BindRecordConstructorBody(RecordDeclarationSyntax recordDecl,
Debug.Assert(bodyBinder != null);
BoundExpressionStatement initializer = null;
- if (recordDecl.BaseWithArguments is SimpleBaseTypeSyntax baseWithArguments)
+ if (recordDecl.PrimaryConstructorBaseType is PrimaryConstructorBaseTypeSyntax baseWithArguments)
{
initializer = bodyBinder.BindConstructorInitializer(baseWithArguments, diagnostics);
}
@@ -3334,10 +3334,8 @@ private BoundNode BindRecordConstructorBody(RecordDeclarationSyntax recordDecl,
expressionBody: null);
}
- internal BoundExpressionStatement BindConstructorInitializer(SimpleBaseTypeSyntax initializer, DiagnosticBag diagnostics)
+ internal virtual BoundExpressionStatement BindConstructorInitializer(PrimaryConstructorBaseTypeSyntax initializer, DiagnosticBag diagnostics)
{
- Debug.Assert(initializer.Parent?.Parent is RecordDeclarationSyntax recordDecl && recordDecl.ParameterList is object && recordDecl.BaseWithArguments == initializer);
-
BoundExpression initializerInvocation = GetBinder(initializer).BindConstructorInitializer(initializer.ArgumentList, (MethodSymbol)this.ContainingMember(), diagnostics);
var constructorInitializer = new BoundExpressionStatement(initializer, initializerInvocation);
Debug.Assert(initializerInvocation.HasAnyErrors || constructorInitializer.IsConstructorInitializer(), "Please keep this bound node in sync with BoundNodeExtensions.IsConstructorInitializer.");
diff --git a/src/Compilers/CSharp/Portable/Binder/ExpressionVariableFinder.cs b/src/Compilers/CSharp/Portable/Binder/ExpressionVariableFinder.cs
index 48bd938480ade..a2a2eb2767d3b 100644
--- a/src/Compilers/CSharp/Portable/Binder/ExpressionVariableFinder.cs
+++ b/src/Compilers/CSharp/Portable/Binder/ExpressionVariableFinder.cs
@@ -49,7 +49,7 @@ protected void FindExpressionVariables(
case SyntaxKind.GotoCaseStatement:
break;
case SyntaxKind.ArgumentList:
- Debug.Assert(node.Parent is ConstructorInitializerSyntax);
+ Debug.Assert(node.Parent is ConstructorInitializerSyntax || node.Parent is PrimaryConstructorBaseTypeSyntax);
break;
case SyntaxKind.RecordDeclaration:
Debug.Assert(((RecordDeclarationSyntax)node).ParameterList is object);
@@ -397,7 +397,7 @@ public override void VisitRecordDeclaration(RecordDeclarationSyntax node)
{
Debug.Assert(node.ParameterList is object);
- if (node.BaseWithArguments is SimpleBaseTypeSyntax baseWithArguments)
+ if (node.PrimaryConstructorBaseType is PrimaryConstructorBaseTypeSyntax baseWithArguments)
{
VisitNodeToBind(baseWithArguments);
}
diff --git a/src/Compilers/CSharp/Portable/Binder/LocalBinderFactory.cs b/src/Compilers/CSharp/Portable/Binder/LocalBinderFactory.cs
index ef27e8dcdd1cf..7a025be2810c6 100644
--- a/src/Compilers/CSharp/Portable/Binder/LocalBinderFactory.cs
+++ b/src/Compilers/CSharp/Portable/Binder/LocalBinderFactory.cs
@@ -162,13 +162,14 @@ public override void VisitRecordDeclaration(RecordDeclarationSyntax node)
Binder enclosing = new ExpressionVariableBinder(node, _enclosing);
AddToMap(node, enclosing);
+ Visit(node.PrimaryConstructorBaseType, enclosing);
+ }
- if (node.BaseWithArguments is SimpleBaseTypeSyntax baseWithArguments)
- {
- enclosing = enclosing.WithAdditionalFlags(BinderFlags.ConstructorInitializer);
- AddToMap(baseWithArguments, enclosing);
- Visit(baseWithArguments.ArgumentList, enclosing);
- }
+ public override void VisitPrimaryConstructorBaseType(PrimaryConstructorBaseTypeSyntax node)
+ {
+ Binder enclosing = _enclosing.WithAdditionalFlags(BinderFlags.ConstructorInitializer);
+ AddToMap(node, enclosing);
+ VisitConstructorInitializerArgumentList(node, node.ArgumentList, enclosing);
}
public override void VisitDestructorDeclaration(DestructorDeclarationSyntax node)
@@ -317,16 +318,20 @@ public override void VisitConstructorInitializer(ConstructorInitializerSyntax no
{
var binder = _enclosing.WithAdditionalFlags(BinderFlags.ConstructorInitializer);
AddToMap(node, binder);
+ VisitConstructorInitializerArgumentList(node, node.ArgumentList, binder);
+ }
- if (node.ArgumentList != null)
+ private void VisitConstructorInitializerArgumentList(CSharpSyntaxNode node, ArgumentListSyntax argumentList, Binder binder)
+ {
+ if (argumentList != null)
{
if (_root == node)
{
- binder = new ExpressionVariableBinder(node.ArgumentList, binder);
- AddToMap(node.ArgumentList, binder);
+ binder = new ExpressionVariableBinder(argumentList, binder);
+ AddToMap(argumentList, binder);
}
- Visit(node.ArgumentList, binder);
+ Visit(argumentList, binder);
}
}
diff --git a/src/Compilers/CSharp/Portable/CSharpExtensions.cs b/src/Compilers/CSharp/Portable/CSharpExtensions.cs
index 1875ac2f36bf3..8e7998236412d 100644
--- a/src/Compilers/CSharp/Portable/CSharpExtensions.cs
+++ b/src/Compilers/CSharp/Portable/CSharpExtensions.cs
@@ -537,6 +537,22 @@ public static Conversion ClassifyConversion(this Compilation? compilation, IType
}
}
+ ///
+ /// Returns what symbol(s), if any, the given constructor initializer syntax bound to in the program.
+ ///
+ public static SymbolInfo GetSymbolInfo(this SemanticModel? semanticModel, PrimaryConstructorBaseTypeSyntax constructorInitializer, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ var csmodel = semanticModel as CSharpSemanticModel;
+ if (csmodel != null)
+ {
+ return csmodel.GetSymbolInfo(constructorInitializer, cancellationToken);
+ }
+ else
+ {
+ return SymbolInfo.None;
+ }
+ }
+
///
/// Returns what symbol(s), if any, the given attribute syntax bound to in the program.
///
@@ -643,6 +659,27 @@ public static SymbolInfo GetSpeculativeSymbolInfo(this SemanticModel? semanticMo
}
}
+ ///
+ /// Bind the constructor initializer in the context of the specified location and get semantic information
+ /// about symbols. This method is used to get semantic information about a constructor
+ /// initializer that did not actually appear in the source code.
+ ///
+ /// NOTE: This will only work in locations where there is already a constructor initializer.
+ /// .
+ ///
+ public static SymbolInfo GetSpeculativeSymbolInfo(this SemanticModel? semanticModel, int position, PrimaryConstructorBaseTypeSyntax constructorInitializer)
+ {
+ var csmodel = semanticModel as CSharpSemanticModel;
+ if (csmodel != null)
+ {
+ return csmodel.GetSpeculativeSymbolInfo(position, constructorInitializer);
+ }
+ else
+ {
+ return SymbolInfo.None;
+ }
+ }
+
///
/// Gets type information about a constructor initializer.
///
@@ -1178,6 +1215,27 @@ public static bool TryGetSpeculativeSemanticModel([NotNullWhen(true)] this Seman
}
}
+ ///
+ /// Get a SemanticModel object that is associated with a constructor initializer that did not appear in
+ /// this source code. This can be used to get detailed semantic information about sub-parts
+ /// of a constructor initializer that did not appear in source code.
+ ///
+ /// NOTE: This will only work in locations where there is already a constructor initializer.
+ ///
+ public static bool TryGetSpeculativeSemanticModel([NotNullWhen(true)] this SemanticModel? semanticModel, int position, PrimaryConstructorBaseTypeSyntax constructorInitializer, [NotNullWhen(true)] out SemanticModel? speculativeModel)
+ {
+ var csmodel = semanticModel as CSharpSemanticModel;
+ if (csmodel != null)
+ {
+ return csmodel.TryGetSpeculativeSemanticModel(position, constructorInitializer, out speculativeModel);
+ }
+ else
+ {
+ speculativeModel = null;
+ return false;
+ }
+ }
+
///
/// Get a SemanticModel object that is associated with an attribute that did not appear in
/// this source code. This can be used to get detailed semantic information about sub-parts
diff --git a/src/Compilers/CSharp/Portable/Compilation/AttributeSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/AttributeSemanticModel.cs
index cd1a135d60701..c5a400824172a 100644
--- a/src/Compilers/CSharp/Portable/Compilation/AttributeSemanticModel.cs
+++ b/src/Compilers/CSharp/Portable/Compilation/AttributeSemanticModel.cs
@@ -118,6 +118,12 @@ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticMode
return false;
}
+ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, PrimaryConstructorBaseTypeSyntax constructorInitializer, out SemanticModel speculativeModel)
+ {
+ speculativeModel = null;
+ return false;
+ }
+
internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, EqualsValueClauseSyntax initializer, out SemanticModel speculativeModel)
{
speculativeModel = null;
diff --git a/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs
index 41f8b3b4f4eb5..07fb552aeeb41 100644
--- a/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs
+++ b/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs
@@ -120,6 +120,7 @@ internal static bool CanGetSemanticInfo(CSharpSyntaxNode node, bool allowNamedAr
return
(node is ExpressionSyntax && (isSpeculative || allowNamedArgumentName || !SyntaxFacts.IsNamedArgumentName(node))) ||
(node is ConstructorInitializerSyntax) ||
+ (node is PrimaryConstructorBaseTypeSyntax) ||
(node is AttributeSyntax) ||
(node is CrefSyntax);
}
@@ -636,7 +637,6 @@ private static SymbolInfo GetSymbolInfoFromSymbolOrNone(ITypeSymbol type)
return SymbolInfo.None;
}
-
///
/// Returns what symbol(s), if any, the given constructor initializer syntax bound to in the program.
///
@@ -651,6 +651,20 @@ private static SymbolInfo GetSymbolInfoFromSymbolOrNone(ITypeSymbol type)
: SymbolInfo.None;
}
+ ///
+ /// Returns what symbol(s), if any, the given constructor initializer syntax bound to in the program.
+ ///
+ /// The syntax node to get semantic information for.
+ /// The cancellation token.
+ public SymbolInfo GetSymbolInfo(PrimaryConstructorBaseTypeSyntax constructorInitializer, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ CheckSyntaxNode(constructorInitializer);
+
+ return CanGetSemanticInfo(constructorInitializer)
+ ? GetSymbolInfoWorker(constructorInitializer, SymbolInfoOptions.DefaultOptions, cancellationToken)
+ : SymbolInfo.None;
+ }
+
///
/// Returns what symbol(s), if any, the given attribute syntax bound to in the program.
///
@@ -798,7 +812,82 @@ public SymbolInfo GetSpeculativeSymbolInfo(int position, ConstructorInitializerS
binder = new ExecutableCodeBinder(constructorInitializer, binder.ContainingMemberOrLambda, binder);
BoundExpressionStatement bnode = binder.BindConstructorInitializer(constructorInitializer, diagnostics);
- var binfo = memberModel.GetSymbolInfoForNode(SymbolInfoOptions.DefaultOptions, bnode.Expression, bnode.Expression, boundNodeForSyntacticParent: null, binderOpt: binder);
+ var binfo = GetSymbolInfoFromBoundConstructorInitializer(memberModel, binder, bnode);
+ diagnostics.Free();
+ return binfo;
+ }
+ else
+ {
+ return SymbolInfo.None;
+ }
+ }
+
+ private static SymbolInfo GetSymbolInfoFromBoundConstructorInitializer(MemberSemanticModel memberModel, Binder binder, BoundExpressionStatement bnode)
+ {
+ BoundExpression expression = bnode.Expression;
+
+ while (expression is BoundSequence sequence)
+ {
+ expression = sequence.Value;
+ }
+
+ return memberModel.GetSymbolInfoForNode(SymbolInfoOptions.DefaultOptions, expression, expression, boundNodeForSyntacticParent: null, binderOpt: binder);
+ }
+
+ ///
+ /// Bind the constructor initializer in the context of the specified location and get semantic information
+ /// about symbols. This method is used to get semantic information about a constructor
+ /// initializer that did not actually appear in the source code.
+ ///
+ /// NOTE: This will only work in locations where there is already a constructor initializer.
+ ///
+ /// A character position used to identify a declaration scope and accessibility. This
+ /// character position must be within the span of an existing constructor initializer.
+ ///
+ /// A syntax node that represents a parsed constructor initializer. This syntax node
+ /// need not and typically does not appear in the source code referred to SemanticModel instance.
+ /// The semantic information for the topmost node of the constructor initializer.
+ public SymbolInfo GetSpeculativeSymbolInfo(int position, PrimaryConstructorBaseTypeSyntax constructorInitializer)
+ {
+ Debug.Assert(CanGetSemanticInfo(constructorInitializer, isSpeculative: true));
+
+ position = CheckAndAdjustPosition(position);
+
+ if (constructorInitializer == null)
+ {
+ throw new ArgumentNullException(nameof(constructorInitializer));
+ }
+
+ // NOTE: since we're going to be depending on a MemberModel to do the binding for us,
+ // we need to find a constructor initializer in the tree of this semantic model.
+ // NOTE: This approach will not allow speculative binding of a constructor initializer
+ // on a constructor that didn't formerly have one.
+ // TODO: Should we support positions that are not in existing constructor initializers?
+ // If so, we will need to build up the context that would otherwise be built up by
+ // InitializerMemberModel.
+ var existingConstructorInitializer = this.Root.FindToken(position).Parent.AncestorsAndSelf().OfType().FirstOrDefault();
+
+ if (existingConstructorInitializer == null)
+ {
+ return SymbolInfo.None;
+ }
+
+ MemberSemanticModel memberModel = GetMemberModel(existingConstructorInitializer);
+
+ if (memberModel == null)
+ {
+ return SymbolInfo.None;
+ }
+
+ var argumentList = existingConstructorInitializer.ArgumentList;
+ var binder = memberModel.GetEnclosingBinder(LookupPosition.IsBetweenTokens(position, argumentList.OpenParenToken, argumentList.CloseParenToken) ? position : argumentList.OpenParenToken.SpanStart);
+ if (binder != null)
+ {
+ var diagnostics = DiagnosticBag.GetInstance();
+ binder = new ExecutableCodeBinder(constructorInitializer, binder.ContainingMemberOrLambda, binder);
+
+ BoundExpressionStatement bnode = binder.BindConstructorInitializer(constructorInitializer, diagnostics);
+ SymbolInfo binfo = GetSymbolInfoFromBoundConstructorInitializer(memberModel, binder, bnode);
diagnostics.Free();
return binfo;
}
@@ -1014,7 +1103,7 @@ public Conversion GetSpeculativeConversion(int position, ExpressionSyntax expres
}
///
- /// Gets a list of method or indexed property symbols for a syntax node.
+ /// Gets a list of method symbols for a syntax node.
///
/// The syntax node to get semantic information for.
/// The cancellation token.
@@ -2514,6 +2603,33 @@ public bool TryGetSpeculativeSemanticModel(int position, ConstructorInitializerS
internal abstract bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ConstructorInitializerSyntax constructorInitializer, out SemanticModel speculativeModel);
+ ///
+ /// Get a SemanticModel object that is associated with a constructor initializer that did not appear in
+ /// this source code. This can be used to get detailed semantic information about sub-parts
+ /// of a constructor initializer that did not appear in source code.
+ ///
+ /// NOTE: This will only work in locations where there is already a constructor initializer.
+ ///
+ /// A character position used to identify a declaration scope and accessibility. This
+ /// character position must be within the span of an existing constructor initializer.
+ ///
+ /// A syntax node that represents a parsed constructor initializer.
+ /// This node should not be present in the syntax tree associated with this object.
+ /// A SemanticModel object that can be used to inquire about the semantic
+ /// information associated with syntax nodes within .
+ /// Flag indicating whether a speculative semantic model was created.
+ /// Throws this exception if the node is contained any SyntaxTree in the current Compilation.
+ /// Throws this exception if is null.
+ /// Throws this exception if this model is a speculative semantic model, i.e. is true.
+ /// Chaining of speculative semantic model is not supported.
+ public bool TryGetSpeculativeSemanticModel(int position, PrimaryConstructorBaseTypeSyntax constructorInitializer, out SemanticModel speculativeModel)
+ {
+ CheckModelAndSyntaxNodeToSpeculate(constructorInitializer);
+ return TryGetSpeculativeSemanticModelCore((SyntaxTreeSemanticModel)this, position, constructorInitializer, out speculativeModel);
+ }
+
+ internal abstract bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, PrimaryConstructorBaseTypeSyntax constructorInitializer, out SemanticModel speculativeModel);
+
///
/// Get a SemanticModel object that is associated with a cref that did not appear in
/// this source code. This can be used to get detailed semantic information about sub-parts
@@ -4753,6 +4869,8 @@ private SymbolInfo GetSymbolInfoFromNode(SyntaxNode node, CancellationToken canc
return this.GetSymbolInfo(expression, cancellationToken);
case ConstructorInitializerSyntax initializer:
return this.GetSymbolInfo(initializer, cancellationToken);
+ case PrimaryConstructorBaseTypeSyntax initializer:
+ return this.GetSymbolInfo(initializer, cancellationToken);
case AttributeSyntax attribute:
return this.GetSymbolInfo(attribute, cancellationToken);
case CrefSyntax cref:
@@ -4820,6 +4938,8 @@ protected sealed override SymbolInfo GetSpeculativeSymbolInfoCore(int position,
return GetSpeculativeSymbolInfo(position, expression, bindingOption);
case ConstructorInitializerSyntax initializer:
return GetSpeculativeSymbolInfo(position, initializer);
+ case PrimaryConstructorBaseTypeSyntax initializer:
+ return GetSpeculativeSymbolInfo(position, initializer);
case AttributeSyntax attribute:
return GetSpeculativeSymbolInfo(position, attribute);
case CrefSyntax cref:
diff --git a/src/Compilers/CSharp/Portable/Compilation/InitializerSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/InitializerSemanticModel.cs
index bcaca17ced874..7ae4615fa0954 100644
--- a/src/Compilers/CSharp/Portable/Compilation/InitializerSemanticModel.cs
+++ b/src/Compilers/CSharp/Portable/Compilation/InitializerSemanticModel.cs
@@ -30,7 +30,7 @@ private InitializerSemanticModel(CSharpSyntaxNode syntax,
int speculatedPosition = 0) :
base(syntax, symbol, rootBinder, containingSemanticModelOpt, parentSemanticModelOpt, snapshotManagerOpt: null, parentRemappedSymbolsOpt, speculatedPosition)
{
- Debug.Assert(!(syntax is ConstructorInitializerSyntax));
+ Debug.Assert(!(syntax is ConstructorInitializerSyntax || syntax is PrimaryConstructorBaseTypeSyntax));
}
///
@@ -104,11 +104,6 @@ internal override BoundNode GetBoundRoot()
rootSyntax = ((EnumMemberDeclarationSyntax)rootSyntax).EqualsValue.Value;
break;
- case SyntaxKind.BaseConstructorInitializer:
- case SyntaxKind.ThisConstructorInitializer:
- case SyntaxKind.ArgumentList:
- break;
-
case SyntaxKind.PropertyDeclaration:
rootSyntax = ((PropertyDeclarationSyntax)rootSyntax).Initializer.Value;
break;
@@ -207,11 +202,6 @@ private bool IsBindableInitializer(CSharpSyntaxNode node)
return this.Root == node || /*enum or parameter initializer*/
this.Root == node.Parent /*field initializer*/;
- case SyntaxKind.BaseConstructorInitializer:
- case SyntaxKind.ThisConstructorInitializer:
- case SyntaxKind.ArgumentList:
- return this.Root == node;
-
default:
return false;
}
@@ -237,6 +227,12 @@ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticMode
return false;
}
+ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, PrimaryConstructorBaseTypeSyntax constructorInitializer, out SemanticModel speculativeModel)
+ {
+ speculativeModel = null;
+ return false;
+ }
+
internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ArrowExpressionClauseSyntax expressionBody, out SemanticModel speculativeModel)
{
speculativeModel = null;
diff --git a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.SpeculativeMemberSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.SpeculativeMemberSemanticModel.cs
index 197ac790a5366..9b41ade76912c 100644
--- a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.SpeculativeMemberSemanticModel.cs
+++ b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.SpeculativeMemberSemanticModel.cs
@@ -49,6 +49,11 @@ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticMode
throw ExceptionUtilities.Unreachable;
}
+ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, PrimaryConstructorBaseTypeSyntax constructorInitializer, out SemanticModel speculativeModel)
+ {
+ throw ExceptionUtilities.Unreachable;
+ }
+
internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, EqualsValueClauseSyntax initializer, out SemanticModel speculativeModel)
{
throw ExceptionUtilities.Unreachable;
diff --git a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs
index 6a2d25d132d91..233dc45f1f834 100644
--- a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs
+++ b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs
@@ -317,7 +317,7 @@ private static Binder GetEnclosingBinderInternalWithinRoot(SyntaxNode node, int
{
binder = rootBinder.GetBinder(current);
}
- else if (kind == SyntaxKind.ThisConstructorInitializer || kind == SyntaxKind.BaseConstructorInitializer || kind == SyntaxKind.SimpleBaseType)
+ else if (kind == SyntaxKind.ThisConstructorInitializer || kind == SyntaxKind.BaseConstructorInitializer || kind == SyntaxKind.PrimaryConstructorBaseType)
{
binder = rootBinder.GetBinder(current);
}
@@ -1549,6 +1549,7 @@ private CSharpSyntaxNode GetBindingRoot(CSharpSyntaxNode node)
{
case SyntaxKind.ThisConstructorInitializer:
case SyntaxKind.BaseConstructorInitializer:
+ case SyntaxKind.PrimaryConstructorBaseType:
return current;
case SyntaxKind.ArrowExpressionClause:
// If this is an arrow expression on a local function statement, then our bindable root is actually our parent syntax as it's
@@ -2207,6 +2208,7 @@ internal protected virtual CSharpSyntaxNode GetBindableSyntaxNode(CSharpSyntaxNo
!(node is JoinIntoClauseSyntax) &&
!(node is QueryContinuationSyntax) &&
!(node is ConstructorInitializerSyntax) &&
+ !(node is PrimaryConstructorBaseTypeSyntax) &&
!(node is ArrowExpressionClauseSyntax) &&
!(node is PatternSyntax))
{
@@ -2433,6 +2435,11 @@ internal override BoundExpressionStatement BindConstructorInitializer(Constructo
return (BoundExpressionStatement)TryGetBoundNodeFromMap(node) ?? base.BindConstructorInitializer(node, diagnostics);
}
+ internal override BoundExpressionStatement BindConstructorInitializer(PrimaryConstructorBaseTypeSyntax node, DiagnosticBag diagnostics)
+ {
+ return (BoundExpressionStatement)TryGetBoundNodeFromMap(node) ?? base.BindConstructorInitializer(node, diagnostics);
+ }
+
internal override BoundBlock BindExpressionBodyAsBlock(ArrowExpressionClauseSyntax node, DiagnosticBag diagnostics)
{
BoundBlock block = (BoundBlock)TryGetBoundNodeFromMap(node);
diff --git a/src/Compilers/CSharp/Portable/Compilation/MethodBodySemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/MethodBodySemanticModel.cs
index 7a2090bd1e8d8..9a43b48c9a43d 100644
--- a/src/Compilers/CSharp/Portable/Compilation/MethodBodySemanticModel.cs
+++ b/src/Compilers/CSharp/Portable/Compilation/MethodBodySemanticModel.cs
@@ -4,6 +4,7 @@
using System.Collections.Immutable;
using System.Diagnostics;
+using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
@@ -85,6 +86,9 @@ internal override BoundNode Bind(Binder binder, CSharpSyntaxNode node, Diagnosti
case SyntaxKind.ThisConstructorInitializer:
return binder.BindConstructorInitializer((ConstructorInitializerSyntax)node, diagnostics);
+ case SyntaxKind.PrimaryConstructorBaseType:
+ return binder.BindConstructorInitializer((PrimaryConstructorBaseTypeSyntax)node, diagnostics);
+
case SyntaxKind.MethodDeclaration:
case SyntaxKind.ConversionOperatorDeclaration:
case SyntaxKind.OperatorDeclaration:
@@ -149,6 +153,19 @@ internal static MethodBodySemanticModel CreateSpeculative(SyntaxTreeSemanticMode
return new MethodBodySemanticModel(owner, rootBinder, syntax, parentSemanticModelOpt: parentSemanticModel, speculatedPosition: position);
}
+ ///
+ /// Creates a speculative SemanticModel for a constructor initializer that did not appear in the original source code.
+ ///
+ internal static MethodBodySemanticModel CreateSpeculative(SyntaxTreeSemanticModel parentSemanticModel, MethodSymbol owner, PrimaryConstructorBaseTypeSyntax syntax, Binder rootBinder, int position)
+ {
+ Debug.Assert(parentSemanticModel != null);
+ Debug.Assert(syntax != null);
+ Debug.Assert(rootBinder != null);
+ Debug.Assert(rootBinder.IsSemanticModelBinder);
+
+ return new MethodBodySemanticModel(owner, rootBinder, syntax, parentSemanticModelOpt: parentSemanticModel, speculatedPosition: position);
+ }
+
internal override bool TryGetSpeculativeSemanticModelForMethodBodyCore(SyntaxTreeSemanticModel parentModel, int position, BaseMethodDeclarationSyntax method, out SemanticModel speculativeModel)
{
// CONSIDER: Do we want to ensure that speculated method and the original method have identical signatures?
@@ -231,12 +248,12 @@ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticMode
internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ConstructorInitializerSyntax constructorInitializer, out SemanticModel speculativeModel)
{
- if ((MemberSymbol as MethodSymbol)?.MethodKind == MethodKind.Constructor)
+ if (MemberSymbol is MethodSymbol methodSymbol && methodSymbol.MethodKind == MethodKind.Constructor &&
+ Root.FindToken(position).Parent?.AncestorsAndSelf().OfType().FirstOrDefault()?.Parent == Root)
{
var binder = this.GetEnclosingBinder(position);
if (binder != null)
{
- var methodSymbol = (MethodSymbol)this.MemberSymbol;
binder = new WithNullableContextBinder(SyntaxTree, position, binder);
binder = new ExecutableCodeBinder(constructorInitializer, methodSymbol, binder);
speculativeModel = CreateSpeculative(parentModel, methodSymbol, constructorInitializer, binder, position);
@@ -248,6 +265,25 @@ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticMode
return false;
}
+ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, PrimaryConstructorBaseTypeSyntax constructorInitializer, out SemanticModel speculativeModel)
+ {
+ if (MemberSymbol is SynthesizedRecordConstructor primaryCtor &&
+ Root.FindToken(position).Parent?.AncestorsAndSelf().OfType().FirstOrDefault() == primaryCtor.GetSyntax().PrimaryConstructorBaseType)
+ {
+ var binder = this.GetEnclosingBinder(position);
+ if (binder != null)
+ {
+ binder = new WithNullableContextBinder(SyntaxTree, position, binder);
+ binder = new ExecutableCodeBinder(constructorInitializer, primaryCtor, binder);
+ speculativeModel = CreateSpeculative(parentModel, primaryCtor, constructorInitializer, binder, position);
+ return true;
+ }
+ }
+
+ speculativeModel = null;
+ return false;
+ }
+
internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, EqualsValueClauseSyntax initializer, out SemanticModel speculativeModel)
{
speculativeModel = null;
diff --git a/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs
index e31435850de7a..1c5c44a5064d7 100644
--- a/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs
+++ b/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs
@@ -711,10 +711,34 @@ internal sealed override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSeman
{
position = CheckAndAdjustPosition(position);
- var model = this.GetMemberModel(position);
- if (model != null)
+ var existingConstructorInitializer = this.Root.FindToken(position).Parent.AncestorsAndSelf().OfType().FirstOrDefault();
+
+ if (existingConstructorInitializer != null)
+ {
+ var model = this.GetMemberModel(position);
+ if (model != null)
+ {
+ return model.TryGetSpeculativeSemanticModelCore(parentModel, position, constructorInitializer, out speculativeModel);
+ }
+ }
+
+ speculativeModel = null;
+ return false;
+ }
+
+ internal sealed override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, PrimaryConstructorBaseTypeSyntax constructorInitializer, out SemanticModel speculativeModel)
+ {
+ position = CheckAndAdjustPosition(position);
+
+ var existingConstructorInitializer = this.Root.FindToken(position).Parent.AncestorsAndSelf().OfType().FirstOrDefault();
+
+ if (existingConstructorInitializer != null)
{
- return model.TryGetSpeculativeSemanticModelCore(parentModel, position, constructorInitializer, out speculativeModel);
+ var model = this.GetMemberModel(existingConstructorInitializer);
+ if (model != null)
+ {
+ return model.TryGetSpeculativeSemanticModelCore(parentModel, position, constructorInitializer, out speculativeModel);
+ }
}
speculativeModel = null;
@@ -784,7 +808,7 @@ private MemberSemanticModel GetMemberModel(int position)
}
else
{
- var argumentList = recordDecl.BaseWithArguments?.ArgumentList;
+ var argumentList = recordDecl.PrimaryConstructorBaseType?.ArgumentList;
outsideMemberDecl = argumentList is null || !LookupPosition.IsBetweenTokens(position, argumentList.OpenParenToken, argumentList.CloseParenToken);
}
}
@@ -846,7 +870,9 @@ internal override MemberSemanticModel GetMemberModel(SyntaxNode node)
case SyntaxKind.RecordDeclaration:
{
var recordDecl = (RecordDeclarationSyntax)memberDecl;
- return recordDecl.ParameterList is object && recordDecl.BaseWithArguments?.ArgumentList.FullSpan.Contains(span) == true ? GetOrAddModel(memberDecl) : null;
+ return recordDecl.ParameterList is object &&
+ recordDecl.PrimaryConstructorBaseType is PrimaryConstructorBaseTypeSyntax baseWithArguments &&
+ (node == baseWithArguments || baseWithArguments.ArgumentList.FullSpan.Contains(span)) ? GetOrAddModel(memberDecl) : null;
}
case SyntaxKind.DestructorDeclaration:
diff --git a/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4 b/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4
index 9791532660a28..b522789a8b835 100644
--- a/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4
+++ b/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4
@@ -272,11 +272,16 @@ base_list
;
base_type
- : simple_base_type
+ : primary_constructor_base_type
+ | simple_base_type
+ ;
+
+primary_constructor_base_type
+ : type argument_list
;
simple_base_type
- : type argument_list?
+ : type
;
enum_member_declaration
diff --git a/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Internal.Generated.cs b/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Internal.Generated.cs
index 7c7c3d2403d0e..05ef43a82fc30 100644
--- a/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Internal.Generated.cs
+++ b/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Internal.Generated.cs
@@ -22279,50 +22279,124 @@ protected BaseTypeSyntax(ObjectReader reader)
internal sealed partial class SimpleBaseTypeSyntax : BaseTypeSyntax
{
internal readonly TypeSyntax type;
- internal readonly ArgumentListSyntax? argumentList;
- internal SimpleBaseTypeSyntax(SyntaxKind kind, TypeSyntax type, ArgumentListSyntax? argumentList, DiagnosticInfo[]? diagnostics, SyntaxAnnotation[]? annotations)
+ internal SimpleBaseTypeSyntax(SyntaxKind kind, TypeSyntax type, DiagnosticInfo[]? diagnostics, SyntaxAnnotation[]? annotations)
: base(kind, diagnostics, annotations)
{
- this.SlotCount = 2;
+ this.SlotCount = 1;
this.AdjustFlagsAndWidth(type);
this.type = type;
- if (argumentList != null)
+ }
+
+ internal SimpleBaseTypeSyntax(SyntaxKind kind, TypeSyntax type, SyntaxFactoryContext context)
+ : base(kind)
+ {
+ this.SetFactoryContext(context);
+ this.SlotCount = 1;
+ this.AdjustFlagsAndWidth(type);
+ this.type = type;
+ }
+
+ internal SimpleBaseTypeSyntax(SyntaxKind kind, TypeSyntax type)
+ : base(kind)
+ {
+ this.SlotCount = 1;
+ this.AdjustFlagsAndWidth(type);
+ this.type = type;
+ }
+
+ public override TypeSyntax Type => this.type;
+
+ internal override GreenNode? GetSlot(int index)
+ => index == 0 ? this.type : null;
+
+ internal override SyntaxNode CreateRed(SyntaxNode? parent, int position) => new CSharp.Syntax.SimpleBaseTypeSyntax(this, parent, position);
+
+ public override void Accept(CSharpSyntaxVisitor visitor) => visitor.VisitSimpleBaseType(this);
+ public override TResult Accept(CSharpSyntaxVisitor visitor) => visitor.VisitSimpleBaseType(this);
+
+ public SimpleBaseTypeSyntax Update(TypeSyntax type)
+ {
+ if (type != this.Type)
{
- this.AdjustFlagsAndWidth(argumentList);
- this.argumentList = argumentList;
+ var newNode = SyntaxFactory.SimpleBaseType(type);
+ var diags = GetDiagnostics();
+ if (diags?.Length > 0)
+ newNode = newNode.WithDiagnosticsGreen(diags);
+ var annotations = GetAnnotations();
+ if (annotations?.Length > 0)
+ newNode = newNode.WithAnnotationsGreen(annotations);
+ return newNode;
}
+
+ return this;
+ }
+
+ internal override GreenNode SetDiagnostics(DiagnosticInfo[]? diagnostics)
+ => new SimpleBaseTypeSyntax(this.Kind, this.type, diagnostics, GetAnnotations());
+
+ internal override GreenNode SetAnnotations(SyntaxAnnotation[]? annotations)
+ => new SimpleBaseTypeSyntax(this.Kind, this.type, GetDiagnostics(), annotations);
+
+ internal SimpleBaseTypeSyntax(ObjectReader reader)
+ : base(reader)
+ {
+ this.SlotCount = 1;
+ var type = (TypeSyntax)reader.ReadValue();
+ AdjustFlagsAndWidth(type);
+ this.type = type;
+ }
+
+ internal override void WriteTo(ObjectWriter writer)
+ {
+ base.WriteTo(writer);
+ writer.WriteValue(this.type);
+ }
+
+ static SimpleBaseTypeSyntax()
+ {
+ ObjectBinder.RegisterTypeReader(typeof(SimpleBaseTypeSyntax), r => new SimpleBaseTypeSyntax(r));
+ }
+ }
+
+ internal sealed partial class PrimaryConstructorBaseTypeSyntax : BaseTypeSyntax
+ {
+ internal readonly TypeSyntax type;
+ internal readonly ArgumentListSyntax argumentList;
+
+ internal PrimaryConstructorBaseTypeSyntax(SyntaxKind kind, TypeSyntax type, ArgumentListSyntax argumentList, DiagnosticInfo[]? diagnostics, SyntaxAnnotation[]? annotations)
+ : base(kind, diagnostics, annotations)
+ {
+ this.SlotCount = 2;
+ this.AdjustFlagsAndWidth(type);
+ this.type = type;
+ this.AdjustFlagsAndWidth(argumentList);
+ this.argumentList = argumentList;
}
- internal SimpleBaseTypeSyntax(SyntaxKind kind, TypeSyntax type, ArgumentListSyntax? argumentList, SyntaxFactoryContext context)
+ internal PrimaryConstructorBaseTypeSyntax(SyntaxKind kind, TypeSyntax type, ArgumentListSyntax argumentList, SyntaxFactoryContext context)
: base(kind)
{
this.SetFactoryContext(context);
this.SlotCount = 2;
this.AdjustFlagsAndWidth(type);
this.type = type;
- if (argumentList != null)
- {
- this.AdjustFlagsAndWidth(argumentList);
- this.argumentList = argumentList;
- }
+ this.AdjustFlagsAndWidth(argumentList);
+ this.argumentList = argumentList;
}
- internal SimpleBaseTypeSyntax(SyntaxKind kind, TypeSyntax type, ArgumentListSyntax? argumentList)
+ internal PrimaryConstructorBaseTypeSyntax(SyntaxKind kind, TypeSyntax type, ArgumentListSyntax argumentList)
: base(kind)
{
this.SlotCount = 2;
this.AdjustFlagsAndWidth(type);
this.type = type;
- if (argumentList != null)
- {
- this.AdjustFlagsAndWidth(argumentList);
- this.argumentList = argumentList;
- }
+ this.AdjustFlagsAndWidth(argumentList);
+ this.argumentList = argumentList;
}
public override TypeSyntax Type => this.type;
- public ArgumentListSyntax? ArgumentList => this.argumentList;
+ public ArgumentListSyntax ArgumentList => this.argumentList;
internal override GreenNode? GetSlot(int index)
=> index switch
@@ -22332,16 +22406,16 @@ internal SimpleBaseTypeSyntax(SyntaxKind kind, TypeSyntax type, ArgumentListSynt
_ => null,
};
- internal override SyntaxNode CreateRed(SyntaxNode? parent, int position) => new CSharp.Syntax.SimpleBaseTypeSyntax(this, parent, position);
+ internal override SyntaxNode CreateRed(SyntaxNode? parent, int position) => new CSharp.Syntax.PrimaryConstructorBaseTypeSyntax(this, parent, position);
- public override void Accept(CSharpSyntaxVisitor visitor) => visitor.VisitSimpleBaseType(this);
- public override TResult Accept(CSharpSyntaxVisitor visitor) => visitor.VisitSimpleBaseType(this);
+ public override void Accept(CSharpSyntaxVisitor visitor) => visitor.VisitPrimaryConstructorBaseType(this);
+ public override TResult Accept(CSharpSyntaxVisitor visitor) => visitor.VisitPrimaryConstructorBaseType(this);
- public SimpleBaseTypeSyntax Update(TypeSyntax type, ArgumentListSyntax argumentList)
+ public PrimaryConstructorBaseTypeSyntax Update(TypeSyntax type, ArgumentListSyntax argumentList)
{
if (type != this.Type || argumentList != this.ArgumentList)
{
- var newNode = SyntaxFactory.SimpleBaseType(type, argumentList);
+ var newNode = SyntaxFactory.PrimaryConstructorBaseType(type, argumentList);
var diags = GetDiagnostics();
if (diags?.Length > 0)
newNode = newNode.WithDiagnosticsGreen(diags);
@@ -22355,24 +22429,21 @@ public SimpleBaseTypeSyntax Update(TypeSyntax type, ArgumentListSyntax argumentL
}
internal override GreenNode SetDiagnostics(DiagnosticInfo[]? diagnostics)
- => new SimpleBaseTypeSyntax(this.Kind, this.type, this.argumentList, diagnostics, GetAnnotations());
+ => new PrimaryConstructorBaseTypeSyntax(this.Kind, this.type, this.argumentList, diagnostics, GetAnnotations());
internal override GreenNode SetAnnotations(SyntaxAnnotation[]? annotations)
- => new SimpleBaseTypeSyntax(this.Kind, this.type, this.argumentList, GetDiagnostics(), annotations);
+ => new PrimaryConstructorBaseTypeSyntax(this.Kind, this.type, this.argumentList, GetDiagnostics(), annotations);
- internal SimpleBaseTypeSyntax(ObjectReader reader)
+ internal PrimaryConstructorBaseTypeSyntax(ObjectReader reader)
: base(reader)
{
this.SlotCount = 2;
var type = (TypeSyntax)reader.ReadValue();
AdjustFlagsAndWidth(type);
this.type = type;
- var argumentList = (ArgumentListSyntax?)reader.ReadValue();
- if (argumentList != null)
- {
- AdjustFlagsAndWidth(argumentList);
- this.argumentList = argumentList;
- }
+ var argumentList = (ArgumentListSyntax)reader.ReadValue();
+ AdjustFlagsAndWidth(argumentList);
+ this.argumentList = argumentList;
}
internal override void WriteTo(ObjectWriter writer)
@@ -22382,9 +22453,9 @@ internal override void WriteTo(ObjectWriter writer)
writer.WriteValue(this.argumentList);
}
- static SimpleBaseTypeSyntax()
+ static PrimaryConstructorBaseTypeSyntax()
{
- ObjectBinder.RegisterTypeReader(typeof(SimpleBaseTypeSyntax), r => new SimpleBaseTypeSyntax(r));
+ ObjectBinder.RegisterTypeReader(typeof(PrimaryConstructorBaseTypeSyntax), r => new PrimaryConstructorBaseTypeSyntax(r));
}
}
@@ -32376,6 +32447,7 @@ internal partial class CSharpSyntaxVisitor
public virtual TResult VisitEnumMemberDeclaration(EnumMemberDeclarationSyntax node) => this.DefaultVisit(node);
public virtual TResult VisitBaseList(BaseListSyntax node) => this.DefaultVisit(node);
public virtual TResult VisitSimpleBaseType(SimpleBaseTypeSyntax node) => this.DefaultVisit(node);
+ public virtual TResult VisitPrimaryConstructorBaseType(PrimaryConstructorBaseTypeSyntax node) => this.DefaultVisit(node);
public virtual TResult VisitTypeParameterConstraintClause(TypeParameterConstraintClauseSyntax node) => this.DefaultVisit(node);
public virtual TResult VisitConstructorConstraint(ConstructorConstraintSyntax node) => this.DefaultVisit(node);
public virtual TResult VisitClassOrStructConstraint(ClassOrStructConstraintSyntax node) => this.DefaultVisit(node);
@@ -32604,6 +32676,7 @@ internal partial class CSharpSyntaxVisitor
public virtual void VisitEnumMemberDeclaration(EnumMemberDeclarationSyntax node) => this.DefaultVisit(node);
public virtual void VisitBaseList(BaseListSyntax node) => this.DefaultVisit(node);
public virtual void VisitSimpleBaseType(SimpleBaseTypeSyntax node) => this.DefaultVisit(node);
+ public virtual void VisitPrimaryConstructorBaseType(PrimaryConstructorBaseTypeSyntax node) => this.DefaultVisit(node);
public virtual void VisitTypeParameterConstraintClause(TypeParameterConstraintClauseSyntax node) => this.DefaultVisit(node);
public virtual void VisitConstructorConstraint(ConstructorConstraintSyntax node) => this.DefaultVisit(node);
public virtual void VisitClassOrStructConstraint(ClassOrStructConstraintSyntax node) => this.DefaultVisit(node);
@@ -33148,6 +33221,9 @@ public override CSharpSyntaxNode VisitBaseList(BaseListSyntax node)
=> node.Update((SyntaxToken)Visit(node.ColonToken), VisitList(node.Types));
public override CSharpSyntaxNode VisitSimpleBaseType(SimpleBaseTypeSyntax node)
+ => node.Update((TypeSyntax)Visit(node.Type));
+
+ public override CSharpSyntaxNode VisitPrimaryConstructorBaseType(PrimaryConstructorBaseTypeSyntax node)
=> node.Update((TypeSyntax)Visit(node.Type), (ArgumentListSyntax)Visit(node.ArgumentList));
public override CSharpSyntaxNode VisitTypeParameterConstraintClause(TypeParameterConstraintClauseSyntax node)
@@ -36736,17 +36812,37 @@ public BaseListSyntax BaseList(SyntaxToken colonToken, Microsoft.CodeAnalysis.Sy
return result;
}
- public SimpleBaseTypeSyntax SimpleBaseType(TypeSyntax type, ArgumentListSyntax? argumentList)
+ public SimpleBaseTypeSyntax SimpleBaseType(TypeSyntax type)
{
#if DEBUG
if (type == null) throw new ArgumentNullException(nameof(type));
#endif
int hash;
- var cached = CSharpSyntaxNodeCache.TryGetNode((int)SyntaxKind.SimpleBaseType, type, argumentList, this.context, out hash);
+ var cached = CSharpSyntaxNodeCache.TryGetNode((int)SyntaxKind.SimpleBaseType, type, this.context, out hash);
if (cached != null) return (SimpleBaseTypeSyntax)cached;
- var result = new SimpleBaseTypeSyntax(SyntaxKind.SimpleBaseType, type, argumentList, this.context);
+ var result = new SimpleBaseTypeSyntax(SyntaxKind.SimpleBaseType, type, this.context);
+ if (hash >= 0)
+ {
+ SyntaxNodeCache.AddNode(result, hash);
+ }
+
+ return result;
+ }
+
+ public PrimaryConstructorBaseTypeSyntax PrimaryConstructorBaseType(TypeSyntax type, ArgumentListSyntax argumentList)
+ {
+#if DEBUG
+ if (type == null) throw new ArgumentNullException(nameof(type));
+ if (argumentList == null) throw new ArgumentNullException(nameof(argumentList));
+#endif
+
+ int hash;
+ var cached = CSharpSyntaxNodeCache.TryGetNode((int)SyntaxKind.PrimaryConstructorBaseType, type, argumentList, this.context, out hash);
+ if (cached != null) return (PrimaryConstructorBaseTypeSyntax)cached;
+
+ var result = new PrimaryConstructorBaseTypeSyntax(SyntaxKind.PrimaryConstructorBaseType, type, argumentList, this.context);
if (hash >= 0)
{
SyntaxNodeCache.AddNode(result, hash);
@@ -41486,17 +41582,37 @@ public static BaseListSyntax BaseList(SyntaxToken colonToken, Microsoft.CodeAnal
return result;
}
- public static SimpleBaseTypeSyntax SimpleBaseType(TypeSyntax type, ArgumentListSyntax? argumentList)
+ public static SimpleBaseTypeSyntax SimpleBaseType(TypeSyntax type)
{
#if DEBUG
if (type == null) throw new ArgumentNullException(nameof(type));
#endif
int hash;
- var cached = SyntaxNodeCache.TryGetNode((int)SyntaxKind.SimpleBaseType, type, argumentList, out hash);
+ var cached = SyntaxNodeCache.TryGetNode((int)SyntaxKind.SimpleBaseType, type, out hash);
if (cached != null) return (SimpleBaseTypeSyntax)cached;
- var result = new SimpleBaseTypeSyntax(SyntaxKind.SimpleBaseType, type, argumentList);
+ var result = new SimpleBaseTypeSyntax(SyntaxKind.SimpleBaseType, type);
+ if (hash >= 0)
+ {
+ SyntaxNodeCache.AddNode(result, hash);
+ }
+
+ return result;
+ }
+
+ public static PrimaryConstructorBaseTypeSyntax PrimaryConstructorBaseType(TypeSyntax type, ArgumentListSyntax argumentList)
+ {
+#if DEBUG
+ if (type == null) throw new ArgumentNullException(nameof(type));
+ if (argumentList == null) throw new ArgumentNullException(nameof(argumentList));
+#endif
+
+ int hash;
+ var cached = SyntaxNodeCache.TryGetNode((int)SyntaxKind.PrimaryConstructorBaseType, type, argumentList, out hash);
+ if (cached != null) return (PrimaryConstructorBaseTypeSyntax)cached;
+
+ var result = new PrimaryConstructorBaseTypeSyntax(SyntaxKind.PrimaryConstructorBaseType, type, argumentList);
if (hash >= 0)
{
SyntaxNodeCache.AddNode(result, hash);
@@ -43012,6 +43128,7 @@ internal static IEnumerable GetNodeTypes()
typeof(EnumMemberDeclarationSyntax),
typeof(BaseListSyntax),
typeof(SimpleBaseTypeSyntax),
+ typeof(PrimaryConstructorBaseTypeSyntax),
typeof(TypeParameterConstraintClauseSyntax),
typeof(ConstructorConstraintSyntax),
typeof(ClassOrStructConstraintSyntax),
diff --git a/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Main.Generated.cs b/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Main.Generated.cs
index 9ab4b6174aa34..2940354e56d5f 100644
--- a/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Main.Generated.cs
+++ b/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Main.Generated.cs
@@ -651,6 +651,10 @@ public partial class CSharpSyntaxVisitor
[return: MaybeNull]
public virtual TResult VisitSimpleBaseType(SimpleBaseTypeSyntax node) => this.DefaultVisit(node);
+ /// Called when the visitor visits a PrimaryConstructorBaseTypeSyntax node.
+ [return: MaybeNull]
+ public virtual TResult VisitPrimaryConstructorBaseType(PrimaryConstructorBaseTypeSyntax node) => this.DefaultVisit(node);
+
/// Called when the visitor visits a TypeParameterConstraintClauseSyntax node.
[return: MaybeNull]
public virtual TResult VisitTypeParameterConstraintClause(TypeParameterConstraintClauseSyntax node) => this.DefaultVisit(node);
@@ -1391,6 +1395,9 @@ public partial class CSharpSyntaxVisitor
/// Called when the visitor visits a SimpleBaseTypeSyntax node.
public virtual void VisitSimpleBaseType(SimpleBaseTypeSyntax node) => this.DefaultVisit(node);
+ /// Called when the visitor visits a PrimaryConstructorBaseTypeSyntax node.
+ public virtual void VisitPrimaryConstructorBaseType(PrimaryConstructorBaseTypeSyntax node) => this.DefaultVisit(node);
+
/// Called when the visitor visits a TypeParameterConstraintClauseSyntax node.
public virtual void VisitTypeParameterConstraintClause(TypeParameterConstraintClauseSyntax node) => this.DefaultVisit(node);
@@ -2064,7 +2071,10 @@ public partial class CSharpSyntaxRewriter : CSharpSyntaxVisitor
=> node.Update(VisitToken(node.ColonToken), VisitList(node.Types));
public override SyntaxNode? VisitSimpleBaseType(SimpleBaseTypeSyntax node)
- => node.Update((TypeSyntax?)Visit(node.Type) ?? throw new ArgumentNullException("type"), (ArgumentListSyntax?)Visit(node.ArgumentList));
+ => node.Update((TypeSyntax?)Visit(node.Type) ?? throw new ArgumentNullException("type"));
+
+ public override SyntaxNode? VisitPrimaryConstructorBaseType(PrimaryConstructorBaseTypeSyntax node)
+ => node.Update((TypeSyntax?)Visit(node.Type) ?? throw new ArgumentNullException("type"), (ArgumentListSyntax?)Visit(node.ArgumentList) ?? throw new ArgumentNullException("argumentList"));
public override SyntaxNode? VisitTypeParameterConstraintClause(TypeParameterConstraintClauseSyntax node)
=> node.Update(VisitToken(node.WhereKeyword), (IdentifierNameSyntax?)Visit(node.Name) ?? throw new ArgumentNullException("name"), VisitToken(node.ColonToken), VisitList(node.Constraints));
@@ -5044,15 +5054,23 @@ public static BaseListSyntax BaseList(SeparatedSyntaxList types
=> SyntaxFactory.BaseList(SyntaxFactory.Token(SyntaxKind.ColonToken), types);
/// Creates a new SimpleBaseTypeSyntax instance.
- public static SimpleBaseTypeSyntax SimpleBaseType(TypeSyntax type, ArgumentListSyntax? argumentList)
+ public static SimpleBaseTypeSyntax SimpleBaseType(TypeSyntax type)
{
if (type == null) throw new ArgumentNullException(nameof(type));
- return (SimpleBaseTypeSyntax)Syntax.InternalSyntax.SyntaxFactory.SimpleBaseType((Syntax.InternalSyntax.TypeSyntax)type.Green, argumentList == null ? null : (Syntax.InternalSyntax.ArgumentListSyntax)argumentList.Green).CreateRed();
+ return (SimpleBaseTypeSyntax)Syntax.InternalSyntax.SyntaxFactory.SimpleBaseType((Syntax.InternalSyntax.TypeSyntax)type.Green).CreateRed();
}
- /// Creates a new SimpleBaseTypeSyntax instance.
- public static SimpleBaseTypeSyntax SimpleBaseType(TypeSyntax type)
- => SyntaxFactory.SimpleBaseType(type, default);
+ /// Creates a new PrimaryConstructorBaseTypeSyntax instance.
+ public static PrimaryConstructorBaseTypeSyntax PrimaryConstructorBaseType(TypeSyntax type, ArgumentListSyntax argumentList)
+ {
+ if (type == null) throw new ArgumentNullException(nameof(type));
+ if (argumentList == null) throw new ArgumentNullException(nameof(argumentList));
+ return (PrimaryConstructorBaseTypeSyntax)Syntax.InternalSyntax.SyntaxFactory.PrimaryConstructorBaseType((Syntax.InternalSyntax.TypeSyntax)type.Green, (Syntax.InternalSyntax.ArgumentListSyntax)argumentList.Green).CreateRed();
+ }
+
+ /// Creates a new PrimaryConstructorBaseTypeSyntax instance.
+ public static PrimaryConstructorBaseTypeSyntax PrimaryConstructorBaseType(TypeSyntax type)
+ => SyntaxFactory.PrimaryConstructorBaseType(type, SyntaxFactory.ArgumentList());
/// Creates a new TypeParameterConstraintClauseSyntax instance.
public static TypeParameterConstraintClauseSyntax TypeParameterConstraintClause(SyntaxToken whereKeyword, IdentifierNameSyntax name, SyntaxToken colonToken, SeparatedSyntaxList constraints)
diff --git a/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Syntax.Generated.cs b/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Syntax.Generated.cs
index 88d43df3f1f7f..0535a9109294c 100644
--- a/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Syntax.Generated.cs
+++ b/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Syntax.Generated.cs
@@ -9578,7 +9578,6 @@ internal BaseTypeSyntax(InternalSyntax.CSharpSyntaxNode green, SyntaxNode? paren
public sealed partial class SimpleBaseTypeSyntax : BaseTypeSyntax
{
private TypeSyntax? type;
- private ArgumentListSyntax? argumentList;
internal SimpleBaseTypeSyntax(InternalSyntax.CSharpSyntaxNode green, SyntaxNode? parent, int position)
: base(green, parent, position)
@@ -9587,13 +9586,49 @@ internal SimpleBaseTypeSyntax(InternalSyntax.CSharpSyntaxNode green, SyntaxNode?
public override TypeSyntax Type => GetRedAtZero(ref this.type)!;
- public ArgumentListSyntax? ArgumentList => GetRed(ref this.argumentList, 1);
+ internal override SyntaxNode? GetNodeSlot(int index) => index == 0 ? GetRedAtZero(ref this.type)! : null;
+
+ internal override SyntaxNode? GetCachedSlot(int index) => index == 0 ? this.type : null;
+
+ public override void Accept(CSharpSyntaxVisitor visitor) => visitor.VisitSimpleBaseType(this);
+ [return: MaybeNull]
+ public override TResult Accept(CSharpSyntaxVisitor visitor) => visitor.VisitSimpleBaseType(this);
+
+ public SimpleBaseTypeSyntax Update(TypeSyntax type)
+ {
+ if (type != this.Type)
+ {
+ var newNode = SyntaxFactory.SimpleBaseType(type);
+ var annotations = GetAnnotations();
+ return annotations?.Length > 0 ? newNode.WithAnnotations(annotations) : newNode;
+ }
+
+ return this;
+ }
+
+ internal override BaseTypeSyntax WithTypeCore(TypeSyntax type) => WithType(type);
+ public new SimpleBaseTypeSyntax WithType(TypeSyntax type) => Update(type);
+ }
+
+ public sealed partial class PrimaryConstructorBaseTypeSyntax : BaseTypeSyntax
+ {
+ private TypeSyntax? type;
+ private ArgumentListSyntax? argumentList;
+
+ internal PrimaryConstructorBaseTypeSyntax(InternalSyntax.CSharpSyntaxNode green, SyntaxNode? parent, int position)
+ : base(green, parent, position)
+ {
+ }
+
+ public override TypeSyntax Type => GetRedAtZero(ref this.type)!;
+
+ public ArgumentListSyntax ArgumentList => GetRed(ref this.argumentList, 1)!;
internal override SyntaxNode? GetNodeSlot(int index)
=> index switch
{
0 => GetRedAtZero(ref this.type)!,
- 1 => GetRed(ref this.argumentList, 1),
+ 1 => GetRed(ref this.argumentList, 1)!,
_ => null,
};
@@ -9605,15 +9640,15 @@ internal SimpleBaseTypeSyntax(InternalSyntax.CSharpSyntaxNode green, SyntaxNode?
_ => null,
};
- public override void Accept(CSharpSyntaxVisitor visitor) => visitor.VisitSimpleBaseType(this);
+ public override void Accept(CSharpSyntaxVisitor visitor) => visitor.VisitPrimaryConstructorBaseType(this);
[return: MaybeNull]
- public override TResult Accept(CSharpSyntaxVisitor visitor) => visitor.VisitSimpleBaseType(this);
+ public override TResult Accept(CSharpSyntaxVisitor visitor) => visitor.VisitPrimaryConstructorBaseType(this);
- public SimpleBaseTypeSyntax Update(TypeSyntax type, ArgumentListSyntax? argumentList)
+ public PrimaryConstructorBaseTypeSyntax Update(TypeSyntax type, ArgumentListSyntax argumentList)
{
if (type != this.Type || argumentList != this.ArgumentList)
{
- var newNode = SyntaxFactory.SimpleBaseType(type, argumentList);
+ var newNode = SyntaxFactory.PrimaryConstructorBaseType(type, argumentList);
var annotations = GetAnnotations();
return annotations?.Length > 0 ? newNode.WithAnnotations(annotations) : newNode;
}
@@ -9622,14 +9657,10 @@ public SimpleBaseTypeSyntax Update(TypeSyntax type, ArgumentListSyntax? argument
}
internal override BaseTypeSyntax WithTypeCore(TypeSyntax type) => WithType(type);
- public new SimpleBaseTypeSyntax WithType(TypeSyntax type) => Update(type, this.ArgumentList);
- public SimpleBaseTypeSyntax WithArgumentList(ArgumentListSyntax? argumentList) => Update(this.Type, argumentList);
+ public new PrimaryConstructorBaseTypeSyntax WithType(TypeSyntax type) => Update(type, this.ArgumentList);
+ public PrimaryConstructorBaseTypeSyntax WithArgumentList(ArgumentListSyntax argumentList) => Update(this.Type, argumentList);
- public SimpleBaseTypeSyntax AddArgumentListArguments(params ArgumentSyntax[] items)
- {
- var argumentList = this.ArgumentList ?? SyntaxFactory.ArgumentList();
- return WithArgumentList(argumentList.WithArguments(argumentList.Arguments.AddRange(items)));
- }
+ public PrimaryConstructorBaseTypeSyntax AddArgumentListArguments(params ArgumentSyntax[] items) => WithArgumentList(this.ArgumentList.WithArguments(this.ArgumentList.Arguments.AddRange(items)));
}
/// Type parameter constraint clause.
diff --git a/src/Compilers/CSharp/Portable/GlobalSuppressions.cs b/src/Compilers/CSharp/Portable/GlobalSuppressions.cs
index 90b587b285b06..2f30945ffdf54 100644
--- a/src/Compilers/CSharp/Portable/GlobalSuppressions.cs
+++ b/src/Compilers/CSharp/Portable/GlobalSuppressions.cs
@@ -36,3 +36,5 @@
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0027:Public API with optional parameter(s) should have the most parameters amongst its public overloads.", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.CSharp.SyntaxFactory.DeconstructionPatternClause(Microsoft.CodeAnalysis.SeparatedSyntaxList{Microsoft.CodeAnalysis.CSharp.Syntax.SubpatternSyntax})~Microsoft.CodeAnalysis.CSharp.Syntax.DeconstructionPatternClauseSyntax")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0027:Public API with optional parameter(s) should have the most parameters amongst its public overloads.", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.CSharp.SyntaxFactory.FunctionPointerType(Microsoft.CodeAnalysis.SeparatedSyntaxList{Microsoft.CodeAnalysis.CSharp.Syntax.ParameterSyntax})~Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetDeclaredSymbol(Microsoft.CodeAnalysis.SemanticModel,Microsoft.CodeAnalysis.CSharp.Syntax.CompilationUnitSyntax,System.Threading.CancellationToken)~Microsoft.CodeAnalysis.IMethodSymbol")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetSymbolInfo(Microsoft.CodeAnalysis.SemanticModel,Microsoft.CodeAnalysis.CSharp.Syntax.PrimaryConstructorBaseTypeSyntax,System.Threading.CancellationToken)~Microsoft.CodeAnalysis.SymbolInfo")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetMemberGroup(Microsoft.CodeAnalysis.SemanticModel,Microsoft.CodeAnalysis.CSharp.Syntax.PrimaryConstructorBaseTypeSyntax,System.Threading.CancellationToken)~System.Collections.Immutable.ImmutableArray{Microsoft.CodeAnalysis.ISymbol}")]
diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Call.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Call.cs
index 78ad6ac933582..6b8ce9bac91d9 100644
--- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Call.cs
+++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Call.cs
@@ -1197,6 +1197,8 @@ private static void AppendMissingOptionalArguments(
case SyntaxKind.BaseConstructorInitializer:
case SyntaxKind.ThisConstructorInitializer:
return new SourceLocation(((ConstructorInitializerSyntax)syntax).ArgumentList.OpenParenToken);
+ case SyntaxKind.PrimaryConstructorBaseType:
+ return new SourceLocation(((PrimaryConstructorBaseTypeSyntax)syntax).ArgumentList.OpenParenToken);
case SyntaxKind.ElementAccessExpression:
return new SourceLocation(((ElementAccessExpressionSyntax)syntax).ArgumentList.OpenBracketToken);
case SyntaxKind.FromClause:
diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
index 3f882b1b18ed0..53d6fe582c8be 100644
--- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
+++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
@@ -1752,7 +1752,7 @@ private BaseListSyntax ParseBaseList(SyntaxToken typeKeyword, bool haveParameter
}
}
- list.Add(_syntaxFactory.SimpleBaseType(firstType, argumentList));
+ list.Add(argumentList is object ? _syntaxFactory.PrimaryConstructorBaseType(firstType, argumentList) : (BaseTypeSyntax)_syntaxFactory.SimpleBaseType(firstType));
// any additional types
while (true)
@@ -1766,7 +1766,7 @@ private BaseListSyntax ParseBaseList(SyntaxToken typeKeyword, bool haveParameter
else if (this.CurrentToken.Kind == SyntaxKind.CommaToken || this.IsPossibleType())
{
list.AddSeparator(this.EatToken(SyntaxKind.CommaToken));
- list.Add(_syntaxFactory.SimpleBaseType(this.ParseType(), argumentList: null));
+ list.Add(_syntaxFactory.SimpleBaseType(this.ParseType()));
continue;
}
else if (this.SkipBadBaseListTokens(ref colon, list, SyntaxKind.CommaToken) == PostSkipAction.Abort)
@@ -5013,7 +5013,7 @@ private EnumDeclarationSyntax ParseEnumDeclaration(SyntaxList();
- tmpList.Add(_syntaxFactory.SimpleBaseType(type, argumentList: null));
+ tmpList.Add(_syntaxFactory.SimpleBaseType(type));
baseList = _syntaxFactory.BaseList(colon, tmpList);
_pool.Free(tmpList);
}
diff --git a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt
index a940e60957f16..5a357a9120c6e 100644
--- a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt
+++ b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt
@@ -1,6 +1,12 @@
*REMOVED*Microsoft.CodeAnalysis.CSharp.Syntax.ObjectCreationExpressionSyntax.ArgumentList.get -> Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax
*REMOVED*Microsoft.CodeAnalysis.CSharp.Syntax.ObjectCreationExpressionSyntax.Initializer.get -> Microsoft.CodeAnalysis.CSharp.Syntax.InitializerExpressionSyntax
*REMOVED*Microsoft.CodeAnalysis.CSharp.Syntax.ObjectCreationExpressionSyntax.NewKeyword.get -> Microsoft.CodeAnalysis.SyntaxToken
+Microsoft.CodeAnalysis.CSharp.Syntax.PrimaryConstructorBaseTypeSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.PrimaryConstructorBaseTypeSyntax.AddArgumentListArguments(params Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax[] items) -> Microsoft.CodeAnalysis.CSharp.Syntax.PrimaryConstructorBaseTypeSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.PrimaryConstructorBaseTypeSyntax.ArgumentList.get -> Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.PrimaryConstructorBaseTypeSyntax.Update(Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type, Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax argumentList) -> Microsoft.CodeAnalysis.CSharp.Syntax.PrimaryConstructorBaseTypeSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.PrimaryConstructorBaseTypeSyntax.WithArgumentList(Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax argumentList) -> Microsoft.CodeAnalysis.CSharp.Syntax.PrimaryConstructorBaseTypeSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.PrimaryConstructorBaseTypeSyntax.WithType(Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type) -> Microsoft.CodeAnalysis.CSharp.Syntax.PrimaryConstructorBaseTypeSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.RecordDeclarationSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.RecordDeclarationSyntax.AddAttributeLists(params Microsoft.CodeAnalysis.CSharp.Syntax.AttributeListSyntax[] items) -> Microsoft.CodeAnalysis.CSharp.Syntax.RecordDeclarationSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.RecordDeclarationSyntax.AddBaseListTypes(params Microsoft.CodeAnalysis.CSharp.Syntax.BaseTypeSyntax[] items) -> Microsoft.CodeAnalysis.CSharp.Syntax.RecordDeclarationSyntax
@@ -23,10 +29,7 @@ Microsoft.CodeAnalysis.CSharp.Syntax.RecordDeclarationSyntax.WithOpenBraceToken(
Microsoft.CodeAnalysis.CSharp.Syntax.RecordDeclarationSyntax.WithParameterList(Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax parameterList) -> Microsoft.CodeAnalysis.CSharp.Syntax.RecordDeclarationSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.RecordDeclarationSyntax.WithSemicolonToken(Microsoft.CodeAnalysis.SyntaxToken semicolonToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.RecordDeclarationSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.RecordDeclarationSyntax.WithTypeParameterList(Microsoft.CodeAnalysis.CSharp.Syntax.TypeParameterListSyntax typeParameterList) -> Microsoft.CodeAnalysis.CSharp.Syntax.RecordDeclarationSyntax
-Microsoft.CodeAnalysis.CSharp.Syntax.SimpleBaseTypeSyntax.AddArgumentListArguments(params Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax[] items) -> Microsoft.CodeAnalysis.CSharp.Syntax.SimpleBaseTypeSyntax
-Microsoft.CodeAnalysis.CSharp.Syntax.SimpleBaseTypeSyntax.ArgumentList.get -> Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax
-Microsoft.CodeAnalysis.CSharp.Syntax.SimpleBaseTypeSyntax.Update(Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type, Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax argumentList) -> Microsoft.CodeAnalysis.CSharp.Syntax.SimpleBaseTypeSyntax
-Microsoft.CodeAnalysis.CSharp.Syntax.SimpleBaseTypeSyntax.WithArgumentList(Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax argumentList) -> Microsoft.CodeAnalysis.CSharp.Syntax.SimpleBaseTypeSyntax
+Microsoft.CodeAnalysis.CSharp.SyntaxKind.PrimaryConstructorBaseType = 9065 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind
Microsoft.CodeAnalysis.CSharp.SyntaxKind.RecordDeclaration = 9063 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind
Microsoft.CodeAnalysis.CSharp.SyntaxKind.RecordKeyword = 8444 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind
abstract Microsoft.CodeAnalysis.CSharp.Syntax.BaseObjectCreationExpressionSyntax.ArgumentList.get -> Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax
@@ -51,9 +54,13 @@ Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax.WithLessThanToken
Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax.WithParameters(Microsoft.CodeAnalysis.SeparatedSyntaxList parameters) -> Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax
Microsoft.CodeAnalysis.CSharp.SyntaxKind.FunctionPointerType = 9056 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind
override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitFunctionPointerType(Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax node) -> Microsoft.CodeAnalysis.SyntaxNode
+override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitPrimaryConstructorBaseType(Microsoft.CodeAnalysis.CSharp.Syntax.PrimaryConstructorBaseTypeSyntax node) -> Microsoft.CodeAnalysis.SyntaxNode
override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitRecordDeclaration(Microsoft.CodeAnalysis.CSharp.Syntax.RecordDeclarationSyntax node) -> Microsoft.CodeAnalysis.SyntaxNode
override Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> void
override Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> TResult
+override Microsoft.CodeAnalysis.CSharp.Syntax.PrimaryConstructorBaseTypeSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> void
+override Microsoft.CodeAnalysis.CSharp.Syntax.PrimaryConstructorBaseTypeSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> TResult
+override Microsoft.CodeAnalysis.CSharp.Syntax.PrimaryConstructorBaseTypeSyntax.Type.get -> Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax
override Microsoft.CodeAnalysis.CSharp.Syntax.RecordDeclarationSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> void
override Microsoft.CodeAnalysis.CSharp.Syntax.RecordDeclarationSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> TResult
override Microsoft.CodeAnalysis.CSharp.Syntax.RecordDeclarationSyntax.AttributeLists.get -> Microsoft.CodeAnalysis.SyntaxList
@@ -67,6 +74,9 @@ override Microsoft.CodeAnalysis.CSharp.Syntax.RecordDeclarationSyntax.Modifiers.
override Microsoft.CodeAnalysis.CSharp.Syntax.RecordDeclarationSyntax.OpenBraceToken.get -> Microsoft.CodeAnalysis.SyntaxToken
override Microsoft.CodeAnalysis.CSharp.Syntax.RecordDeclarationSyntax.SemicolonToken.get -> Microsoft.CodeAnalysis.SyntaxToken
override Microsoft.CodeAnalysis.CSharp.Syntax.RecordDeclarationSyntax.TypeParameterList.get -> Microsoft.CodeAnalysis.CSharp.Syntax.TypeParameterListSyntax
+static Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetSpeculativeSymbolInfo(this Microsoft.CodeAnalysis.SemanticModel semanticModel, int position, Microsoft.CodeAnalysis.CSharp.Syntax.PrimaryConstructorBaseTypeSyntax constructorInitializer) -> Microsoft.CodeAnalysis.SymbolInfo
+static Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetSymbolInfo(this Microsoft.CodeAnalysis.SemanticModel semanticModel, Microsoft.CodeAnalysis.CSharp.Syntax.PrimaryConstructorBaseTypeSyntax constructorInitializer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.SymbolInfo
+static Microsoft.CodeAnalysis.CSharp.CSharpExtensions.TryGetSpeculativeSemanticModel(this Microsoft.CodeAnalysis.SemanticModel semanticModel, int position, Microsoft.CodeAnalysis.CSharp.Syntax.PrimaryConstructorBaseTypeSyntax constructorInitializer, out Microsoft.CodeAnalysis.SemanticModel speculativeModel) -> bool
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.FunctionPointerType(Microsoft.CodeAnalysis.SeparatedSyntaxList parameters = default(Microsoft.CodeAnalysis.SeparatedSyntaxList)) -> Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.FunctionPointerType(Microsoft.CodeAnalysis.SyntaxToken callingConvention, Microsoft.CodeAnalysis.SeparatedSyntaxList parameters) -> Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.FunctionPointerType(Microsoft.CodeAnalysis.SyntaxToken delegateKeyword, Microsoft.CodeAnalysis.SyntaxToken asteriskToken, Microsoft.CodeAnalysis.SyntaxToken callingConvention, Microsoft.CodeAnalysis.SyntaxToken lessThanToken, Microsoft.CodeAnalysis.SeparatedSyntaxList parameters, Microsoft.CodeAnalysis.SyntaxToken greaterThanToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax
@@ -176,6 +186,8 @@ static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ImplicitObjectCreationExpress
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ImplicitObjectCreationExpression(Microsoft.CodeAnalysis.SyntaxToken newKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax argumentList, Microsoft.CodeAnalysis.CSharp.Syntax.InitializerExpressionSyntax initializer) -> Microsoft.CodeAnalysis.CSharp.Syntax.ImplicitObjectCreationExpressionSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ParseTypeName(string text, int offset = 0, Microsoft.CodeAnalysis.ParseOptions options = null, bool consumeFullText = true) -> Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ParseTypeName(string text, int offset, bool consumeFullText) -> Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax
+static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.PrimaryConstructorBaseType(Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type) -> Microsoft.CodeAnalysis.CSharp.Syntax.PrimaryConstructorBaseTypeSyntax
+static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.PrimaryConstructorBaseType(Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type, Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax argumentList) -> Microsoft.CodeAnalysis.CSharp.Syntax.PrimaryConstructorBaseTypeSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.RecordDeclaration(Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.SyntaxToken keyword, Microsoft.CodeAnalysis.SyntaxToken identifier, Microsoft.CodeAnalysis.CSharp.Syntax.TypeParameterListSyntax typeParameterList, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax parameterList, Microsoft.CodeAnalysis.CSharp.Syntax.BaseListSyntax baseList, Microsoft.CodeAnalysis.SyntaxList constraintClauses, Microsoft.CodeAnalysis.SyntaxList members) -> Microsoft.CodeAnalysis.CSharp.Syntax.RecordDeclarationSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.RecordDeclaration(Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.SyntaxToken keyword, Microsoft.CodeAnalysis.SyntaxToken identifier, Microsoft.CodeAnalysis.CSharp.Syntax.TypeParameterListSyntax typeParameterList, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax parameterList, Microsoft.CodeAnalysis.CSharp.Syntax.BaseListSyntax baseList, Microsoft.CodeAnalysis.SyntaxList constraintClauses, Microsoft.CodeAnalysis.SyntaxToken openBraceToken, Microsoft.CodeAnalysis.SyntaxList members, Microsoft.CodeAnalysis.SyntaxToken closeBraceToken, Microsoft.CodeAnalysis.SyntaxToken semicolonToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.RecordDeclarationSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.RecordDeclaration(Microsoft.CodeAnalysis.SyntaxToken keyword, Microsoft.CodeAnalysis.SyntaxToken identifier) -> Microsoft.CodeAnalysis.CSharp.Syntax.RecordDeclarationSyntax
@@ -183,12 +195,12 @@ static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.RecordDeclaration(Microsoft.C
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.WithExpression(Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expression, Microsoft.CodeAnalysis.CSharp.Syntax.InitializerExpressionSyntax initializer) -> Microsoft.CodeAnalysis.CSharp.Syntax.WithExpressionSyntax
virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitFunctionPointerType(Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax node) -> void
virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitParenthesizedPattern(Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedPatternSyntax node) -> void
+virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitPrimaryConstructorBaseType(Microsoft.CodeAnalysis.CSharp.Syntax.PrimaryConstructorBaseTypeSyntax node) -> void
virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitRecordDeclaration(Microsoft.CodeAnalysis.CSharp.Syntax.RecordDeclarationSyntax node) -> void
virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitFunctionPointerType(Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax node) -> TResult
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ParenthesizedPattern(Microsoft.CodeAnalysis.CSharp.Syntax.PatternSyntax pattern) -> Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedPatternSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ParenthesizedPattern(Microsoft.CodeAnalysis.SyntaxToken openParenToken, Microsoft.CodeAnalysis.CSharp.Syntax.PatternSyntax pattern, Microsoft.CodeAnalysis.SyntaxToken closeParenToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedPatternSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.RelationalPattern(Microsoft.CodeAnalysis.SyntaxToken operatorToken, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expression) -> Microsoft.CodeAnalysis.CSharp.Syntax.RelationalPatternSyntax
-static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.SimpleBaseType(Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type, Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax argumentList) -> Microsoft.CodeAnalysis.CSharp.Syntax.SimpleBaseTypeSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.TypePattern(Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type) -> Microsoft.CodeAnalysis.CSharp.Syntax.TypePatternSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.UnaryPattern(Microsoft.CodeAnalysis.CSharp.Syntax.PatternSyntax pattern) -> Microsoft.CodeAnalysis.CSharp.Syntax.UnaryPatternSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.UnaryPattern(Microsoft.CodeAnalysis.SyntaxToken operatorToken, Microsoft.CodeAnalysis.CSharp.Syntax.PatternSyntax pattern) -> Microsoft.CodeAnalysis.CSharp.Syntax.UnaryPatternSyntax
@@ -208,6 +220,7 @@ virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitWithExpression(Mi
virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitBinaryPattern(Microsoft.CodeAnalysis.CSharp.Syntax.BinaryPatternSyntax node) -> TResult
virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitImplicitObjectCreationExpression(Microsoft.CodeAnalysis.CSharp.Syntax.ImplicitObjectCreationExpressionSyntax node) -> TResult
virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitParenthesizedPattern(Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedPatternSyntax node) -> TResult
+virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitPrimaryConstructorBaseType(Microsoft.CodeAnalysis.CSharp.Syntax.PrimaryConstructorBaseTypeSyntax node) -> TResult
virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitRecordDeclaration(Microsoft.CodeAnalysis.CSharp.Syntax.RecordDeclarationSyntax node) -> TResult
virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitRelationalPattern(Microsoft.CodeAnalysis.CSharp.Syntax.RelationalPatternSyntax node) -> TResult
virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitTypePattern(Microsoft.CodeAnalysis.CSharp.Syntax.TypePatternSyntax node) -> TResult
diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs
index 1a024747e2ef8..33c990215fd7b 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs
@@ -169,9 +169,9 @@ internal static LocalSymbol MakeLocalSymbolWithEnclosingContext(
nodeToBind.Kind() == SyntaxKind.CasePatternSwitchLabel ||
nodeToBind.Kind() == SyntaxKind.ThisConstructorInitializer ||
nodeToBind.Kind() == SyntaxKind.BaseConstructorInitializer ||
- nodeToBind.Kind() == SyntaxKind.SimpleBaseType || // initializer for a record constructor
+ nodeToBind.Kind() == SyntaxKind.PrimaryConstructorBaseType || // initializer for a record constructor
nodeToBind.Kind() == SyntaxKind.SwitchExpressionArm ||
- nodeToBind.Kind() == SyntaxKind.ArgumentList && nodeToBind.Parent is ConstructorInitializerSyntax ||
+ nodeToBind.Kind() == SyntaxKind.ArgumentList && (nodeToBind.Parent is ConstructorInitializerSyntax || nodeToBind.Parent is PrimaryConstructorBaseTypeSyntax) ||
nodeToBind.Kind() == SyntaxKind.GotoCaseStatement || // for error recovery
nodeToBind.Kind() == SyntaxKind.VariableDeclarator &&
new[] { SyntaxKind.LocalDeclarationStatement, SyntaxKind.ForStatement, SyntaxKind.UsingStatement, SyntaxKind.FixedStatement }.
@@ -741,8 +741,8 @@ public LocalSymbolWithEnclosingContext(
nodeToBind.Kind() == SyntaxKind.CasePatternSwitchLabel ||
nodeToBind.Kind() == SyntaxKind.ThisConstructorInitializer ||
nodeToBind.Kind() == SyntaxKind.BaseConstructorInitializer ||
- nodeToBind.Kind() == SyntaxKind.SimpleBaseType || // initializer for a record constructor
- nodeToBind.Kind() == SyntaxKind.ArgumentList && nodeToBind.Parent is ConstructorInitializerSyntax ||
+ nodeToBind.Kind() == SyntaxKind.PrimaryConstructorBaseType || // initializer for a record constructor
+ nodeToBind.Kind() == SyntaxKind.ArgumentList && (nodeToBind.Parent is ConstructorInitializerSyntax || nodeToBind.Parent is PrimaryConstructorBaseTypeSyntax) ||
nodeToBind.Kind() == SyntaxKind.VariableDeclarator ||
nodeToBind.Kind() == SyntaxKind.SwitchExpressionArm ||
nodeToBind.Kind() == SyntaxKind.GotoCaseStatement ||
@@ -769,12 +769,21 @@ protected override TypeWithAnnotations InferTypeOfVarVariable(DiagnosticBag diag
var initializer = (ConstructorInitializerSyntax)_nodeToBind;
_nodeBinder.BindConstructorInitializer(initializer, diagnostics);
break;
- case SyntaxKind.SimpleBaseType:
- _nodeBinder.BindConstructorInitializer((SimpleBaseTypeSyntax)_nodeToBind, diagnostics);
+ case SyntaxKind.PrimaryConstructorBaseType:
+ _nodeBinder.BindConstructorInitializer((PrimaryConstructorBaseTypeSyntax)_nodeToBind, diagnostics);
break;
case SyntaxKind.ArgumentList:
- var invocation = (ConstructorInitializerSyntax)_nodeToBind.Parent;
- _nodeBinder.BindConstructorInitializer(invocation, diagnostics);
+ switch (_nodeToBind.Parent)
+ {
+ case ConstructorInitializerSyntax ctorInitializer:
+ _nodeBinder.BindConstructorInitializer(ctorInitializer, diagnostics);
+ break;
+ case PrimaryConstructorBaseTypeSyntax ctorInitializer:
+ _nodeBinder.BindConstructorInitializer(ctorInitializer, diagnostics);
+ break;
+ default:
+ throw ExceptionUtilities.UnexpectedValue(_nodeToBind.Parent);
+ }
break;
case SyntaxKind.CasePatternSwitchLabel:
_nodeBinder.BindPatternSwitchLabelForInference((CasePatternSwitchLabelSyntax)_nodeToBind, diagnostics);
diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordConstructor.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordConstructor.cs
index 733a516bba650..3d083b323c07c 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordConstructor.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordConstructor.cs
@@ -33,14 +33,7 @@ internal RecordDeclarationSyntax GetSyntax()
protected override CSharpSyntaxNode? GetInitializer()
{
- var baseTypeSyntax = GetSyntax().BaseList?.Types.FirstOrDefault() as SimpleBaseTypeSyntax;
-
- if (baseTypeSyntax?.ArgumentList is object)
- {
- return baseTypeSyntax;
- }
-
- return null;
+ return GetSyntax().PrimaryConstructorBaseType;
}
internal override bool IsExpressionBodied
diff --git a/src/Compilers/CSharp/Portable/Syntax/LambdaUtilities.cs b/src/Compilers/CSharp/Portable/Syntax/LambdaUtilities.cs
index 697435103fca4..c22abae528445 100644
--- a/src/Compilers/CSharp/Portable/Syntax/LambdaUtilities.cs
+++ b/src/Compilers/CSharp/Portable/Syntax/LambdaUtilities.cs
@@ -404,8 +404,6 @@ internal static bool IsClosureScope(SyntaxNode node)
case SyntaxKind.IfStatement:
case SyntaxKind.LockStatement:
case SyntaxKind.ReturnStatement:
- case SyntaxKind.ThisConstructorInitializer:
- case SyntaxKind.BaseConstructorInitializer:
case SyntaxKind.ThrowStatement:
case SyntaxKind.WhileStatement:
case SyntaxKind.YieldReturnStatement:
diff --git a/src/Compilers/CSharp/Portable/Syntax/RecordDeclarationSyntax.cs b/src/Compilers/CSharp/Portable/Syntax/RecordDeclarationSyntax.cs
index 19ac288a66fd9..0e2ab8a4a75d9 100644
--- a/src/Compilers/CSharp/Portable/Syntax/RecordDeclarationSyntax.cs
+++ b/src/Compilers/CSharp/Portable/Syntax/RecordDeclarationSyntax.cs
@@ -8,16 +8,11 @@ namespace Microsoft.CodeAnalysis.CSharp.Syntax
{
public partial class RecordDeclarationSyntax
{
- internal SimpleBaseTypeSyntax? BaseWithArguments
+ internal PrimaryConstructorBaseTypeSyntax? PrimaryConstructorBaseType
{
get
{
- if (BaseList?.Types.FirstOrDefault() is SimpleBaseTypeSyntax { ArgumentList: { } } firstBase)
- {
- return firstBase;
- }
-
- return null;
+ return BaseList?.Types.FirstOrDefault() as PrimaryConstructorBaseTypeSyntax;
}
}
}
diff --git a/src/Compilers/CSharp/Portable/Syntax/SimpleBaseTypeSyntax.cs b/src/Compilers/CSharp/Portable/Syntax/SimpleBaseTypeSyntax.cs
deleted file mode 100644
index f6c8032094ff5..0000000000000
--- a/src/Compilers/CSharp/Portable/Syntax/SimpleBaseTypeSyntax.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-#nullable enable
-
-namespace Microsoft.CodeAnalysis.CSharp.Syntax
-{
- public partial class SimpleBaseTypeSyntax
- {
- public SimpleBaseTypeSyntax Update(TypeSyntax type)
- => Update(type, argumentList: null);
- }
-}
diff --git a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml
index f7e0fecb2c6d6..1549c7356df01 100644
--- a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml
+++ b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml
@@ -3451,9 +3451,14 @@
-
+
+
+
+
+
+
Type parameter constraint clause.
diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxExtensions.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxExtensions.cs
index e2132deefc706..77d1b868cc6db 100644
--- a/src/Compilers/CSharp/Portable/Syntax/SyntaxExtensions.cs
+++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxExtensions.cs
@@ -250,6 +250,7 @@ private static bool IsInContextWhichNeedsDynamicAttribute(CSharpSyntaxNode node)
case SyntaxKind.EventFieldDeclaration:
case SyntaxKind.BaseList:
case SyntaxKind.SimpleBaseType:
+ case SyntaxKind.PrimaryConstructorBaseType:
return true;
case SyntaxKind.Block:
diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxFacts.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxFacts.cs
index c7ecb7a3edfdd..d6794e6184813 100644
--- a/src/Compilers/CSharp/Portable/Syntax/SyntaxFacts.cs
+++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxFacts.cs
@@ -186,6 +186,9 @@ public static bool IsInTypeOnlyContext(ExpressionSyntax node)
case SimpleBaseType:
return true;
+ case PrimaryConstructorBaseType:
+ return ((PrimaryConstructorBaseTypeSyntax)parent).Type == node;
+
case CrefParameter:
return true;
@@ -313,6 +316,7 @@ public static bool IsNamedArgumentName(SyntaxNode node)
case Attribute:
case BaseConstructorInitializer:
case ThisConstructorInitializer:
+ case PrimaryConstructorBaseType:
return true;
default:
return false;
diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs
index b25aa6cbd8093..fde6f519abf04 100644
--- a/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs
+++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs
@@ -621,6 +621,8 @@ public enum SyntaxKind : ushort
WithExpression = 9061,
WithInitializerExpression = 9062,
- RecordDeclaration = 9063
+ RecordDeclaration = 9063,
+
+ PrimaryConstructorBaseType = 9065,
}
}
diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxNodeExtensions.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxNodeExtensions.cs
index 9651b6d3d119b..5dab21460a44a 100644
--- a/src/Compilers/CSharp/Portable/Syntax/SyntaxNodeExtensions.cs
+++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxNodeExtensions.cs
@@ -78,14 +78,11 @@ internal static bool CanHaveAssociatedLocalBinder(this SyntaxNode syntax)
case SyntaxKind.BaseConstructorInitializer:
case SyntaxKind.ThisConstructorInitializer:
case SyntaxKind.ConstructorDeclaration:
+ case SyntaxKind.PrimaryConstructorBaseType:
return true;
case SyntaxKind.RecordDeclaration:
return ((RecordDeclarationSyntax)syntax).ParameterList is object;
- case SyntaxKind.SimpleBaseType:
- return ((SimpleBaseTypeSyntax)syntax).ArgumentList is object &&
- syntax.Parent?.Parent is RecordDeclarationSyntax recordDecl &&
- recordDecl.ParameterList is object && recordDecl.BaseWithArguments == syntax;
default:
return syntax is StatementSyntax || IsValidScopeDesignator(syntax as ExpressionSyntax);
diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs
index ca68d91577e0d..2627940b0f6d1 100644
--- a/src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs
+++ b/src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs
@@ -4,6 +4,7 @@
#nullable enable
+using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
@@ -7033,6 +7034,8 @@ public static void Main()
var c = new C(1, 2);
Console.WriteLine(c.Z);
}
+
+ C(int X, int Y, int Z) : this(X, Y) {}
}";
var verifier = CompileAndVerify(src, expectedOutput: @"
1
@@ -7077,10 +7080,42 @@ .maxstack 3
Assert.Contains(symbol, model.LookupSymbols(x.SpanStart, name: "X"));
Assert.Contains("X", model.LookupNames(x.SpanStart));
- var baseWithargs = tree.GetRoot().DescendantNodes().OfType().Single();
- Assert.Equal("Base(X, Y)", baseWithargs.ToString());
- Assert.Null(model.GetTypeInfo(baseWithargs).Type);
- Assert.Null(model.GetSymbolInfo(baseWithargs).Symbol);
+ {
+ var baseWithargs = tree.GetRoot().DescendantNodes().OfType().Single();
+ Assert.Equal("Base(X, Y)", baseWithargs.ToString());
+ Assert.Equal("Base", model.GetTypeInfo(baseWithargs.Type).Type.ToTestDisplayString());
+ Assert.Equal(TypeInfo.None, model.GetTypeInfo(baseWithargs));
+ Assert.Equal("Base..ctor(System.Int32 X, System.Int32 Y)", model.GetSymbolInfo((SyntaxNode)baseWithargs).Symbol.ToTestDisplayString());
+ Assert.Equal("Base..ctor(System.Int32 X, System.Int32 Y)", model.GetSymbolInfo(baseWithargs).Symbol.ToTestDisplayString());
+ Assert.Equal("Base..ctor(System.Int32 X, System.Int32 Y)", CSharpExtensions.GetSymbolInfo(model, baseWithargs).Symbol.ToTestDisplayString());
+
+ Assert.Empty(model.GetMemberGroup((SyntaxNode)baseWithargs));
+ Assert.Empty(model.GetMemberGroup(baseWithargs));
+
+ model = comp.GetSemanticModel(tree);
+ Assert.Equal("Base..ctor(System.Int32 X, System.Int32 Y)", model.GetSymbolInfo((SyntaxNode)baseWithargs).Symbol.ToTestDisplayString());
+ model = comp.GetSemanticModel(tree);
+ Assert.Equal("Base..ctor(System.Int32 X, System.Int32 Y)", model.GetSymbolInfo(baseWithargs).Symbol.ToTestDisplayString());
+ model = comp.GetSemanticModel(tree);
+ Assert.Equal("Base..ctor(System.Int32 X, System.Int32 Y)", CSharpExtensions.GetSymbolInfo(model, baseWithargs).Symbol.ToTestDisplayString());
+
+ model = comp.GetSemanticModel(tree);
+ Assert.Empty(model.GetMemberGroup((SyntaxNode)baseWithargs));
+ model = comp.GetSemanticModel(tree);
+ Assert.Empty(model.GetMemberGroup(baseWithargs));
+ model = comp.GetSemanticModel(tree);
+ }
+ {
+ var baseWithargs = tree.GetRoot().DescendantNodes().OfType().Single();
+ Assert.Equal(": this(X, Y)", baseWithargs.ToString());
+ Assert.Equal("C..ctor(System.Int32 X, System.Int32 Y)", model.GetSymbolInfo((SyntaxNode)baseWithargs).Symbol.ToTestDisplayString());
+ Assert.Equal("C..ctor(System.Int32 X, System.Int32 Y)", model.GetSymbolInfo(baseWithargs).Symbol.ToTestDisplayString());
+ Assert.Equal("C..ctor(System.Int32 X, System.Int32 Y)", CSharpExtensions.GetSymbolInfo(model, baseWithargs).Symbol.ToTestDisplayString());
+
+ Assert.Empty(model.GetMemberGroup((SyntaxNode)baseWithargs).Select(m => m.ToTestDisplayString()));
+ Assert.Empty(model.GetMemberGroup(baseWithargs).Select(m => m.ToTestDisplayString()));
+ Assert.Empty(CSharpExtensions.GetMemberGroup(model, baseWithargs).Select(m => m.ToTestDisplayString()));
+ }
}
[Fact]
@@ -7825,6 +7860,327 @@ private static int Test(int x, out int y)
);
}
+ [Fact]
+ public void BaseArguments_19()
+ {
+ var src = @"
+record Base
+{
+ public Base(int X)
+ {
+ }
+
+ public Base() {}
+}
+
+record C(int X, int Y) : Base(GetInt(X, out var xx) + xx, Y), I
+{
+ C(int X, int Y, int Z) : this(X, Y, Z, 1) { return; }
+
+ static int GetInt(int x1, out int x2)
+ {
+ throw null;
+ }
+}
+
+interface I {}
+";
+
+ var comp = CreateCompilation(src);
+
+ comp.VerifyDiagnostics(
+ // (11,30): error CS1729: 'Base' does not contain a constructor that takes 2 arguments
+ // record C(int X, int Y) : Base(GetInt(X, out var xx) + xx, Y)
+ Diagnostic(ErrorCode.ERR_BadCtorArgCount, "(GetInt(X, out var xx) + xx, Y)").WithArguments("Base", "2").WithLocation(11, 30),
+ // (13,30): error CS1729: 'C' does not contain a constructor that takes 4 arguments
+ // C(int X, int Y, int Z) : this(X, Y, Z, 1) {}
+ Diagnostic(ErrorCode.ERR_BadCtorArgCount, "this").WithArguments("C", "4").WithLocation(13, 30)
+ );
+
+ var tree = comp.SyntaxTrees.First();
+ var model = comp.GetSemanticModel(tree);
+ SymbolInfo symbolInfo;
+ PrimaryConstructorBaseTypeSyntax speculativePrimaryInitializer;
+ ConstructorInitializerSyntax speculativeBaseInitializer;
+
+ {
+ var baseWithargs = tree.GetRoot().DescendantNodes().OfType().Single();
+ Assert.Equal("Base(GetInt(X, out var xx) + xx, Y)", baseWithargs.ToString());
+ Assert.Equal("Base", model.GetTypeInfo(baseWithargs.Type).Type.ToTestDisplayString());
+ Assert.Equal(TypeInfo.None, model.GetTypeInfo(baseWithargs));
+ symbolInfo = model.GetSymbolInfo((SyntaxNode)baseWithargs);
+ Assert.Null(symbolInfo.Symbol);
+ Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason);
+ string[] candidates = new[] { "Base..ctor(System.Int32 X)", "Base..ctor()", "Base..ctor(Base )" };
+ Assert.Equal(candidates, symbolInfo.CandidateSymbols.Select(m => m.ToTestDisplayString()));
+ symbolInfo = model.GetSymbolInfo(baseWithargs);
+ Assert.Null(symbolInfo.Symbol);
+ Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason);
+ Assert.Equal(candidates, symbolInfo.CandidateSymbols.Select(m => m.ToTestDisplayString()));
+ symbolInfo = CSharpExtensions.GetSymbolInfo(model, baseWithargs);
+ Assert.Null(symbolInfo.Symbol);
+ Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason);
+ Assert.Equal(candidates, symbolInfo.CandidateSymbols.Select(m => m.ToTestDisplayString()));
+
+ Assert.Empty(model.GetMemberGroup((SyntaxNode)baseWithargs));
+ Assert.Empty(model.GetMemberGroup(baseWithargs));
+
+ model = comp.GetSemanticModel(tree);
+ symbolInfo = model.GetSymbolInfo((SyntaxNode)baseWithargs);
+ Assert.Null(symbolInfo.Symbol);
+ Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason);
+ Assert.Equal(candidates, symbolInfo.CandidateSymbols.Select(m => m.ToTestDisplayString()));
+ model = comp.GetSemanticModel(tree);
+ symbolInfo = model.GetSymbolInfo(baseWithargs);
+ Assert.Null(symbolInfo.Symbol);
+ Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason);
+ Assert.Equal(candidates, symbolInfo.CandidateSymbols.Select(m => m.ToTestDisplayString()));
+ model = comp.GetSemanticModel(tree);
+ symbolInfo = CSharpExtensions.GetSymbolInfo(model, baseWithargs);
+ Assert.Null(symbolInfo.Symbol);
+ Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason);
+ Assert.Equal(candidates, symbolInfo.CandidateSymbols.Select(m => m.ToTestDisplayString()));
+
+ model = comp.GetSemanticModel(tree);
+ Assert.Empty(model.GetMemberGroup((SyntaxNode)baseWithargs));
+ model = comp.GetSemanticModel(tree);
+ Assert.Empty(model.GetMemberGroup(baseWithargs));
+ model = comp.GetSemanticModel(tree);
+
+ SemanticModel speculativeModel;
+ speculativePrimaryInitializer = baseWithargs.WithArgumentList(baseWithargs.ArgumentList.WithArguments(baseWithargs.ArgumentList.Arguments.RemoveAt(1)));
+
+ speculativeBaseInitializer = SyntaxFactory.ConstructorInitializer(SyntaxKind.BaseConstructorInitializer, speculativePrimaryInitializer.ArgumentList);
+ Assert.False(model.TryGetSpeculativeSemanticModel(baseWithargs.ArgumentList.OpenParenToken.SpanStart, speculativeBaseInitializer, out _));
+
+ symbolInfo = model.GetSpeculativeSymbolInfo(baseWithargs.ArgumentList.OpenParenToken.SpanStart, (SyntaxNode)speculativeBaseInitializer, SpeculativeBindingOption.BindAsExpression);
+ Assert.Equal(SymbolInfo.None, symbolInfo);
+
+ symbolInfo = CSharpExtensions.GetSpeculativeSymbolInfo(model, baseWithargs.ArgumentList.OpenParenToken.SpanStart, speculativeBaseInitializer);
+ Assert.Equal(SymbolInfo.None, symbolInfo);
+
+ Assert.False(model.TryGetSpeculativeSemanticModel(tree.GetRoot().DescendantNodes().OfType().Single().SpanStart,
+ speculativeBaseInitializer, out _));
+
+ var otherBasePosition = ((BaseListSyntax)baseWithargs.Parent!).Types[1].SpanStart;
+ Assert.False(model.TryGetSpeculativeSemanticModel(otherBasePosition, speculativePrimaryInitializer, out _));
+
+ Assert.True(model.TryGetSpeculativeSemanticModel(baseWithargs.SpanStart, speculativePrimaryInitializer, out speculativeModel!));
+ Assert.Equal("Base..ctor(System.Int32 X)", speculativeModel!.GetSymbolInfo((SyntaxNode)speculativePrimaryInitializer).Symbol.ToTestDisplayString());
+ Assert.Equal("Base..ctor(System.Int32 X)", speculativeModel.GetSymbolInfo(speculativePrimaryInitializer).Symbol.ToTestDisplayString());
+ Assert.Equal("Base..ctor(System.Int32 X)", CSharpExtensions.GetSymbolInfo(speculativeModel, speculativePrimaryInitializer).Symbol.ToTestDisplayString());
+
+ Assert.True(model.TryGetSpeculativeSemanticModel(baseWithargs.ArgumentList.OpenParenToken.SpanStart, speculativePrimaryInitializer, out speculativeModel!));
+
+ var xxDecl = OutVarTests.GetOutVarDeclaration(speculativePrimaryInitializer.SyntaxTree, "xx");
+ var xxRef = OutVarTests.GetReferences(speculativePrimaryInitializer.SyntaxTree, "xx").ToArray();
+ Assert.Equal(1, xxRef.Length);
+ OutVarTests.VerifyModelForOutVar(speculativeModel, xxDecl, xxRef);
+
+ Assert.Equal("Base..ctor(System.Int32 X)", speculativeModel!.GetSymbolInfo((SyntaxNode)speculativePrimaryInitializer).Symbol.ToTestDisplayString());
+ Assert.Equal("Base..ctor(System.Int32 X)", speculativeModel.GetSymbolInfo(speculativePrimaryInitializer).Symbol.ToTestDisplayString());
+ Assert.Equal("Base..ctor(System.Int32 X)", CSharpExtensions.GetSymbolInfo(speculativeModel, speculativePrimaryInitializer).Symbol.ToTestDisplayString());
+
+ Assert.Throws(() => model.TryGetSpeculativeSemanticModel(baseWithargs.ArgumentList.OpenParenToken.SpanStart, (PrimaryConstructorBaseTypeSyntax)null!, out _));
+ Assert.Throws(() => model.TryGetSpeculativeSemanticModel(baseWithargs.ArgumentList.OpenParenToken.SpanStart, baseWithargs, out _));
+
+ symbolInfo = model.GetSpeculativeSymbolInfo(otherBasePosition, (SyntaxNode)speculativePrimaryInitializer, SpeculativeBindingOption.BindAsExpression);
+ Assert.Equal(SymbolInfo.None, symbolInfo);
+
+ symbolInfo = CSharpExtensions.GetSpeculativeSymbolInfo(model, otherBasePosition, speculativePrimaryInitializer);
+ Assert.Equal(SymbolInfo.None, symbolInfo);
+
+ symbolInfo = model.GetSpeculativeSymbolInfo(baseWithargs.SpanStart, (SyntaxNode)speculativePrimaryInitializer, SpeculativeBindingOption.BindAsExpression);
+ Assert.Equal("Base..ctor(System.Int32 X)", symbolInfo.Symbol.ToTestDisplayString());
+
+ symbolInfo = CSharpExtensions.GetSpeculativeSymbolInfo(model, baseWithargs.SpanStart, speculativePrimaryInitializer);
+ Assert.Equal("Base..ctor(System.Int32 X)", symbolInfo.Symbol.ToTestDisplayString());
+
+ symbolInfo = model.GetSpeculativeSymbolInfo(baseWithargs.ArgumentList.OpenParenToken.SpanStart, (SyntaxNode)speculativePrimaryInitializer, SpeculativeBindingOption.BindAsExpression);
+ Assert.Equal("Base..ctor(System.Int32 X)", symbolInfo.Symbol.ToTestDisplayString());
+
+ symbolInfo = CSharpExtensions.GetSpeculativeSymbolInfo(model, baseWithargs.ArgumentList.OpenParenToken.SpanStart, speculativePrimaryInitializer);
+ Assert.Equal("Base..ctor(System.Int32 X)", symbolInfo.Symbol.ToTestDisplayString());
+
+ Assert.Equal(TypeInfo.None, model.GetSpeculativeTypeInfo(baseWithargs.ArgumentList.OpenParenToken.SpanStart, (SyntaxNode)speculativePrimaryInitializer, SpeculativeBindingOption.BindAsExpression));
+ Assert.Equal(TypeInfo.None, model.GetSpeculativeTypeInfo(tree.GetRoot().DescendantNodes().OfType().Single().ArgumentList.OpenParenToken.SpanStart,
+ (SyntaxNode)speculativePrimaryInitializer, SpeculativeBindingOption.BindAsExpression));
+ }
+ {
+ var baseWithargs = tree.GetRoot().DescendantNodes().OfType().Single();
+ Assert.Equal(": this(X, Y, Z, 1)", baseWithargs.ToString());
+ symbolInfo = model.GetSymbolInfo((SyntaxNode)baseWithargs);
+ Assert.Null(symbolInfo.Symbol);
+ Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason);
+ string[] candidates = new[] { "C..ctor(System.Int32 X, System.Int32 Y, System.Int32 Z)", "C..ctor(System.Int32 X, System.Int32 Y)", "C..ctor(C )" };
+ Assert.Equal(candidates, symbolInfo.CandidateSymbols.Select(m => m.ToTestDisplayString()));
+ symbolInfo = model.GetSymbolInfo(baseWithargs);
+ Assert.Null(symbolInfo.Symbol);
+ Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason);
+ Assert.Equal(candidates, symbolInfo.CandidateSymbols.Select(m => m.ToTestDisplayString()));
+ symbolInfo = CSharpExtensions.GetSymbolInfo(model, baseWithargs);
+ Assert.Null(symbolInfo.Symbol);
+ Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason);
+ Assert.Equal(candidates, symbolInfo.CandidateSymbols.Select(m => m.ToTestDisplayString()));
+
+ Assert.Empty(model.GetMemberGroup((SyntaxNode)baseWithargs).Select(m => m.ToTestDisplayString()));
+ Assert.Empty(model.GetMemberGroup(baseWithargs).Select(m => m.ToTestDisplayString()));
+ Assert.Empty(CSharpExtensions.GetMemberGroup(model, baseWithargs).Select(m => m.ToTestDisplayString()));
+
+ Assert.False(model.TryGetSpeculativeSemanticModel(baseWithargs.ArgumentList.OpenParenToken.SpanStart, speculativePrimaryInitializer, out _));
+
+ symbolInfo = model.GetSpeculativeSymbolInfo(baseWithargs.ArgumentList.OpenParenToken.SpanStart, speculativePrimaryInitializer);
+ Assert.Equal(SymbolInfo.None, symbolInfo);
+
+ symbolInfo = model.GetSpeculativeSymbolInfo(baseWithargs.ArgumentList.OpenParenToken.SpanStart, (SyntaxNode)speculativeBaseInitializer, SpeculativeBindingOption.BindAsExpression);
+ Assert.Equal("Base..ctor(System.Int32 X)", symbolInfo.Symbol.ToTestDisplayString());
+
+ symbolInfo = CSharpExtensions.GetSpeculativeSymbolInfo(model, baseWithargs.ArgumentList.OpenParenToken.SpanStart, speculativeBaseInitializer);
+ Assert.Equal("Base..ctor(System.Int32 X)", symbolInfo.Symbol.ToTestDisplayString());
+
+ Assert.Equal(TypeInfo.None, model.GetSpeculativeTypeInfo(baseWithargs.ArgumentList.OpenParenToken.SpanStart, (SyntaxNode)speculativePrimaryInitializer, SpeculativeBindingOption.BindAsExpression));
+ }
+ }
+
+ [Fact]
+ public void BaseArguments_20()
+ {
+ var src = @"
+class Base
+{
+ public Base(int X)
+ {
+ }
+
+ public Base() {}
+}
+
+class C : Base(GetInt(X, out var xx) + xx, Y), I
+{
+ C(int X, int Y, int Z) : base(X, Y, Z, 1) { return; }
+
+ static int GetInt(int x1, out int x2)
+ {
+ throw null;
+ }
+}
+
+interface I {}
+";
+
+ var comp = CreateCompilation(src);
+
+ comp.VerifyDiagnostics(
+ // (11,15): error CS8861: Unexpected argument list.
+ // class C : Base(GetInt(X, out var xx) + xx, Y), I
+ Diagnostic(ErrorCode.ERR_UnexpectedArgumentList, "(").WithLocation(11, 15),
+ // (13,30): error CS1729: 'Base' does not contain a constructor that takes 4 arguments
+ // C(int X, int Y, int Z) : base(X, Y, Z, 1) { return; }
+ Diagnostic(ErrorCode.ERR_BadCtorArgCount, "base").WithArguments("Base", "4").WithLocation(13, 30)
+ );
+
+ var tree = comp.SyntaxTrees.First();
+ var model = comp.GetSemanticModel(tree);
+ SymbolInfo symbolInfo;
+ PrimaryConstructorBaseTypeSyntax speculativePrimaryInitializer;
+ ConstructorInitializerSyntax speculativeBaseInitializer;
+
+ {
+ var baseWithargs = tree.GetRoot().DescendantNodes().OfType().Single();
+ Assert.Equal("Base(GetInt(X, out var xx) + xx, Y)", baseWithargs.ToString());
+ Assert.Equal("Base", model.GetTypeInfo(baseWithargs.Type).Type.ToTestDisplayString());
+ Assert.Equal(TypeInfo.None, model.GetTypeInfo(baseWithargs));
+ symbolInfo = model.GetSymbolInfo((SyntaxNode)baseWithargs);
+ Assert.Equal(SymbolInfo.None, symbolInfo);
+ symbolInfo = model.GetSymbolInfo(baseWithargs);
+ Assert.Equal(SymbolInfo.None, symbolInfo);
+ symbolInfo = CSharpExtensions.GetSymbolInfo(model, baseWithargs);
+ Assert.Equal(SymbolInfo.None, symbolInfo);
+
+ Assert.Empty(model.GetMemberGroup((SyntaxNode)baseWithargs));
+ Assert.Empty(model.GetMemberGroup(baseWithargs));
+
+ speculativePrimaryInitializer = baseWithargs.WithArgumentList(baseWithargs.ArgumentList.WithArguments(baseWithargs.ArgumentList.Arguments.RemoveAt(1)));
+
+ speculativeBaseInitializer = SyntaxFactory.ConstructorInitializer(SyntaxKind.BaseConstructorInitializer, speculativePrimaryInitializer.ArgumentList);
+ Assert.False(model.TryGetSpeculativeSemanticModel(baseWithargs.ArgumentList.OpenParenToken.SpanStart, speculativeBaseInitializer, out _));
+
+ symbolInfo = model.GetSpeculativeSymbolInfo(baseWithargs.ArgumentList.OpenParenToken.SpanStart, (SyntaxNode)speculativeBaseInitializer, SpeculativeBindingOption.BindAsExpression);
+ Assert.Equal(SymbolInfo.None, symbolInfo);
+
+ symbolInfo = CSharpExtensions.GetSpeculativeSymbolInfo(model, baseWithargs.ArgumentList.OpenParenToken.SpanStart, speculativeBaseInitializer);
+ Assert.Equal(SymbolInfo.None, symbolInfo);
+
+ Assert.False(model.TryGetSpeculativeSemanticModel(tree.GetRoot().DescendantNodes().OfType().Single().SpanStart,
+ speculativeBaseInitializer, out _));
+
+ var otherBasePosition = ((BaseListSyntax)baseWithargs.Parent!).Types[1].SpanStart;
+ Assert.False(model.TryGetSpeculativeSemanticModel(otherBasePosition, speculativePrimaryInitializer, out _));
+
+ Assert.False(model.TryGetSpeculativeSemanticModel(baseWithargs.SpanStart, speculativePrimaryInitializer, out _));
+ Assert.False(model.TryGetSpeculativeSemanticModel(baseWithargs.ArgumentList.OpenParenToken.SpanStart, speculativePrimaryInitializer, out _));
+
+ Assert.Throws(() => model.TryGetSpeculativeSemanticModel(baseWithargs.ArgumentList.OpenParenToken.SpanStart, (PrimaryConstructorBaseTypeSyntax)null!, out _));
+ Assert.Throws(() => model.TryGetSpeculativeSemanticModel(baseWithargs.ArgumentList.OpenParenToken.SpanStart, baseWithargs, out _));
+
+ symbolInfo = model.GetSpeculativeSymbolInfo(otherBasePosition, (SyntaxNode)speculativePrimaryInitializer, SpeculativeBindingOption.BindAsExpression);
+ Assert.Equal(SymbolInfo.None, symbolInfo);
+
+ symbolInfo = CSharpExtensions.GetSpeculativeSymbolInfo(model, otherBasePosition, speculativePrimaryInitializer);
+ Assert.Equal(SymbolInfo.None, symbolInfo);
+
+ symbolInfo = model.GetSpeculativeSymbolInfo(baseWithargs.SpanStart, (SyntaxNode)speculativePrimaryInitializer, SpeculativeBindingOption.BindAsExpression);
+ Assert.Equal(SymbolInfo.None, symbolInfo);
+
+ symbolInfo = CSharpExtensions.GetSpeculativeSymbolInfo(model, baseWithargs.SpanStart, speculativePrimaryInitializer);
+ Assert.Equal(SymbolInfo.None, symbolInfo);
+
+ symbolInfo = model.GetSpeculativeSymbolInfo(baseWithargs.ArgumentList.OpenParenToken.SpanStart, (SyntaxNode)speculativePrimaryInitializer, SpeculativeBindingOption.BindAsExpression);
+ Assert.Equal(SymbolInfo.None, symbolInfo);
+
+ symbolInfo = CSharpExtensions.GetSpeculativeSymbolInfo(model, baseWithargs.ArgumentList.OpenParenToken.SpanStart, speculativePrimaryInitializer);
+ Assert.Equal(SymbolInfo.None, symbolInfo);
+
+ Assert.Equal(TypeInfo.None, model.GetSpeculativeTypeInfo(baseWithargs.ArgumentList.OpenParenToken.SpanStart, (SyntaxNode)speculativePrimaryInitializer, SpeculativeBindingOption.BindAsExpression));
+ Assert.Equal(TypeInfo.None, model.GetSpeculativeTypeInfo(tree.GetRoot().DescendantNodes().OfType().Single().ArgumentList.OpenParenToken.SpanStart,
+ (SyntaxNode)speculativePrimaryInitializer, SpeculativeBindingOption.BindAsExpression));
+ }
+ {
+ var baseWithargs = tree.GetRoot().DescendantNodes().OfType().Single();
+ Assert.Equal(": base(X, Y, Z, 1)", baseWithargs.ToString());
+ symbolInfo = model.GetSymbolInfo((SyntaxNode)baseWithargs);
+ Assert.Null(symbolInfo.Symbol);
+ Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason);
+ string[] candidates = new[] { "Base..ctor(System.Int32 X)", "Base..ctor()" };
+ Assert.Equal(candidates, symbolInfo.CandidateSymbols.Select(m => m.ToTestDisplayString()));
+ symbolInfo = model.GetSymbolInfo(baseWithargs);
+ Assert.Null(symbolInfo.Symbol);
+ Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason);
+ Assert.Equal(candidates, symbolInfo.CandidateSymbols.Select(m => m.ToTestDisplayString()));
+ symbolInfo = CSharpExtensions.GetSymbolInfo(model, baseWithargs);
+ Assert.Null(symbolInfo.Symbol);
+ Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason);
+ Assert.Equal(candidates, symbolInfo.CandidateSymbols.Select(m => m.ToTestDisplayString()));
+
+ Assert.Empty(model.GetMemberGroup((SyntaxNode)baseWithargs).Select(m => m.ToTestDisplayString()));
+ Assert.Empty(model.GetMemberGroup(baseWithargs).Select(m => m.ToTestDisplayString()));
+ Assert.Empty(CSharpExtensions.GetMemberGroup(model, baseWithargs).Select(m => m.ToTestDisplayString()));
+
+ Assert.False(model.TryGetSpeculativeSemanticModel(baseWithargs.ArgumentList.OpenParenToken.SpanStart, speculativePrimaryInitializer, out _));
+
+ symbolInfo = model.GetSpeculativeSymbolInfo(baseWithargs.ArgumentList.OpenParenToken.SpanStart, speculativePrimaryInitializer);
+ Assert.Equal(SymbolInfo.None, symbolInfo);
+
+ symbolInfo = model.GetSpeculativeSymbolInfo(baseWithargs.ArgumentList.OpenParenToken.SpanStart, (SyntaxNode)speculativeBaseInitializer, SpeculativeBindingOption.BindAsExpression);
+ Assert.Equal("Base..ctor(System.Int32 X)", symbolInfo.Symbol.ToTestDisplayString());
+
+ symbolInfo = CSharpExtensions.GetSpeculativeSymbolInfo(model, baseWithargs.ArgumentList.OpenParenToken.SpanStart, speculativeBaseInitializer);
+ Assert.Equal("Base..ctor(System.Int32 X)", symbolInfo.Symbol.ToTestDisplayString());
+
+ Assert.Equal(TypeInfo.None, model.GetSpeculativeTypeInfo(baseWithargs.ArgumentList.OpenParenToken.SpanStart, (SyntaxNode)speculativePrimaryInitializer, SpeculativeBindingOption.BindAsExpression));
+ }
+ }
+
[Fact(Skip = "record struct")]
public void Equality_01()
{
diff --git a/src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelAPITests.cs b/src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelAPITests.cs
index e7080f3e3a947..f66303e94ff84 100644
--- a/src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelAPITests.cs
+++ b/src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelAPITests.cs
@@ -2145,7 +2145,7 @@ void M(int x)
SemanticModel speculativeModel;
Assert.Throws(() => model.TryGetSpeculativeSemanticModel(statement.SpanStart, statement: null, speculativeModel: out speculativeModel));
- Assert.Throws(() => model.TryGetSpeculativeSemanticModel(statement.SpanStart, constructorInitializer: null, speculativeModel: out speculativeModel));
+ Assert.Throws(() => model.TryGetSpeculativeSemanticModel(statement.SpanStart, constructorInitializer: (ConstructorInitializerSyntax)null, speculativeModel: out speculativeModel));
Assert.Throws(() => model.TryGetSpeculativeSemanticModel(statement.SpanStart, attribute: null, speculativeModel: out speculativeModel));
// Speculate on a node from the same syntax tree.
diff --git a/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs b/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs
index 68752b7c4a6ab..1fe6a5b00fce9 100644
--- a/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs
+++ b/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs
@@ -485,7 +485,10 @@ private static Syntax.InternalSyntax.BaseListSyntax GenerateBaseList()
=> InternalSyntaxFactory.BaseList(InternalSyntaxFactory.Token(SyntaxKind.ColonToken), new Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList());
private static Syntax.InternalSyntax.SimpleBaseTypeSyntax GenerateSimpleBaseType()
- => InternalSyntaxFactory.SimpleBaseType(GenerateIdentifierName(), null);
+ => InternalSyntaxFactory.SimpleBaseType(GenerateIdentifierName());
+
+ private static Syntax.InternalSyntax.PrimaryConstructorBaseTypeSyntax GeneratePrimaryConstructorBaseType()
+ => InternalSyntaxFactory.PrimaryConstructorBaseType(GenerateIdentifierName(), GenerateArgumentList());
private static Syntax.InternalSyntax.TypeParameterConstraintClauseSyntax GenerateTypeParameterConstraintClause()
=> InternalSyntaxFactory.TypeParameterConstraintClause(InternalSyntaxFactory.Token(SyntaxKind.WhereKeyword), GenerateIdentifierName(), InternalSyntaxFactory.Token(SyntaxKind.ColonToken), new Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList());
@@ -2690,7 +2693,17 @@ public void TestSimpleBaseTypeFactoryAndProperties()
var node = GenerateSimpleBaseType();
Assert.NotNull(node.Type);
- Assert.Null(node.ArgumentList);
+
+ AttachAndCheckDiagnostics(node);
+ }
+
+ [Fact]
+ public void TestPrimaryConstructorBaseTypeFactoryAndProperties()
+ {
+ var node = GeneratePrimaryConstructorBaseType();
+
+ Assert.NotNull(node.Type);
+ Assert.NotNull(node.ArgumentList);
AttachAndCheckDiagnostics(node);
}
@@ -7700,6 +7713,32 @@ public void TestSimpleBaseTypeIdentityRewriter()
Assert.Same(oldNode, newNode);
}
+ [Fact]
+ public void TestPrimaryConstructorBaseTypeTokenDeleteRewriter()
+ {
+ var oldNode = GeneratePrimaryConstructorBaseType();
+ var rewriter = new TokenDeleteRewriter();
+ var newNode = rewriter.Visit(oldNode);
+
+ if(!oldNode.IsMissing)
+ {
+ Assert.NotEqual(oldNode, newNode);
+ }
+
+ Assert.NotNull(newNode);
+ Assert.True(newNode.IsMissing, "No tokens => missing");
+ }
+
+ [Fact]
+ public void TestPrimaryConstructorBaseTypeIdentityRewriter()
+ {
+ var oldNode = GeneratePrimaryConstructorBaseType();
+ var rewriter = new IdentityRewriter();
+ var newNode = rewriter.Visit(oldNode);
+
+ Assert.Same(oldNode, newNode);
+ }
+
[Fact]
public void TestTypeParameterConstraintClauseTokenDeleteRewriter()
{
@@ -9870,7 +9909,10 @@ private static BaseListSyntax GenerateBaseList()
=> SyntaxFactory.BaseList(SyntaxFactory.Token(SyntaxKind.ColonToken), new SeparatedSyntaxList());
private static SimpleBaseTypeSyntax GenerateSimpleBaseType()
- => SyntaxFactory.SimpleBaseType(GenerateIdentifierName(), default(ArgumentListSyntax));
+ => SyntaxFactory.SimpleBaseType(GenerateIdentifierName());
+
+ private static PrimaryConstructorBaseTypeSyntax GeneratePrimaryConstructorBaseType()
+ => SyntaxFactory.PrimaryConstructorBaseType(GenerateIdentifierName(), GenerateArgumentList());
private static TypeParameterConstraintClauseSyntax GenerateTypeParameterConstraintClause()
=> SyntaxFactory.TypeParameterConstraintClause(SyntaxFactory.Token(SyntaxKind.WhereKeyword), GenerateIdentifierName(), SyntaxFactory.Token(SyntaxKind.ColonToken), new SeparatedSyntaxList());
@@ -12075,7 +12117,17 @@ public void TestSimpleBaseTypeFactoryAndProperties()
var node = GenerateSimpleBaseType();
Assert.NotNull(node.Type);
- Assert.Null(node.ArgumentList);
+ var newNode = node.WithType(node.Type);
+ Assert.Equal(node, newNode);
+ }
+
+ [Fact]
+ public void TestPrimaryConstructorBaseTypeFactoryAndProperties()
+ {
+ var node = GeneratePrimaryConstructorBaseType();
+
+ Assert.NotNull(node.Type);
+ Assert.NotNull(node.ArgumentList);
var newNode = node.WithType(node.Type).WithArgumentList(node.ArgumentList);
Assert.Equal(node, newNode);
}
@@ -17085,6 +17137,32 @@ public void TestSimpleBaseTypeIdentityRewriter()
Assert.Same(oldNode, newNode);
}
+ [Fact]
+ public void TestPrimaryConstructorBaseTypeTokenDeleteRewriter()
+ {
+ var oldNode = GeneratePrimaryConstructorBaseType();
+ var rewriter = new TokenDeleteRewriter();
+ var newNode = rewriter.Visit(oldNode);
+
+ if(!oldNode.IsMissing)
+ {
+ Assert.NotEqual(oldNode, newNode);
+ }
+
+ Assert.NotNull(newNode);
+ Assert.True(newNode.IsMissing, "No tokens => missing");
+ }
+
+ [Fact]
+ public void TestPrimaryConstructorBaseTypeIdentityRewriter()
+ {
+ var oldNode = GeneratePrimaryConstructorBaseType();
+ var rewriter = new IdentityRewriter();
+ var newNode = rewriter.Visit(oldNode);
+
+ Assert.Same(oldNode, newNode);
+ }
+
[Fact]
public void TestTypeParameterConstraintClauseTokenDeleteRewriter()
{
diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/RecordParsing.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/RecordParsing.cs
index e18ae00885564..60c4e35205323 100644
--- a/src/Compilers/CSharp/Test/Syntax/Parsing/RecordParsing.cs
+++ b/src/Compilers/CSharp/Test/Syntax/Parsing/RecordParsing.cs
@@ -1499,7 +1499,7 @@ public void Base_01(
N(SyntaxKind.BaseList);
{
N(SyntaxKind.ColonToken);
- N(SyntaxKind.SimpleBaseType);
+ N(withBaseArguments ? SyntaxKind.PrimaryConstructorBaseType : SyntaxKind.SimpleBaseType);
{
N(SyntaxKind.IdentifierName);
{
@@ -1797,7 +1797,7 @@ public void Base_05()
N(SyntaxKind.BaseList);
{
N(SyntaxKind.ColonToken);
- N(SyntaxKind.SimpleBaseType);
+ N(SyntaxKind.PrimaryConstructorBaseType);
{
N(SyntaxKind.IdentifierName);
{