diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
index ea2cf793cc199788e15378a3e474f61b1c13f8e1..f9130d2783046663d94dc991524d1139f7ea695c 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
@@ -20,7 +20,7 @@ namespace Microsoft.CodeAnalysis.CSharp
internal partial class Binder
{
///
- /// This is the set of parameters and local variables that were used as arguments to
+ /// This is the set of parameters and local variables that were used as arguments to
/// lock or using statements in enclosing scopes.
///
///
@@ -153,8 +153,8 @@ public virtual BoundStatement BindStatement(StatementSyntax node, DiagnosticBag
Debug.Assert(result.Syntax is StatementSyntax, "BoundStatement should be associated with a statement syntax.");
- Debug.Assert(System.Linq.Enumerable.Contains(result.Syntax.AncestorsAndSelf(), node), @"Bound statement (or one of its parents)
- should have same syntax as the given syntax node.
+ Debug.Assert(System.Linq.Enumerable.Contains(result.Syntax.AncestorsAndSelf(), node), @"Bound statement (or one of its parents)
+ should have same syntax as the given syntax node.
Otherwise it may be confusing to the binder cache that uses syntax node as keys.");
return result;
@@ -467,7 +467,7 @@ private BoundLabeledStatement BindLabeled(LabeledStatementSyntax node, Diagnosti
HashSet useSiteDiagnostics = null;
var binder = this.LookupSymbolsWithFallback(result, node.Identifier.ValueText, arity: 0, useSiteDiagnostics: ref useSiteDiagnostics, options: LookupOptions.LabelsOnly);
- // result.Symbols can be empty in some malformed code, e.g. when a labeled statement is used an embedded statement in an if or foreach statement
+ // result.Symbols can be empty in some malformed code, e.g. when a labeled statement is used an embedded statement in an if or foreach statement
// In this case we create new label symbol on the fly, and an error is reported by parser
var symbol = result.Symbols.Count > 0 && result.IsMultiViable ?
(LabelSymbol)result.Symbols.First() :
@@ -776,7 +776,7 @@ private TypeWithAnnotations BindVariableTypeWithAnnotations(CSharpSyntaxNode dec
if (isVar)
{
- // There are a number of ways in which a var decl can be illegal, but in these
+ // There are a number of ways in which a var decl can be illegal, but in these
// cases we should report an error and then keep right on going with the inference.
if (isConst)
@@ -793,11 +793,11 @@ private TypeWithAnnotations BindVariableTypeWithAnnotations(CSharpSyntaxNode dec
// users showed that there was no consensus on whether the above should mean
// "double x = 10, y = 123.4;", taking the best type available and substituting
// that for "var", or treating it as "var x = 10; var y = 123.4;" -- since there
- // was no consensus we decided to simply make it illegal.
+ // was no consensus we decided to simply make it illegal.
//
// In dev10 for error recovery in the IDE we do an odd thing -- we simply take
// the type of the first variable and use it. So that is "int x = 10, y = 123.4;".
- //
+ //
// This seems less than ideal. In the error recovery scenario it probably makes
// more sense to treat that as "var x = 10; var y = 123.4;" and do each inference
// separately.
@@ -813,7 +813,7 @@ private TypeWithAnnotations BindVariableTypeWithAnnotations(CSharpSyntaxNode dec
// In the native compiler when given a situation like
//
// D[] x;
- //
+ //
// where D is a static type we report both that D cannot be an element type
// of an array, and that D[] is not a valid type for a local variable.
// This seems silly; the first error is entirely sufficient. We no longer
@@ -867,7 +867,7 @@ protected BoundExpression BindInferredVariableInitializer(DiagnosticBag diagnost
BoundExpression expression = BindToNaturalType(BindValue(initializer, diagnostics, valueKind), diagnostics);
- // Certain expressions (null literals, method groups and anonymous functions) have no type of
+ // Certain expressions (null literals, method groups and anonymous functions) have no type of
// their own and therefore cannot be the initializer of an implicitly typed local.
if (!expression.HasAnyErrors && !expression.HasExpressionType())
{
@@ -990,7 +990,7 @@ protected BoundExpression BindInferredVariableInitializer(DiagnosticBag diagnost
initializerOpt = BindInferredVariableInitializer(diagnostics, value, valueKind, localSymbol.RefKind, declarator);
- // If we got a good result then swap the inferred type for the "var"
+ // If we got a good result then swap the inferred type for the "var"
TypeSymbol initializerType = initializerOpt?.Type;
if ((object)initializerType != null)
{
@@ -1030,7 +1030,7 @@ protected BoundExpression BindInferredVariableInitializer(DiagnosticBag diagnost
initializerOpt = BindPossibleArrayInitializer(value, declTypeOpt.Type, valueKind, diagnostics);
if (kind != LocalDeclarationKind.FixedVariable)
{
- // If this is for a fixed statement, we'll do our own conversion since there are some special cases.
+ // If this is for a fixed statement, we'll do our own conversion since there are some special cases.
initializerOpt = GenerateConversionForAssignment(
declTypeOpt.Type,
initializerOpt,
@@ -1091,9 +1091,9 @@ protected BoundExpression BindInferredVariableInitializer(DiagnosticBag diagnost
if (kind == LocalDeclarationKind.FixedVariable || kind == LocalDeclarationKind.UsingVariable)
{
- // CONSIDER: The error message is "you must provide an initializer in a fixed
- // CONSIDER: or using declaration". The error message could be targeted to
- // CONSIDER: the actual situation. "you must provide an initializer in a
+ // CONSIDER: The error message is "you must provide an initializer in a fixed
+ // CONSIDER: or using declaration". The error message could be targeted to
+ // CONSIDER: the actual situation. "you must provide an initializer in a
// CONSIDER: 'fixed' declaration."
if (initializerOpt == null)
@@ -1167,8 +1167,8 @@ protected bool CheckRefLocalInAsyncOrIteratorMethod(SyntaxToken identifierToken,
internal ImmutableArray BindDeclaratorArguments(VariableDeclaratorSyntax declarator, DiagnosticBag diagnostics)
{
- // It is possible that we have a bracketed argument list, like "int x[];" or "int x[123];"
- // in a non-fixed-size-array declaration . This is a common error made by C++ programmers.
+ // It is possible that we have a bracketed argument list, like "int x[];" or "int x[123];"
+ // in a non-fixed-size-array declaration . This is a common error made by C++ programmers.
// We have already given a good error at parse time telling the user to either make it "fixed"
// or to move the brackets to the type. However, we should still do semantic analysis of
// the arguments, so that errors in them are discovered, hovering over them in the IDE
@@ -1279,7 +1279,7 @@ private bool IsValidFixedVariableInitializer(TypeSymbol declType, SourceLocalSym
break;
}
- // if the feature was enabled, but something went wrong with the method, report that, otherwise don't.
+ // if the feature was enabled, but something went wrong with the method, report that, otherwise don't.
// If feature is not enabled, additional errors would be just noise.
bool extensibleFixedEnabled = ((CSharpParseOptions)initializerOpt.SyntaxTree.Options)?.IsFeatureEnabled(MessageID.IDS_FeatureExtensibleFixedStatement) != false;
if (extensibleFixedEnabled)
@@ -1466,11 +1466,11 @@ private BoundExpression InferTypeForDiscardAssignment(BoundDiscardExpression op1
if (!op1.HasAnyErrors)
{
- // Build bound conversion. The node might not be used if this is a dynamic conversion
+ // Build bound conversion. The node might not be used if this is a dynamic conversion
// but diagnostics should be reported anyways.
var conversion = GenerateConversionForAssignment(op1.Type, op2, diagnostics, isRefAssignment: isRef);
- // If the result is a dynamic assignment operation (SetMember or SetIndex),
+ // If the result is a dynamic assignment operation (SetMember or SetIndex),
// don't generate the boxing conversion to the dynamic type.
// Leave the values as they are, and deal with the conversions at runtime.
if (op1.Kind != BoundKind.DynamicIndexerAccess &&
@@ -1621,7 +1621,7 @@ private static bool AccessingAutoPropertyFromConstructor(BoundExpression receive
propertySymbol = propertySymbol.OriginalDefinition;
}
- var sourceProperty = propertySymbol as SourceOrRecordPropertySymbol;
+ var sourceProperty = propertySymbol as SourcePropertySymbolBase;
var propertyIsStatic = propertySymbol.IsStatic;
return (object)sourceProperty != null &&
@@ -1766,13 +1766,13 @@ internal BoundExpression GenerateConversionForAssignment(TypeSymbol targetType,
Debug.Assert((object)targetType != null);
Debug.Assert(expression != null);
- // We wish to avoid "cascading" errors, so if the expression we are
+ // We wish to avoid "cascading" errors, so if the expression we are
// attempting to convert to a type had errors, suppress additional
- // diagnostics. However, if the expression
+ // diagnostics. However, if the expression
// with errors is an unbound lambda then the errors are almost certainly
// syntax errors. For error recovery analysis purposes we wish to bind
// error lambdas like "Action f = x=>{ x. };" because IntelliSense
- // needs to know that x is of type int.
+ // needs to know that x is of type int.
if (expression.HasAnyErrors && expression.Kind != BoundKind.UnboundLambda)
{
@@ -1796,7 +1796,7 @@ internal BoundExpression GenerateConversionForAssignment(TypeSymbol targetType,
}
else if (!conversion.IsImplicit || !conversion.IsValid)
{
- // We suppress conversion errors on default parameters; eg,
+ // We suppress conversion errors on default parameters; eg,
// if someone says "void M(string s = 123) {}". We will report
// a special error in the default parameter binder.
@@ -1832,7 +1832,7 @@ internal BoundExpression GenerateConversionForAssignment(TypeSymbol targetType,
var reason = Conversions.IsAnonymousFunctionCompatibleWithType(anonymousFunction, targetType);
- // It is possible that the conversion from lambda to delegate is just fine, and
+ // It is possible that the conversion from lambda to delegate is just fine, and
// that we ended up here because the target type, though itself is not an error
// type, contains a type argument which is an error type. For example, converting
// (Goo goo)=>{} to Action is a perfectly legal conversion even if Goo is undefined!
@@ -1875,7 +1875,7 @@ internal BoundExpression GenerateConversionForAssignment(TypeSymbol targetType,
var delegateType = targetType.GetDelegateType();
- // The target type is a valid delegate or expression tree type. Is there something wrong with the
+ // The target type is a valid delegate or expression tree type. Is there something wrong with the
// parameter list?
// First off, is there a parameter list at all?
@@ -1889,7 +1889,7 @@ internal BoundExpression GenerateConversionForAssignment(TypeSymbol targetType,
// D d = delegate {};
//
// error CS1676: Parameter 1 must be declared with the 'out' keyword
- // error CS1688: Cannot convert anonymous method block without a parameter list
+ // error CS1688: Cannot convert anonymous method block without a parameter list
// to delegate type 'D' because it has one or more out parameters
//
// This seems redundant, (because there is no "parameter 1" in the source code)
@@ -1910,7 +1910,7 @@ internal BoundExpression GenerateConversionForAssignment(TypeSymbol targetType,
// The parameter list exists and had the right number of parameters. Were any of its types bad?
- // If any parameter type of the lambda is an error type then suppress
+ // If any parameter type of the lambda is an error type then suppress
// further errors. We've already reported errors on the bad type.
if (anonymousFunction.HasExplicitlyTypedParameterList)
{
@@ -2041,7 +2041,7 @@ internal BoundExpression GenerateConversionForAssignment(TypeSymbol targetType,
// CLEVERNESS: By passing ConstantValue.Bad, we tell HasImplicitConstantExpressionConversion to ignore the constant
// value and only consider the types.
- // If there would be an implicit constant conversion for a different constant of the same type
+ // If there would be an implicit constant conversion for a different constant of the same type
// (i.e. one that's not out of range), then it's more helpful to report the range check failure
// than to suggest inserting a cast.
Error(diagnostics, ErrorCode.ERR_ConstOutOfRange, syntax, sourceConstantValueOpt.Value, targetType);
@@ -2266,9 +2266,9 @@ void reportMethodGroupErrors(BoundMethodGroup methodGroup, bool fromAddressOf)
// report all leaf elements of the tuple literal that failed to convert
// NOTE: we are not responsible for reporting use site errors here, just the failed leaf conversions.
- // By the time we get here we have done analysis and know we have failed the cast in general, and diagnostics collected in the process is already in the bag.
+ // By the time we get here we have done analysis and know we have failed the cast in general, and diagnostics collected in the process is already in the bag.
// The only thing left is to form a diagnostics about the actually failing conversion(s).
- // This whole method does not itself collect any usesite diagnostics. Its only purpose is to produce an error better than "conversion failed here"
+ // This whole method does not itself collect any usesite diagnostics. Its only purpose is to produce an error better than "conversion failed here"
HashSet usDiagsUnused = null;
for (int i = 0; i < targetElementTypes.Length; i++)
@@ -2296,24 +2296,24 @@ private BoundStatement BindIfStatement(IfStatementSyntax node, DiagnosticBag dia
internal BoundExpression BindBooleanExpression(ExpressionSyntax node, DiagnosticBag diagnostics)
{
- // SPEC:
- // A boolean-expression is an expression that yields a result of type bool;
- // either directly or through application of operator true in certain
+ // SPEC:
+ // A boolean-expression is an expression that yields a result of type bool;
+ // either directly or through application of operator true in certain
// contexts as specified in the following.
//
- // The controlling conditional expression of an if-statement, while-statement,
- // do-statement, or for-statement is a boolean-expression. The controlling
- // conditional expression of the ?: operator follows the same rules as a
+ // The controlling conditional expression of an if-statement, while-statement,
+ // do-statement, or for-statement is a boolean-expression. The controlling
+ // conditional expression of the ?: operator follows the same rules as a
// boolean-expression, but for reasons of operator precedence is classified
// as a conditional-or-expression.
//
- // A boolean-expression is required to be implicitly convertible to bool
- // or of a type that implements operator true. If neither requirement
+ // A boolean-expression is required to be implicitly convertible to bool
+ // or of a type that implements operator true. If neither requirement
// is satisfied, a binding-time error occurs.
//
- // When a boolean expression cannot be implicitly converted to bool but does
- // implement operator true, then following evaluation of the expression,
- // the operator true implementation provided by that type is invoked
+ // When a boolean expression cannot be implicitly converted to bool but does
+ // implement operator true, then following evaluation of the expression,
+ // the operator true implementation provided by that type is invoked
// to produce a bool value.
//
// SPEC ERROR: The third paragraph above is obviously not correct; we need
@@ -2420,7 +2420,7 @@ internal BoundExpression BindBooleanExpression(ExpressionSyntax node, Diagnostic
diagnostics: diagnostics);
// Consider op_true to be compiler-generated so that it doesn't appear in the semantic model.
- // UNDONE: If we decide to expose the operator in the semantic model, we'll have to remove the
+ // UNDONE: If we decide to expose the operator in the semantic model, we'll have to remove the
// WasCompilerGenerated flag (and possibly suppress the symbol in specific APIs).
return new BoundUnaryOperator(node, signature.Kind, resultOperand, ConstantValue.NotAvailable, signature.Method, resultKind, originalUserDefinedOperators, signature.ReturnType)
{
@@ -2511,7 +2511,7 @@ internal BoundStatement BindForOrUsingOrFixedDeclarations(VariableDeclarationSyn
if (isVar && count > 1)
{
- // There are a number of ways in which a var decl can be illegal, but in these
+ // There are a number of ways in which a var decl can be illegal, but in these
// cases we should report an error and then keep right on going with the inference.
Error(diagnostics, ErrorCode.ERR_ImplicitlyTypedVariableMultipleDeclarator, nodeOpt);
@@ -2729,8 +2729,8 @@ private BoundStatement BindReturn(ReturnStatementSyntax syntax, DiagnosticBag di
return new BoundReturnStatement(syntax, refKind, BindToTypeForErrorRecovery(arg), hasErrors: true);
}
- // The return type could be null; we might be attempting to infer the return type either
- // because of method type inference, or because we are attempting to do error analysis
+ // The return type could be null; we might be attempting to infer the return type either
+ // because of method type inference, or because we are attempting to do error analysis
// on a lambda expression of unknown return type.
if ((object)retType != null)
{
@@ -2742,7 +2742,7 @@ private BoundStatement BindReturn(ReturnStatementSyntax syntax, DiagnosticBag di
var lambda = container as LambdaSymbol;
if ((object)lambda != null)
{
- // Error case: void-returning or async task-returning method or lambda with "return x;"
+ // Error case: void-returning or async task-returning method or lambda with "return x;"
var errorCode = retType.IsVoidType()
? ErrorCode.ERR_RetNoObjectRequiredLambda
: ErrorCode.ERR_TaskRetNoObjectRequiredLambda;
@@ -2754,12 +2754,12 @@ private BoundStatement BindReturn(ReturnStatementSyntax syntax, DiagnosticBag di
// COMPATIBILITY: The native compiler also produced an error
// COMPATIBILITY: "Cannot convert lambda expression to delegate type 'Action' because some of the
// COMPATIBILITY: return types in the block are not implicitly convertible to the delegate return type"
- // COMPATIBILITY: This error doesn't make sense in the "void" case because the whole idea of
+ // COMPATIBILITY: This error doesn't make sense in the "void" case because the whole idea of
// COMPATIBILITY: "conversion to void" is a bit unusual, and we've already given a good error.
}
else
{
- // Error case: void-returning or async task-returning method or lambda with "return x;"
+ // Error case: void-returning or async task-returning method or lambda with "return x;"
var errorCode = retType.IsVoidType()
? ErrorCode.ERR_RetNoObjectRequired
: ErrorCode.ERR_TaskRetNoObjectRequired;
@@ -2963,7 +2963,7 @@ private BoundCatchBlock BindCatchBlock(CatchClauseSyntax node, ArrayBuilder
- /// Wrap a given expression e into a block as either { e; } or { return e; }
+ /// Wrap a given expression e into a block as either { e; } or { return e; }
/// Shared between lambda and expression-bodied method binding.
///
internal BoundBlock CreateBlockFromExpression(CSharpSyntaxNode node, ImmutableArray locals, RefKind refKind, BoundExpression expression, ExpressionSyntax expressionSyntax, DiagnosticBag diagnostics)
@@ -3422,7 +3422,7 @@ internal virtual ImmutableArray Labels
}
///
- /// Perform a lookup for the specified method on the specified expression by attempting to invoke it
+ /// Perform a lookup for the specified method on the specified expression by attempting to invoke it
///
/// The expression to perform pattern lookup on
/// Method to search for.
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs
index 31f4f4729a67f14babb53e393f0b386231ebd221..b7c177257d9dfca1e15a9be74341555bc151dd5c 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs
@@ -383,17 +383,17 @@ internal NamespaceOrTypeOrAliasSymbolWithAnnotations BindNamespaceOrTypeSymbol(E
#nullable enable
///
- /// Bind the syntax into a namespace, type or alias symbol.
+ /// Bind the syntax into a namespace, type or alias symbol.
///
///
/// This method is used in deeply recursive parts of the compiler. Specifically this and
///
- /// are mutually recursive. The non-recursive parts of this method tend to reserve significantly large
+ /// are mutually recursive. The non-recursive parts of this method tend to reserve significantly large
/// stack frames due to their use of large struct like .
///
- /// To keep the stack frame size on recursive paths small the non-recursive parts are factored into local
- /// functions. This means we pay their stack penalty only when they are used. They are themselves big
- /// enough they should be disqualified from inlining. In the future when attributes are allowed on
+ /// To keep the stack frame size on recursive paths small the non-recursive parts are factored into local
+ /// functions. This means we pay their stack penalty only when they are used. They are themselves big
+ /// enough they should be disqualified from inlining. In the future when attributes are allowed on
/// local functions we should explicitly mark them as
///
internal NamespaceOrTypeOrAliasSymbolWithAnnotations BindNamespaceOrTypeOrAliasSymbol(ExpressionSyntax syntax, DiagnosticBag diagnostics, ConsList basesBeingResolved, bool suppressUseSiteDiagnostics)
@@ -757,7 +757,7 @@ private NamedTypeSymbol BindPredefinedTypeSymbol(PredefinedTypeSyntax node, Diag
}
///
- /// Binds a simple name or the simple name portion of a qualified name.
+ /// Binds a simple name or the simple name portion of a qualified name.
///
private NamespaceOrTypeOrAliasSymbolWithAnnotations BindSimpleNamespaceOrTypeOrAliasSymbol(
SimpleNameSyntax syntax,
@@ -766,10 +766,10 @@ private NamedTypeSymbol BindPredefinedTypeSymbol(PredefinedTypeSyntax node, Diag
bool suppressUseSiteDiagnostics,
NamespaceOrTypeSymbol qualifierOpt = null)
{
- // Note that the comment above is a small lie; there is no such thing as the "simple name portion" of
+ // Note that the comment above is a small lie; there is no such thing as the "simple name portion" of
// a qualified alias member expression. A qualified alias member expression has the form
// "identifier :: identifier optional-type-arguments" -- the right hand side of which
- // happens to match the syntactic form of a simple name. As a convenience, we analyze the
+ // happens to match the syntactic form of a simple name. As a convenience, we analyze the
// right hand side of the "::" here because it is so similar to a simple name; the left hand
// side is in qualifierOpt.
@@ -819,7 +819,7 @@ private static bool IsViableType(LookupResult result)
var identifierValueText = node.Identifier.ValueText;
// If we are here in an error-recovery scenario, say, "goo(123);" then
- // we might have an 'empty' simple name. In that case do not report an
+ // we might have an 'empty' simple name. In that case do not report an
// 'unable to find ""' error; we've already reported an error in the parser so
// just bail out with an error symbol.
@@ -945,9 +945,9 @@ private static LookupOptions GetSimpleNameLookupOptions(NameSyntax node, bool is
{
if (SyntaxFacts.IsAttributeName(node))
{
- // SPEC: By convention, attribute classes are named with a suffix of Attribute.
+ // SPEC: By convention, attribute classes are named with a suffix of Attribute.
// SPEC: An attribute-name of the form type-name may either include or omit this suffix.
- // SPEC: If an attribute class is found both with and without this suffix, an ambiguity
+ // SPEC: If an attribute class is found both with and without this suffix, an ambiguity
// SPEC: is present, and a compile-time error results. If the attribute-name is spelled
// SPEC: such that its right-most identifier is a verbatim identifier (ยง2.4.2), then only
// SPEC: an attribute without a suffix is matched, thus enabling such an ambiguity to be resolved.
@@ -1036,10 +1036,10 @@ private Symbol UnwrapAlias(Symbol symbol, out AliasSymbol alias, DiagnosticBag d
// us an identifier followed by a type argument list. Therefore they
// must expect the result to be a generic type, and not a namespace or alias.
- // The result of this method will therefore always be a type symbol of the
+ // The result of this method will therefore always be a type symbol of the
// correct arity, though it might have to be an error type.
- // We might be asked to bind a generic simple name of the form "T<,,,>",
+ // We might be asked to bind a generic simple name of the form "T<,,,>",
// which is only legal in the context of "typeof(T<,,,>)". If we are given
// no type arguments and we are not in such a context, we'll give an error.
@@ -1051,15 +1051,15 @@ private Symbol UnwrapAlias(Symbol symbol, out AliasSymbol alias, DiagnosticBag d
// * Lookup could fail to find anything at all.
// * Lookup could find a type of the wrong arity
// * Lookup could find something but it is not a type.
- //
+ //
// Second, we could be asked to resolve an unbound type T<,,,> when
- // not in a context where it is legal to do so. Note that this is
- // intended an improvement over the analysis performed by the
- // native compiler; in the native compiler we catch bad uses of unbound
+ // not in a context where it is legal to do so. Note that this is
+ // intended an improvement over the analysis performed by the
+ // native compiler; in the native compiler we catch bad uses of unbound
// types at parse time, not at semantic analysis time. That means that
// we end up giving confusing "unexpected comma" or "expected type"
// errors when it would be more informative to the user to simply
- // tell them that an unbound type is not legal in this position.
+ // tell them that an unbound type is not legal in this position.
//
// This also means that we can get semantic analysis of the open
// type in the IDE even in what would have been a syntax error case
@@ -1072,11 +1072,11 @@ private Symbol UnwrapAlias(Symbol symbol, out AliasSymbol alias, DiagnosticBag d
// a partially unbound type.
//
// The heuristic we will use is that the former kind of error takes priority
- // over the latter; if the meaning of "Bogus<>" cannot be successfully
+ // over the latter; if the meaning of "Bogus<>" cannot be successfully
// determined then there is no point telling the user that in addition,
// it is syntactically wrong. Moreover, at this point we do not know what they
- // mean by the remainder ".Blah" of the expression and so it seems wrong to
- // deduce more errors from it.
+ // mean by the remainder ".Blah" of the expression and so it seems wrong to
+ // deduce more errors from it.
var plainName = node.Identifier.ValueText;
@@ -1114,9 +1114,9 @@ private Symbol UnwrapAlias(Symbol symbol, out AliasSymbol alias, DiagnosticBag d
}
else
{
- // It's not an unbound type expression, so we must have type arguments, and we have a
- // generic type of the correct arity in hand (possibly an error type). Bind the type
- // arguments and construct the final result.
+ // It's not an unbound type expression, so we must have type arguments, and we have a
+ // generic type of the correct arity in hand (possibly an error type). Bind the type
+ // arguments and construct the final result.
resultType = ConstructNamedType(
unconstructedType,
node,
@@ -1172,12 +1172,12 @@ private Symbol UnwrapAlias(Symbol symbol, out AliasSymbol alias, DiagnosticBag d
// In the third case we will be given back the symbol -- say, a local variable symbol.
//
// In all three cases the appropriate error has already been reported. (That the
- // type was not found, that the generic type found does not have that arity, that
+ // type was not found, that the generic type found does not have that arity, that
// the non-generic type found cannot be used with a type argument list, or that
// the symbol found is not something that takes type arguments. )
// The first thing to do is to make sure that we have some sort of generic type in hand.
- // (Note that an error type symbol is always a generic type.)
+ // (Note that an error type symbol is always a generic type.)
NamedTypeSymbol type = lookupResultSymbol as NamedTypeSymbol;
@@ -1489,7 +1489,16 @@ internal static bool ReportUseSiteDiagnostics(Symbol symbol, DiagnosticBag diagn
///
internal NamedTypeSymbol GetWellKnownType(WellKnownType type, DiagnosticBag diagnostics, SyntaxNode node)
{
- return GetWellKnownType(this.Compilation, type, diagnostics, node.Location);
+ return GetWellKnownType(type, diagnostics, node.Location);
+ }
+
+ ///
+ /// This is a layer on top of the Compilation version that generates a diagnostic if the well-known
+ /// type isn't found.
+ ///
+ internal NamedTypeSymbol GetWellKnownType(WellKnownType type, DiagnosticBag diagnostics, Location location)
+ {
+ return GetWellKnownType(this.Compilation, type, diagnostics, location);
}
///
@@ -1892,7 +1901,7 @@ public int Compare(Symbol fst, Symbol snd)
Compilation.IsAttributeType((NamedTypeSymbol)first) &&
Compilation.IsAttributeType((NamedTypeSymbol)second))
{
- // SPEC: If an attribute class is found both with and without Attribute suffix, an ambiguity
+ // SPEC: If an attribute class is found both with and without Attribute suffix, an ambiguity
// SPEC: is present, and a compile-time error results.
info = new CSDiagnosticInfo(ErrorCode.ERR_AmbiguousAttribute, originalSymbols,
@@ -1960,7 +1969,7 @@ public int Compare(Symbol fst, Symbol snd)
}
else if (singleResult.Kind == SymbolKind.ErrorType)
{
- // We want to report ERR_CircularBase error on the spot to make sure
+ // We want to report ERR_CircularBase error on the spot to make sure
// that the right location is used for it.
var errorType = (ErrorTypeSymbol)singleResult;
@@ -2341,7 +2350,7 @@ protected AssemblySymbol GetForwardedToAssembly(string fullName, DiagnosticBag d
/// The name of the (potentially) forwarded type.
/// The arity of the forwarded type.
/// The namespace of the potentially forwarded type. If none is provided, will
- /// try Usings of the current import for eligible namespaces and return the namespace of the found forwarder,
+ /// try Usings of the current import for eligible namespaces and return the namespace of the found forwarder,
/// if any.
/// Will be used to report non-fatal errors during look up.
/// Location to report errors on.
@@ -2355,8 +2364,8 @@ protected AssemblySymbol GetForwardedToAssembly(string name, int arity, ref Name
// If we are in the process of binding assembly level attributes, we might get into an infinite cycle
// if any of the referenced assemblies forwards type to this assembly. Since forwarded types
// are specified through assembly level attributes, an attempt to resolve the forwarded type
- // might require us to examine types forwarded by this assembly, thus binding assembly level
- // attributes again. And the cycle continues.
+ // might require us to examine types forwarded by this assembly, thus binding assembly level
+ // attributes again. And the cycle continues.
// So, we won't do the analysis in this case, at the expense of better diagnostics.
if ((this.Flags & BinderFlags.InContextualAttributeBinder) != 0)
{
diff --git a/src/Compilers/CSharp/Portable/Compiler/MethodBodySynthesizer.cs b/src/Compilers/CSharp/Portable/Compiler/MethodBodySynthesizer.cs
index 60622484421bb54beea585dca87e1fd99b32b9a2..1fc5ee975f8cbf868bf241d0efa93b9732f01d43 100644
--- a/src/Compilers/CSharp/Portable/Compiler/MethodBodySynthesizer.cs
+++ b/src/Compilers/CSharp/Portable/Compiler/MethodBodySynthesizer.cs
@@ -12,7 +12,7 @@
namespace Microsoft.CodeAnalysis.CSharp
{
///
- /// Contains methods related to synthesizing bound nodes in initial binding
+ /// Contains methods related to synthesizing bound nodes in initial binding
/// form that needs lowering, primarily method bodies for compiler-generated methods.
///
internal static class MethodBodySynthesizer
@@ -25,8 +25,8 @@ internal static class MethodBodySynthesizer
{
// Script field initializers have to be emitted after the call to the base constructor because they can refer to "this" instance.
//
- // Unlike regular field initializers, initializers of global script variables can access "this" instance.
- // If the base class had a constructor that initializes its state a global variable would access partially initialized object.
+ // Unlike regular field initializers, initializers of global script variables can access "this" instance.
+ // If the base class had a constructor that initializes its state a global variable would access partially initialized object.
// For this reason Script class must always derive directly from a class that has no state (System.Object).
SyntaxNode syntax = loweredBody.Syntax;
@@ -172,7 +172,7 @@ internal static BoundBlock ConstructAutoPropertyAccessorBody(SourceMemberMethodS
{
Debug.Assert(accessor.MethodKind == MethodKind.PropertyGet || accessor.MethodKind == MethodKind.PropertySet);
- var property = (SourcePropertySymbol)accessor.AssociatedSymbol;
+ var property = (SourcePropertySymbolBase)accessor.AssociatedSymbol;
CSharpSyntaxNode syntax = property.CSharpSyntaxNode;
BoundExpression thisReference = null;
if (!accessor.IsStatic)
@@ -219,10 +219,10 @@ internal static BoundBlock ConstructFieldLikeEventAccessorBody(SourceEventSymbol
///
/// Generate a thread-safe accessor for a WinRT field-like event.
- ///
+ ///
/// Add:
/// return EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).AddEventHandler(value);
- ///
+ ///
/// Remove:
/// EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).RemoveEventHandler(value);
///
@@ -302,7 +302,7 @@ internal static BoundBlock ConstructFieldLikeEventAccessorBody_WinRT(SourceEvent
{
// {
// return EventRegistrationTokenTable.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).AddHandler(value);
- // }
+ // }
BoundStatement returnStatement = BoundReturnStatement.Synthesized(syntax, RefKind.None, processHandlerCall);
return BoundBlock.SynthesizedNoLocals(syntax, returnStatement);
}
@@ -311,7 +311,7 @@ internal static BoundBlock ConstructFieldLikeEventAccessorBody_WinRT(SourceEvent
// {
// EventRegistrationTokenTable.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).RemoveHandler(value);
// return;
- // }
+ // }
BoundStatement callStatement = new BoundExpressionStatement(syntax, processHandlerCall);
BoundStatement returnStatement = new BoundReturnStatement(syntax, RefKind.None, expressionOpt: null);
return BoundBlock.SynthesizedNoLocals(syntax, callStatement, returnStatement);
@@ -320,7 +320,7 @@ internal static BoundBlock ConstructFieldLikeEventAccessorBody_WinRT(SourceEvent
///
/// Generate a thread-safe accessor for a regular field-like event.
- ///
+ ///
/// DelegateType tmp0 = _event; //backing field
/// DelegateType tmp1;
/// DelegateType tmp2;
@@ -329,12 +329,12 @@ internal static BoundBlock ConstructFieldLikeEventAccessorBody_WinRT(SourceEvent
/// tmp2 = (DelegateType)Delegate.Combine(tmp1, value); //Remove for -=
/// tmp0 = Interlocked.CompareExchange<DelegateType>(ref _event, tmp2, tmp1);
/// } while ((object)tmp0 != (object)tmp1);
- ///
+ ///
/// Note, if System.Threading.Interlocked.CompareExchange<T> is not available,
/// we emit the following code and mark the method Synchronized (unless it is a struct).
- ///
+ ///
/// _event = (DelegateType)Delegate.Combine(_event, value); //Remove for -=
- ///
+ ///
///
internal static BoundBlock ConstructFieldLikeEventAccessorBody_Regular(SourceEventSymbol eventSymbol, bool isAddMethod, CSharpCompilation compilation, DiagnosticBag diagnostics)
{
@@ -522,7 +522,7 @@ internal static BoundBlock ConstructDestructorBody(MethodSymbol method, BoundBlo
Debug.Assert(method.MethodKind == MethodKind.Destructor);
Debug.Assert(syntax.Kind() == SyntaxKind.Block || syntax.Kind() == SyntaxKind.ArrowExpressionClause);
- // If this is a destructor and a base type has a Finalize method (see GetBaseTypeFinalizeMethod for exact
+ // If this is a destructor and a base type has a Finalize method (see GetBaseTypeFinalizeMethod for exact
// requirements), then we need to call that method in a finally block. Otherwise, just return block as-is.
// NOTE: the Finalize method need not be a destructor or be overridden by the current method.
MethodSymbol baseTypeFinalize = GetBaseTypeFinalizeMethod(method);
@@ -572,11 +572,11 @@ internal static BoundBlock ConstructDestructorBody(MethodSymbol method, BoundBlo
}
///
- /// Look for a base type method named "Finalize" that is protected (or protected internal), has no parameters,
+ /// Look for a base type method named "Finalize" that is protected (or protected internal), has no parameters,
/// and returns void. It doesn't need to be virtual or a destructor.
///
///
- /// You may assume that this would share code and logic with PEMethodSymbol.OverridesRuntimeFinalizer,
+ /// You may assume that this would share code and logic with PEMethodSymbol.OverridesRuntimeFinalizer,
/// but FUNCBRECCS::bindDestructor has its own loop that performs these checks (differently).
///
private static MethodSymbol GetBaseTypeFinalizeMethod(MethodSymbol method)
diff --git a/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs b/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs
index 584e0b251b4d9059b4a7b02147d86edf5dd2623c..950919f3bfc0ac06aec0cd820e4fca3d9c62f06f 100644
--- a/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs
+++ b/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs
@@ -39,16 +39,16 @@ internal sealed class MethodCompiler : CSharpSymbolVisitor _compilerTasks;
@@ -70,7 +70,7 @@ private void SetGlobalErrorIfTrue(bool arg)
// It is ok if other tasks will see the change after some delay or does not observe at all.
// Such races are unavoidable and will just result in performing some work that is safe to do
// but may no longer be needed.
- // The final Join of compiling tasks cannot happen without interlocked operations and that
+ // The final Join of compiling tasks cannot happen without interlocked operations and that
// will ensure that any write of the flag is globally visible.
if (arg)
{
@@ -119,7 +119,7 @@ private void SetGlobalErrorIfTrue(bool arg)
if (compilation.PreviousSubmission != null)
{
- // In case there is a previous submission, we should ensure
+ // In case there is a previous submission, we should ensure
// it has already created anonymous type/delegates templates
// NOTE: if there are any errors, we will pick up what was created anyway
@@ -515,7 +515,7 @@ private void CompileNamedType(NamedTypeSymbol containingType)
case SymbolKind.Property:
{
- SourcePropertySymbol sourceProperty = member as SourcePropertySymbol;
+ var sourceProperty = member as SourcePropertySymbolBase;
if ((object)sourceProperty != null && sourceProperty.IsSealed && compilationState.Emitting)
{
CompileSynthesizedSealedAccessors(sourceProperty, compilationState);
@@ -690,7 +690,7 @@ private void CompileSynthesizedMethods(TypeCompilationState compilationState)
var importChain = methodWithBody.ImportChain;
compilationState.CurrentImportChain = importChain;
- // We make sure that an asynchronous mutation to the diagnostic bag does not
+ // We make sure that an asynchronous mutation to the diagnostic bag does not
// confuse the method body generator by making a fresh bag and then loading
// any diagnostics emitted into it back into the main diagnostic bag.
var diagnosticsThisMethod = DiagnosticBag.GetInstance();
@@ -702,7 +702,7 @@ private void CompileSynthesizedMethods(TypeCompilationState compilationState)
_moduleBeingBuiltOpt.TryCreateVariableSlotAllocator(method, method, diagnosticsThisMethod);
// Synthesized methods have no ordinal stored in custom debug information (only user-defined methods have ordinals).
- // In case of async lambdas, which synthesize a state machine type during the following rewrite, the containing method has already been uniquely named,
+ // In case of async lambdas, which synthesize a state machine type during the following rewrite, the containing method has already been uniquely named,
// so there is no need to produce a unique method ordinal for the corresponding state machine type, whose name includes the (unique) containing method name.
const int methodOrdinal = -1;
MethodBody emittedBody = null;
@@ -775,7 +775,7 @@ private static bool IsFieldLikeEventAccessor(MethodSymbol method)
}
///
- /// In some circumstances (e.g. implicit implementation of an interface method by a non-virtual method in a
+ /// In some circumstances (e.g. implicit implementation of an interface method by a non-virtual method in a
/// base type from another assembly) it is necessary for the compiler to generate explicit implementations for
/// some interface methods. They don't go in the symbol table, but if we are emitting, then we should
/// generate code for them.
@@ -797,7 +797,7 @@ private void CompileSynthesizedExplicitImplementations(SourceMemberContainerType
}
}
- private void CompileSynthesizedSealedAccessors(SourcePropertySymbol sourceProperty, TypeCompilationState compilationState)
+ private void CompileSynthesizedSealedAccessors(SourcePropertySymbolBase sourceProperty, TypeCompilationState compilationState)
{
SynthesizedSealedPropertyAccessor synthesizedAccessor = sourceProperty.SynthesizedSealedAccessorOpt;
@@ -991,9 +991,9 @@ public override object VisitField(FieldSymbol symbol, TypeCompilationState argum
UnassignedFieldsWalker.Analyze(_compilation, methodSymbol, body, diagsForCurrentMethod);
}
- // lower initializers just once. the lowered tree will be reused when emitting all constructors
+ // lower initializers just once. the lowered tree will be reused when emitting all constructors
// with field initializers. Once lowered, these initializers will be stashed in processedInitializers.LoweredInitializers
- // (see later in this method). Don't bother lowering _now_ if this particular ctor won't have the initializers
+ // (see later in this method). Don't bother lowering _now_ if this particular ctor won't have the initializers
// appended to its body.
if (includeInitializersInBody && processedInitializers.LoweredInitializers == null)
{
@@ -1098,7 +1098,7 @@ public override object VisitField(FieldSymbol symbol, TypeCompilationState argum
_compilation.EventQueue.TryEnqueue(new SymbolDeclaredCompilationEvent(_compilation, methodSymbol.GetPublicSymbol(), lazySemanticModel));
}
- // Don't lower if we're not emitting or if there were errors.
+ // Don't lower if we're not emitting or if there were errors.
// Methods that had binding errors are considered too broken to be lowered reliably.
if (_moduleBeingBuiltOpt == null || hasErrors)
{
@@ -1108,7 +1108,7 @@ public override object VisitField(FieldSymbol symbol, TypeCompilationState argum
// ############################
// LOWERING AND EMIT
- // Any errors generated below here are considered Emit diagnostics
+ // Any errors generated below here are considered Emit diagnostics
// and will not be reported to callers Compilation.GetDiagnostics()
ImmutableArray dynamicAnalysisSpans = ImmutableArray.Empty;
@@ -1320,9 +1320,9 @@ public override object VisitField(FieldSymbol symbol, TypeCompilationState argum
if (sawAwaitInExceptionHandler)
{
- // If we have awaits in handlers, we need to
+ // If we have awaits in handlers, we need to
// replace handlers with synthetic ones which can be consumed by async rewriter.
- // The reason why this rewrite happens before the lambda rewrite
+ // The reason why this rewrite happens before the lambda rewrite
// is that we may need access to exception locals and it would be fairly hard to do
// if these locals are captured into closures (possibly nested ones).
loweredBody = AsyncExceptionHandlerRewriter.Rewrite(
@@ -1442,7 +1442,7 @@ public override object VisitField(FieldSymbol symbol, TypeCompilationState argum
isAsyncStateMachine = kickoffMethod.IsAsync;
- // Async void method may be partial. Debug info needs to be associated with the emitted definition,
+ // Async void method may be partial. Debug info needs to be associated with the emitted definition,
// but the kickoff method is the method implementation (the part with body).
kickoffMethod = kickoffMethod.PartialDefinitionPart ?? kickoffMethod;
}
@@ -1488,7 +1488,7 @@ public override object VisitField(FieldSymbol symbol, TypeCompilationState argum
var stateMachineHoistedLocalScopes = ((object)kickoffMethod != null) ?
builder.GetHoistedLocalScopes() : default(ImmutableArray);
- // Translate the imports even if we are not writing PDBs. The translation has an impact on generated metadata
+ // Translate the imports even if we are not writing PDBs. The translation has an impact on generated metadata
// and we don't want to emit different metadata depending on whether or we emit with PDB stream.
// TODO (https://github.com/dotnet/roslyn/issues/2846): This will need to change for member initializers in partial class.
var importScopeOpt = importChainOpt?.Translate(moduleBuilder, diagnosticsForThisMethod);
@@ -1722,7 +1722,7 @@ internal static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationSt
}
else
{
- var property = sourceMethod.AssociatedSymbol as SourcePropertySymbol;
+ var property = sourceMethod.AssociatedSymbol as SourcePropertySymbolBase;
if ((object)property != null && property.IsAutoProperty)
{
return MethodBodySynthesizer.ConstructAutoPropertyAccessorBody(sourceMethod);
@@ -1863,7 +1863,7 @@ private static void ReportCtorInitializerCycles(MethodSymbol method, BoundExpres
// to be inside the body of a derived class in order for it to be in the
// accessibility domain of the protected base class ctor.
//
- // In the second case the binder could be the binder associated with
+ // In the second case the binder could be the binder associated with
// the body of D2; since the implicit call to base() will have no arguments
// there is no need to look up "x".
Binder outerBinder;
@@ -1871,7 +1871,7 @@ private static void ReportCtorInitializerCycles(MethodSymbol method, BoundExpres
if ((object)sourceConstructor == null)
{
// The constructor is implicit. We need to get the binder for the body
- // of the enclosing class.
+ // of the enclosing class.
CSharpSyntaxNode containerNode = constructor.GetNonNullSyntaxNode();
BinderFactory binderFactory = compilation.GetBinderFactory(containerNode.SyntaxTree);
diff --git a/src/Compilers/CSharp/Portable/Compiler/SynthesizedMetadataCompiler.cs b/src/Compilers/CSharp/Portable/Compiler/SynthesizedMetadataCompiler.cs
index bdbb19e68ee1f15a9bfedbb51beb315ced12e11d..b2747e63356ee6646fa80a7b3502f6d84866346c 100644
--- a/src/Compilers/CSharp/Portable/Compiler/SynthesizedMetadataCompiler.cs
+++ b/src/Compilers/CSharp/Portable/Compiler/SynthesizedMetadataCompiler.cs
@@ -14,9 +14,9 @@
namespace Microsoft.CodeAnalysis.CSharp
{
///
- /// When compiling in metadata-only mode, is not run. This is problematic because
+ /// When compiling in metadata-only mode, is not run. This is problematic because
/// adds synthesized explicit implementations to the list of synthesized definitions.
- /// In lieu of running , this class performs a quick
+ /// In lieu of running , this class performs a quick
/// traversal of the symbol table and performs processing of synthesized symbols if necessary
///
internal sealed class SynthesizedMetadataCompiler : CSharpSymbolVisitor
@@ -66,7 +66,7 @@ public override void VisitNamedType(NamedTypeSymbol symbol)
{
if (_moduleBeingBuilt != null)
{
- // In some circumstances (e.g. implicit implementation of an interface method by a non-virtual method in a
+ // In some circumstances (e.g. implicit implementation of an interface method by a non-virtual method in a
// base type from another assembly) it is necessary for the compiler to generate explicit implementations for
// some interface methods. They don't go in the symbol table, but if we are emitting metadata, then we should
// generate MethodDef entries for them.
@@ -91,7 +91,7 @@ public override void VisitNamedType(NamedTypeSymbol symbol)
public override void VisitProperty(PropertySymbol symbol)
{
- var sourceProperty = symbol as SourcePropertySymbol;
+ var sourceProperty = symbol as SourcePropertySymbolBase;
if ((object)sourceProperty != null && sourceProperty.IsSealed)
{
var synthesizedAccessor = sourceProperty.SynthesizedSealedAccessorOpt;
diff --git a/src/Compilers/CSharp/Portable/Emitter/Model/PropertySymbolAdapter.cs b/src/Compilers/CSharp/Portable/Emitter/Model/PropertySymbolAdapter.cs
index 9fd66b696363a063aa3edf5cc7a14cef6c84f9de..515243c7303ca64711531ac196f3603ccb544c68 100644
--- a/src/Compilers/CSharp/Portable/Emitter/Model/PropertySymbolAdapter.cs
+++ b/src/Compilers/CSharp/Portable/Emitter/Model/PropertySymbolAdapter.cs
@@ -33,7 +33,7 @@ IEnumerable IPropertyDefinition.GetAccessors(EmitContext conte
yield return setMethod;
}
- SourcePropertySymbol sourceProperty = this as SourcePropertySymbol;
+ var sourceProperty = this as SourcePropertySymbolBase;
if ((object)sourceProperty != null && sourceProperty.ShouldInclude(context))
{
SynthesizedSealedPropertyAccessor synthesizedAccessor = sourceProperty.SynthesizedSealedAccessorOpt;
@@ -266,7 +266,7 @@ string INamedEntity.Name
private IMethodReference GetSynthesizedSealedAccessor(MethodKind targetMethodKind)
{
- SourcePropertySymbol sourceProperty = this as SourcePropertySymbol;
+ var sourceProperty = this as SourcePropertySymbolBase;
if ((object)sourceProperty != null)
{
SynthesizedSealedPropertyAccessor synthesized = sourceProperty.SynthesizedSealedAccessorOpt;
diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass.cs
index 1d723640a7b2e5b625258f3acfb38ce174b4db00..624de88c4ebb8e6feae912bd63a1b4f13a90240b 100644
--- a/src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass.cs
+++ b/src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass.cs
@@ -563,7 +563,7 @@ protected void VisitLvalue(BoundExpression node)
if (Binder.AccessingAutoPropertyFromConstructor(access, _symbol))
{
- var backingField = (access.PropertySymbol as SourcePropertySymbol)?.BackingField;
+ var backingField = (access.PropertySymbol as SourcePropertySymbolBase)?.BackingField;
if (backingField != null)
{
VisitFieldAccessInternal(access.ReceiverOpt, backingField);
@@ -1077,7 +1077,7 @@ public override BoundNode VisitStringInsert(BoundStringInsert node)
public override BoundNode VisitArgList(BoundArgList node)
{
- // The "__arglist" expression that is legal inside a varargs method has no
+ // The "__arglist" expression that is legal inside a varargs method has no
// effect on flow analysis and it has no children.
return null;
}
@@ -1576,7 +1576,7 @@ public override BoundNode VisitTryStatement(BoundTryStatement node)
RestorePending(pendingBeforeTry);
// NOTE: At this point all branches that are internal to try or catch blocks have been resolved.
- // However we have not yet restored the oldPending branches. Therefore all the branches
+ // However we have not yet restored the oldPending branches. Therefore all the branches
// that are currently pending must have been introduced in try/catch and do not terminate inside those blocks.
//
// With exception of YieldReturn, these branches logically go through finally, if such present,
@@ -1811,7 +1811,7 @@ protected virtual void PropertySetter(BoundExpression node, BoundExpression rece
VisitReceiverAfterCall(receiver, setter);
}
- // returns false if expression is not a property access
+ // returns false if expression is not a property access
// or if the property has a backing field
// and accessed in a corresponding constructor
private bool RegularPropertyAccess(BoundExpression expr)
@@ -1958,7 +1958,7 @@ public override BoundNode VisitPropertyAccess(BoundPropertyAccess node)
if (Binder.AccessingAutoPropertyFromConstructor(node, _symbol))
{
- var backingField = (property as SourcePropertySymbol)?.BackingField;
+ var backingField = (property as SourcePropertySymbolBase)?.BackingField;
if (backingField != null)
{
VisitFieldAccessInternal(node.ReceiverOpt, backingField);
@@ -3144,10 +3144,10 @@ private void VisitMethodBodies(BoundBlock blockBody, BoundBlock expressionBody)
// In error cases we have two bodies. These are two unrelated pieces of code,
// they are not executed one after another. As we don't really know which one the developer
// intended to use, we need to visit both. We are going to pretend that there is
- // an unconditional fork in execution and then we are converging after each body is executed.
+ // an unconditional fork in execution and then we are converging after each body is executed.
// For example, if only one body assigns an out parameter, then after visiting both bodies
// we should consider that parameter is not definitely assigned.
- // Note, that today this code is not executed for regular definite assignment analysis. It is
+ // Note, that today this code is not executed for regular definite assignment analysis. It is
// only executed for region analysis.
TLocalState initialState = this.State.Clone();
Visit(blockBody);
diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs
index 7dc700b80e83825f97ad93c3c30fe76c5e37f67e..10edf68f437f6ca58658bb9b1cc802f4909c732b 100644
--- a/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs
+++ b/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs
@@ -584,11 +584,11 @@ protected virtual void NoteWrite(Symbol variable, BoundExpression value, bool re
// unless the written value is always a constant. The reasons for this
// unusual behavior are:
//
- // * The debugger does not make it easy to see the returned value of
+ // * The debugger does not make it easy to see the returned value of
// a method. Often a call whose returned value would normally be
// discarded is written into a local variable so that it can be
// easily inspected in the debugger.
- //
+ //
// * An otherwise unread local variable that contains a reference to an
// object can keep the object alive longer, particularly if the jitter
// is not optimizing the lifetimes of locals. (Because, for example,
@@ -597,7 +597,7 @@ protected virtual void NoteWrite(Symbol variable, BoundExpression value, bool re
// the developer to more easily examine its state.
//
// * A developer who wishes to deliberately discard a value returned by
- // a method can do so in a self-documenting manner via
+ // a method can do so in a self-documenting manner via
// "var unread = M();"
//
// We suppress the "written but not read" message on locals unless what is
@@ -625,7 +625,7 @@ internal static bool WriteConsideredUse(TypeSymbol type, BoundExpression value)
if ((object)type != null && type.IsPointerOrFunctionPointer())
{
- // We always suppress the warning for pointer types.
+ // We always suppress the warning for pointer types.
return true;
}
@@ -798,7 +798,7 @@ protected override bool TryGetReceiverAndMember(BoundExpression expr, out BoundE
if (Binder.AccessingAutoPropertyFromConstructor(propAccess, this.CurrentSymbol))
{
var propSymbol = propAccess.PropertySymbol;
- member = (propSymbol as SourcePropertySymbol)?.BackingField;
+ member = (propSymbol as SourcePropertySymbolBase)?.BackingField;
if (member is null)
{
return false;
@@ -1023,7 +1023,7 @@ private bool IsAssigned(BoundExpression node, out int unassignedSlot)
if (Binder.AccessingAutoPropertyFromConstructor(propertyAccess, this.CurrentSymbol))
{
var property = propertyAccess.PropertySymbol;
- var backingField = (property as SourcePropertySymbol)?.BackingField;
+ var backingField = (property as SourcePropertySymbolBase)?.BackingField;
if (backingField != null)
{
if (!MayRequireTracking(propertyAccess.ReceiverOpt, backingField) || IsAssigned(propertyAccess.ReceiverOpt, out unassignedSlot))
@@ -2036,7 +2036,7 @@ public override BoundNode VisitPropertyAccess(BoundPropertyAccess node)
if (Binder.AccessingAutoPropertyFromConstructor(node, this.CurrentSymbol))
{
var property = node.PropertySymbol;
- var backingField = (property as SourcePropertySymbol)?.BackingField;
+ var backingField = (property as SourcePropertySymbolBase)?.BackingField;
if (backingField != null)
{
if (MayRequireTracking(node.ReceiverOpt, backingField))
diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
index cd2e671546eb7842db4e386072b98668384c996c..e676ecbad85d9ace5b47c8f5f6686980b71d1c17 100644
--- a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
+++ b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
@@ -7039,14 +7039,14 @@ static FlowAnalysisAnnotations getSetterAnnotations(PropertySymbol property)
{
return accessor.Parameters.Last().FlowAnalysisAnnotations;
}
- if (property is SourcePropertySymbol sourceProperty)
+ if (property is SourcePropertySymbolBase sourceProperty)
{
return getPropertyAnnotations(sourceProperty);
}
return FlowAnalysisAnnotations.None;
}
- static FlowAnalysisAnnotations getPropertyAnnotations(SourcePropertySymbol property)
+ static FlowAnalysisAnnotations getPropertyAnnotations(SourcePropertySymbolBase property)
{
var annotations = FlowAnalysisAnnotations.None;
if (property.HasAllowNull)
diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_AssignmentOperator.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_AssignmentOperator.cs
index 23a081e2b9ba04df55af943a0381c13dd7efd644..b4cfb49bcde36311d1d62429bc1ae2555cfc0c31 100644
--- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_AssignmentOperator.cs
+++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_AssignmentOperator.cs
@@ -300,7 +300,7 @@ private BoundExpression VisitAssignmentOperator(BoundAssignmentOperator node, bo
if (setMethod is null)
{
- var autoProp = (SourceOrRecordPropertySymbol)property;
+ var autoProp = (SourcePropertySymbolBase)property;
Debug.Assert(autoProp.IsAutoProperty,
"only autoproperties can be assignable without having setters");
diff --git a/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Members.cs b/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Members.cs
index 2973c5f824cecceabb85de4f515f5fafb98b9fa5..eeffec10f0fa0eb8979ebc33a4069d612d37d3e8 100644
--- a/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Members.cs
+++ b/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Members.cs
@@ -104,7 +104,7 @@ private static bool ShouldMethodDisplayReadOnly(IMethodSymbol method, IPropertyS
}
if ((method as Symbols.PublicModel.MethodSymbol)?.UnderlyingMethodSymbol is SourcePropertyAccessorSymbol sourceAccessor &&
- (propertyOpt as Symbols.PublicModel.PropertySymbol)?.UnderlyingSymbol is SourcePropertySymbol sourceProperty)
+ (propertyOpt as Symbols.PublicModel.PropertySymbol)?.UnderlyingSymbol is SourcePropertySymbolBase sourceProperty)
{
// only display if the accessor is explicitly readonly
return sourceAccessor.LocalDeclaredReadOnly || sourceProperty.HasReadOnlyModifier;
@@ -319,7 +319,7 @@ public override void VisitMethod(IMethodSymbol symbol)
}
}
- // Method members always have a type unless (1) this is a lambda method symbol, which we
+ // Method members always have a type unless (1) this is a lambda method symbol, which we
// have dealt with already, or (2) this is an error method symbol. If we have an error method
// symbol then we do not know its accessibility, modifiers, etc, all of which require knowing
// the containing type, so we'll skip them.
@@ -343,7 +343,7 @@ public override void VisitMethod(IMethodSymbol symbol)
break;
case MethodKind.Destructor:
case MethodKind.Conversion:
- // If we're using the metadata format, then include the return type.
+ // If we're using the metadata format, then include the return type.
// Otherwise we eschew it since it is redundant in a conversion
// signature.
if (format.CompilerInternalOptions.IncludesOption(SymbolDisplayCompilerInternalOptions.UseMetadataMethodNames))
@@ -354,8 +354,8 @@ public override void VisitMethod(IMethodSymbol symbol)
break;
default:
// The display code is called by the debugger; if a developer is debugging Roslyn and attempts
- // to visualize a symbol *during its construction*, the parameters and return type might
- // still be null.
+ // to visualize a symbol *during its construction*, the parameters and return type might
+ // still be null.
if (symbol.ReturnsByRef)
{
@@ -777,8 +777,8 @@ private void AddParametersIfRequired(bool hasThisParameter, bool isVarargs, Immu
var first = true;
// The display code is called by the debugger; if a developer is debugging Roslyn and attempts
- // to visualize a symbol *during its construction*, the parameters and return type might
- // still be null.
+ // to visualize a symbol *during its construction*, the parameters and return type might
+ // still be null.
if (!parameters.IsDefault)
{
diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs
index fc641778b60c7d1a4c9c5c5743d924c52cf1dc87..e374bf80d9d0807c932078e6477456e6670e3e7e 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs
@@ -986,7 +986,7 @@ internal bool TryCalculateSyntaxOffsetOfPositionInInitializer(int position, Synt
// |<-----------distanceFromCtorBody----------->|
// [ initializer 0 ][ initializer 1 ][ initializer 2 ][ctor initializer][ctor body]
// |<--preceding init len-->| ^
- // position
+ // position
int initializersLength = isStatic ? membersAndInitializers.StaticInitializersSyntaxLength : membersAndInitializers.InstanceInitializersSyntaxLength;
int distanceFromInitializerStart = position - siblingInitializers[index].Syntax.Span.Start;
@@ -1255,7 +1255,7 @@ internal override IEnumerable GetFieldsToEmit()
///
/// During early attribute decoding, we consider a safe subset of all members that will not
/// cause cyclic dependencies. Get all such members for this symbol.
- ///
+ ///
/// In particular, this method will return nested types and fields (other than auto-property
/// backing fields).
///
@@ -1267,7 +1267,7 @@ internal override ImmutableArray GetEarlyAttributeDecodingMembers()
///
/// During early attribute decoding, we consider a safe subset of all members that will not
/// cause cyclic dependencies. Get all such members for this symbol that have a particular name.
- ///
+ ///
/// In particular, this method will return nested types and fields (other than auto-property
/// backing fields).
///
@@ -1478,23 +1478,23 @@ private void CheckMemberNameConflicts(DiagnosticBag diagnostics)
// not need any special handling in this method.
//
// However, we must have special handling for conversions because conversions
- // use a completely different rule for detecting collisions between two
+ // use a completely different rule for detecting collisions between two
// conversions: conversion signatures consist only of the source and target
// types of the conversions, and not the kind of the conversion (implicit or explicit),
// the name of the method, and so on.
//
// Therefore we must detect the following kinds of member name conflicts:
//
- // 1. a method, conversion or field has the same name as a (different) field (* see note below)
+ // 1. a method, conversion or field has the same name as a (different) field (* see note below)
// 2. a method has the same method signature as another method or conversion
// 3. a conversion has the same conversion signature as another conversion.
//
- // However, we must *not* detect "a conversion has the same *method* signature
- // as another conversion" because conversions are allowed to overload on
+ // However, we must *not* detect "a conversion has the same *method* signature
+ // as another conversion" because conversions are allowed to overload on
// return type but methods are not.
//
// (*) NOTE: Throughout the rest of this method I will use "field" as a shorthand for
- // "non-method, non-conversion, non-type member", rather than spelling out
+ // "non-method, non-conversion, non-type member", rather than spelling out
// "field, property or event...")
foreach (var pair in membersByName)
@@ -1521,7 +1521,7 @@ private void CheckMemberNameConflicts(DiagnosticBag diagnostics)
// * a field directly following a field
// * a field directly following a method or conversion
//
- // Furthermore: we do not wish to detect collisions between nested types in
+ // Furthermore: we do not wish to detect collisions between nested types in
// this code; that is tested elsewhere. However, we do wish to detect a collision
// between a nested type and a field, method or conversion. Therefore we
// initialize our "bad transition" detector with a type of the given name,
@@ -1537,8 +1537,8 @@ private void CheckMemberNameConflicts(DiagnosticBag diagnostics)
//
// If either the current symbol or the "last symbol" are not methods then
// there must be a collision:
- //
- // * if the current symbol is not a method and the last symbol is, then
+ //
+ // * if the current symbol is not a method and the last symbol is, then
// there is a field directly following a method of the same name
// * if the current symbol is a method and the last symbol is not, then
// there is a method directly or indirectly following a field of the same name,
@@ -1698,7 +1698,7 @@ private void CheckIndexerNameConflicts(DiagnosticBag diagnostics, Dictionary(MemberSignatureComparer.DuplicateSourceComparer);
- // Note: Can't assume that all indexers are called WellKnownMemberNames.Indexer because
+ // Note: Can't assume that all indexers are called WellKnownMemberNames.Indexer because
// they may be explicit interface implementations.
foreach (var members in membersByName.Values)
{
@@ -1955,17 +1955,17 @@ private void CheckForProtectedInStaticClass(DiagnosticBag diagnostics)
private void CheckForUnmatchedOperators(DiagnosticBag diagnostics)
{
// SPEC: The true and false unary operators require pairwise declaration.
- // SPEC: A compile-time error occurs if a class or struct declares one
+ // SPEC: A compile-time error occurs if a class or struct declares one
// SPEC: of these operators without also declaring the other.
//
// SPEC DEFICIENCY: The line of the specification quoted above should say
// the same thing as the lines below: that the formal parameters of the
- // paired true/false operators must match exactly. You can't do
+ // paired true/false operators must match exactly. You can't do
// op true(S) and op false(S?) for example.
// SPEC: Certain binary operators require pairwise declaration. For every
// SPEC: declaration of either operator of a pair, there must be a matching
- // SPEC: declaration of the other operator of the pair. Two operator
+ // SPEC: declaration of the other operator of the pair. Two operator
// SPEC: declarations match when they have the same return type and the same
// SPEC: type for each parameter. The following operators require pairwise
// SPEC: declaration: == and !=, > and <, >= and <=.
@@ -2987,9 +2987,6 @@ private void AddSynthesizedRecordMembersIfNecessary(MembersAndInitializersBuilde
diagnostics.Add(ErrorCode.ERR_BadRecordDeclaration, paramList.Location);
}
- BinderFactory binderFactory = this.DeclaringCompilation.GetBinderFactory(paramList.SyntaxTree);
- var binder = binderFactory.GetBinder(paramList);
-
var ctor = addCtor(builder.RecordDeclarationWithParameters);
var existingOrAddedMembers = addProperties(ctor.Parameters);
addDeconstruct(ctor.Parameters, existingOrAddedMembers);
@@ -3280,8 +3277,8 @@ private void AddSynthesizedConstructorsIfNecessary(ArrayBuilder members,
}
// constants don't count, since they do not exist as fields at runtime
- // NOTE: even for decimal constants (which require field initializers),
- // we do not create .cctor here since a static constructor implicitly created for a decimal
+ // NOTE: even for decimal constants (which require field initializers),
+ // we do not create .cctor here since a static constructor implicitly created for a decimal
// should not appear in the list returned by public API like GetMembers().
if (!hasStaticConstructor && HasNonConstantInitializer(staticInitializers))
{
@@ -3438,7 +3435,7 @@ private static bool HasNonConstantInitializer(ArrayBuilder
- /// In some circumstances (e.g. implicit implementation of an interface method by a non-virtual method in a
+ /// In some circumstances (e.g. implicit implementation of an interface method by a non-virtual method in a
/// base type from another assembly) it is necessary for the compiler to generate explicit implementations for
/// some interface methods. They don't go in the symbol table, but if we are emitting, then we should
/// generate code for them.
@@ -96,9 +96,9 @@ private void CheckAbstractClassImplementations(DiagnosticBag diagnostics)
{
var synthesizedImplementations = ArrayBuilder.GetInstance();
- // NOTE: We can't iterator over this collection directly, since it is not ordered. Instead we
- // iterate over AllInterfaces and filter out the interfaces that are not in this set. This is
- // preferable to doing the DFS ourselves because both AllInterfaces and
+ // NOTE: We can't iterator over this collection directly, since it is not ordered. Instead we
+ // iterate over AllInterfaces and filter out the interfaces that are not in this set. This is
+ // preferable to doing the DFS ourselves because both AllInterfaces and
// InterfacesAndTheirBaseInterfaces are cached and used in multiple places.
MultiDictionary interfacesAndTheirBases = this.InterfacesAndTheirBaseInterfacesNoUseSiteDiagnostics;
@@ -215,8 +215,8 @@ private void CheckAbstractClassImplementations(DiagnosticBag diagnostics)
ReportAccessorOfInterfacePropertyOrEvent(associatedPropertyOrEvent) ||
(wasImplementingMemberFound && !implementingMember.IsAccessor()))
{
- //we're here because
- //(a) the interface member is not an accessor, or
+ //we're here because
+ //(a) the interface member is not an accessor, or
//(b) the interface member is an accessor of an interesting (see ReportAccessorOfInterfacePropertyOrEvent) property or event, or
//(c) the implementing member exists and is not an accessor.
bool reportedAnError = false;
@@ -289,14 +289,14 @@ private void CheckAbstractClassImplementations(DiagnosticBag diagnostics)
{
// Don't report use site errors on properties - we'll report them on each of their accessors.
- // Don't report use site errors for implementations in other types unless
+ // Don't report use site errors for implementations in other types unless
// a synthesized implementation is needed that invokes the base method.
// We can do so only if there are no use-site errors.
if ((object)synthesizedImplementation != null || TypeSymbol.Equals(implementingMember.ContainingType, this, TypeCompareKind.ConsiderEverything2))
{
DiagnosticInfo useSiteDiagnostic = interfaceMember.GetUseSiteDiagnostic();
- // CAVEAT: don't report ERR_ByRefReturnUnsupported since by-ref return types are
+ // CAVEAT: don't report ERR_ByRefReturnUnsupported since by-ref return types are
// specifically allowed for the purposes of interface implementation (for C++ interop).
// However, if there's a reference to the interface member in source, then we do want
// to produce a use site error.
@@ -494,7 +494,7 @@ private void HasBaseInterfaceDeclaringInterface(NamedTypeSymbol baseInterface, N
case TypeKind.Class:
case TypeKind.Struct:
case TypeKind.Interface:
- case TypeKind.Submission: // we have to check that "override" is not used
+ case TypeKind.Submission: // we have to check that "override" is not used
break;
default:
@@ -566,7 +566,7 @@ private void HasBaseInterfaceDeclaringInterface(NamedTypeSymbol baseInterface, N
}
}
}
- else if (property is SourcePropertySymbol sourceProperty)
+ else if (property is SourcePropertySymbolBase sourceProperty)
{
var isNewProperty = sourceProperty.IsNew;
CheckNonOverrideMember(property, isNewProperty, property.OverriddenOrHiddenMembers, diagnostics, out suppressAccessors);
@@ -813,11 +813,11 @@ private void CheckNewModifier(Symbol symbol, bool isNew, DiagnosticBag diagnosti
}
// From: SymbolPreparer.cpp
- // DevDiv Bugs 115384: Both out and ref parameters are implemented as references. In addition, out parameters are
+ // DevDiv Bugs 115384: Both out and ref parameters are implemented as references. In addition, out parameters are
// decorated with OutAttribute. In CLR when a signature is looked up in virtual dispatch, CLR does not distinguish
- // between these to parameter types. The choice is the last method in the vtable. Therefore we check and warn if
- // there would potentially be a mismatch in CLRs and C#s choice of the overridden method. Unfortunately we have no
- // way of communicating to CLR which method is the overridden one. We only run into this problem when the
+ // between these to parameter types. The choice is the last method in the vtable. Therefore we check and warn if
+ // there would potentially be a mismatch in CLRs and C#s choice of the overridden method. Unfortunately we have no
+ // way of communicating to CLR which method is the overridden one. We only run into this problem when the
// parameters are generic.
var runtimeOverriddenMembers = overriddenOrHiddenMembers.RuntimeOverriddenMembers;
Debug.Assert(!runtimeOverriddenMembers.IsDefault);
@@ -1544,19 +1544,19 @@ private SynthesizedExplicitImplementationForwardingMethod SynthesizeInterfaceMem
/// 1) declares that it implements that interface; or
/// 2) is a base class of a type that declares that it implements the interface but not
/// a subtype of a class that declares that it implements the interface.
- ///
+ ///
/// For example,
- ///
+ ///
/// interface I
/// class A
/// class B : A, I
/// class C : B
/// class D : C, I
- ///
- /// Suppose the runtime is looking for D's implementation of a member of I. It will look in
+ ///
+ /// Suppose the runtime is looking for D's implementation of a member of I. It will look in
/// D because of (1), will not look in C, will look in B because of (1), and will look in A
/// because of (2).
- ///
+ ///
/// The key point is that it does not look in C, which C# *does*.
///
private static bool IsPossibleImplementationUnderRuntimeRules(MethodSymbol implementingMethod, NamedTypeSymbol @interface)
@@ -1577,7 +1577,7 @@ private static bool IsPossibleImplementationUnderRuntimeRules(MethodSymbol imple
///
///
/// This is based on SymbolPreparer::IsCLRMethodImplSame in the native compiler.
- ///
+ ///
/// ACASEY: What the native compiler actually does is compute the C# answer, compute the CLR answer,
/// and then confirm that they override the same method. What I've done here is check for the situations
/// where the answers could disagree. I believe the results will be equivalent. If in doubt, a more conservative
diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrRecordPropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrRecordPropertySymbol.cs
deleted file mode 100644
index 37f0054257ca3f3dd39b6a50272e305e6020628a..0000000000000000000000000000000000000000
--- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrRecordPropertySymbol.cs
+++ /dev/null
@@ -1,38 +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.
-
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-
-namespace Microsoft.CodeAnalysis.CSharp.Symbols
-{
- internal abstract class SourceOrRecordPropertySymbol : PropertySymbol, IAttributeTargetSymbol
- {
- public Location Location { get; }
-
- public SourceOrRecordPropertySymbol(Location location)
- {
- Location = location;
- }
-
- internal abstract SynthesizedBackingFieldSymbol BackingField { get; }
-
- internal abstract bool IsAutoProperty { get; }
-
- internal abstract bool HasPointerType { get; }
-
- public abstract SyntaxList AttributeDeclarationSyntaxList { get; }
-
- protected abstract IAttributeTargetSymbol AttributesOwner { get; }
-
- protected abstract AttributeLocation AllowedAttributeLocations { get; }
-
- protected abstract AttributeLocation DefaultAttributeLocation { get; }
-
- IAttributeTargetSymbol IAttributeTargetSymbol.AttributesOwner => AttributesOwner;
-
- AttributeLocation IAttributeTargetSymbol.AllowedAttributeLocations => AllowedAttributeLocations;
-
- AttributeLocation IAttributeTargetSymbol.DefaultAttributeLocation => DefaultAttributeLocation;
- }
-}
diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs
index 7bd24deef3f442a3d8ea1f1eca8e7ec5c8e9b14b..d460ceccfa29ce15916418275008335d6fe5925e 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs
@@ -14,7 +14,7 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
internal sealed class SourcePropertyAccessorSymbol : SourceMemberMethodSymbol
{
- private readonly SourcePropertySymbol _property;
+ private readonly SourcePropertySymbolBase _property;
private ImmutableArray _lazyParameters;
private TypeWithAnnotations _lazyReturnType;
private ImmutableArray _lazyRefCustomModifiers;
@@ -53,6 +53,10 @@ internal sealed class SourcePropertyAccessorSymbol : SourceMemberMethodSymbol
out explicitInterfaceImplementations);
var methodKind = isGetMethod ? MethodKind.PropertyGet : MethodKind.PropertySet;
+
+ bool hasBody = syntax.Body is object;
+ bool hasExpressionBody = syntax.ExpressionBody is object;
+ CheckForBlockAndExpressionBody(syntax.Body, syntax.ExpressionBody, syntax, diagnostics);
return new SourcePropertyAccessorSymbol(
containingType,
name,
@@ -61,7 +65,12 @@ internal sealed class SourcePropertyAccessorSymbol : SourceMemberMethodSymbol
explicitInterfaceImplementations,
syntax.Keyword.GetLocation(),
syntax,
+ hasBody,
+ hasExpressionBody,
+ isIterator: SyntaxFacts.HasYieldOperations(syntax.Body),
+ syntax.Modifiers,
methodKind,
+ syntax.Keyword.IsKind(SyntaxKind.InitKeyword),
isAutoPropertyAccessor,
isExplicitInterfaceImplementation,
diagnostics);
@@ -102,6 +111,50 @@ internal sealed class SourcePropertyAccessorSymbol : SourceMemberMethodSymbol
diagnostics);
}
+#nullable enable
+ public static SourcePropertyAccessorSymbol CreateAccessorSymbol(
+ bool isGetMethod,
+ bool usesInit,
+ NamedTypeSymbol containingType,
+ SynthesizedRecordPropertySymbol property,
+ DeclarationModifiers propertyModifiers,
+ string propertyName,
+ Location location,
+ CSharpSyntaxNode syntax,
+ DiagnosticBag diagnostics)
+ {
+ string name;
+ ImmutableArray explicitInterfaceImplementations;
+ GetNameAndExplicitInterfaceImplementations(
+ explicitlyImplementedPropertyOpt: null,
+ propertyName,
+ property.IsCompilationOutputWinMdObj(),
+ aliasQualifierOpt: null,
+ isGetMethod,
+ out name,
+ out explicitInterfaceImplementations);
+
+ var methodKind = isGetMethod ? MethodKind.PropertyGet : MethodKind.PropertySet;
+ return new SourcePropertyAccessorSymbol(
+ containingType,
+ name,
+ property,
+ propertyModifiers,
+ explicitInterfaceImplementations,
+ location,
+ syntax,
+ hasBody: false,
+ hasExpressionBody: false,
+ isIterator: false,
+ modifiers: new SyntaxTokenList(),
+ methodKind,
+ usesInit,
+ isAutoPropertyAccessor: true,
+ isExplicitInterfaceImplementation: false,
+ diagnostics);
+ }
+#nullable restore
+
internal override bool IsExpressionBodied
=> _isExpressionBodied;
@@ -197,39 +250,43 @@ internal sealed override ImmutableArray NotNullWhenFalseMembers
}
}
+#nullable enable
private SourcePropertyAccessorSymbol(
NamedTypeSymbol containingType,
string name,
- SourcePropertySymbol property,
+ SourcePropertySymbolBase property,
DeclarationModifiers propertyModifiers,
ImmutableArray explicitInterfaceImplementations,
Location location,
- AccessorDeclarationSyntax syntax,
+ CSharpSyntaxNode syntax,
+ bool hasBody,
+ bool hasExpressionBody,
+ bool isIterator,
+ SyntaxTokenList modifiers,
MethodKind methodKind,
+ bool usesInit,
bool isAutoPropertyAccessor,
bool isExplicitInterfaceImplementation,
DiagnosticBag diagnostics)
: base(containingType,
syntax.GetReference(),
location,
- isIterator: SyntaxFacts.HasYieldOperations(syntax.Body))
+ isIterator: isIterator)
{
_property = property;
_explicitInterfaceImplementations = explicitInterfaceImplementations;
_name = name;
_isAutoPropertyAccessor = isAutoPropertyAccessor;
Debug.Assert(!_property.IsExpressionBodied, "Cannot have accessors in expression bodied lightweight properties");
- var hasBody = syntax.Body != null;
- var hasExpressionBody = syntax.ExpressionBody != null;
_isExpressionBodied = !hasBody && hasExpressionBody;
- _usesInit = syntax.Keyword.IsKind(SyntaxKind.InitKeyword);
+ _usesInit = usesInit;
if (_usesInit)
{
- Binder.CheckFeatureAvailability(syntax, MessageID.IDS_FeatureInitOnlySetters, diagnostics, syntax.Keyword.GetLocation());
+ Binder.CheckFeatureAvailability(syntax, MessageID.IDS_FeatureInitOnlySetters, diagnostics, location);
}
bool modifierErrors;
- var declarationModifiers = this.MakeModifiers(syntax, isExplicitInterfaceImplementation, hasBody || hasExpressionBody, location, diagnostics, out modifierErrors);
+ var declarationModifiers = this.MakeModifiers(modifiers, isExplicitInterfaceImplementation, hasBody || hasExpressionBody, location, diagnostics, out modifierErrors);
// Include some modifiers from the containing property, but not the accessibility modifiers.
declarationModifiers |= GetAccessorModifiers(propertyModifiers) & ~DeclarationModifiers.AccessibilityMask;
@@ -274,9 +331,8 @@ internal sealed override ImmutableArray NotNullWhenFalseMembers
}
}
- CheckForBlockAndExpressionBody(
- syntax.Body, syntax.ExpressionBody, syntax, diagnostics);
}
+#nullable restore
private static DeclarationModifiers GetAccessorModifiers(DeclarationModifiers propertyModifiers) =>
propertyModifiers & ~(DeclarationModifiers.Indexer | DeclarationModifiers.ReadOnly);
@@ -299,7 +355,7 @@ protected override void MethodChecks(DiagnosticBag diagnostics)
}
else if (this.IsOverride)
{
- // This will cause another call to SourceMethodSymbol.LazyMethodChecks,
+ // This will cause another call to SourceMethodSymbol.LazyMethodChecks,
// but that method already handles reentrancy for exactly this case.
MethodSymbol overriddenMethod = this.OverriddenMethod;
if ((object)overriddenMethod != null)
@@ -525,7 +581,7 @@ internal override bool IsDeclaredReadOnly
internal override bool IsInitOnly => !IsStatic && _usesInit;
- private DeclarationModifiers MakeModifiers(AccessorDeclarationSyntax syntax, bool isExplicitInterfaceImplementation,
+ private DeclarationModifiers MakeModifiers(SyntaxTokenList modifiers, bool isExplicitInterfaceImplementation,
bool hasBody, Location location, DiagnosticBag diagnostics, out bool modifierErrors)
{
// No default accessibility. If unset, accessibility
@@ -546,7 +602,7 @@ internal override bool IsDeclaredReadOnly
defaultInterfaceImplementationModifiers = DeclarationModifiers.AccessibilityMask;
}
- var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(syntax.Modifiers, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors);
+ var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(modifiers, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors);
ModifierUtils.ReportDefaultInterfaceImplementationModifiers(hasBody, mods,
defaultInterfaceImplementationModifiers,
@@ -610,7 +666,8 @@ internal static string GetAccessorName(string propertyName, bool getNotSet, bool
}
///
- /// or
+ /// The declaring syntax for the accessor, or property if there is no accessor-specific
+ /// syntax.
///
internal CSharpSyntaxNode GetSyntax()
{
@@ -661,8 +718,17 @@ public override bool IsImplicitlyDeclared
get
{
// Per design meeting resolution [see bug 11253], no source accessor is implicitly declared in C#,
- // because there is "get", "set", or expression-body syntax.
- return false;
+ // if there is "get", "set", or expression-body syntax.
+ switch (GetSyntax().Kind())
+ {
+ case SyntaxKind.GetAccessorDeclaration:
+ case SyntaxKind.SetAccessorDeclaration:
+ case SyntaxKind.InitAccessorDeclaration:
+ case SyntaxKind.ArrowExpressionClause:
+ return false;
+ };
+
+ return true;
}
}
diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs
index 53206e2e027445b3d4fb2e8cf416f2ab4b3c1b93..21a5af29642270dbe28f1d96444145ac3cbd0908 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs
@@ -2,67 +2,33 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
+#nullable enable
+
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
-using System.Globalization;
using System.Linq;
-using System.Runtime.CompilerServices;
-using System.Threading;
-using Microsoft.CodeAnalysis.CSharp.Emit;
using Microsoft.CodeAnalysis.CSharp.Syntax;
-using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
- internal sealed class SourcePropertySymbol : SourceOrRecordPropertySymbol
+ internal sealed class SourcePropertySymbol : SourcePropertySymbolBase
{
- ///
- /// Condensed flags storing useful information about the
- /// so that we do not have to go back to source to compute this data.
- ///
- [Flags]
- private enum Flags : byte
- {
- IsExpressionBodied = 1 << 0,
- IsAutoProperty = 1 << 1,
- IsExplicitInterfaceImplementation = 1 << 2,
- }
-
private const string DefaultIndexerName = "Item";
- // TODO (tomat): consider splitting into multiple subclasses/rare data.
-
- private readonly SourceMemberContainerTypeSymbol _containingType;
- private readonly string _name;
- private readonly SyntaxReference _syntaxRef;
- private readonly DeclarationModifiers _modifiers;
- private readonly ImmutableArray _refCustomModifiers;
- private readonly SourcePropertyAccessorSymbol _getMethod;
- private readonly SourcePropertyAccessorSymbol _setMethod;
- private readonly TypeSymbol _explicitInterfaceType;
- private readonly ImmutableArray _explicitInterfaceImplementations;
- private readonly Flags _propertyFlags;
- private readonly RefKind _refKind;
-
- private SymbolCompletionState _state;
- private ImmutableArray _lazyParameters;
- private TypeWithAnnotations.Boxed _lazyType;
-
- ///
- /// Set in constructor, might be changed while decoding .
- ///
- private readonly string _sourceName;
-
- private string _lazyDocComment;
- private string _lazyExpandedDocComment;
- private OverriddenOrHiddenMembersResult _lazyOverriddenOrHiddenMembers;
- private SynthesizedSealedPropertyAccessor _lazySynthesizedSealedAccessor;
- private CustomAttributesBag _lazyCustomAttributesBag;
+ internal static SourcePropertySymbol Create(SourceMemberContainerTypeSymbol containingType, Binder bodyBinder, PropertyDeclarationSyntax syntax, DiagnosticBag diagnostics)
+ {
+ var nameToken = syntax.Identifier;
+ var location = nameToken.GetLocation();
+ return new SourcePropertySymbol(containingType, bodyBinder, syntax, nameToken.ValueText, location, diagnostics);
+ }
- // CONSIDER: if the parameters were computed lazily, ParameterCount could be overridden to fall back on the syntax (as in SourceMemberMethodSymbol).
+ internal static SourcePropertySymbol Create(SourceMemberContainerTypeSymbol containingType, Binder bodyBinder, IndexerDeclarationSyntax syntax, DiagnosticBag diagnostics)
+ {
+ var location = syntax.ThisKeyword.GetLocation();
+ return new SourcePropertySymbol(containingType, bodyBinder, syntax, DefaultIndexerName, location, diagnostics);
+ }
private SourcePropertySymbol(
SourceMemberContainerTypeSymbol containingType,
@@ -71,378 +37,53 @@ private enum Flags : byte
string name,
Location location,
DiagnosticBag diagnostics)
- : base(location)
+ : base(containingType, bodyBinder, syntax, syntax.Type.GetRefKind(), name, location, diagnostics)
{
- // This has the value that IsIndexer will ultimately have, once we've populated the fields of this object.
- bool isIndexer = syntax.Kind() == SyntaxKind.IndexerDeclaration;
- var interfaceSpecifier = GetExplicitInterfaceSpecifier(syntax);
- bool isExplicitInterfaceImplementation = interfaceSpecifier != null;
- if (isExplicitInterfaceImplementation)
- {
- _propertyFlags |= Flags.IsExplicitInterfaceImplementation;
- }
-
- _containingType = containingType;
- _syntaxRef = syntax.GetReference();
- _refKind = syntax.Type.GetRefKind();
-
- SyntaxTokenList modifiers = syntax.Modifiers;
- bodyBinder = bodyBinder.WithUnsafeRegionIfNecessary(modifiers);
- bodyBinder = bodyBinder.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.SuppressConstraintChecks, this);
-
- var propertySyntax = syntax as PropertyDeclarationSyntax;
- var arrowExpression = propertySyntax != null
- ? propertySyntax.ExpressionBody
- : ((IndexerDeclarationSyntax)syntax).ExpressionBody;
- bool hasExpressionBody = arrowExpression != null;
- bool hasInitializer = !isIndexer && propertySyntax.Initializer != null;
-
- GetAcessorDeclarations(syntax, diagnostics, out bool isAutoProperty, out bool hasAccessorList,
- out AccessorDeclarationSyntax getSyntax, out AccessorDeclarationSyntax setSyntax);
-
- bool accessorsHaveImplementation;
- if (hasAccessorList)
- {
- accessorsHaveImplementation = (getSyntax != null && (getSyntax.Body != null || getSyntax.ExpressionBody != null)) ||
- (setSyntax != null && (setSyntax.Body != null || setSyntax.ExpressionBody != null));
- }
- else
- {
- accessorsHaveImplementation = hasExpressionBody;
- }
-
- bool modifierErrors;
- _modifiers = MakeModifiers(modifiers, isExplicitInterfaceImplementation, isIndexer,
- accessorsHaveImplementation, location,
- diagnostics, out modifierErrors);
- this.CheckAccessibility(location, diagnostics, isExplicitInterfaceImplementation);
-
- this.CheckModifiers(isExplicitInterfaceImplementation, location, isIndexer, diagnostics);
-
- isAutoProperty = isAutoProperty && (!(containingType.IsInterface && !IsStatic) && !IsAbstract && !IsExtern && !isIndexer && hasAccessorList);
-
- if (isIndexer && !isExplicitInterfaceImplementation)
- {
- // Evaluate the attributes immediately in case the IndexerNameAttribute has been applied.
- // NOTE: we want IsExplicitInterfaceImplementation, IsOverride, Locations, and the syntax reference
- // to be initialized before we pass this symbol to LoadCustomAttributes.
-
- // CONSIDER: none of the information from this early binding pass is cached. Everything will
- // be re-bound when someone calls GetAttributes. If this gets to be a problem, we could
- // always use the real attribute bag of this symbol and modify LoadAndValidateAttributes to
- // handle partially filled bags.
- CustomAttributesBag temp = null;
- LoadAndValidateAttributes(OneOrMany.Create(this.CSharpSyntaxNode.AttributeLists), ref temp, earlyDecodingOnly: true);
- if (temp != null)
- {
- Debug.Assert(temp.IsEarlyDecodedWellKnownAttributeDataComputed);
- var propertyData = (PropertyEarlyWellKnownAttributeData)temp.EarlyDecodedWellKnownAttributeData;
- if (propertyData != null)
- {
- _sourceName = propertyData.IndexerName;
- }
- }
- }
-
- string aliasQualifierOpt;
- string memberName = ExplicitInterfaceHelpers.GetMemberNameAndInterfaceSymbol(bodyBinder, interfaceSpecifier, name, diagnostics, out _explicitInterfaceType, out aliasQualifierOpt);
- _sourceName = _sourceName ?? memberName; //sourceName may have been set while loading attributes
- _name = isIndexer ? ExplicitInterfaceHelpers.GetMemberName(WellKnownMemberNames.Indexer, _explicitInterfaceType, aliasQualifierOpt) : _sourceName;
-
- if (hasInitializer)
- {
- CheckInitializer(isAutoProperty, containingType.IsInterface, IsStatic, location, diagnostics);
- }
-
- if (isAutoProperty || hasInitializer)
- {
- var hasGetSyntax = getSyntax != null;
- var isAutoPropertyWithGetSyntax = isAutoProperty && hasGetSyntax;
- if (isAutoPropertyWithGetSyntax)
- {
- _propertyFlags |= Flags.IsAutoProperty;
- }
-
- bool isGetterOnly = hasGetSyntax && setSyntax == null;
-
- if (isAutoPropertyWithGetSyntax && !IsStatic && !isGetterOnly)
- {
- if (ContainingType.IsReadOnly)
- {
- diagnostics.Add(ErrorCode.ERR_AutoPropsInRoStruct, location);
- }
- else if (HasReadOnlyModifier)
- {
- diagnostics.Add(ErrorCode.ERR_AutoPropertyWithSetterCantBeReadOnly, location, this);
- }
- }
-
- if (isAutoPropertyWithGetSyntax || hasInitializer)
- {
- if (isAutoPropertyWithGetSyntax)
- {
- //issue a diagnostic if the compiler generated attribute ctor is not found.
- Binder.ReportUseSiteDiagnosticForSynthesizedAttribute(bodyBinder.Compilation,
- WellKnownMember.System_Runtime_CompilerServices_CompilerGeneratedAttribute__ctor, diagnostics, syntax: syntax);
-
- if (this._refKind != RefKind.None && !_containingType.IsInterface)
- {
- diagnostics.Add(ErrorCode.ERR_AutoPropertyCannotBeRefReturning, location, this);
- }
- }
-
- string fieldName = GeneratedNames.MakeBackingFieldName(_sourceName);
- bool isInitOnly = !IsStatic && setSyntax?.Keyword.IsKind(SyntaxKind.InitKeyword) == true;
- BackingField = new SynthesizedBackingFieldSymbol(this,
- fieldName,
- isReadOnly: isGetterOnly || isInitOnly,
- this.IsStatic,
- hasInitializer);
- }
-
- if (isAutoProperty)
- {
- Binder.CheckFeatureAvailability(
- syntax,
- isGetterOnly ? MessageID.IDS_FeatureReadonlyAutoImplementedProperties : MessageID.IDS_FeatureAutoImplementedProperties,
- diagnostics,
- location);
- }
- }
-
- PropertySymbol explicitlyImplementedProperty = null;
- _refCustomModifiers = ImmutableArray.Empty;
-
- // The runtime will not treat the accessors of this property as overrides or implementations
- // of those of another property unless both the signatures and the custom modifiers match.
- // Hence, in the case of overrides and *explicit* implementations, we need to copy the custom
- // modifiers that are in the signatures of the overridden/implemented property accessors.
- // (From source, we know that there can only be one overridden/implemented property, so there
- // are no conflicts.) This is unnecessary for implicit implementations because, if the custom
- // modifiers don't match, we'll insert bridge methods for the accessors (explicit implementations
- // that delegate to the implicit implementations) with the correct custom modifiers
- // (see SourceMemberContainerTypeSymbol.SynthesizeInterfaceMemberImplementation).
-
- // Note: we're checking if the syntax indicates explicit implementation rather,
- // than if explicitInterfaceType is null because we don't want to look for an
- // overridden property if this is supposed to be an explicit implementation.
- if (isExplicitInterfaceImplementation || this.IsOverride)
- {
- // Type and parameters for overrides and explicit implementations cannot be bound
- // lazily since the property name depends on the metadata name of the base property,
- // and the property name is required to add the property to the containing type, and
- // the type and parameters are required to determine the override or implementation.
- var type = this.ComputeType(bodyBinder, syntax, diagnostics);
- _lazyType = new TypeWithAnnotations.Boxed(type);
- _lazyParameters = this.ComputeParameters(bodyBinder, syntax, diagnostics);
-
- bool isOverride = false;
- PropertySymbol overriddenOrImplementedProperty = null;
-
- if (!isExplicitInterfaceImplementation)
- {
- // If this property is an override, we may need to copy custom modifiers from
- // the overridden property (so that the runtime will recognize it as an override).
- // We check for this case here, while we can still modify the parameters and
- // return type without losing the appearance of immutability.
- isOverride = true;
- overriddenOrImplementedProperty = this.OverriddenProperty;
- }
- else
- {
- string interfacePropertyName = isIndexer ? WellKnownMemberNames.Indexer : name;
- explicitlyImplementedProperty = this.FindExplicitlyImplementedProperty(_explicitInterfaceType, interfacePropertyName, interfaceSpecifier, diagnostics);
- this.FindExplicitlyImplementedMemberVerification(explicitlyImplementedProperty, diagnostics);
- overriddenOrImplementedProperty = explicitlyImplementedProperty;
- }
-
- if ((object)overriddenOrImplementedProperty != null)
- {
- _refCustomModifiers = _refKind != RefKind.None ? overriddenOrImplementedProperty.RefCustomModifiers : ImmutableArray.Empty;
-
- TypeWithAnnotations overriddenPropertyType = overriddenOrImplementedProperty.TypeWithAnnotations;
-
- // We do an extra check before copying the type to handle the case where the overriding
- // property (incorrectly) has a different type than the overridden property. In such cases,
- // we want to retain the original (incorrect) type to avoid hiding the type given in source.
- if (type.Type.Equals(overriddenPropertyType.Type, TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds | TypeCompareKind.IgnoreNullableModifiersForReferenceTypes | TypeCompareKind.IgnoreDynamic))
- {
- type = type.WithTypeAndModifiers(
- CustomModifierUtils.CopyTypeCustomModifiers(overriddenPropertyType.Type, type.Type, this.ContainingAssembly),
- overriddenPropertyType.CustomModifiers);
-
- _lazyType = new TypeWithAnnotations.Boxed(type);
- }
-
- _lazyParameters = CustomModifierUtils.CopyParameterCustomModifiers(overriddenOrImplementedProperty.Parameters, _lazyParameters, alsoCopyParamsModifier: isOverride);
- }
- }
- else if (_refKind == RefKind.RefReadOnly)
- {
- var modifierType = bodyBinder.GetWellKnownType(WellKnownType.System_Runtime_InteropServices_InAttribute, diagnostics, syntax.Type);
-
- _refCustomModifiers = ImmutableArray.Create(CSharpCustomModifier.CreateRequired(modifierType));
- }
-
- if (!hasAccessorList)
- {
- if (hasExpressionBody)
- {
- _propertyFlags |= Flags.IsExpressionBodied;
- _getMethod = SourcePropertyAccessorSymbol.CreateAccessorSymbol(
- containingType,
- this,
- _modifiers,
- _sourceName,
- arrowExpression,
- explicitlyImplementedProperty,
- aliasQualifierOpt,
- isExplicitInterfaceImplementation,
- diagnostics);
- }
- else
- {
- _getMethod = null;
- }
- _setMethod = null;
- }
- else
- {
- _getMethod = CreateAccessorSymbol(getSyntax, explicitlyImplementedProperty, aliasQualifierOpt, isAutoProperty, isExplicitInterfaceImplementation, diagnostics);
- _setMethod = CreateAccessorSymbol(setSyntax, explicitlyImplementedProperty, aliasQualifierOpt, isAutoProperty, isExplicitInterfaceImplementation, diagnostics);
-
- if ((getSyntax == null) || (setSyntax == null))
- {
- if ((getSyntax == null) && (setSyntax == null))
- {
- diagnostics.Add(ErrorCode.ERR_PropertyWithNoAccessors, location, this);
- }
- else if (_refKind != RefKind.None)
- {
- if (getSyntax == null)
- {
- diagnostics.Add(ErrorCode.ERR_RefPropertyMustHaveGetAccessor, location, this);
- }
- }
- else if (isAutoProperty)
- {
- var accessor = _getMethod ?? _setMethod;
- if (getSyntax == null)
- {
- diagnostics.Add(ErrorCode.ERR_AutoPropertyMustHaveGetAccessor, accessor.Locations[0], accessor);
- }
- }
- }
-
- // Check accessor accessibility is more restrictive than property accessibility.
- CheckAccessibilityMoreRestrictive(_getMethod, diagnostics);
- CheckAccessibilityMoreRestrictive(_setMethod, diagnostics);
-
- if (((object)_getMethod != null) && ((object)_setMethod != null))
- {
- if (_refKind != RefKind.None)
- {
- diagnostics.Add(ErrorCode.ERR_RefPropertyCannotHaveSetAccessor, _setMethod.Locations[0], _setMethod);
- }
- else if ((_getMethod.LocalAccessibility != Accessibility.NotApplicable) &&
- (_setMethod.LocalAccessibility != Accessibility.NotApplicable))
- {
- // Check accessibility is set on at most one accessor.
- diagnostics.Add(ErrorCode.ERR_DuplicatePropertyAccessMods, location, this);
- }
- else if (_getMethod.LocalDeclaredReadOnly && _setMethod.LocalDeclaredReadOnly)
- {
- diagnostics.Add(ErrorCode.ERR_DuplicatePropertyReadOnlyMods, location, this);
- }
- else if (this.IsAbstract)
- {
- // Check abstract property accessors are not private.
- CheckAbstractPropertyAccessorNotPrivate(_getMethod, diagnostics);
- CheckAbstractPropertyAccessorNotPrivate(_setMethod, diagnostics);
- }
- }
- else
- {
- if (!this.IsOverride)
- {
- var accessor = _getMethod ?? _setMethod;
- if ((object)accessor != null)
- {
- // Check accessibility is not set on the one accessor.
- if (accessor.LocalAccessibility != Accessibility.NotApplicable)
- {
- diagnostics.Add(ErrorCode.ERR_AccessModMissingAccessor, location, this);
- }
-
- // Check that 'readonly' is not set on the one accessor.
- if (accessor.LocalDeclaredReadOnly)
- {
- diagnostics.Add(ErrorCode.ERR_ReadOnlyModMissingAccessor, location, this);
- }
- }
- }
- }
- }
-
- if ((object)explicitlyImplementedProperty != null)
- {
- CheckExplicitImplementationAccessor(this.GetMethod, explicitlyImplementedProperty.GetMethod, explicitlyImplementedProperty, diagnostics);
- CheckExplicitImplementationAccessor(this.SetMethod, explicitlyImplementedProperty.SetMethod, explicitlyImplementedProperty, diagnostics);
- }
-
- _explicitInterfaceImplementations =
- (object)explicitlyImplementedProperty == null ?
- ImmutableArray.Empty :
- ImmutableArray.Create(explicitlyImplementedProperty);
+ }
- // get-only auto property should not override settable properties
- if ((_propertyFlags & Flags.IsAutoProperty) != 0)
- {
- if (_setMethod is null && !this.IsReadOnly)
- {
- diagnostics.Add(ErrorCode.ERR_AutoPropertyMustOverrideSet, location, this);
- }
+ private TypeSyntax GetTypeSyntax(SyntaxNode syntax) => ((BasePropertyDeclarationSyntax)syntax).Type;
- CheckForFieldTargetedAttribute(syntax, diagnostics);
- }
+ protected override Location TypeLocation
+ => GetTypeSyntax(CSharpSyntaxNode).Location;
- CheckForBlockAndExpressionBody(
- syntax.AccessorList, syntax.GetExpressionBodySyntax(), syntax, diagnostics);
- }
+ protected override SyntaxTokenList GetModifierTokens(SyntaxNode syntax)
+ => ((BasePropertyDeclarationSyntax)syntax).Modifiers;
- private void CheckForFieldTargetedAttribute(BasePropertyDeclarationSyntax syntax, DiagnosticBag diagnostics)
- {
- var languageVersion = this.DeclaringCompilation.LanguageVersion;
- if (languageVersion.AllowAttributesOnBackingFields())
+ protected override ArrowExpressionClauseSyntax? GetArrowExpression(SyntaxNode syntax)
+ => syntax switch
{
- return;
- }
+ PropertyDeclarationSyntax p => p.ExpressionBody,
+ IndexerDeclarationSyntax i => i.ExpressionBody,
+ _ => throw ExceptionUtilities.UnexpectedValue(syntax.Kind())
+ };
- foreach (var attribute in syntax.AttributeLists)
- {
- if (attribute.Target?.GetAttributeLocation() == AttributeLocation.Field)
- {
- diagnostics.Add(
- new CSDiagnosticInfo(ErrorCode.WRN_AttributesOnBackingFieldsNotAvailable,
- languageVersion.ToDisplayString(),
- new CSharpRequiredLanguageVersion(MessageID.IDS_FeatureAttributesOnBackingFields.RequiredVersion())),
- attribute.Target.Location);
- }
- }
- }
+ protected override bool HasInitializer(SyntaxNode syntax)
+ => syntax is PropertyDeclarationSyntax { Initializer: { } };
- private static void GetAcessorDeclarations(BasePropertyDeclarationSyntax syntax, DiagnosticBag diagnostics,
- out bool isAutoProperty, out bool hasAccessorList,
- out AccessorDeclarationSyntax getSyntax, out AccessorDeclarationSyntax setSyntax)
- {
+ public override SyntaxList AttributeDeclarationSyntaxList
+ => ((BasePropertyDeclarationSyntax)CSharpSyntaxNode).AttributeLists;
+
+ protected override void GetAccessorDeclarations(
+ CSharpSyntaxNode syntaxNode,
+ DiagnosticBag diagnostics,
+ out bool isAutoProperty,
+ out bool hasAccessorList,
+ out bool accessorsHaveImplementation,
+ out bool isInitOnly,
+ out CSharpSyntaxNode? getSyntax,
+ out CSharpSyntaxNode? setSyntax)
+ {
+ var syntax = (BasePropertyDeclarationSyntax)syntaxNode;
isAutoProperty = true;
hasAccessorList = syntax.AccessorList != null;
getSyntax = null;
setSyntax = null;
+ isInitOnly = false;
if (hasAccessorList)
{
- foreach (var accessor in syntax.AccessorList.Accessors)
+ accessorsHaveImplementation = false;
+ foreach (var accessor in syntax.AccessorList!.Accessors)
{
switch (accessor.Kind())
{
@@ -461,6 +102,10 @@ private void CheckForFieldTargetedAttribute(BasePropertyDeclarationSyntax syntax
if (setSyntax == null)
{
setSyntax = accessor;
+ if (accessor.Keyword.IsKind(SyntaxKind.InitKeyword))
+ {
+ isInitOnly = true;
+ }
}
else
{
@@ -482,466 +127,196 @@ private void CheckForFieldTargetedAttribute(BasePropertyDeclarationSyntax syntax
if (accessor.Body != null || accessor.ExpressionBody != null)
{
isAutoProperty = false;
+ accessorsHaveImplementation = true;
}
}
}
else
{
isAutoProperty = false;
+ accessorsHaveImplementation = GetArrowExpression(syntax) is object;
}
}
- internal sealed override ImmutableArray NotNullMembers =>
- GetDecodedWellKnownAttributeData()?.NotNullMembers ?? ImmutableArray.Empty;
-
- internal sealed override ImmutableArray NotNullWhenTrueMembers =>
- GetDecodedWellKnownAttributeData()?.NotNullWhenTrueMembers ?? ImmutableArray.Empty;
-
- internal sealed override ImmutableArray NotNullWhenFalseMembers =>
- GetDecodedWellKnownAttributeData()?.NotNullWhenFalseMembers ?? ImmutableArray.Empty;
-
- internal bool IsExpressionBodied
- => (_propertyFlags & Flags.IsExpressionBodied) != 0;
-
- private void CheckInitializer(
- bool isAutoProperty,
- bool isInterface,
- bool isStatic,
- Location location,
- DiagnosticBag diagnostics)
+ protected override void CheckForBlockAndExpressionBody(CSharpSyntaxNode syntax, DiagnosticBag diagnostics)
{
- if (isInterface && !isStatic)
- {
- diagnostics.Add(ErrorCode.ERR_InstancePropertyInitializerInInterface, location, this);
- }
- else if (!isAutoProperty)
- {
- diagnostics.Add(ErrorCode.ERR_InitializerOnNonAutoProperty, location, this);
- }
+ var prop = (BasePropertyDeclarationSyntax)syntax;
+ CheckForBlockAndExpressionBody(
+ prop.AccessorList,
+ prop.GetExpressionBodySyntax(),
+ prop,
+ diagnostics);
}
- internal static SourcePropertySymbol Create(SourceMemberContainerTypeSymbol containingType, Binder bodyBinder, PropertyDeclarationSyntax syntax, DiagnosticBag diagnostics)
+ protected override DeclarationModifiers MakeModifiers(
+ SyntaxTokenList modifiers,
+ bool isExplicitInterfaceImplementation,
+ bool isIndexer,
+ bool accessorsHaveImplementation,
+ Location location,
+ DiagnosticBag diagnostics,
+ out bool modifierErrors)
{
- var nameToken = syntax.Identifier;
- var location = nameToken.GetLocation();
- return new SourcePropertySymbol(containingType, bodyBinder, syntax, nameToken.ValueText, location, diagnostics);
- }
+ bool isInterface = this.ContainingType.IsInterface;
+ var defaultAccess = isInterface && !isExplicitInterfaceImplementation ? DeclarationModifiers.Public : DeclarationModifiers.Private;
- internal static SourcePropertySymbol Create(SourceMemberContainerTypeSymbol containingType, Binder bodyBinder, IndexerDeclarationSyntax syntax, DiagnosticBag diagnostics)
- {
- var location = syntax.ThisKeyword.GetLocation();
- return new SourcePropertySymbol(containingType, bodyBinder, syntax, DefaultIndexerName, location, diagnostics);
- }
+ // Check that the set of modifiers is allowed
+ var allowedModifiers = DeclarationModifiers.Unsafe;
+ var defaultInterfaceImplementationModifiers = DeclarationModifiers.None;
- public override RefKind RefKind
- {
- get
+ if (!isExplicitInterfaceImplementation)
{
- return _refKind;
- }
- }
+ allowedModifiers |= DeclarationModifiers.New |
+ DeclarationModifiers.Sealed |
+ DeclarationModifiers.Abstract |
+ DeclarationModifiers.Virtual |
+ DeclarationModifiers.AccessibilityMask;
- public override TypeWithAnnotations TypeWithAnnotations
- {
- get
- {
- if (_lazyType == null)
+ if (!isIndexer)
{
- var diagnostics = DiagnosticBag.GetInstance();
- var binder = this.CreateBinderForTypeAndParameters();
- var syntax = (BasePropertyDeclarationSyntax)_syntaxRef.GetSyntax();
- var result = this.ComputeType(binder, syntax, diagnostics);
- if (Interlocked.CompareExchange(ref _lazyType, new TypeWithAnnotations.Boxed(result), null) == null)
- {
- this.AddDeclarationDiagnostics(diagnostics);
- }
- diagnostics.Free();
+ allowedModifiers |= DeclarationModifiers.Static;
}
- return _lazyType.Value;
- }
- }
-
- internal override bool HasPointerType
- {
- get
- {
- if (_lazyType != null)
+ if (!isInterface)
{
-
- var hasPointerType = _lazyType.Value.DefaultType.IsPointerOrFunctionPointer();
- Debug.Assert(hasPointerType == hasPointerTypeSyntactically());
- return hasPointerType;
+ allowedModifiers |= DeclarationModifiers.Override;
}
-
- return hasPointerTypeSyntactically();
-
- bool hasPointerTypeSyntactically()
+ else
{
- var syntax = (BasePropertyDeclarationSyntax)_syntaxRef.GetSyntax();
- var typeSyntax = syntax.Type.SkipRef(out _);
- return typeSyntax.Kind() switch { SyntaxKind.PointerType => true, SyntaxKind.FunctionPointerType => true, _ => false };
+ // This is needed to make sure we can detect 'public' modifier specified explicitly and
+ // check it against language version below.
+ defaultAccess = DeclarationModifiers.None;
+
+ defaultInterfaceImplementationModifiers |= DeclarationModifiers.Sealed |
+ DeclarationModifiers.Abstract |
+ (isIndexer ? 0 : DeclarationModifiers.Static) |
+ DeclarationModifiers.Virtual |
+ DeclarationModifiers.Extern |
+ DeclarationModifiers.AccessibilityMask;
}
}
- }
-
- ///
- /// To facilitate lookup, all indexer symbols have the same name.
- /// Check the MetadataName property to find the name that will be
- /// emitted (based on IndexerNameAttribute, or the default "Item").
- ///
- public override string Name
- {
- get
+ else if (isInterface)
{
- return _name;
+ Debug.Assert(isExplicitInterfaceImplementation);
+ allowedModifiers |= DeclarationModifiers.Abstract;
}
- }
- public override string MetadataName
- {
- get
+ if (ContainingType.IsStructType())
{
- // Explicit implementation names may have spaces if the interface
- // is generic (between the type arguments).
- return _sourceName.Replace(" ", "");
+ allowedModifiers |= DeclarationModifiers.ReadOnly;
}
- }
- public override Symbol ContainingSymbol
- {
- get
+ allowedModifiers |= DeclarationModifiers.Extern;
+
+ var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(modifiers, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors);
+
+ this.CheckUnsafeModifier(mods, diagnostics);
+
+ ModifierUtils.ReportDefaultInterfaceImplementationModifiers(accessorsHaveImplementation, mods,
+ defaultInterfaceImplementationModifiers,
+ location, diagnostics);
+
+ // Let's overwrite modifiers for interface properties with what they are supposed to be.
+ // Proper errors must have been reported by now.
+ if (isInterface)
{
- return _containingType;
+ mods = ModifierUtils.AdjustModifiersForAnInterfaceMember(mods, accessorsHaveImplementation, isExplicitInterfaceImplementation);
}
- }
- public override NamedTypeSymbol ContainingType
- {
- get
+ if (isIndexer)
{
- return _containingType;
- }
- }
-
- internal override LexicalSortKey GetLexicalSortKey()
- {
- return new LexicalSortKey(Location, this.DeclaringCompilation);
- }
-
- public override ImmutableArray Locations
- {
- get
- {
- return ImmutableArray.Create(Location);
- }
- }
-
- public override ImmutableArray DeclaringSyntaxReferences
- {
- get
- {
- return ImmutableArray.Create(_syntaxRef);
- }
- }
-
- public override bool IsAbstract
- {
- get { return (_modifiers & DeclarationModifiers.Abstract) != 0; }
- }
-
- public override bool IsExtern
- {
- get { return (_modifiers & DeclarationModifiers.Extern) != 0; }
- }
-
- public override bool IsStatic
- {
- get { return (_modifiers & DeclarationModifiers.Static) != 0; }
- }
-
- internal bool IsFixed
- {
- get { return false; }
- }
-
- ///
- /// Even though it is declared with an IndexerDeclarationSyntax, an explicit
- /// interface implementation is not an indexer because it will not cause the
- /// containing type to be emitted with a DefaultMemberAttribute (and even if
- /// there is another indexer, the name of the explicit implementation won't
- /// match). This is important for round-tripping.
- ///
- public override bool IsIndexer
- {
- get { return (_modifiers & DeclarationModifiers.Indexer) != 0; }
- }
-
- public override bool IsOverride
- {
- get { return (_modifiers & DeclarationModifiers.Override) != 0; }
- }
-
- public override bool IsSealed
- {
- get { return (_modifiers & DeclarationModifiers.Sealed) != 0; }
- }
-
- public override bool IsVirtual
- {
- get { return (_modifiers & DeclarationModifiers.Virtual) != 0; }
- }
-
- internal bool IsNew
- {
- get { return (_modifiers & DeclarationModifiers.New) != 0; }
- }
-
- internal bool HasReadOnlyModifier => (_modifiers & DeclarationModifiers.ReadOnly) != 0;
-
- public override MethodSymbol GetMethod
- {
- get { return _getMethod; }
- }
-
- public override MethodSymbol SetMethod
- {
- get { return _setMethod; }
- }
-
- internal override Microsoft.Cci.CallingConvention CallingConvention
- {
- get { return (IsStatic ? 0 : Microsoft.Cci.CallingConvention.HasThis); }
- }
-
- public override ImmutableArray Parameters
- {
- get
- {
- if (_lazyParameters.IsDefault)
- {
- var diagnostics = DiagnosticBag.GetInstance();
- var binder = this.CreateBinderForTypeAndParameters();
- var syntax = (BasePropertyDeclarationSyntax)_syntaxRef.GetSyntax();
- var result = this.ComputeParameters(binder, syntax, diagnostics);
- if (ImmutableInterlocked.InterlockedInitialize(ref _lazyParameters, result))
- {
- this.AddDeclarationDiagnostics(diagnostics);
- }
- diagnostics.Free();
- }
-
- return _lazyParameters;
- }
- }
-
- internal override bool IsExplicitInterfaceImplementation
- => (_propertyFlags & Flags.IsExplicitInterfaceImplementation) != 0;
-
- public override ImmutableArray ExplicitInterfaceImplementations
- {
- get { return _explicitInterfaceImplementations; }
- }
-
- public override ImmutableArray RefCustomModifiers
- {
- get { return _refCustomModifiers; }
- }
-
- public override Accessibility DeclaredAccessibility
- {
- get
- {
- return ModifierUtils.EffectiveAccessibility(_modifiers);
- }
- }
-
- public bool HasSkipLocalsInitAttribute
- {
- get
- {
- var data = this.GetDecodedWellKnownAttributeData();
- return data?.HasSkipLocalsInitAttribute == true;
- }
- }
-
- internal override bool IsAutoProperty
- => (_propertyFlags & Flags.IsAutoProperty) != 0;
-
- ///
- /// Backing field for automatically implemented property, or
- /// for a property with an initializer.
- ///
- internal override SynthesizedBackingFieldSymbol BackingField { get; }
-
- internal override bool MustCallMethodsDirectly
- {
- get { return false; }
- }
-
- internal SyntaxReference SyntaxReference
- {
- get
- {
- return _syntaxRef;
+ mods |= DeclarationModifiers.Indexer;
}
- }
- internal BasePropertyDeclarationSyntax CSharpSyntaxNode
- {
- get
- {
- return (BasePropertyDeclarationSyntax)_syntaxRef.GetSyntax();
- }
+ return mods;
}
- public override SyntaxList AttributeDeclarationSyntaxList
- => CSharpSyntaxNode.AttributeLists;
-
- internal SyntaxTree SyntaxTree
+ protected override SourcePropertyAccessorSymbol? CreateAccessorSymbol(
+ bool isGet,
+ CSharpSyntaxNode? syntaxOpt,
+ PropertySymbol? explicitlyImplementedPropertyOpt,
+ string aliasQualifierOpt,
+ bool isAutoPropertyAccessor,
+ bool isExplicitInterfaceImplementation,
+ DiagnosticBag diagnostics)
{
- get
+ if (syntaxOpt is null)
{
- return _syntaxRef.SyntaxTree;
+ return null;
}
- }
-
- internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, DiagnosticBag diagnostics)
+ return SourcePropertyAccessorSymbol.CreateAccessorSymbol(
+ ContainingType,
+ this,
+ _modifiers,
+ _sourceName,
+ (AccessorDeclarationSyntax)syntaxOpt,
+ explicitlyImplementedPropertyOpt,
+ aliasQualifierOpt,
+ isAutoPropertyAccessor,
+ isExplicitInterfaceImplementation,
+ diagnostics);
+ }
+
+ protected override SourcePropertyAccessorSymbol CreateExpressionBodiedAccessor(
+ ArrowExpressionClauseSyntax syntax,
+ PropertySymbol? explicitlyImplementedPropertyOpt,
+ string aliasQualifierOpt,
+ bool isExplicitInterfaceImplementation,
+ DiagnosticBag diagnostics)
{
- Location location = CSharpSyntaxNode.Type.Location;
- var compilation = DeclaringCompilation;
-
- Debug.Assert(location != null);
-
- // Check constraints on return type and parameters. Note: Dev10 uses the
- // property name location for any such errors. We'll do the same for return
- // type errors but for parameter errors, we'll use the parameter location.
-
- if ((object)_explicitInterfaceType != null)
- {
- var explicitInterfaceSpecifier = GetExplicitInterfaceSpecifier(this.CSharpSyntaxNode);
- Debug.Assert(explicitInterfaceSpecifier != null);
- _explicitInterfaceType.CheckAllConstraints(compilation, conversions, new SourceLocation(explicitInterfaceSpecifier.Name), diagnostics);
-
- // Note: we delayed nullable-related checks that could pull on NonNullTypes
- if (!_explicitInterfaceImplementations.IsEmpty)
- {
- TypeSymbol.CheckNullableReferenceTypeMismatchOnImplementingMember(this.ContainingType, this, _explicitInterfaceImplementations[0], isExplicit: true, diagnostics);
- }
- }
-
- if (_refKind == RefKind.RefReadOnly)
- {
- compilation.EnsureIsReadOnlyAttributeExists(diagnostics, location, modifyCompilation: true);
- }
-
- ParameterHelpers.EnsureIsReadOnlyAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true);
-
- if (Type.ContainsNativeInteger())
- {
- compilation.EnsureNativeIntegerAttributeExists(diagnostics, location, modifyCompilation: true);
- }
-
- ParameterHelpers.EnsureNativeIntegerAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true);
-
- if (compilation.ShouldEmitNullableAttributes(this) &&
- this.TypeWithAnnotations.NeedsNullableAttribute())
- {
- compilation.EnsureNullableAttributeExists(diagnostics, location, modifyCompilation: true);
- }
-
- ParameterHelpers.EnsureNullableAttributeExists(compilation, this, Parameters, diagnostics, modifyCompilation: true);
+ return SourcePropertyAccessorSymbol.CreateAccessorSymbol(
+ ContainingType,
+ this,
+ _modifiers,
+ _sourceName,
+ syntax,
+ explicitlyImplementedPropertyOpt,
+ aliasQualifierOpt,
+ isExplicitInterfaceImplementation,
+ diagnostics);
}
- private void CheckAccessibility(Location location, DiagnosticBag diagnostics, bool isExplicitInterfaceImplementation)
+ private Binder CreateBinderForTypeAndParameters()
{
- var info = ModifierUtils.CheckAccessibility(_modifiers, this, isExplicitInterfaceImplementation);
- if (info != null)
- {
- diagnostics.Add(new CSDiagnostic(info, location));
- }
+ var compilation = this.DeclaringCompilation;
+ var syntaxTree = SyntaxTree;
+ var syntax = CSharpSyntaxNode;
+ var binderFactory = compilation.GetBinderFactory(syntaxTree);
+ var binder = binderFactory.GetBinder(syntax, syntax, this);
+ SyntaxTokenList modifiers = GetModifierTokens(syntax);
+ binder = binder.WithUnsafeRegionIfNecessary(modifiers);
+ return binder.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.SuppressConstraintChecks, this);
}
- private DeclarationModifiers MakeModifiers(SyntaxTokenList modifiers, bool isExplicitInterfaceImplementation,
- bool isIndexer, bool accessorsHaveImplementation,
- Location location, DiagnosticBag diagnostics, out bool modifierErrors)
+ protected override TypeWithAnnotations ComputeType(Binder? binder, SyntaxNode syntax, DiagnosticBag diagnostics)
{
- bool isInterface = this.ContainingType.IsInterface;
- var defaultAccess = isInterface && !isExplicitInterfaceImplementation ? DeclarationModifiers.Public : DeclarationModifiers.Private;
-
- // Check that the set of modifiers is allowed
- var allowedModifiers = DeclarationModifiers.Unsafe;
- var defaultInterfaceImplementationModifiers = DeclarationModifiers.None;
-
- if (!isExplicitInterfaceImplementation)
- {
- allowedModifiers |= DeclarationModifiers.New |
- DeclarationModifiers.Sealed |
- DeclarationModifiers.Abstract |
- DeclarationModifiers.Virtual |
- DeclarationModifiers.AccessibilityMask;
-
- if (!isIndexer)
- {
- allowedModifiers |= DeclarationModifiers.Static;
- }
-
- if (!isInterface)
- {
- allowedModifiers |= DeclarationModifiers.Override;
- }
- else
- {
- // This is needed to make sure we can detect 'public' modifier specified explicitly and
- // check it against language version below.
- defaultAccess = DeclarationModifiers.None;
+ binder ??= CreateBinderForTypeAndParameters();
- defaultInterfaceImplementationModifiers |= DeclarationModifiers.Sealed |
- DeclarationModifiers.Abstract |
- (isIndexer ? 0 : DeclarationModifiers.Static) |
- DeclarationModifiers.Virtual |
- DeclarationModifiers.Extern |
- DeclarationModifiers.AccessibilityMask;
- }
- }
- else if (isInterface)
- {
- Debug.Assert(isExplicitInterfaceImplementation);
- allowedModifiers |= DeclarationModifiers.Abstract;
- }
+ RefKind refKind;
+ var typeSyntax = GetTypeSyntax(syntax).SkipRef(out refKind);
+ var type = binder.BindType(typeSyntax, diagnostics);
+ HashSet? useSiteDiagnostics = null;
- if (ContainingType.IsStructType())
+ if (GetExplicitInterfaceSpecifier(syntax) is null && !this.IsNoMoreVisibleThan(type, ref useSiteDiagnostics))
{
- allowedModifiers |= DeclarationModifiers.ReadOnly;
+ // "Inconsistent accessibility: indexer return type '{1}' is less accessible than indexer '{0}'"
+ // "Inconsistent accessibility: property type '{1}' is less accessible than property '{0}'"
+ diagnostics.Add((this.IsIndexer ? ErrorCode.ERR_BadVisIndexerReturn : ErrorCode.ERR_BadVisPropertyType), Location, this, type.Type);
}
- allowedModifiers |= DeclarationModifiers.Extern;
-
- var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(modifiers, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors);
-
- this.CheckUnsafeModifier(mods, diagnostics);
-
- ModifierUtils.ReportDefaultInterfaceImplementationModifiers(accessorsHaveImplementation, mods,
- defaultInterfaceImplementationModifiers,
- location, diagnostics);
-
- // Let's overwrite modifiers for interface properties with what they are supposed to be.
- // Proper errors must have been reported by now.
- if (isInterface)
- {
- mods = ModifierUtils.AdjustModifiersForAnInterfaceMember(mods, accessorsHaveImplementation, isExplicitInterfaceImplementation);
- }
+ diagnostics.Add(Location, useSiteDiagnostics);
- if (isIndexer)
+ if (type.IsVoidType())
{
- mods |= DeclarationModifiers.Indexer;
+ ErrorCode errorCode = this.IsIndexer ? ErrorCode.ERR_IndexerCantHaveVoidType : ErrorCode.ERR_PropertyCantHaveVoidType;
+ diagnostics.Add(errorCode, Location, this);
}
- return mods;
+ return type;
}
private static ImmutableArray MakeParameters(
- Binder binder, SourcePropertySymbol owner, BaseParameterListSyntax parameterSyntaxOpt, DiagnosticBag diagnostics, bool addRefReadOnlyModifier)
+ Binder binder, SourcePropertySymbolBase owner, BaseParameterListSyntax? parameterSyntaxOpt, DiagnosticBag diagnostics, bool addRefReadOnlyModifier)
{
if (parameterSyntaxOpt == null)
{
@@ -981,728 +356,43 @@ private void CheckAccessibility(Location location, DiagnosticBag diagnostics, bo
return parameters;
}
- private void CheckModifiers(bool isExplicitInterfaceImplementation, Location location, bool isIndexer, DiagnosticBag diagnostics)
+ protected override ImmutableArray ComputeParameters(Binder? binder, CSharpSyntaxNode syntax, DiagnosticBag diagnostics)
{
- bool isExplicitInterfaceImplementationInInterface = isExplicitInterfaceImplementation && ContainingType.IsInterface;
+ binder ??= CreateBinderForTypeAndParameters();
- if (this.DeclaredAccessibility == Accessibility.Private && (IsVirtual || (IsAbstract && !isExplicitInterfaceImplementationInInterface) || IsOverride))
- {
- diagnostics.Add(ErrorCode.ERR_VirtualPrivate, location, this);
- }
- else if (IsStatic && (IsOverride || IsVirtual || IsAbstract))
- {
- // A static member '{0}' cannot be marked as override, virtual, or abstract
- diagnostics.Add(ErrorCode.ERR_StaticNotVirtual, location, this);
- }
- else if (IsStatic && HasReadOnlyModifier)
- {
- // Static member '{0}' cannot be marked 'readonly'.
- diagnostics.Add(ErrorCode.ERR_StaticMemberCantBeReadOnly, location, this);
- }
- else if (IsOverride && (IsNew || IsVirtual))
- {
- // A member '{0}' marked as override cannot be marked as new or virtual
- diagnostics.Add(ErrorCode.ERR_OverrideNotNew, location, this);
- }
- else if (IsSealed && !IsOverride && !(IsAbstract && isExplicitInterfaceImplementationInInterface))
- {
- // '{0}' cannot be sealed because it is not an override
- diagnostics.Add(ErrorCode.ERR_SealedNonOverride, location, this);
- }
- else if (IsAbstract && ContainingType.TypeKind == TypeKind.Struct)
- {
- // The modifier '{0}' is not valid for this item
- diagnostics.Add(ErrorCode.ERR_BadMemberFlag, location, SyntaxFacts.GetText(SyntaxKind.AbstractKeyword));
- }
- else if (IsVirtual && ContainingType.TypeKind == TypeKind.Struct)
- {
- // The modifier '{0}' is not valid for this item
- diagnostics.Add(ErrorCode.ERR_BadMemberFlag, location, SyntaxFacts.GetText(SyntaxKind.VirtualKeyword));
- }
- else if (IsAbstract && IsExtern)
- {
- diagnostics.Add(ErrorCode.ERR_AbstractAndExtern, location, this);
- }
- else if (IsAbstract && IsSealed && !isExplicitInterfaceImplementationInInterface)
- {
- diagnostics.Add(ErrorCode.ERR_AbstractAndSealed, location, this);
- }
- else if (IsAbstract && IsVirtual)
- {
- diagnostics.Add(ErrorCode.ERR_AbstractNotVirtual, location, this.Kind.Localize(), this);
- }
- else if (ContainingType.IsSealed && this.DeclaredAccessibility.HasProtected() && !this.IsOverride)
- {
- diagnostics.Add(AccessCheck.GetProtectedMemberInSealedTypeError(ContainingType), location, this);
- }
- else if (ContainingType.IsStatic && !IsStatic)
- {
- ErrorCode errorCode = isIndexer ? ErrorCode.ERR_IndexerInStaticClass : ErrorCode.ERR_InstanceMemberInStaticClass;
- diagnostics.Add(errorCode, location, this);
- }
- }
+ var parameterSyntaxOpt = GetParameterListSyntax(syntax);
+ var parameters = MakeParameters(binder, this, parameterSyntaxOpt, diagnostics, addRefReadOnlyModifier: IsVirtual || IsAbstract);
+ HashSet? useSiteDiagnostics = null;
- // Create AccessorSymbol for AccessorDeclarationSyntax
- private SourcePropertyAccessorSymbol CreateAccessorSymbol(AccessorDeclarationSyntax syntaxOpt,
- PropertySymbol explicitlyImplementedPropertyOpt, string aliasQualifierOpt, bool isAutoPropertyAccessor, bool isExplicitInterfaceImplementation, DiagnosticBag diagnostics)
- {
- if (syntaxOpt == null)
+ foreach (ParameterSymbol param in parameters)
{
- return null;
+ if (GetExplicitInterfaceSpecifier(syntax) == null && !this.IsNoMoreVisibleThan(param.Type, ref useSiteDiagnostics))
+ {
+ diagnostics.Add(ErrorCode.ERR_BadVisIndexerParam, Location, this, param.Type);
+ }
+ else if (SetMethod is object && param.Name == ParameterSymbol.ValueParameterName)
+ {
+ diagnostics.Add(ErrorCode.ERR_DuplicateGeneratedName, param.Locations.FirstOrDefault() ?? Location, param.Name);
+ }
}
- return SourcePropertyAccessorSymbol.CreateAccessorSymbol(_containingType, this, _modifiers, _sourceName, syntaxOpt,
- explicitlyImplementedPropertyOpt, aliasQualifierOpt, isAutoPropertyAccessor, isExplicitInterfaceImplementation, diagnostics);
- }
- private void CheckAccessibilityMoreRestrictive(SourcePropertyAccessorSymbol accessor, DiagnosticBag diagnostics)
- {
- if (((object)accessor != null) &&
- !IsAccessibilityMoreRestrictive(this.DeclaredAccessibility, accessor.LocalAccessibility))
- {
- diagnostics.Add(ErrorCode.ERR_InvalidPropertyAccessMod, accessor.Locations[0], accessor, this);
- }
+ diagnostics.Add(Location, useSiteDiagnostics);
+ return parameters;
}
- ///
- /// Return true if the accessor accessibility is more restrictive
- /// than the property accessibility, otherwise false.
- ///
- private static bool IsAccessibilityMoreRestrictive(Accessibility property, Accessibility accessor)
+ protected override bool HasPointerTypeSyntactically
{
- if (accessor == Accessibility.NotApplicable)
+ get
{
- return true;
+ var typeSyntax = GetTypeSyntax(CSharpSyntaxNode).SkipRef(out _);
+ return typeSyntax.Kind() switch { SyntaxKind.PointerType => true, SyntaxKind.FunctionPointerType => true, _ => false };
}
- return (accessor < property) &&
- ((accessor != Accessibility.Protected) || (property != Accessibility.Internal));
}
- private static void CheckAbstractPropertyAccessorNotPrivate(SourcePropertyAccessorSymbol accessor, DiagnosticBag diagnostics)
- {
- if (accessor.LocalAccessibility == Accessibility.Private)
- {
- diagnostics.Add(ErrorCode.ERR_PrivateAbstractAccessor, accessor.Locations[0], accessor);
- }
- }
+ protected override ExplicitInterfaceSpecifierSyntax? GetExplicitInterfaceSpecifier(SyntaxNode syntax)
+ => ((BasePropertyDeclarationSyntax)syntax).ExplicitInterfaceSpecifier;
- public override string GetDocumentationCommentXml(CultureInfo preferredCulture = null, bool expandIncludes = false, CancellationToken cancellationToken = default(CancellationToken))
- {
- ref var lazyDocComment = ref expandIncludes ? ref _lazyExpandedDocComment : ref _lazyDocComment;
- return SourceDocumentationCommentUtils.GetAndCacheDocumentationComment(this, expandIncludes, ref lazyDocComment);
- }
-
- // Separate these checks out of FindExplicitlyImplementedProperty because they depend on the accessor symbols,
- // which depend on the explicitly implemented property
- private void CheckExplicitImplementationAccessor(MethodSymbol thisAccessor, MethodSymbol otherAccessor, PropertySymbol explicitlyImplementedProperty, DiagnosticBag diagnostics)
- {
- var thisHasAccessor = (object)thisAccessor != null;
- var otherHasAccessor = otherAccessor.IsImplementable();
-
- if (otherHasAccessor && !thisHasAccessor)
- {
- diagnostics.Add(ErrorCode.ERR_ExplicitPropertyMissingAccessor, this.Location, this, otherAccessor);
- }
- else if (!otherHasAccessor && thisHasAccessor)
- {
- diagnostics.Add(ErrorCode.ERR_ExplicitPropertyAddingAccessor, thisAccessor.Locations[0], thisAccessor, explicitlyImplementedProperty);
- }
- else if (TypeSymbol.HaveInitOnlyMismatch(thisAccessor, otherAccessor))
- {
- Debug.Assert(thisAccessor.MethodKind == MethodKind.PropertySet);
- diagnostics.Add(ErrorCode.ERR_ExplicitPropertyMismatchInitOnly, thisAccessor.Locations[0], thisAccessor, otherAccessor);
- }
- }
-
- internal override OverriddenOrHiddenMembersResult OverriddenOrHiddenMembers
- {
- get
- {
- if (_lazyOverriddenOrHiddenMembers == null)
- {
- Interlocked.CompareExchange(ref _lazyOverriddenOrHiddenMembers, this.MakeOverriddenOrHiddenMembers(), null);
- }
- return _lazyOverriddenOrHiddenMembers;
- }
- }
-
- ///
- /// If this property is sealed, then we have to emit both accessors - regardless of whether
- /// they are present in the source - so that they can be marked final. (i.e. sealed).
- ///
- internal SynthesizedSealedPropertyAccessor SynthesizedSealedAccessorOpt
- {
- get
- {
- bool hasGetter = (object)_getMethod != null;
- bool hasSetter = (object)_setMethod != null;
- if (!this.IsSealed || (hasGetter && hasSetter))
- {
- return null;
- }
-
- // This has to be cached because the CCI layer depends on reference equality.
- // However, there's no point in having more than one field, since we don't
- // expect to have to synthesize more than one accessor.
- if ((object)_lazySynthesizedSealedAccessor == null)
- {
- Interlocked.CompareExchange(ref _lazySynthesizedSealedAccessor, MakeSynthesizedSealedAccessor(), null);
- }
- return _lazySynthesizedSealedAccessor;
- }
- }
-
- ///
- /// Only non-null for sealed properties without both accessors.
- ///
- private SynthesizedSealedPropertyAccessor MakeSynthesizedSealedAccessor()
- {
- Debug.Assert(this.IsSealed && ((object)_getMethod == null || (object)_setMethod == null));
-
- if ((object)_getMethod != null)
- {
- // need to synthesize setter
- MethodSymbol overriddenAccessor = this.GetOwnOrInheritedSetMethod();
- return (object)overriddenAccessor == null ? null : new SynthesizedSealedPropertyAccessor(this, overriddenAccessor);
- }
- else if ((object)_setMethod != null)
- {
- // need to synthesize getter
- MethodSymbol overriddenAccessor = this.GetOwnOrInheritedGetMethod();
- return (object)overriddenAccessor == null ? null : new SynthesizedSealedPropertyAccessor(this, overriddenAccessor);
- }
- else
- {
- // Arguably, it would be more correct to return an array containing two
- // synthesized accessors, but we're already in an error case, so we'll
- // minimize the cascading error behavior by suppressing synthesis.
- return null;
- }
- }
-
- #region Attributes
-
- protected override IAttributeTargetSymbol AttributesOwner => this;
-
- protected override AttributeLocation DefaultAttributeLocation => AttributeLocation.Property;
-
- protected override AttributeLocation AllowedAttributeLocations
- => (_propertyFlags & Flags.IsAutoProperty) != 0
- ? AttributeLocation.Property | AttributeLocation.Field
- : AttributeLocation.Property;
-
- ///
- /// Returns a bag of custom attributes applied on the property and data decoded from well-known attributes. Returns null if there are no attributes.
- ///
- ///
- /// Forces binding and decoding of attributes.
- ///
- private CustomAttributesBag GetAttributesBag()
- {
- var bag = _lazyCustomAttributesBag;
- if (bag != null && bag.IsSealed)
- {
- return bag;
- }
-
- // The property is responsible for completion of the backing field
- _ = BackingField?.GetAttributes();
-
- if (LoadAndValidateAttributes(OneOrMany.Create(this.CSharpSyntaxNode.AttributeLists), ref _lazyCustomAttributesBag))
- {
- var completed = _state.NotePartComplete(CompletionPart.Attributes);
- Debug.Assert(completed);
- }
-
- Debug.Assert(_lazyCustomAttributesBag.IsSealed);
- return _lazyCustomAttributesBag;
- }
-
- ///
- /// Gets the attributes applied on this symbol.
- /// Returns an empty array if there are no attributes.
- ///
- ///
- /// NOTE: This method should always be kept as a sealed override.
- /// If you want to override attribute binding logic for a sub-class, then override method.
- ///
- public sealed override ImmutableArray GetAttributes()
- {
- return this.GetAttributesBag().Attributes;
- }
-
- ///
- /// Returns data decoded from well-known attributes applied to the symbol or null if there are no applied attributes.
- ///
- ///
- /// Forces binding and decoding of attributes.
- ///
- private PropertyWellKnownAttributeData GetDecodedWellKnownAttributeData()
- {
- var attributesBag = _lazyCustomAttributesBag;
- if (attributesBag == null || !attributesBag.IsDecodedWellKnownAttributeDataComputed)
- {
- attributesBag = this.GetAttributesBag();
- }
-
- return (PropertyWellKnownAttributeData)attributesBag.DecodedWellKnownAttributeData;
- }
-
- ///
- /// Returns data decoded from special early bound well-known attributes applied to the symbol or null if there are no applied attributes.
- ///
- ///
- /// Forces binding and decoding of attributes.
- ///
- internal PropertyEarlyWellKnownAttributeData GetEarlyDecodedWellKnownAttributeData()
- {
- var attributesBag = _lazyCustomAttributesBag;
- if (attributesBag == null || !attributesBag.IsEarlyDecodedWellKnownAttributeDataComputed)
- {
- attributesBag = this.GetAttributesBag();
- }
-
- return (PropertyEarlyWellKnownAttributeData)attributesBag.EarlyDecodedWellKnownAttributeData;
- }
-
- internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes)
- {
- base.AddSynthesizedAttributes(moduleBuilder, ref attributes);
-
- var compilation = this.DeclaringCompilation;
- var type = this.TypeWithAnnotations;
-
- if (type.Type.ContainsDynamic())
- {
- AddSynthesizedAttribute(ref attributes,
- compilation.SynthesizeDynamicAttribute(type.Type, type.CustomModifiers.Length + RefCustomModifiers.Length, _refKind));
- }
-
- if (type.Type.ContainsNativeInteger())
- {
- AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeNativeIntegerAttribute(this, type.Type));
- }
-
- if (type.Type.ContainsTupleNames())
- {
- AddSynthesizedAttribute(ref attributes,
- compilation.SynthesizeTupleNamesAttribute(type.Type));
- }
-
- if (compilation.ShouldEmitNullableAttributes(this))
- {
- AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeNullableAttributeIfNecessary(this, ContainingType.GetNullableContextValue(), type));
- }
-
- if (this.ReturnsByRefReadonly)
- {
- AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeIsReadOnlyAttribute(this));
- }
- }
-
- internal sealed override bool IsDirectlyExcludedFromCodeCoverage =>
- GetDecodedWellKnownAttributeData()?.HasExcludeFromCodeCoverageAttribute == true;
-
- internal override bool HasSpecialName
- {
- get
- {
- var data = GetDecodedWellKnownAttributeData();
- return data != null && data.HasSpecialNameAttribute;
- }
- }
-
- internal override CSharpAttributeData EarlyDecodeWellKnownAttribute(ref EarlyDecodeWellKnownAttributeArguments arguments)
- {
- CSharpAttributeData boundAttribute;
- ObsoleteAttributeData obsoleteData;
-
- if (EarlyDecodeDeprecatedOrExperimentalOrObsoleteAttribute(ref arguments, out boundAttribute, out obsoleteData))
- {
- if (obsoleteData != null)
- {
- arguments.GetOrCreateData().ObsoleteAttributeData = obsoleteData;
- }
-
- return boundAttribute;
- }
-
- if (CSharpAttributeData.IsTargetEarlyAttribute(arguments.AttributeType, arguments.AttributeSyntax, AttributeDescription.IndexerNameAttribute))
- {
- bool hasAnyDiagnostics;
- boundAttribute = arguments.Binder.GetAttribute(arguments.AttributeSyntax, arguments.AttributeType, out hasAnyDiagnostics);
- if (!boundAttribute.HasErrors)
- {
- string indexerName = boundAttribute.CommonConstructorArguments[0].DecodeValue(SpecialType.System_String);
- if (indexerName != null)
- {
- arguments.GetOrCreateData().IndexerName = indexerName;
- }
-
- if (!hasAnyDiagnostics)
- {
- return boundAttribute;
- }
- }
-
- return null;
- }
-
- return base.EarlyDecodeWellKnownAttribute(ref arguments);
- }
-
- ///
- /// Returns data decoded from Obsolete attribute or null if there is no Obsolete attribute.
- /// This property returns ObsoleteAttributeData.Uninitialized if attribute arguments haven't been decoded yet.
- ///
- internal override ObsoleteAttributeData ObsoleteAttributeData
- {
- get
- {
- if (!_containingType.AnyMemberHasAttributes)
- {
- return null;
- }
-
- var lazyCustomAttributesBag = _lazyCustomAttributesBag;
- if (lazyCustomAttributesBag != null && lazyCustomAttributesBag.IsEarlyDecodedWellKnownAttributeDataComputed)
- {
- return ((PropertyEarlyWellKnownAttributeData)lazyCustomAttributesBag.EarlyDecodedWellKnownAttributeData)?.ObsoleteAttributeData;
- }
-
- return ObsoleteAttributeData.Uninitialized;
- }
- }
-
- internal override void DecodeWellKnownAttribute(ref DecodeWellKnownAttributeArguments arguments)
- {
- Debug.Assert(arguments.AttributeSyntaxOpt != null);
-
- var attribute = arguments.Attribute;
- Debug.Assert(!attribute.HasErrors);
- Debug.Assert(arguments.SymbolPart == AttributeLocation.None);
-
- if (attribute.IsTargetAttribute(this, AttributeDescription.IndexerNameAttribute))
- {
- //NOTE: decoding was done by EarlyDecodeWellKnownAttribute.
- ValidateIndexerNameAttribute(attribute, arguments.AttributeSyntaxOpt, arguments.Diagnostics);
- }
- else if (attribute.IsTargetAttribute(this, AttributeDescription.SpecialNameAttribute))
- {
- arguments.GetOrCreateData().HasSpecialNameAttribute = true;
- }
- else if (attribute.IsTargetAttribute(this, AttributeDescription.ExcludeFromCodeCoverageAttribute))
- {
- arguments.GetOrCreateData().HasExcludeFromCodeCoverageAttribute = true;
- }
- else if (attribute.IsTargetAttribute(this, AttributeDescription.SkipLocalsInitAttribute))
- {
- CSharpAttributeData.DecodeSkipLocalsInitAttribute(DeclaringCompilation, ref arguments);
- }
- else if (attribute.IsTargetAttribute(this, AttributeDescription.DynamicAttribute))
- {
- // DynamicAttribute should not be set explicitly.
- arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitDynamicAttr, arguments.AttributeSyntaxOpt.Location);
- }
- else if (ReportExplicitUseOfReservedAttributes(in arguments,
- ReservedAttributes.DynamicAttribute | ReservedAttributes.IsReadOnlyAttribute | ReservedAttributes.IsUnmanagedAttribute | ReservedAttributes.IsByRefLikeAttribute | ReservedAttributes.TupleElementNamesAttribute | ReservedAttributes.NullableAttribute | ReservedAttributes.NativeIntegerAttribute))
- {
- }
- else if (attribute.IsTargetAttribute(this, AttributeDescription.DisallowNullAttribute))
- {
- arguments.GetOrCreateData().HasDisallowNullAttribute = true;
- }
- else if (attribute.IsTargetAttribute(this, AttributeDescription.AllowNullAttribute))
- {
- arguments.GetOrCreateData().HasAllowNullAttribute = true;
- }
- else if (attribute.IsTargetAttribute(this, AttributeDescription.MaybeNullAttribute))
- {
- arguments.GetOrCreateData().HasMaybeNullAttribute = true;
- }
- else if (attribute.IsTargetAttribute(this, AttributeDescription.NotNullAttribute))
- {
- arguments.GetOrCreateData().HasNotNullAttribute = true;
- }
- else if (attribute.IsTargetAttribute(this, AttributeDescription.MemberNotNullAttribute))
- {
- MessageID.IDS_FeatureMemberNotNull.CheckFeatureAvailability(arguments.Diagnostics, arguments.AttributeSyntaxOpt);
- CSharpAttributeData.DecodeMemberNotNullAttribute(ContainingType, ref arguments);
- }
- else if (attribute.IsTargetAttribute(this, AttributeDescription.MemberNotNullWhenAttribute))
- {
- MessageID.IDS_FeatureMemberNotNull.CheckFeatureAvailability(arguments.Diagnostics, arguments.AttributeSyntaxOpt);
- CSharpAttributeData.DecodeMemberNotNullWhenAttribute(ContainingType, ref arguments);
- }
- }
-
- internal bool HasDisallowNull
- {
- get
- {
- var data = GetDecodedWellKnownAttributeData();
- return data != null && data.HasDisallowNullAttribute;
- }
- }
-
- internal bool HasAllowNull
- {
- get
- {
- var data = GetDecodedWellKnownAttributeData();
- return data != null && data.HasAllowNullAttribute;
- }
- }
-
- internal bool HasMaybeNull
- {
- get
- {
- var data = GetDecodedWellKnownAttributeData();
- return data != null && data.HasMaybeNullAttribute;
- }
- }
-
- internal bool HasNotNull
- {
- get
- {
- var data = GetDecodedWellKnownAttributeData();
- return data != null && data.HasNotNullAttribute;
- }
- }
-
- internal SourceAttributeData DisallowNullAttributeIfExists
- => FindAttribute(AttributeDescription.DisallowNullAttribute);
-
- internal SourceAttributeData AllowNullAttributeIfExists
- => FindAttribute(AttributeDescription.AllowNullAttribute);
-
- internal SourceAttributeData MaybeNullAttributeIfExists
- => FindAttribute(AttributeDescription.MaybeNullAttribute);
-
- internal SourceAttributeData NotNullAttributeIfExists
- => FindAttribute(AttributeDescription.NotNullAttribute);
-
- internal ImmutableArray MemberNotNullAttributeIfExists
- => FindAttributes(AttributeDescription.MemberNotNullAttribute);
-
- internal ImmutableArray MemberNotNullWhenAttributeIfExists
- => FindAttributes(AttributeDescription.MemberNotNullWhenAttribute);
-
- private SourceAttributeData FindAttribute(AttributeDescription attributeDescription)
- => (SourceAttributeData)GetAttributes().First(a => a.IsTargetAttribute(this, attributeDescription));
-
- private ImmutableArray FindAttributes(AttributeDescription attributeDescription)
- => GetAttributes().Where(a => a.IsTargetAttribute(this, attributeDescription)).Cast().ToImmutableArray();
-
- internal override void PostDecodeWellKnownAttributes(ImmutableArray boundAttributes, ImmutableArray allAttributeSyntaxNodes, DiagnosticBag diagnostics, AttributeLocation symbolPart, WellKnownAttributeData decodedData)
- {
- Debug.Assert(!boundAttributes.IsDefault);
- Debug.Assert(!allAttributeSyntaxNodes.IsDefault);
- Debug.Assert(boundAttributes.Length == allAttributeSyntaxNodes.Length);
- Debug.Assert(_lazyCustomAttributesBag != null);
- Debug.Assert(_lazyCustomAttributesBag.IsDecodedWellKnownAttributeDataComputed);
- Debug.Assert(symbolPart == AttributeLocation.None);
-
- base.PostDecodeWellKnownAttributes(boundAttributes, allAttributeSyntaxNodes, diagnostics, symbolPart, decodedData);
- }
-
- private void ValidateIndexerNameAttribute(CSharpAttributeData attribute, AttributeSyntax node, DiagnosticBag diagnostics)
- {
- if (!this.IsIndexer || this.IsExplicitInterfaceImplementation)
- {
- diagnostics.Add(ErrorCode.ERR_BadIndexerNameAttr, node.Name.Location, node.GetErrorDisplayName());
- }
- else
- {
- string indexerName = attribute.CommonConstructorArguments[0].DecodeValue(SpecialType.System_String);
- if (indexerName == null || !SyntaxFacts.IsValidIdentifier(indexerName))
- {
- diagnostics.Add(ErrorCode.ERR_BadArgumentToAttribute, node.ArgumentList.Arguments[0].Location, node.GetErrorDisplayName());
- }
- }
- }
-
- #endregion
-
- #region Completion
-
- internal sealed override bool RequiresCompletion
- {
- get { return true; }
- }
-
- internal sealed override bool HasComplete(CompletionPart part)
- {
- return _state.HasComplete(part);
- }
-
- internal override void ForceComplete(SourceLocation locationOpt, CancellationToken cancellationToken)
- {
- while (true)
- {
- cancellationToken.ThrowIfCancellationRequested();
- var incompletePart = _state.NextIncompletePart;
- switch (incompletePart)
- {
- case CompletionPart.Attributes:
- GetAttributes();
- break;
-
- case CompletionPart.StartPropertyParameters:
- case CompletionPart.FinishPropertyParameters:
- {
- if (_state.NotePartComplete(CompletionPart.StartPropertyParameters))
- {
- var parameters = this.Parameters;
- if (parameters.Length > 0)
- {
- var diagnostics = DiagnosticBag.GetInstance();
- var conversions = new TypeConversions(this.ContainingAssembly.CorLibrary);
- foreach (var parameter in this.Parameters)
- {
- parameter.ForceComplete(locationOpt, cancellationToken);
- parameter.Type.CheckAllConstraints(DeclaringCompilation, conversions, parameter.Locations[0], diagnostics);
- }
-
- this.AddDeclarationDiagnostics(diagnostics);
- diagnostics.Free();
- }
-
- DeclaringCompilation.SymbolDeclaredEvent(this);
- var completedOnThisThread = _state.NotePartComplete(CompletionPart.FinishPropertyParameters);
- Debug.Assert(completedOnThisThread);
- }
- else
- {
- // StartPropertyParameters was completed by another thread. Wait for it to finish the parameters.
- _state.SpinWaitComplete(CompletionPart.FinishPropertyParameters, cancellationToken);
- }
- }
- break;
-
- case CompletionPart.StartPropertyType:
- case CompletionPart.FinishPropertyType:
- {
- if (_state.NotePartComplete(CompletionPart.StartPropertyType))
- {
- var diagnostics = DiagnosticBag.GetInstance();
- var conversions = new TypeConversions(this.ContainingAssembly.CorLibrary);
- this.Type.CheckAllConstraints(DeclaringCompilation, conversions, Location, diagnostics);
-
- var type = this.Type;
- if (type.IsRestrictedType(ignoreSpanLikeTypes: true))
- {
- diagnostics.Add(ErrorCode.ERR_FieldCantBeRefAny, this.CSharpSyntaxNode.Type.Location, type);
- }
- else if (this.IsAutoProperty && type.IsRefLikeType && (this.IsStatic || !this.ContainingType.IsRefLikeType))
- {
- diagnostics.Add(ErrorCode.ERR_FieldAutoPropCantBeByRefLike, this.CSharpSyntaxNode.Type.Location, type);
- }
-
- this.AddDeclarationDiagnostics(diagnostics);
- var completedOnThisThread = _state.NotePartComplete(CompletionPart.FinishPropertyType);
- Debug.Assert(completedOnThisThread);
- diagnostics.Free();
- }
- else
- {
- // StartPropertyType was completed by another thread. Wait for it to finish the type.
- _state.SpinWaitComplete(CompletionPart.FinishPropertyType, cancellationToken);
- }
- }
- break;
-
- case CompletionPart.None:
- return;
-
- default:
- // any other values are completion parts intended for other kinds of symbols
- _state.NotePartComplete(CompletionPart.All & ~CompletionPart.PropertySymbolAll);
- break;
- }
-
- _state.SpinWaitComplete(incompletePart, cancellationToken);
- }
- }
-
- #endregion
-
- private TypeWithAnnotations ComputeType(Binder binder, BasePropertyDeclarationSyntax syntax, DiagnosticBag diagnostics)
- {
- RefKind refKind;
- var typeSyntax = syntax.Type.SkipRef(out refKind);
- var type = binder.BindType(typeSyntax, diagnostics);
- HashSet useSiteDiagnostics = null;
-
- if (syntax.ExplicitInterfaceSpecifier == null && !this.IsNoMoreVisibleThan(type, ref useSiteDiagnostics))
- {
- // "Inconsistent accessibility: indexer return type '{1}' is less accessible than indexer '{0}'"
- // "Inconsistent accessibility: property type '{1}' is less accessible than property '{0}'"
- diagnostics.Add((this.IsIndexer ? ErrorCode.ERR_BadVisIndexerReturn : ErrorCode.ERR_BadVisPropertyType), Location, this, type.Type);
- }
-
- diagnostics.Add(Location, useSiteDiagnostics);
-
- if (type.IsVoidType())
- {
- ErrorCode errorCode = this.IsIndexer ? ErrorCode.ERR_IndexerCantHaveVoidType : ErrorCode.ERR_PropertyCantHaveVoidType;
- diagnostics.Add(errorCode, Location, this);
- }
-
- return type;
- }
-
- private ImmutableArray ComputeParameters(Binder binder, BasePropertyDeclarationSyntax syntax, DiagnosticBag diagnostics)
- {
- var parameterSyntaxOpt = GetParameterListSyntax(syntax);
- var parameters = MakeParameters(binder, this, parameterSyntaxOpt, diagnostics, addRefReadOnlyModifier: IsVirtual || IsAbstract);
- HashSet useSiteDiagnostics = null;
-
- foreach (ParameterSymbol param in parameters)
- {
- if (syntax.ExplicitInterfaceSpecifier == null && !this.IsNoMoreVisibleThan(param.Type, ref useSiteDiagnostics))
- {
- diagnostics.Add(ErrorCode.ERR_BadVisIndexerParam, Location, this, param.Type);
- }
- else if ((object)_setMethod != null && param.Name == ParameterSymbol.ValueParameterName)
- {
- diagnostics.Add(ErrorCode.ERR_DuplicateGeneratedName, param.Locations.FirstOrDefault() ?? Location, param.Name);
- }
- }
-
- diagnostics.Add(Location, useSiteDiagnostics);
- return parameters;
- }
-
- private Binder CreateBinderForTypeAndParameters()
- {
- var compilation = this.DeclaringCompilation;
- var syntaxTree = _syntaxRef.SyntaxTree;
- var syntax = (BasePropertyDeclarationSyntax)_syntaxRef.GetSyntax();
- var binderFactory = compilation.GetBinderFactory(syntaxTree);
- var binder = binderFactory.GetBinder(syntax, syntax, this);
- SyntaxTokenList modifiers = syntax.Modifiers;
- binder = binder.WithUnsafeRegionIfNecessary(modifiers);
- return binder.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.SuppressConstraintChecks, this);
- }
-
- private static ExplicitInterfaceSpecifierSyntax GetExplicitInterfaceSpecifier(BasePropertyDeclarationSyntax syntax)
- {
- switch (syntax.Kind())
- {
- case SyntaxKind.PropertyDeclaration:
- return ((PropertyDeclarationSyntax)syntax).ExplicitInterfaceSpecifier;
- case SyntaxKind.IndexerDeclaration:
- return ((IndexerDeclarationSyntax)syntax).ExplicitInterfaceSpecifier;
- default:
- throw ExceptionUtilities.UnexpectedValue(syntax.Kind());
- }
- }
-
- private static BaseParameterListSyntax GetParameterListSyntax(BasePropertyDeclarationSyntax syntax)
- {
- return (syntax.Kind() == SyntaxKind.IndexerDeclaration) ? ((IndexerDeclarationSyntax)syntax).ParameterList : null;
- }
+ protected override BaseParameterListSyntax? GetParameterListSyntax(CSharpSyntaxNode syntax)
+ => (syntax as IndexerDeclarationSyntax)?.ParameterList;
}
-}
+}
\ No newline at end of file
diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs
new file mode 100644
index 0000000000000000000000000000000000000000..0245143c7ac95d4439f2365a007147f0adaf1b46
--- /dev/null
+++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs
@@ -0,0 +1,1470 @@
+๏ปฟ// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Diagnostics;
+using System.Globalization;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Threading;
+using Microsoft.CodeAnalysis.CSharp.Emit;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.PooledObjects;
+using Roslyn.Utilities;
+
+namespace Microsoft.CodeAnalysis.CSharp.Symbols
+{
+ internal abstract class SourcePropertySymbolBase : PropertySymbol, IAttributeTargetSymbol
+ {
+ ///
+ /// Condensed flags storing useful information about the
+ /// so that we do not have to go back to source to compute this data.
+ ///
+ [Flags]
+ private enum Flags : byte
+ {
+ IsExpressionBodied = 1 << 0,
+ IsAutoProperty = 1 << 1,
+ IsExplicitInterfaceImplementation = 1 << 2,
+ }
+
+ // TODO (tomat): consider splitting into multiple subclasses/rare data.
+
+ private readonly SourceMemberContainerTypeSymbol _containingType;
+ private readonly string _name;
+ private readonly SyntaxReference _syntaxRef;
+ protected readonly DeclarationModifiers _modifiers;
+ private readonly ImmutableArray _refCustomModifiers;
+ private readonly SourcePropertyAccessorSymbol _getMethod;
+ private readonly SourcePropertyAccessorSymbol _setMethod;
+ private readonly TypeSymbol _explicitInterfaceType;
+ private readonly ImmutableArray _explicitInterfaceImplementations;
+ private readonly Flags _propertyFlags;
+ private readonly RefKind _refKind;
+
+ private SymbolCompletionState _state;
+ private ImmutableArray _lazyParameters;
+ private TypeWithAnnotations.Boxed _lazyType;
+
+ ///
+ /// Set in constructor, might be changed while decoding .
+ ///
+ protected readonly string _sourceName;
+
+ private string _lazyDocComment;
+ private string _lazyExpandedDocComment;
+ private OverriddenOrHiddenMembersResult _lazyOverriddenOrHiddenMembers;
+ private SynthesizedSealedPropertyAccessor _lazySynthesizedSealedAccessor;
+ private CustomAttributesBag _lazyCustomAttributesBag;
+
+ // CONSIDER: if the parameters were computed lazily, ParameterCount could be overridden to fall back on the syntax (as in SourceMemberMethodSymbol).
+
+ public Location Location { get; }
+
+#nullable enable
+ ///
+ /// The is passed for explicit interface implementations or
+ /// overrides to . If a binder is not required in this situation
+ /// the parameter can be null.
+ ///
+ protected SourcePropertySymbolBase(
+ SourceMemberContainerTypeSymbol containingType,
+ Binder? binder,
+ CSharpSyntaxNode syntax,
+ RefKind refKind,
+ string name,
+ Location location,
+ DiagnosticBag diagnostics)
+ {
+ _syntaxRef = syntax.GetReference();
+ Location = location;
+
+ // This has the value that IsIndexer will ultimately have, once we've populated the fields of this object.
+ bool isIndexer = syntax.Kind() == SyntaxKind.IndexerDeclaration;
+ var interfaceSpecifier = GetExplicitInterfaceSpecifier(syntax);
+ bool isExplicitInterfaceImplementation = interfaceSpecifier != null;
+ if (isExplicitInterfaceImplementation)
+ {
+ _propertyFlags |= Flags.IsExplicitInterfaceImplementation;
+ }
+
+ _containingType = containingType;
+ _refKind = refKind;
+
+ SyntaxTokenList modifiers = GetModifierTokens(syntax);
+ if (binder is object)
+ {
+ binder = binder.WithUnsafeRegionIfNecessary(modifiers);
+ binder = binder.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.SuppressConstraintChecks, this);
+ }
+
+ var arrowExpression = GetArrowExpression(syntax);
+ bool hasExpressionBody = arrowExpression != null;
+ bool hasInitializer = HasInitializer(syntax);
+
+ GetAccessorDeclarations(
+ syntax,
+ diagnostics,
+ out bool isAutoProperty,
+ out bool hasAccessorList,
+ out bool accessorsHaveImplementation,
+ out bool isInitOnly,
+ out var getSyntax,
+ out var setSyntax);
+
+ var hasGetAccessor = getSyntax is object;
+ var hasSetAccessor = setSyntax is object;
+
+ bool modifierErrors;
+ _modifiers = MakeModifiers(modifiers, isExplicitInterfaceImplementation, isIndexer,
+ accessorsHaveImplementation, location,
+ diagnostics, out modifierErrors);
+ this.CheckAccessibility(location, diagnostics, isExplicitInterfaceImplementation);
+
+ this.CheckModifiers(isExplicitInterfaceImplementation, location, isIndexer, diagnostics);
+
+ isAutoProperty = isAutoProperty && (!(containingType.IsInterface && !IsStatic) && !IsAbstract && !IsExtern && !isIndexer);
+
+ if (isIndexer && !isExplicitInterfaceImplementation)
+ {
+ // Evaluate the attributes immediately in case the IndexerNameAttribute has been applied.
+ // NOTE: we want IsExplicitInterfaceImplementation, IsOverride, Locations, and the syntax reference
+ // to be initialized before we pass this symbol to LoadCustomAttributes.
+
+ // CONSIDER: none of the information from this early binding pass is cached. Everything will
+ // be re-bound when someone calls GetAttributes. If this gets to be a problem, we could
+ // always use the real attribute bag of this symbol and modify LoadAndValidateAttributes to
+ // handle partially filled bags.
+ CustomAttributesBag? temp = null;
+ LoadAndValidateAttributes(OneOrMany.Create(AttributeDeclarationSyntaxList), ref temp, earlyDecodingOnly: true);
+ if (temp != null)
+ {
+ Debug.Assert(temp.IsEarlyDecodedWellKnownAttributeDataComputed);
+ var propertyData = (PropertyEarlyWellKnownAttributeData)temp.EarlyDecodedWellKnownAttributeData;
+ if (propertyData != null)
+ {
+ _sourceName = propertyData.IndexerName;
+ }
+ }
+ }
+
+ string aliasQualifierOpt;
+ string memberName = ExplicitInterfaceHelpers.GetMemberNameAndInterfaceSymbol(binder, interfaceSpecifier, name, diagnostics, out _explicitInterfaceType, out aliasQualifierOpt);
+ _sourceName = _sourceName ?? memberName; //sourceName may have been set while loading attributes
+ _name = isIndexer ? ExplicitInterfaceHelpers.GetMemberName(WellKnownMemberNames.Indexer, _explicitInterfaceType, aliasQualifierOpt) : _sourceName;
+
+ if (hasInitializer)
+ {
+ CheckInitializer(isAutoProperty, containingType.IsInterface, IsStatic, location, diagnostics);
+ }
+
+ if (isAutoProperty || hasInitializer)
+ {
+ var isAutoPropertyWithGetSyntax = isAutoProperty && hasGetAccessor;
+ if (isAutoPropertyWithGetSyntax)
+ {
+ _propertyFlags |= Flags.IsAutoProperty;
+ }
+
+ bool isGetterOnly = hasGetAccessor && !hasSetAccessor;
+
+ if (isAutoPropertyWithGetSyntax && !IsStatic && !isGetterOnly)
+ {
+ if (ContainingType.IsReadOnly)
+ {
+ diagnostics.Add(ErrorCode.ERR_AutoPropsInRoStruct, location);
+ }
+ else if (HasReadOnlyModifier)
+ {
+ diagnostics.Add(ErrorCode.ERR_AutoPropertyWithSetterCantBeReadOnly, location, this);
+ }
+ }
+
+ if (isAutoPropertyWithGetSyntax || hasInitializer)
+ {
+ if (isAutoPropertyWithGetSyntax)
+ {
+ //issue a diagnostic if the compiler generated attribute ctor is not found.
+ Binder.ReportUseSiteDiagnosticForSynthesizedAttribute(DeclaringCompilation,
+ WellKnownMember.System_Runtime_CompilerServices_CompilerGeneratedAttribute__ctor, diagnostics, syntax: syntax);
+
+ if (this._refKind != RefKind.None && !_containingType.IsInterface)
+ {
+ diagnostics.Add(ErrorCode.ERR_AutoPropertyCannotBeRefReturning, location, this);
+ }
+ }
+
+ string fieldName = GeneratedNames.MakeBackingFieldName(_sourceName);
+ BackingField = new SynthesizedBackingFieldSymbol(this,
+ fieldName,
+ isReadOnly: isGetterOnly || isInitOnly,
+ this.IsStatic,
+ hasInitializer);
+ }
+
+ if (isAutoProperty)
+ {
+ Binder.CheckFeatureAvailability(
+ syntax,
+ isGetterOnly ? MessageID.IDS_FeatureReadonlyAutoImplementedProperties : MessageID.IDS_FeatureAutoImplementedProperties,
+ diagnostics,
+ location);
+ }
+ }
+
+ PropertySymbol? explicitlyImplementedProperty = null;
+ _refCustomModifiers = ImmutableArray.Empty;
+
+ // The runtime will not treat the accessors of this property as overrides or implementations
+ // of those of another property unless both the signatures and the custom modifiers match.
+ // Hence, in the case of overrides and *explicit* implementations, we need to copy the custom
+ // modifiers that are in the signatures of the overridden/implemented property accessors.
+ // (From source, we know that there can only be one overridden/implemented property, so there
+ // are no conflicts.) This is unnecessary for implicit implementations because, if the custom
+ // modifiers don't match, we'll insert bridge methods for the accessors (explicit implementations
+ // that delegate to the implicit implementations) with the correct custom modifiers
+ // (see SourceMemberContainerTypeSymbol.SynthesizeInterfaceMemberImplementation).
+
+ // Note: we're checking if the syntax indicates explicit implementation rather,
+ // than if explicitInterfaceType is null because we don't want to look for an
+ // overridden property if this is supposed to be an explicit implementation.
+ if (isExplicitInterfaceImplementation || this.IsOverride)
+ {
+ // Type and parameters for overrides and explicit implementations cannot be bound
+ // lazily since the property name depends on the metadata name of the base property,
+ // and the property name is required to add the property to the containing type, and
+ // the type and parameters are required to determine the override or implementation.
+ var type = this.ComputeType(binder, syntax, diagnostics);
+ _lazyType = new TypeWithAnnotations.Boxed(type);
+ _lazyParameters = this.ComputeParameters(binder, syntax, diagnostics);
+
+ bool isOverride = false;
+ PropertySymbol? overriddenOrImplementedProperty = null;
+
+ if (!isExplicitInterfaceImplementation)
+ {
+ // If this property is an override, we may need to copy custom modifiers from
+ // the overridden property (so that the runtime will recognize it as an override).
+ // We check for this case here, while we can still modify the parameters and
+ // return type without losing the appearance of immutability.
+ isOverride = true;
+ overriddenOrImplementedProperty = this.OverriddenProperty;
+ }
+ else
+ {
+ string interfacePropertyName = isIndexer ? WellKnownMemberNames.Indexer : name;
+ explicitlyImplementedProperty = this.FindExplicitlyImplementedProperty(_explicitInterfaceType, interfacePropertyName, interfaceSpecifier, diagnostics);
+ this.FindExplicitlyImplementedMemberVerification(explicitlyImplementedProperty, diagnostics);
+ overriddenOrImplementedProperty = explicitlyImplementedProperty;
+ }
+
+ if ((object)overriddenOrImplementedProperty != null)
+ {
+ _refCustomModifiers = _refKind != RefKind.None ? overriddenOrImplementedProperty.RefCustomModifiers : ImmutableArray.Empty;
+
+ TypeWithAnnotations overriddenPropertyType = overriddenOrImplementedProperty.TypeWithAnnotations;
+
+ // We do an extra check before copying the type to handle the case where the overriding
+ // property (incorrectly) has a different type than the overridden property. In such cases,
+ // we want to retain the original (incorrect) type to avoid hiding the type given in source.
+ if (type.Type.Equals(overriddenPropertyType.Type, TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds | TypeCompareKind.IgnoreNullableModifiersForReferenceTypes | TypeCompareKind.IgnoreDynamic))
+ {
+ type = type.WithTypeAndModifiers(
+ CustomModifierUtils.CopyTypeCustomModifiers(overriddenPropertyType.Type, type.Type, this.ContainingAssembly),
+ overriddenPropertyType.CustomModifiers);
+
+ _lazyType = new TypeWithAnnotations.Boxed(type);
+ }
+
+ _lazyParameters = CustomModifierUtils.CopyParameterCustomModifiers(overriddenOrImplementedProperty.Parameters, _lazyParameters, alsoCopyParamsModifier: isOverride);
+ }
+ }
+ else if (_refKind == RefKind.RefReadOnly)
+ {
+ var modifierType = Binder.GetWellKnownType(DeclaringCompilation, WellKnownType.System_Runtime_InteropServices_InAttribute, diagnostics, TypeLocation);
+
+ _refCustomModifiers = ImmutableArray.Create(CSharpCustomModifier.CreateRequired(modifierType));
+ }
+
+ if (!hasAccessorList && hasExpressionBody)
+ {
+ Debug.Assert(arrowExpression is object);
+ _propertyFlags |= Flags.IsExpressionBodied;
+ _getMethod = CreateExpressionBodiedAccessor(
+ arrowExpression,
+ explicitlyImplementedProperty,
+ aliasQualifierOpt,
+ isExplicitInterfaceImplementation,
+ diagnostics);
+ _setMethod = null;
+ }
+ else
+ {
+ _getMethod = CreateAccessorSymbol(isGet: true, getSyntax, explicitlyImplementedProperty, aliasQualifierOpt, isAutoProperty, isExplicitInterfaceImplementation, diagnostics);
+ _setMethod = CreateAccessorSymbol(isGet: false, setSyntax, explicitlyImplementedProperty, aliasQualifierOpt, isAutoProperty, isExplicitInterfaceImplementation, diagnostics);
+
+ if (!hasGetAccessor || !hasSetAccessor)
+ {
+ if (!hasGetAccessor && !hasSetAccessor)
+ {
+ diagnostics.Add(ErrorCode.ERR_PropertyWithNoAccessors, location, this);
+ }
+ else if (_refKind != RefKind.None)
+ {
+ if (!hasGetAccessor)
+ {
+ diagnostics.Add(ErrorCode.ERR_RefPropertyMustHaveGetAccessor, location, this);
+ }
+ }
+ else if (isAutoProperty)
+ {
+ var accessor = _getMethod ?? _setMethod;
+ if (!hasGetAccessor)
+ {
+ diagnostics.Add(ErrorCode.ERR_AutoPropertyMustHaveGetAccessor, accessor!.Locations[0], accessor);
+ }
+ }
+ }
+
+ // Check accessor accessibility is more restrictive than property accessibility.
+ CheckAccessibilityMoreRestrictive(_getMethod, diagnostics);
+ CheckAccessibilityMoreRestrictive(_setMethod, diagnostics);
+
+ if ((_getMethod is object) && (_setMethod is object))
+ {
+ if (_refKind != RefKind.None)
+ {
+ diagnostics.Add(ErrorCode.ERR_RefPropertyCannotHaveSetAccessor, _setMethod.Locations[0], _setMethod);
+ }
+ else if ((_getMethod.LocalAccessibility != Accessibility.NotApplicable) &&
+ (_setMethod.LocalAccessibility != Accessibility.NotApplicable))
+ {
+ // Check accessibility is set on at most one accessor.
+ diagnostics.Add(ErrorCode.ERR_DuplicatePropertyAccessMods, location, this);
+ }
+ else if (_getMethod.LocalDeclaredReadOnly && _setMethod.LocalDeclaredReadOnly)
+ {
+ diagnostics.Add(ErrorCode.ERR_DuplicatePropertyReadOnlyMods, location, this);
+ }
+ else if (this.IsAbstract)
+ {
+ // Check abstract property accessors are not private.
+ CheckAbstractPropertyAccessorNotPrivate(_getMethod, diagnostics);
+ CheckAbstractPropertyAccessorNotPrivate(_setMethod, diagnostics);
+ }
+ }
+ else
+ {
+ if (!this.IsOverride)
+ {
+ var accessor = _getMethod ?? _setMethod;
+ if (accessor is object)
+ {
+ // Check accessibility is not set on the one accessor.
+ if (accessor.LocalAccessibility != Accessibility.NotApplicable)
+ {
+ diagnostics.Add(ErrorCode.ERR_AccessModMissingAccessor, location, this);
+ }
+
+ // Check that 'readonly' is not set on the one accessor.
+ if (accessor.LocalDeclaredReadOnly)
+ {
+ diagnostics.Add(ErrorCode.ERR_ReadOnlyModMissingAccessor, location, this);
+ }
+ }
+ }
+ }
+ }
+
+ if (explicitlyImplementedProperty is object)
+ {
+ CheckExplicitImplementationAccessor(this.GetMethod, explicitlyImplementedProperty.GetMethod, explicitlyImplementedProperty, diagnostics);
+ CheckExplicitImplementationAccessor(this.SetMethod, explicitlyImplementedProperty.SetMethod, explicitlyImplementedProperty, diagnostics);
+ }
+
+ _explicitInterfaceImplementations =
+ explicitlyImplementedProperty is null ?
+ ImmutableArray.Empty :
+ ImmutableArray.Create(explicitlyImplementedProperty);
+
+ // get-only auto property should not override settable properties
+ if ((_propertyFlags & Flags.IsAutoProperty) != 0)
+ {
+ if (_setMethod is null && !this.IsReadOnly)
+ {
+ diagnostics.Add(ErrorCode.ERR_AutoPropertyMustOverrideSet, location, this);
+ }
+
+ CheckForFieldTargetedAttribute(diagnostics);
+ }
+
+ CheckForBlockAndExpressionBody(syntax, diagnostics);
+ }
+
+ protected abstract Location TypeLocation { get; }
+
+ protected abstract SyntaxTokenList GetModifierTokens(SyntaxNode syntax);
+
+ protected abstract ArrowExpressionClauseSyntax? GetArrowExpression(SyntaxNode syntax);
+
+ protected abstract bool HasInitializer(SyntaxNode syntax);
+
+ private void CheckForFieldTargetedAttribute(DiagnosticBag diagnostics)
+ {
+ var languageVersion = this.DeclaringCompilation.LanguageVersion;
+ if (languageVersion.AllowAttributesOnBackingFields())
+ {
+ return;
+ }
+
+ foreach (var attribute in AttributeDeclarationSyntaxList)
+ {
+ if (attribute.Target?.GetAttributeLocation() == AttributeLocation.Field)
+ {
+ diagnostics.Add(
+ new CSDiagnosticInfo(ErrorCode.WRN_AttributesOnBackingFieldsNotAvailable,
+ languageVersion.ToDisplayString(),
+ new CSharpRequiredLanguageVersion(MessageID.IDS_FeatureAttributesOnBackingFields.RequiredVersion())),
+ attribute.Target.Location);
+ }
+ }
+ }
+
+ protected abstract void GetAccessorDeclarations(
+ CSharpSyntaxNode syntax,
+ DiagnosticBag diagnostics,
+ out bool isAutoProperty,
+ out bool hasAccessorList,
+ out bool accessorsHaveImplementation,
+ out bool isInitOnly,
+ out CSharpSyntaxNode? getSyntax,
+ out CSharpSyntaxNode? setSyntax);
+
+ protected abstract void CheckForBlockAndExpressionBody(CSharpSyntaxNode syntax, DiagnosticBag diagnostics);
+
+#nullable restore
+
+ internal sealed override ImmutableArray NotNullMembers =>
+ GetDecodedWellKnownAttributeData()?.NotNullMembers ?? ImmutableArray.Empty;
+
+ internal sealed override ImmutableArray NotNullWhenTrueMembers =>
+ GetDecodedWellKnownAttributeData()?.NotNullWhenTrueMembers ?? ImmutableArray.Empty;
+
+ internal sealed override ImmutableArray NotNullWhenFalseMembers =>
+ GetDecodedWellKnownAttributeData()?.NotNullWhenFalseMembers ?? ImmutableArray.Empty;
+
+ internal bool IsExpressionBodied
+ => (_propertyFlags & Flags.IsExpressionBodied) != 0;
+
+ private void CheckInitializer(
+ bool isAutoProperty,
+ bool isInterface,
+ bool isStatic,
+ Location location,
+ DiagnosticBag diagnostics)
+ {
+ if (isInterface && !isStatic)
+ {
+ diagnostics.Add(ErrorCode.ERR_InstancePropertyInitializerInInterface, location, this);
+ }
+ else if (!isAutoProperty)
+ {
+ diagnostics.Add(ErrorCode.ERR_InitializerOnNonAutoProperty, location, this);
+ }
+ }
+
+ public override RefKind RefKind
+ {
+ get
+ {
+ return _refKind;
+ }
+ }
+
+ public override TypeWithAnnotations TypeWithAnnotations
+ {
+ get
+ {
+ if (_lazyType == null)
+ {
+ var diagnostics = DiagnosticBag.GetInstance();
+ var result = this.ComputeType(binder: null, CSharpSyntaxNode, diagnostics);
+ if (Interlocked.CompareExchange(ref _lazyType, new TypeWithAnnotations.Boxed(result), null) == null)
+ {
+ this.AddDeclarationDiagnostics(diagnostics);
+ }
+ diagnostics.Free();
+ }
+
+ return _lazyType.Value;
+ }
+ }
+
+ internal bool HasPointerType
+ {
+ get
+ {
+ if (_lazyType != null)
+ {
+
+ var hasPointerType = _lazyType.Value.DefaultType.IsPointerOrFunctionPointer();
+ Debug.Assert(hasPointerType == HasPointerTypeSyntactically);
+ return hasPointerType;
+ }
+
+ return HasPointerTypeSyntactically;
+ }
+ }
+
+ protected abstract bool HasPointerTypeSyntactically { get; }
+
+ ///
+ /// To facilitate lookup, all indexer symbols have the same name.
+ /// Check the MetadataName property to find the name that will be
+ /// emitted (based on IndexerNameAttribute, or the default "Item").
+ ///
+ public override string Name
+ {
+ get
+ {
+ return _name;
+ }
+ }
+
+ public override string MetadataName
+ {
+ get
+ {
+ // Explicit implementation names may have spaces if the interface
+ // is generic (between the type arguments).
+ return _sourceName.Replace(" ", "");
+ }
+ }
+
+ public override Symbol ContainingSymbol
+ {
+ get
+ {
+ return _containingType;
+ }
+ }
+
+ public override NamedTypeSymbol ContainingType
+ {
+ get
+ {
+ return _containingType;
+ }
+ }
+
+ internal override LexicalSortKey GetLexicalSortKey()
+ {
+ return new LexicalSortKey(Location, this.DeclaringCompilation);
+ }
+
+ public override ImmutableArray Locations
+ {
+ get
+ {
+ return ImmutableArray.Create(Location);
+ }
+ }
+
+ public override ImmutableArray DeclaringSyntaxReferences
+ {
+ get
+ {
+ return ImmutableArray.Create(_syntaxRef);
+ }
+ }
+
+ public override bool IsAbstract
+ {
+ get { return (_modifiers & DeclarationModifiers.Abstract) != 0; }
+ }
+
+ public override bool IsExtern
+ {
+ get { return (_modifiers & DeclarationModifiers.Extern) != 0; }
+ }
+
+ public override bool IsStatic
+ {
+ get { return (_modifiers & DeclarationModifiers.Static) != 0; }
+ }
+
+ internal bool IsFixed
+ {
+ get { return false; }
+ }
+
+ ///
+ /// Even though it is declared with an IndexerDeclarationSyntax, an explicit
+ /// interface implementation is not an indexer because it will not cause the
+ /// containing type to be emitted with a DefaultMemberAttribute (and even if
+ /// there is another indexer, the name of the explicit implementation won't
+ /// match). This is important for round-tripping.
+ ///
+ public override bool IsIndexer
+ {
+ get { return (_modifiers & DeclarationModifiers.Indexer) != 0; }
+ }
+
+ public override bool IsOverride
+ {
+ get { return (_modifiers & DeclarationModifiers.Override) != 0; }
+ }
+
+ public override bool IsSealed
+ {
+ get { return (_modifiers & DeclarationModifiers.Sealed) != 0; }
+ }
+
+ public override bool IsVirtual
+ {
+ get { return (_modifiers & DeclarationModifiers.Virtual) != 0; }
+ }
+
+ internal bool IsNew
+ {
+ get { return (_modifiers & DeclarationModifiers.New) != 0; }
+ }
+
+ internal bool HasReadOnlyModifier => (_modifiers & DeclarationModifiers.ReadOnly) != 0;
+
+ public override MethodSymbol GetMethod
+ {
+ get { return _getMethod; }
+ }
+
+ public override MethodSymbol SetMethod
+ {
+ get { return _setMethod; }
+ }
+
+ internal override Microsoft.Cci.CallingConvention CallingConvention
+ {
+ get { return (IsStatic ? 0 : Microsoft.Cci.CallingConvention.HasThis); }
+ }
+
+ public override ImmutableArray Parameters
+ {
+ get
+ {
+ if (_lazyParameters.IsDefault)
+ {
+ var diagnostics = DiagnosticBag.GetInstance();
+ var result = this.ComputeParameters(binder: null, CSharpSyntaxNode, diagnostics);
+ if (ImmutableInterlocked.InterlockedInitialize(ref _lazyParameters, result))
+ {
+ this.AddDeclarationDiagnostics(diagnostics);
+ }
+ diagnostics.Free();
+ }
+
+ return _lazyParameters;
+ }
+ }
+
+ internal override bool IsExplicitInterfaceImplementation
+ => (_propertyFlags & Flags.IsExplicitInterfaceImplementation) != 0;
+
+ public override ImmutableArray ExplicitInterfaceImplementations
+ {
+ get { return _explicitInterfaceImplementations; }
+ }
+
+ public override ImmutableArray RefCustomModifiers
+ {
+ get { return _refCustomModifiers; }
+ }
+
+ public override Accessibility DeclaredAccessibility
+ {
+ get
+ {
+ return ModifierUtils.EffectiveAccessibility(_modifiers);
+ }
+ }
+
+ public bool HasSkipLocalsInitAttribute
+ {
+ get
+ {
+ var data = this.GetDecodedWellKnownAttributeData();
+ return data?.HasSkipLocalsInitAttribute == true;
+ }
+ }
+
+ internal bool IsAutoProperty
+ => (_propertyFlags & Flags.IsAutoProperty) != 0;
+
+ ///
+ /// Backing field for automatically implemented property, or
+ /// for a property with an initializer.
+ ///
+ internal SynthesizedBackingFieldSymbol BackingField { get; }
+
+ internal override bool MustCallMethodsDirectly
+ {
+ get { return false; }
+ }
+
+ internal SyntaxReference SyntaxReference
+ {
+ get
+ {
+ return _syntaxRef;
+ }
+ }
+
+ internal CSharpSyntaxNode CSharpSyntaxNode
+ {
+ get
+ {
+ return (CSharpSyntaxNode)_syntaxRef.GetSyntax();
+ }
+ }
+
+ public abstract SyntaxList AttributeDeclarationSyntaxList { get; }
+
+ internal SyntaxTree SyntaxTree
+ {
+ get
+ {
+ return _syntaxRef.SyntaxTree;
+ }
+ }
+
+ internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, DiagnosticBag diagnostics)
+ {
+ Location location = TypeLocation;
+ var compilation = DeclaringCompilation;
+
+ Debug.Assert(location != null);
+
+ // Check constraints on return type and parameters. Note: Dev10 uses the
+ // property name location for any such errors. We'll do the same for return
+ // type errors but for parameter errors, we'll use the parameter location.
+
+ if ((object)_explicitInterfaceType != null)
+ {
+ var explicitInterfaceSpecifier = GetExplicitInterfaceSpecifier(this.CSharpSyntaxNode);
+ Debug.Assert(explicitInterfaceSpecifier != null);
+ _explicitInterfaceType.CheckAllConstraints(compilation, conversions, new SourceLocation(explicitInterfaceSpecifier.Name), diagnostics);
+
+ // Note: we delayed nullable-related checks that could pull on NonNullTypes
+ if (!_explicitInterfaceImplementations.IsEmpty)
+ {
+ TypeSymbol.CheckNullableReferenceTypeMismatchOnImplementingMember(this.ContainingType, this, _explicitInterfaceImplementations[0], isExplicit: true, diagnostics);
+ }
+ }
+
+ if (_refKind == RefKind.RefReadOnly)
+ {
+ compilation.EnsureIsReadOnlyAttributeExists(diagnostics, location, modifyCompilation: true);
+ }
+
+ ParameterHelpers.EnsureIsReadOnlyAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true);
+
+ if (Type.ContainsNativeInteger())
+ {
+ compilation.EnsureNativeIntegerAttributeExists(diagnostics, location, modifyCompilation: true);
+ }
+
+ ParameterHelpers.EnsureNativeIntegerAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true);
+
+ if (compilation.ShouldEmitNullableAttributes(this) &&
+ this.TypeWithAnnotations.NeedsNullableAttribute())
+ {
+ compilation.EnsureNullableAttributeExists(diagnostics, location, modifyCompilation: true);
+ }
+
+ ParameterHelpers.EnsureNullableAttributeExists(compilation, this, Parameters, diagnostics, modifyCompilation: true);
+ }
+
+ private void CheckAccessibility(Location location, DiagnosticBag diagnostics, bool isExplicitInterfaceImplementation)
+ {
+ var info = ModifierUtils.CheckAccessibility(_modifiers, this, isExplicitInterfaceImplementation);
+ if (info != null)
+ {
+ diagnostics.Add(new CSDiagnostic(info, location));
+ }
+ }
+
+#nullable enable
+ protected abstract DeclarationModifiers MakeModifiers(
+ SyntaxTokenList modifiers, bool isExplicitInterfaceImplementation,
+ bool isIndexer, bool accessorsHaveImplementation,
+ Location location, DiagnosticBag diagnostics, out bool modifierErrors);
+#nullable restore
+
+
+
+ private void CheckModifiers(bool isExplicitInterfaceImplementation, Location location, bool isIndexer, DiagnosticBag diagnostics)
+ {
+ bool isExplicitInterfaceImplementationInInterface = isExplicitInterfaceImplementation && ContainingType.IsInterface;
+
+ if (this.DeclaredAccessibility == Accessibility.Private && (IsVirtual || (IsAbstract && !isExplicitInterfaceImplementationInInterface) || IsOverride))
+ {
+ diagnostics.Add(ErrorCode.ERR_VirtualPrivate, location, this);
+ }
+ else if (IsStatic && (IsOverride || IsVirtual || IsAbstract))
+ {
+ // A static member '{0}' cannot be marked as override, virtual, or abstract
+ diagnostics.Add(ErrorCode.ERR_StaticNotVirtual, location, this);
+ }
+ else if (IsStatic && HasReadOnlyModifier)
+ {
+ // Static member '{0}' cannot be marked 'readonly'.
+ diagnostics.Add(ErrorCode.ERR_StaticMemberCantBeReadOnly, location, this);
+ }
+ else if (IsOverride && (IsNew || IsVirtual))
+ {
+ // A member '{0}' marked as override cannot be marked as new or virtual
+ diagnostics.Add(ErrorCode.ERR_OverrideNotNew, location, this);
+ }
+ else if (IsSealed && !IsOverride && !(IsAbstract && isExplicitInterfaceImplementationInInterface))
+ {
+ // '{0}' cannot be sealed because it is not an override
+ diagnostics.Add(ErrorCode.ERR_SealedNonOverride, location, this);
+ }
+ else if (IsAbstract && ContainingType.TypeKind == TypeKind.Struct)
+ {
+ // The modifier '{0}' is not valid for this item
+ diagnostics.Add(ErrorCode.ERR_BadMemberFlag, location, SyntaxFacts.GetText(SyntaxKind.AbstractKeyword));
+ }
+ else if (IsVirtual && ContainingType.TypeKind == TypeKind.Struct)
+ {
+ // The modifier '{0}' is not valid for this item
+ diagnostics.Add(ErrorCode.ERR_BadMemberFlag, location, SyntaxFacts.GetText(SyntaxKind.VirtualKeyword));
+ }
+ else if (IsAbstract && IsExtern)
+ {
+ diagnostics.Add(ErrorCode.ERR_AbstractAndExtern, location, this);
+ }
+ else if (IsAbstract && IsSealed && !isExplicitInterfaceImplementationInInterface)
+ {
+ diagnostics.Add(ErrorCode.ERR_AbstractAndSealed, location, this);
+ }
+ else if (IsAbstract && IsVirtual)
+ {
+ diagnostics.Add(ErrorCode.ERR_AbstractNotVirtual, location, this.Kind.Localize(), this);
+ }
+ else if (ContainingType.IsSealed && this.DeclaredAccessibility.HasProtected() && !this.IsOverride)
+ {
+ diagnostics.Add(AccessCheck.GetProtectedMemberInSealedTypeError(ContainingType), location, this);
+ }
+ else if (ContainingType.IsStatic && !IsStatic)
+ {
+ ErrorCode errorCode = isIndexer ? ErrorCode.ERR_IndexerInStaticClass : ErrorCode.ERR_InstanceMemberInStaticClass;
+ diagnostics.Add(errorCode, location, this);
+ }
+ }
+
+#nullable enable
+ protected abstract SourcePropertyAccessorSymbol? CreateAccessorSymbol(
+ bool isGet,
+ CSharpSyntaxNode? syntaxOpt,
+ PropertySymbol? explicitlyImplementedPropertyOpt,
+ string aliasQualifierOpt,
+ bool isAutoPropertyAccessor,
+ bool isExplicitInterfaceImplementation,
+ DiagnosticBag diagnostics);
+
+ protected abstract SourcePropertyAccessorSymbol CreateExpressionBodiedAccessor(
+ ArrowExpressionClauseSyntax syntax,
+ PropertySymbol? explicitlyImplementedPropertyOpt,
+ string aliasQualifierOpt,
+ bool isExplicitInterfaceImplementation,
+ DiagnosticBag diagnostics);
+#nullable restore
+
+ private void CheckAccessibilityMoreRestrictive(SourcePropertyAccessorSymbol accessor, DiagnosticBag diagnostics)
+ {
+ if (((object)accessor != null) &&
+ !IsAccessibilityMoreRestrictive(this.DeclaredAccessibility, accessor.LocalAccessibility))
+ {
+ diagnostics.Add(ErrorCode.ERR_InvalidPropertyAccessMod, accessor.Locations[0], accessor, this);
+ }
+ }
+
+ ///
+ /// Return true if the accessor accessibility is more restrictive
+ /// than the property accessibility, otherwise false.
+ ///
+ private static bool IsAccessibilityMoreRestrictive(Accessibility property, Accessibility accessor)
+ {
+ if (accessor == Accessibility.NotApplicable)
+ {
+ return true;
+ }
+ return (accessor < property) &&
+ ((accessor != Accessibility.Protected) || (property != Accessibility.Internal));
+ }
+
+ private static void CheckAbstractPropertyAccessorNotPrivate(SourcePropertyAccessorSymbol accessor, DiagnosticBag diagnostics)
+ {
+ if (accessor.LocalAccessibility == Accessibility.Private)
+ {
+ diagnostics.Add(ErrorCode.ERR_PrivateAbstractAccessor, accessor.Locations[0], accessor);
+ }
+ }
+
+ public override string GetDocumentationCommentXml(CultureInfo preferredCulture = null, bool expandIncludes = false, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ ref var lazyDocComment = ref expandIncludes ? ref _lazyExpandedDocComment : ref _lazyDocComment;
+ return SourceDocumentationCommentUtils.GetAndCacheDocumentationComment(this, expandIncludes, ref lazyDocComment);
+ }
+
+ // Separate these checks out of FindExplicitlyImplementedProperty because they depend on the accessor symbols,
+ // which depend on the explicitly implemented property
+ private void CheckExplicitImplementationAccessor(MethodSymbol thisAccessor, MethodSymbol otherAccessor, PropertySymbol explicitlyImplementedProperty, DiagnosticBag diagnostics)
+ {
+ var thisHasAccessor = (object)thisAccessor != null;
+ var otherHasAccessor = otherAccessor.IsImplementable();
+
+ if (otherHasAccessor && !thisHasAccessor)
+ {
+ diagnostics.Add(ErrorCode.ERR_ExplicitPropertyMissingAccessor, this.Location, this, otherAccessor);
+ }
+ else if (!otherHasAccessor && thisHasAccessor)
+ {
+ diagnostics.Add(ErrorCode.ERR_ExplicitPropertyAddingAccessor, thisAccessor.Locations[0], thisAccessor, explicitlyImplementedProperty);
+ }
+ else if (TypeSymbol.HaveInitOnlyMismatch(thisAccessor, otherAccessor))
+ {
+ Debug.Assert(thisAccessor.MethodKind == MethodKind.PropertySet);
+ diagnostics.Add(ErrorCode.ERR_ExplicitPropertyMismatchInitOnly, thisAccessor.Locations[0], thisAccessor, otherAccessor);
+ }
+ }
+
+ internal override OverriddenOrHiddenMembersResult OverriddenOrHiddenMembers
+ {
+ get
+ {
+ if (_lazyOverriddenOrHiddenMembers == null)
+ {
+ Interlocked.CompareExchange(ref _lazyOverriddenOrHiddenMembers, this.MakeOverriddenOrHiddenMembers(), null);
+ }
+ return _lazyOverriddenOrHiddenMembers;
+ }
+ }
+
+ ///
+ /// If this property is sealed, then we have to emit both accessors - regardless of whether
+ /// they are present in the source - so that they can be marked final. (i.e. sealed).
+ ///
+ internal SynthesizedSealedPropertyAccessor SynthesizedSealedAccessorOpt
+ {
+ get
+ {
+ bool hasGetter = (object)_getMethod != null;
+ bool hasSetter = (object)_setMethod != null;
+ if (!this.IsSealed || (hasGetter && hasSetter))
+ {
+ return null;
+ }
+
+ // This has to be cached because the CCI layer depends on reference equality.
+ // However, there's no point in having more than one field, since we don't
+ // expect to have to synthesize more than one accessor.
+ if ((object)_lazySynthesizedSealedAccessor == null)
+ {
+ Interlocked.CompareExchange(ref _lazySynthesizedSealedAccessor, MakeSynthesizedSealedAccessor(), null);
+ }
+ return _lazySynthesizedSealedAccessor;
+ }
+ }
+
+ ///
+ /// Only non-null for sealed properties without both accessors.
+ ///
+ private SynthesizedSealedPropertyAccessor MakeSynthesizedSealedAccessor()
+ {
+ Debug.Assert(this.IsSealed && ((object)_getMethod == null || (object)_setMethod == null));
+
+ if ((object)_getMethod != null)
+ {
+ // need to synthesize setter
+ MethodSymbol overriddenAccessor = this.GetOwnOrInheritedSetMethod();
+ return (object)overriddenAccessor == null ? null : new SynthesizedSealedPropertyAccessor(this, overriddenAccessor);
+ }
+ else if ((object)_setMethod != null)
+ {
+ // need to synthesize getter
+ MethodSymbol overriddenAccessor = this.GetOwnOrInheritedGetMethod();
+ return (object)overriddenAccessor == null ? null : new SynthesizedSealedPropertyAccessor(this, overriddenAccessor);
+ }
+ else
+ {
+ // Arguably, it would be more correct to return an array containing two
+ // synthesized accessors, but we're already in an error case, so we'll
+ // minimize the cascading error behavior by suppressing synthesis.
+ return null;
+ }
+ }
+
+ #region Attributes
+
+ IAttributeTargetSymbol IAttributeTargetSymbol.AttributesOwner => this;
+
+ AttributeLocation IAttributeTargetSymbol.DefaultAttributeLocation => AttributeLocation.Property;
+
+ AttributeLocation IAttributeTargetSymbol.AllowedAttributeLocations
+ => (_propertyFlags & Flags.IsAutoProperty) != 0
+ ? AttributeLocation.Property | AttributeLocation.Field
+ : AttributeLocation.Property;
+
+ ///
+ /// Returns a bag of custom attributes applied on the property and data decoded from well-known attributes. Returns null if there are no attributes.
+ ///
+ ///
+ /// Forces binding and decoding of attributes.
+ ///
+ private CustomAttributesBag GetAttributesBag()
+ {
+ var bag = _lazyCustomAttributesBag;
+ if (bag != null && bag.IsSealed)
+ {
+ return bag;
+ }
+
+ // The property is responsible for completion of the backing field
+ _ = BackingField?.GetAttributes();
+
+ if (LoadAndValidateAttributes(OneOrMany.Create(AttributeDeclarationSyntaxList), ref _lazyCustomAttributesBag))
+ {
+ var completed = _state.NotePartComplete(CompletionPart.Attributes);
+ Debug.Assert(completed);
+ }
+
+ Debug.Assert(_lazyCustomAttributesBag.IsSealed);
+ return _lazyCustomAttributesBag;
+ }
+
+ ///
+ /// Gets the attributes applied on this symbol.
+ /// Returns an empty array if there are no attributes.
+ ///
+ ///
+ /// NOTE: This method should always be kept as a sealed override.
+ /// If you want to override attribute binding logic for a sub-class, then override method.
+ ///
+ public sealed override ImmutableArray GetAttributes()
+ {
+ return this.GetAttributesBag().Attributes;
+ }
+
+ ///
+ /// Returns data decoded from well-known attributes applied to the symbol or null if there are no applied attributes.
+ ///
+ ///
+ /// Forces binding and decoding of attributes.
+ ///
+ private PropertyWellKnownAttributeData GetDecodedWellKnownAttributeData()
+ {
+ var attributesBag = _lazyCustomAttributesBag;
+ if (attributesBag == null || !attributesBag.IsDecodedWellKnownAttributeDataComputed)
+ {
+ attributesBag = this.GetAttributesBag();
+ }
+
+ return (PropertyWellKnownAttributeData)attributesBag.DecodedWellKnownAttributeData;
+ }
+
+ ///
+ /// Returns data decoded from special early bound well-known attributes applied to the symbol or null if there are no applied attributes.
+ ///
+ ///
+ /// Forces binding and decoding of attributes.
+ ///
+ internal PropertyEarlyWellKnownAttributeData GetEarlyDecodedWellKnownAttributeData()
+ {
+ var attributesBag = _lazyCustomAttributesBag;
+ if (attributesBag == null || !attributesBag.IsEarlyDecodedWellKnownAttributeDataComputed)
+ {
+ attributesBag = this.GetAttributesBag();
+ }
+
+ return (PropertyEarlyWellKnownAttributeData)attributesBag.EarlyDecodedWellKnownAttributeData;
+ }
+
+ internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes)
+ {
+ base.AddSynthesizedAttributes(moduleBuilder, ref attributes);
+
+ var compilation = this.DeclaringCompilation;
+ var type = this.TypeWithAnnotations;
+
+ if (type.Type.ContainsDynamic())
+ {
+ AddSynthesizedAttribute(ref attributes,
+ compilation.SynthesizeDynamicAttribute(type.Type, type.CustomModifiers.Length + RefCustomModifiers.Length, _refKind));
+ }
+
+ if (type.Type.ContainsNativeInteger())
+ {
+ AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeNativeIntegerAttribute(this, type.Type));
+ }
+
+ if (type.Type.ContainsTupleNames())
+ {
+ AddSynthesizedAttribute(ref attributes,
+ compilation.SynthesizeTupleNamesAttribute(type.Type));
+ }
+
+ if (compilation.ShouldEmitNullableAttributes(this))
+ {
+ AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeNullableAttributeIfNecessary(this, ContainingType.GetNullableContextValue(), type));
+ }
+
+ if (this.ReturnsByRefReadonly)
+ {
+ AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeIsReadOnlyAttribute(this));
+ }
+ }
+
+ internal sealed override bool IsDirectlyExcludedFromCodeCoverage =>
+ GetDecodedWellKnownAttributeData()?.HasExcludeFromCodeCoverageAttribute == true;
+
+ internal override bool HasSpecialName
+ {
+ get
+ {
+ var data = GetDecodedWellKnownAttributeData();
+ return data != null && data.HasSpecialNameAttribute;
+ }
+ }
+
+ internal override CSharpAttributeData EarlyDecodeWellKnownAttribute(ref EarlyDecodeWellKnownAttributeArguments arguments)
+ {
+ CSharpAttributeData boundAttribute;
+ ObsoleteAttributeData obsoleteData;
+
+ if (EarlyDecodeDeprecatedOrExperimentalOrObsoleteAttribute(ref arguments, out boundAttribute, out obsoleteData))
+ {
+ if (obsoleteData != null)
+ {
+ arguments.GetOrCreateData().ObsoleteAttributeData = obsoleteData;
+ }
+
+ return boundAttribute;
+ }
+
+ if (CSharpAttributeData.IsTargetEarlyAttribute(arguments.AttributeType, arguments.AttributeSyntax, AttributeDescription.IndexerNameAttribute))
+ {
+ bool hasAnyDiagnostics;
+ boundAttribute = arguments.Binder.GetAttribute(arguments.AttributeSyntax, arguments.AttributeType, out hasAnyDiagnostics);
+ if (!boundAttribute.HasErrors)
+ {
+ string indexerName = boundAttribute.CommonConstructorArguments[0].DecodeValue(SpecialType.System_String);
+ if (indexerName != null)
+ {
+ arguments.GetOrCreateData().IndexerName = indexerName;
+ }
+
+ if (!hasAnyDiagnostics)
+ {
+ return boundAttribute;
+ }
+ }
+
+ return null;
+ }
+
+ return base.EarlyDecodeWellKnownAttribute(ref arguments);
+ }
+
+ ///
+ /// Returns data decoded from Obsolete attribute or null if there is no Obsolete attribute.
+ /// This property returns ObsoleteAttributeData.Uninitialized if attribute arguments haven't been decoded yet.
+ ///
+ internal override ObsoleteAttributeData ObsoleteAttributeData
+ {
+ get
+ {
+ if (!_containingType.AnyMemberHasAttributes)
+ {
+ return null;
+ }
+
+ var lazyCustomAttributesBag = _lazyCustomAttributesBag;
+ if (lazyCustomAttributesBag != null && lazyCustomAttributesBag.IsEarlyDecodedWellKnownAttributeDataComputed)
+ {
+ return ((PropertyEarlyWellKnownAttributeData)lazyCustomAttributesBag.EarlyDecodedWellKnownAttributeData)?.ObsoleteAttributeData;
+ }
+
+ return ObsoleteAttributeData.Uninitialized;
+ }
+ }
+
+ internal override void DecodeWellKnownAttribute(ref DecodeWellKnownAttributeArguments arguments)
+ {
+ Debug.Assert(arguments.AttributeSyntaxOpt != null);
+
+ var attribute = arguments.Attribute;
+ Debug.Assert(!attribute.HasErrors);
+ Debug.Assert(arguments.SymbolPart == AttributeLocation.None);
+
+ if (attribute.IsTargetAttribute(this, AttributeDescription.IndexerNameAttribute))
+ {
+ //NOTE: decoding was done by EarlyDecodeWellKnownAttribute.
+ ValidateIndexerNameAttribute(attribute, arguments.AttributeSyntaxOpt, arguments.Diagnostics);
+ }
+ else if (attribute.IsTargetAttribute(this, AttributeDescription.SpecialNameAttribute))
+ {
+ arguments.GetOrCreateData().HasSpecialNameAttribute = true;
+ }
+ else if (attribute.IsTargetAttribute(this, AttributeDescription.ExcludeFromCodeCoverageAttribute))
+ {
+ arguments.GetOrCreateData().HasExcludeFromCodeCoverageAttribute = true;
+ }
+ else if (attribute.IsTargetAttribute(this, AttributeDescription.SkipLocalsInitAttribute))
+ {
+ CSharpAttributeData.DecodeSkipLocalsInitAttribute(DeclaringCompilation, ref arguments);
+ }
+ else if (attribute.IsTargetAttribute(this, AttributeDescription.DynamicAttribute))
+ {
+ // DynamicAttribute should not be set explicitly.
+ arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitDynamicAttr, arguments.AttributeSyntaxOpt.Location);
+ }
+ else if (ReportExplicitUseOfReservedAttributes(in arguments,
+ ReservedAttributes.DynamicAttribute | ReservedAttributes.IsReadOnlyAttribute | ReservedAttributes.IsUnmanagedAttribute | ReservedAttributes.IsByRefLikeAttribute | ReservedAttributes.TupleElementNamesAttribute | ReservedAttributes.NullableAttribute | ReservedAttributes.NativeIntegerAttribute))
+ {
+ }
+ else if (attribute.IsTargetAttribute(this, AttributeDescription.DisallowNullAttribute))
+ {
+ arguments.GetOrCreateData().HasDisallowNullAttribute = true;
+ }
+ else if (attribute.IsTargetAttribute(this, AttributeDescription.AllowNullAttribute))
+ {
+ arguments.GetOrCreateData().HasAllowNullAttribute = true;
+ }
+ else if (attribute.IsTargetAttribute(this, AttributeDescription.MaybeNullAttribute))
+ {
+ arguments.GetOrCreateData().HasMaybeNullAttribute = true;
+ }
+ else if (attribute.IsTargetAttribute(this, AttributeDescription.NotNullAttribute))
+ {
+ arguments.GetOrCreateData().HasNotNullAttribute = true;
+ }
+ else if (attribute.IsTargetAttribute(this, AttributeDescription.MemberNotNullAttribute))
+ {
+ MessageID.IDS_FeatureMemberNotNull.CheckFeatureAvailability(arguments.Diagnostics, arguments.AttributeSyntaxOpt);
+ CSharpAttributeData.DecodeMemberNotNullAttribute(ContainingType, ref arguments);
+ }
+ else if (attribute.IsTargetAttribute(this, AttributeDescription.MemberNotNullWhenAttribute))
+ {
+ MessageID.IDS_FeatureMemberNotNull.CheckFeatureAvailability(arguments.Diagnostics, arguments.AttributeSyntaxOpt);
+ CSharpAttributeData.DecodeMemberNotNullWhenAttribute(ContainingType, ref arguments);
+ }
+ }
+
+ internal bool HasDisallowNull
+ {
+ get
+ {
+ var data = GetDecodedWellKnownAttributeData();
+ return data != null && data.HasDisallowNullAttribute;
+ }
+ }
+
+ internal bool HasAllowNull
+ {
+ get
+ {
+ var data = GetDecodedWellKnownAttributeData();
+ return data != null && data.HasAllowNullAttribute;
+ }
+ }
+
+ internal bool HasMaybeNull
+ {
+ get
+ {
+ var data = GetDecodedWellKnownAttributeData();
+ return data != null && data.HasMaybeNullAttribute;
+ }
+ }
+
+ internal bool HasNotNull
+ {
+ get
+ {
+ var data = GetDecodedWellKnownAttributeData();
+ return data != null && data.HasNotNullAttribute;
+ }
+ }
+
+ internal SourceAttributeData DisallowNullAttributeIfExists
+ => FindAttribute(AttributeDescription.DisallowNullAttribute);
+
+ internal SourceAttributeData AllowNullAttributeIfExists
+ => FindAttribute(AttributeDescription.AllowNullAttribute);
+
+ internal SourceAttributeData MaybeNullAttributeIfExists
+ => FindAttribute(AttributeDescription.MaybeNullAttribute);
+
+ internal SourceAttributeData NotNullAttributeIfExists
+ => FindAttribute(AttributeDescription.NotNullAttribute);
+
+ internal ImmutableArray MemberNotNullAttributeIfExists
+ => FindAttributes(AttributeDescription.MemberNotNullAttribute);
+
+ internal ImmutableArray MemberNotNullWhenAttributeIfExists
+ => FindAttributes(AttributeDescription.MemberNotNullWhenAttribute);
+
+ private SourceAttributeData FindAttribute(AttributeDescription attributeDescription)
+ => (SourceAttributeData)GetAttributes().First(a => a.IsTargetAttribute(this, attributeDescription));
+
+ private ImmutableArray FindAttributes(AttributeDescription attributeDescription)
+ => GetAttributes().Where(a => a.IsTargetAttribute(this, attributeDescription)).Cast().ToImmutableArray();
+
+ internal override void PostDecodeWellKnownAttributes(ImmutableArray boundAttributes, ImmutableArray allAttributeSyntaxNodes, DiagnosticBag diagnostics, AttributeLocation symbolPart, WellKnownAttributeData decodedData)
+ {
+ Debug.Assert(!boundAttributes.IsDefault);
+ Debug.Assert(!allAttributeSyntaxNodes.IsDefault);
+ Debug.Assert(boundAttributes.Length == allAttributeSyntaxNodes.Length);
+ Debug.Assert(_lazyCustomAttributesBag != null);
+ Debug.Assert(_lazyCustomAttributesBag.IsDecodedWellKnownAttributeDataComputed);
+ Debug.Assert(symbolPart == AttributeLocation.None);
+
+ base.PostDecodeWellKnownAttributes(boundAttributes, allAttributeSyntaxNodes, diagnostics, symbolPart, decodedData);
+ }
+
+ private void ValidateIndexerNameAttribute(CSharpAttributeData attribute, AttributeSyntax node, DiagnosticBag diagnostics)
+ {
+ if (!this.IsIndexer || this.IsExplicitInterfaceImplementation)
+ {
+ diagnostics.Add(ErrorCode.ERR_BadIndexerNameAttr, node.Name.Location, node.GetErrorDisplayName());
+ }
+ else
+ {
+ string indexerName = attribute.CommonConstructorArguments[0].DecodeValue(SpecialType.System_String);
+ if (indexerName == null || !SyntaxFacts.IsValidIdentifier(indexerName))
+ {
+ diagnostics.Add(ErrorCode.ERR_BadArgumentToAttribute, node.ArgumentList.Arguments[0].Location, node.GetErrorDisplayName());
+ }
+ }
+ }
+
+ #endregion
+
+ #region Completion
+
+ internal sealed override bool RequiresCompletion
+ {
+ get { return true; }
+ }
+
+ internal sealed override bool HasComplete(CompletionPart part)
+ {
+ return _state.HasComplete(part);
+ }
+
+ internal override void ForceComplete(SourceLocation locationOpt, CancellationToken cancellationToken)
+ {
+ while (true)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ var incompletePart = _state.NextIncompletePart;
+ switch (incompletePart)
+ {
+ case CompletionPart.Attributes:
+ GetAttributes();
+ break;
+
+ case CompletionPart.StartPropertyParameters:
+ case CompletionPart.FinishPropertyParameters:
+ {
+ if (_state.NotePartComplete(CompletionPart.StartPropertyParameters))
+ {
+ var parameters = this.Parameters;
+ if (parameters.Length > 0)
+ {
+ var diagnostics = DiagnosticBag.GetInstance();
+ var conversions = new TypeConversions(this.ContainingAssembly.CorLibrary);
+ foreach (var parameter in this.Parameters)
+ {
+ parameter.ForceComplete(locationOpt, cancellationToken);
+ parameter.Type.CheckAllConstraints(DeclaringCompilation, conversions, parameter.Locations[0], diagnostics);
+ }
+
+ this.AddDeclarationDiagnostics(diagnostics);
+ diagnostics.Free();
+ }
+
+ DeclaringCompilation.SymbolDeclaredEvent(this);
+ var completedOnThisThread = _state.NotePartComplete(CompletionPart.FinishPropertyParameters);
+ Debug.Assert(completedOnThisThread);
+ }
+ else
+ {
+ // StartPropertyParameters was completed by another thread. Wait for it to finish the parameters.
+ _state.SpinWaitComplete(CompletionPart.FinishPropertyParameters, cancellationToken);
+ }
+ }
+ break;
+
+ case CompletionPart.StartPropertyType:
+ case CompletionPart.FinishPropertyType:
+ {
+ if (_state.NotePartComplete(CompletionPart.StartPropertyType))
+ {
+ var diagnostics = DiagnosticBag.GetInstance();
+ var conversions = new TypeConversions(this.ContainingAssembly.CorLibrary);
+ this.Type.CheckAllConstraints(DeclaringCompilation, conversions, Location, diagnostics);
+
+ var type = this.Type;
+ if (type.IsRestrictedType(ignoreSpanLikeTypes: true))
+ {
+ diagnostics.Add(ErrorCode.ERR_FieldCantBeRefAny, TypeLocation, type);
+ }
+ else if (this.IsAutoProperty && type.IsRefLikeType && (this.IsStatic || !this.ContainingType.IsRefLikeType))
+ {
+ diagnostics.Add(ErrorCode.ERR_FieldAutoPropCantBeByRefLike, TypeLocation, type);
+ }
+
+ this.AddDeclarationDiagnostics(diagnostics);
+ var completedOnThisThread = _state.NotePartComplete(CompletionPart.FinishPropertyType);
+ Debug.Assert(completedOnThisThread);
+ diagnostics.Free();
+ }
+ else
+ {
+ // StartPropertyType was completed by another thread. Wait for it to finish the type.
+ _state.SpinWaitComplete(CompletionPart.FinishPropertyType, cancellationToken);
+ }
+ }
+ break;
+
+ case CompletionPart.None:
+ return;
+
+ default:
+ // any other values are completion parts intended for other kinds of symbols
+ _state.NotePartComplete(CompletionPart.All & ~CompletionPart.PropertySymbolAll);
+ break;
+ }
+
+ _state.SpinWaitComplete(incompletePart, cancellationToken);
+ }
+ }
+
+ #endregion
+
+#nullable enable
+ protected abstract ImmutableArray ComputeParameters(Binder? binder, CSharpSyntaxNode syntax, DiagnosticBag diagnostics);
+
+ protected abstract TypeWithAnnotations ComputeType(Binder? binder, SyntaxNode syntax, DiagnosticBag diagnostics);
+
+ protected abstract ExplicitInterfaceSpecifierSyntax? GetExplicitInterfaceSpecifier(SyntaxNode syntax);
+
+ protected abstract BaseParameterListSyntax? GetParameterListSyntax(CSharpSyntaxNode syntax);
+#nullable restore
+ }
+}
diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordPropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordPropertySymbol.cs
index db9ea5a9197f0d4e34daa07f823e234d8ff05791..db971383e148aa0fb61e7a6993b2b5770cf50d7c 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordPropertySymbol.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordPropertySymbol.cs
@@ -7,338 +7,144 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
+using System.Diagnostics;
using System.Reflection;
using Microsoft.Cci;
using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
- internal sealed class SynthesizedRecordPropertySymbol : SourceOrRecordPropertySymbol
+ internal sealed class SynthesizedRecordPropertySymbol : SourcePropertySymbolBase, IAttributeTargetSymbol
{
- private readonly ParameterSymbol _backingParameter;
- internal override SynthesizedBackingFieldSymbol BackingField { get; }
- public override MethodSymbol GetMethod { get; }
- public override MethodSymbol SetMethod { get; }
- public override NamedTypeSymbol ContainingType { get; }
+ public ParameterSymbol BackingParameter { get; }
public SynthesizedRecordPropertySymbol(
- NamedTypeSymbol containingType,
+ SourceMemberContainerTypeSymbol containingType,
ParameterSymbol backingParameter,
DiagnosticBag diagnostics)
- : base(backingParameter.Locations[0])
+ : base(containingType,
+ binder: null,
+ backingParameter.GetNonNullSyntaxNode(),
+ RefKind.None,
+ backingParameter.Name,
+ backingParameter.Locations[0],
+ diagnostics)
{
- ContainingType = containingType;
- _backingParameter = backingParameter;
- string name = backingParameter.Name;
- BackingField = new SynthesizedBackingFieldSymbol(
- this,
- GeneratedNames.MakeBackingFieldName(name),
- isReadOnly: true,
- isStatic: false,
- hasInitializer: true);
- GetMethod = new GetAccessorSymbol(this, name);
- SetMethod = new InitAccessorSymbol(this, name, diagnostics);
+ BackingParameter = backingParameter;
}
- public ParameterSymbol BackingParameter => _backingParameter;
-
- internal override bool IsAutoProperty => true;
-
- public override RefKind RefKind => RefKind.None;
-
- public override TypeWithAnnotations TypeWithAnnotations => _backingParameter.TypeWithAnnotations;
-
- public override ImmutableArray RefCustomModifiers => ImmutableArray.Empty;
-
- public override ImmutableArray Parameters => ImmutableArray.Empty;
-
- public override bool IsIndexer => false;
-
- public override ImmutableArray ExplicitInterfaceImplementations => ImmutableArray.Empty;
-
- public override Symbol ContainingSymbol => ContainingType;
-
- public override ImmutableArray Locations => _backingParameter.Locations;
-
- public override ImmutableArray DeclaringSyntaxReferences => _backingParameter.DeclaringSyntaxReferences;
-
- public override Accessibility DeclaredAccessibility => Accessibility.Public;
-
- public override bool IsStatic => false;
-
- public override bool IsVirtual => false;
+ IAttributeTargetSymbol IAttributeTargetSymbol.AttributesOwner => this;
- public override bool IsOverride => false;
+ AttributeLocation IAttributeTargetSymbol.AllowedAttributeLocations => AttributeLocation.None;
- public override bool IsAbstract => false;
+ AttributeLocation IAttributeTargetSymbol.DefaultAttributeLocation => AttributeLocation.None;
- public override bool IsSealed => false;
+ protected override Location TypeLocation
+ => ((ParameterSyntax)CSharpSyntaxNode).Type!.Location;
- public override bool IsExtern => false;
+ protected override SyntaxTokenList GetModifierTokens(SyntaxNode syntax)
+ => new SyntaxTokenList();
- internal override bool HasSpecialName => false;
+ protected override ArrowExpressionClauseSyntax? GetArrowExpression(SyntaxNode syntax)
+ => null;
- internal override CallingConvention CallingConvention => CallingConvention.HasThis;
+ protected override bool HasInitializer(SyntaxNode syntax)
+ => true; // Synthesized record properties always have a synthesized initializer
- internal override bool MustCallMethodsDirectly => false;
+ public override SyntaxList AttributeDeclarationSyntaxList
+ => new SyntaxList();
- internal override ObsoleteAttributeData? ObsoleteAttributeData => null;
-
- public override string Name => _backingParameter.Name;
-
- protected override IAttributeTargetSymbol AttributesOwner => this;
-
- protected override AttributeLocation AllowedAttributeLocations => AttributeLocation.None;
-
- protected override AttributeLocation DefaultAttributeLocation => AttributeLocation.None;
-
- public override ImmutableArray GetAttributes() => ImmutableArray.Empty;
-
- internal override bool HasPointerType => Type.IsPointerType();
-
- public override SyntaxList AttributeDeclarationSyntaxList => new SyntaxList();
-
- private sealed class GetAccessorSymbol : SynthesizedInstanceMethodSymbol
+ protected override void GetAccessorDeclarations(
+ CSharpSyntaxNode syntax,
+ DiagnosticBag diagnostics,
+ out bool isAutoProperty,
+ out bool hasAccessorList,
+ out bool accessorsHaveImplementation,
+ out bool isInitOnly,
+ out CSharpSyntaxNode? getSyntax,
+ out CSharpSyntaxNode? setSyntax)
{
- private readonly SynthesizedRecordPropertySymbol _property;
-
- public override string Name { get; }
-
- public GetAccessorSymbol(SynthesizedRecordPropertySymbol property, string paramName)
- {
- _property = property;
- Name = SourcePropertyAccessorSymbol.GetAccessorName(
- paramName,
- getNotSet: true,
- isWinMdOutput: false /* unused for getters */);
- }
-
- public override MethodKind MethodKind => MethodKind.PropertyGet;
-
- public override int Arity => 0;
-
- public override bool IsExtensionMethod => false;
-
- public override bool HidesBaseMethodsByName => false;
-
- public override bool IsVararg => false;
-
- public override bool ReturnsVoid => false;
-
- public override bool IsAsync => false;
-
- public override RefKind RefKind => RefKind.None;
-
- public override TypeWithAnnotations ReturnTypeWithAnnotations => _property.TypeWithAnnotations;
-
- public override FlowAnalysisAnnotations ReturnTypeFlowAnalysisAnnotations => FlowAnalysisAnnotations.None;
-
- public override ImmutableArray TypeArgumentsWithAnnotations => ImmutableArray.Empty;
-
- public override ImmutableArray TypeParameters => ImmutableArray.Empty;
-
- public override ImmutableArray Parameters => _property.Parameters;
-
- public override ImmutableArray ExplicitInterfaceImplementations => ImmutableArray.Empty;
-
- public override ImmutableArray RefCustomModifiers => _property.RefCustomModifiers;
-
- public override Symbol AssociatedSymbol => _property;
-
- public override Symbol ContainingSymbol => _property.ContainingSymbol;
-
- public override ImmutableArray Locations => _property.Locations;
-
- public override Accessibility DeclaredAccessibility => _property.DeclaredAccessibility;
-
- public override bool IsStatic => _property.IsStatic;
-
- public override bool IsVirtual => _property.IsVirtual;
-
- public override bool IsOverride => _property.IsOverride;
-
- public override bool IsAbstract => _property.IsAbstract;
-
- public override bool IsSealed => _property.IsSealed;
-
- public override bool IsExtern => _property.IsExtern;
-
- public override ImmutableHashSet ReturnNotNullIfParameterNotNull => ImmutableHashSet.Empty;
-
- internal override bool HasSpecialName => _property.HasSpecialName;
-
- internal override MethodImplAttributes ImplementationAttributes => MethodImplAttributes.Managed;
-
- internal override bool HasDeclarativeSecurity => false;
-
- internal override MarshalPseudoCustomAttributeData? ReturnValueMarshallingInformation => null;
-
- internal override bool RequiresSecurityObject => false;
-
- internal override CallingConvention CallingConvention => CallingConvention.HasThis;
-
- internal override bool GenerateDebugInfo => false;
-
- public override DllImportData? GetDllImportData() => null;
-
- internal override ImmutableArray GetAppliedConditionalSymbols()
- => ImmutableArray.Empty;
-
- internal override IEnumerable GetSecurityInformation()
- => Array.Empty();
-
- internal override bool IsMetadataNewSlot(bool ignoreInterfaceImplementationChanges = false) => false;
-
- internal override bool IsMetadataVirtual(bool ignoreInterfaceImplementationChanges = false) => false;
-
- internal override bool SynthesizesLoweredBoundBody => true;
-
- internal override void GenerateMethodBody(TypeCompilationState compilationState, DiagnosticBag diagnostics)
- {
- // Method body:
- //
- // {
- // return this.<>backingField;
- // }
-
- var F = new SyntheticBoundNodeFactory(this, this.GetNonNullSyntaxNode(), compilationState, diagnostics);
-
- F.CurrentFunction = this;
- F.CloseMethod(F.Block(F.Return(F.Field(F.This(), _property.BackingField))));
- }
+ isAutoProperty = true;
+ hasAccessorList = false;
+ getSyntax = setSyntax = syntax;
+ isInitOnly = true;
+ accessorsHaveImplementation = false;
}
- private sealed class InitAccessorSymbol : SynthesizedInstanceMethodSymbol
+ protected override void CheckForBlockAndExpressionBody(CSharpSyntaxNode syntax, DiagnosticBag diagnostics)
{
- private readonly SynthesizedRecordPropertySymbol _property;
-
- public override TypeWithAnnotations ReturnTypeWithAnnotations { get; }
- public override string Name { get; }
-
- public InitAccessorSymbol(
- SynthesizedRecordPropertySymbol property,
- string paramName,
- DiagnosticBag diagnostics)
- {
- _property = property;
- Name = SourcePropertyAccessorSymbol.GetAccessorName(
- paramName,
- getNotSet: false,
- // https://github.com/dotnet/roslyn/issues/44684
- isWinMdOutput: false);
-
- var comp = property.DeclaringCompilation;
- var type = TypeWithAnnotations.Create(comp.GetSpecialType(SpecialType.System_Void));
- var initOnlyType = Binder.GetWellKnownType(
- comp,
- WellKnownType.System_Runtime_CompilerServices_IsExternalInit,
- diagnostics,
- property.Location);
- var modifiers = ImmutableArray.Create(CSharpCustomModifier.CreateRequired(initOnlyType));
-
- ReturnTypeWithAnnotations = type.WithModifiers(modifiers);
- }
-
- internal override bool IsInitOnly => true;
-
- public override MethodKind MethodKind => MethodKind.PropertySet;
-
- public override int Arity => 0;
-
- public override bool IsExtensionMethod => false;
-
- public override bool HidesBaseMethodsByName => false;
-
- public override bool IsVararg => false;
-
- public override bool ReturnsVoid => true;
-
- public override bool IsAsync => false;
-
- public override RefKind RefKind => RefKind.None;
-
- public override FlowAnalysisAnnotations ReturnTypeFlowAnalysisAnnotations => FlowAnalysisAnnotations.None;
+ // Nothing to do here
+ }
- public override ImmutableArray TypeArgumentsWithAnnotations => ImmutableArray.Empty;
+ protected override DeclarationModifiers MakeModifiers(
+ SyntaxTokenList modifiers,
+ bool isExplicitInterfaceImplementation,
+ bool isIndexer,
+ bool accessorsHaveImplementation,
+ Location location,
+ DiagnosticBag diagnostics,
+ out bool modifierErrors)
+ {
+ Debug.Assert(!isExplicitInterfaceImplementation);
+ Debug.Assert(!isIndexer);
+ modifierErrors = false;
- public override ImmutableArray TypeParameters => ImmutableArray.Empty;
+ return DeclarationModifiers.Public;
+ }
- public override ImmutableArray Parameters => ImmutableArray.Create(SynthesizedParameterSymbol.Create(
+ protected override SourcePropertyAccessorSymbol CreateAccessorSymbol(
+ bool isGet,
+ CSharpSyntaxNode? syntax,
+ PropertySymbol? explicitlyImplementedPropertyOpt,
+ string aliasQualifierOpt,
+ bool isAutoPropertyAccessor,
+ bool isExplicitInterfaceImplementation,
+ DiagnosticBag diagnostics)
+ {
+ Debug.Assert(syntax is object);
+ Debug.Assert(isAutoPropertyAccessor);
+ return SourcePropertyAccessorSymbol.CreateAccessorSymbol(
+ isGet,
+ usesInit: !isGet, // the setter is always init-only
+ ContainingType,
this,
- _property.TypeWithAnnotations,
- ordinal: 0,
- RefKind.None,
- name: ParameterSymbol.ValueParameterName));
-
- public override ImmutableArray ExplicitInterfaceImplementations => ImmutableArray.Empty;
-
- public override ImmutableArray RefCustomModifiers => _property.RefCustomModifiers;
-
- public override Symbol AssociatedSymbol => _property;
-
- public override Symbol ContainingSymbol => _property.ContainingSymbol;
-
- public override ImmutableArray Locations => _property.Locations;
-
- public override Accessibility DeclaredAccessibility => _property.DeclaredAccessibility;
-
- public override bool IsStatic => _property.IsStatic;
-
- public override bool IsVirtual => _property.IsVirtual;
-
- public override bool IsOverride => _property.IsOverride;
-
- public override bool IsAbstract => _property.IsAbstract;
-
- public override bool IsSealed => _property.IsSealed;
-
- public override bool IsExtern => _property.IsExtern;
-
- public override ImmutableHashSet ReturnNotNullIfParameterNotNull => ImmutableHashSet.Empty;
-
- internal override bool HasSpecialName => _property.HasSpecialName;
-
- internal override MethodImplAttributes ImplementationAttributes => MethodImplAttributes.Managed;
-
- internal override bool HasDeclarativeSecurity => false;
-
- internal override MarshalPseudoCustomAttributeData? ReturnValueMarshallingInformation => null;
-
- internal override bool RequiresSecurityObject => false;
-
- internal override CallingConvention CallingConvention => CallingConvention.HasThis;
-
- internal override bool GenerateDebugInfo => false;
-
- public override DllImportData? GetDllImportData() => null;
-
- internal override ImmutableArray GetAppliedConditionalSymbols()
- => ImmutableArray.Empty;
-
- internal override IEnumerable GetSecurityInformation()
- => Array.Empty();
+ _modifiers,
+ _sourceName,
+ ((ParameterSyntax)syntax).Identifier.GetLocation(),
+ syntax,
+ diagnostics);
+ }
- internal override bool IsMetadataNewSlot(bool ignoreInterfaceImplementationChanges = false) => false;
+ protected override SourcePropertyAccessorSymbol CreateExpressionBodiedAccessor(
+ ArrowExpressionClauseSyntax syntax,
+ PropertySymbol? explicitlyImplementedPropertyOpt,
+ string aliasQualifierOpt,
+ bool isExplicitInterfaceImplementation,
+ DiagnosticBag diagnostics)
+ {
+ // There should be no expression-bodied synthesized record properties
+ throw ExceptionUtilities.Unreachable;
+ }
- internal override bool IsMetadataVirtual(bool ignoreInterfaceImplementationChanges = false) => false;
+ protected override ImmutableArray ComputeParameters(Binder? binder, CSharpSyntaxNode syntax, DiagnosticBag diagnostics)
+ {
+ return ImmutableArray.Empty;
+ }
- internal override bool SynthesizesLoweredBoundBody => true;
+ protected override TypeWithAnnotations ComputeType(Binder? binder, SyntaxNode syntax, DiagnosticBag diagnostics)
+ {
+ return BackingParameter.TypeWithAnnotations;
+ }
- internal override void GenerateMethodBody(TypeCompilationState compilationState, DiagnosticBag diagnostics)
- {
- // Method body:
- //
- // {
- // this.<>backingField = value;
- // }
+ protected override bool HasPointerTypeSyntactically
+ // Since we already bound the type, don't bother looking at syntax
+ => TypeWithAnnotations.DefaultType.IsPointerOrFunctionPointer();
- var F = new SyntheticBoundNodeFactory(this, this.GetNonNullSyntaxNode(), compilationState, diagnostics);
+ protected override ExplicitInterfaceSpecifierSyntax? GetExplicitInterfaceSpecifier(SyntaxNode syntax)
+ => null;
- F.CurrentFunction = this;
- F.CloseMethod(F.Block(
- F.Assignment(F.Field(F.This(), _property.BackingField), F.Parameter(Parameters[0])),
- F.Return()));
- }
- }
+ protected override BaseParameterListSyntax? GetParameterListSyntax(CSharpSyntaxNode syntax)
+ => null;
}
}
diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedAccessorValueParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedAccessorValueParameterSymbol.cs
index ad685f2096d21c7115569fd93126b278da79db55..e410ef762d6ef27f486e72c2c15bf088a28e34f9 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedAccessorValueParameterSymbol.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedAccessorValueParameterSymbol.cs
@@ -32,7 +32,7 @@ internal override FlowAnalysisAnnotations FlowAnalysisAnnotations
get
{
var result = FlowAnalysisAnnotations.None;
- if (ContainingSymbol is SourcePropertyAccessorSymbol propertyAccessor && propertyAccessor.AssociatedSymbol is SourcePropertySymbol property)
+ if (ContainingSymbol is SourcePropertyAccessorSymbol propertyAccessor && propertyAccessor.AssociatedSymbol is SourcePropertySymbolBase property)
{
if (property.HasDisallowNull)
{
@@ -78,7 +78,7 @@ internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, r
{
base.AddSynthesizedAttributes(moduleBuilder, ref attributes);
- if (ContainingSymbol is SourcePropertyAccessorSymbol propertyAccessor && propertyAccessor.AssociatedSymbol is SourcePropertySymbol property)
+ if (ContainingSymbol is SourcePropertyAccessorSymbol propertyAccessor && propertyAccessor.AssociatedSymbol is SourcePropertySymbolBase property)
{
var annotations = FlowAnalysisAnnotations;
if ((annotations & FlowAnalysisAnnotations.DisallowNull) != 0)
diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedBackingFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedBackingFieldSymbol.cs
index 9fb78b198a4ed840e6297da8ee42682137b87ab5..40e379ec1dd2c87baeb93bc464322ace97d2f424 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedBackingFieldSymbol.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedBackingFieldSymbol.cs
@@ -16,13 +16,13 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols
///
internal sealed class SynthesizedBackingFieldSymbol : FieldSymbolWithAttributesAndModifiers
{
- private readonly SourceOrRecordPropertySymbol _property;
+ private readonly SourcePropertySymbolBase _property;
private readonly string _name;
internal bool HasInitializer { get; }
protected override DeclarationModifiers Modifiers { get; }
public SynthesizedBackingFieldSymbol(
- SourceOrRecordPropertySymbol property,
+ SourcePropertySymbolBase property,
string name,
bool isReadOnly,
bool isStatic,
diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs
index 2627940b0f6d1e1838403698bb4439dd352dcb64..beb318ec8f8482d8cc902d968ddc612f8944af79 100644
--- a/src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs
+++ b/src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs
@@ -10232,5 +10232,22 @@ public static void Main()
303
");
}
+
+ [Fact]
+ public void SynthesizedRecordPointerProperty()
+ {
+ var src = @"
+record R(int P1, int* P2, delegate* P3);";
+
+ var comp = CreateCompilation(src);
+ var p = comp.GlobalNamespace.GetTypeMember("R").GetMember("P1");
+ Assert.False(p.HasPointerType);
+
+ p = comp.GlobalNamespace.GetTypeMember("R").GetMember("P2");
+ Assert.True(p.HasPointerType);
+
+ p = comp.GlobalNamespace.GetTypeMember("R").GetMember("P3");
+ Assert.True(p.HasPointerType);
+ }
}
}
diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/Source/RecordTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/Source/RecordTests.cs
index d0a4724aab1f91a4d14db9401977a111ec047b48..ee06c00cb4cd6e9738d4b3bdbbcf3d749a820a62 100644
--- a/src/Compilers/CSharp/Test/Symbol/Symbols/Source/RecordTests.cs
+++ b/src/Compilers/CSharp/Test/Symbol/Symbols/Source/RecordTests.cs
@@ -146,12 +146,13 @@ public void GeneratedProperties()
comp.VerifyDiagnostics();
var c = comp.GlobalNamespace.GetTypeMember("C");
- var x = (SourceOrRecordPropertySymbol)c.GetProperty("x");
+ var x = (SourcePropertySymbolBase)c.GetProperty("x");
Assert.NotNull(x.GetMethod);
Assert.Equal(MethodKind.PropertyGet, x.GetMethod.MethodKind);
Assert.Equal(SpecialType.System_Int32, x.Type.SpecialType);
Assert.False(x.IsReadOnly);
Assert.False(x.IsWriteOnly);
+ Assert.False(x.IsImplicitlyDeclared);
Assert.Equal(Accessibility.Public, x.DeclaredAccessibility);
Assert.False(x.IsVirtual);
Assert.False(x.IsStatic);
@@ -162,26 +163,30 @@ public void GeneratedProperties()
Assert.Equal(x, backing.AssociatedSymbol);
Assert.Equal(c, backing.ContainingSymbol);
Assert.Equal(c, backing.ContainingType);
+ Assert.True(backing.IsImplicitlyDeclared);
var getAccessor = x.GetMethod;
Assert.Equal(x, getAccessor.AssociatedSymbol);
+ Assert.True(getAccessor.IsImplicitlyDeclared);
Assert.Equal(c, getAccessor.ContainingSymbol);
Assert.Equal(c, getAccessor.ContainingType);
Assert.Equal(Accessibility.Public, getAccessor.DeclaredAccessibility);
var setAccessor = x.SetMethod;
Assert.Equal(x, setAccessor.AssociatedSymbol);
+ Assert.True(setAccessor.IsImplicitlyDeclared);
Assert.Equal(c, setAccessor.ContainingSymbol);
Assert.Equal(c, setAccessor.ContainingType);
Assert.Equal(Accessibility.Public, setAccessor.DeclaredAccessibility);
Assert.True(setAccessor.IsInitOnly);
- var y = (SourceOrRecordPropertySymbol)c.GetProperty("y");
+ var y = (SourcePropertySymbolBase)c.GetProperty("y");
Assert.NotNull(y.GetMethod);
Assert.Equal(MethodKind.PropertyGet, y.GetMethod.MethodKind);
Assert.Equal(SpecialType.System_Int32, y.Type.SpecialType);
Assert.False(y.IsReadOnly);
Assert.False(y.IsWriteOnly);
+ Assert.False(y.IsImplicitlyDeclared);
Assert.Equal(Accessibility.Public, y.DeclaredAccessibility);
Assert.False(x.IsVirtual);
Assert.False(x.IsStatic);
@@ -192,14 +197,17 @@ public void GeneratedProperties()
Assert.Equal(y, backing.AssociatedSymbol);
Assert.Equal(c, backing.ContainingSymbol);
Assert.Equal(c, backing.ContainingType);
+ Assert.True(backing.IsImplicitlyDeclared);
getAccessor = y.GetMethod;
Assert.Equal(y, getAccessor.AssociatedSymbol);
+ Assert.True(getAccessor.IsImplicitlyDeclared);
Assert.Equal(c, getAccessor.ContainingSymbol);
Assert.Equal(c, getAccessor.ContainingType);
setAccessor = y.SetMethod;
Assert.Equal(y, setAccessor.AssociatedSymbol);
+ Assert.True(setAccessor.IsImplicitlyDeclared);
Assert.Equal(c, setAccessor.ContainingSymbol);
Assert.Equal(c, setAccessor.ContainingType);
Assert.Equal(Accessibility.Public, setAccessor.DeclaredAccessibility);