/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbolBase.cs
273 строки
12 KB
AlekseyTs
Initial support for union declarations (#82500)
25 фев 2026, 22:37
Не верифицирован
25 фев 2026, 22:37
49a4215
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #nullable disable using System.Collections.Immutable; using System.Diagnostics; using Microsoft.CodeAnalysis.Collections; using Microsoft.CodeAnalysis.CSharp.Emit; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.Symbols { internal abstract class SourceConstructorSymbolBase : SourceMemberMethodSymbol { protected ImmutableArray<ParameterSymbol> _lazyParameters; private TypeWithAnnotations _lazyReturnType; protected SourceConstructorSymbolBase( SourceMemberContainerTypeSymbol containingType, Location location, CSharpSyntaxNode syntax, bool isIterator, (DeclarationModifiers declarationModifiers, Flags flags) modifiersAndFlags) : base(containingType, syntax.GetReference(), location, isIterator, modifiersAndFlags) { Debug.Assert(syntax.Kind() is SyntaxKind.ConstructorDeclaration or SyntaxKind.RecordDeclaration or SyntaxKind.RecordStructDeclaration or SyntaxKind.ClassDeclaration or SyntaxKind.StructDeclaration or SyntaxKind.UnionDeclaration); } protected sealed override void MethodChecks(BindingDiagnosticBag diagnostics) { var syntax = (CSharpSyntaxNode)syntaxReferenceOpt.GetSyntax(); var binderFactory = this.DeclaringCompilation.GetBinderFactory(syntax.SyntaxTree); ParameterListSyntax parameterList = GetParameterList(); // NOTE: if we asked for the binder for the body of the constructor, we'd risk a stack overflow because // we might still be constructing the member list of the containing type. However, getting the binder // for the parameters should be safe. var bodyBinder = binderFactory.GetBinder(parameterList, syntax, this).WithContainingMemberOrLambda(this); // Constraint checking for parameter and return types must be delayed until // the method has been added to the containing type member list since // evaluating the constraints may depend on accessing this method from // the container (comparing this method to others to find overrides for // instance). Constraints are checked in AfterAddingTypeMembersChecks. var signatureBinder = bodyBinder.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.SuppressConstraintChecks, this); _lazyParameters = ParameterHelpers.MakeParameters( signatureBinder, this, parameterList, out _, allowRefOrOut: AllowRefOrOut, allowThis: false, addRefReadOnlyModifier: false, diagnostics: diagnostics).Cast<SourceParameterSymbol, ParameterSymbol>(); _lazyReturnType = TypeWithAnnotations.Create(bodyBinder.GetSpecialType(SpecialType.System_Void, diagnostics, syntax)); var location = this.GetFirstLocation(); // Don't report ERR_StaticConstParam if the ctor symbol name doesn't match the containing type name. // This avoids extra unnecessary errors. // There will already be a diagnostic saying Method must have a return type. if (MethodKind == MethodKind.StaticConstructor && (_lazyParameters.Length != 0) && ContainingType.Name == ((ConstructorDeclarationSyntax)this.SyntaxNode).Identifier.ValueText) { diagnostics.Add(ErrorCode.ERR_StaticConstParam, location, this); } this.CheckEffectiveAccessibility(_lazyReturnType, _lazyParameters, diagnostics); this.CheckFileTypeUsage(_lazyReturnType, _lazyParameters, diagnostics); if (this.IsVararg && (IsGenericMethod || ContainingType.IsGenericType || _lazyParameters.Length > 0 && _lazyParameters[_lazyParameters.Length - 1].IsParams)) { diagnostics.Add(ErrorCode.ERR_BadVarargs, location); } } #nullable enable protected abstract ParameterListSyntax GetParameterList(); protected abstract bool AllowRefOrOut { get; } #nullable disable internal sealed override void AfterAddingTypeMembersChecks(ConversionsBase conversions, BindingDiagnosticBag diagnostics) { base.AfterAddingTypeMembersChecks(conversions, diagnostics); var compilation = DeclaringCompilation; ParameterHelpers.EnsureRefKindAttributesExist(compilation, Parameters, diagnostics, modifyCompilation: true); ParameterHelpers.EnsureParamCollectionAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true); ParameterHelpers.EnsureNativeIntegerAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true); ParameterHelpers.EnsureScopedRefAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true); ParameterHelpers.EnsureNullableAttributeExists(compilation, this, Parameters, diagnostics, modifyCompilation: true); foreach (var parameter in this.Parameters) { parameter.Type.CheckAllConstraints(compilation, conversions, parameter.GetFirstLocation(), diagnostics); } PartialConstructorChecks(diagnostics); } protected virtual void PartialConstructorChecks(BindingDiagnosticBag diagnostics) { Debug.Assert(!IsPartial); } public sealed override bool IsImplicitlyDeclared { get { return base.IsImplicitlyDeclared; } } internal sealed override int ParameterCount { get { if (!_lazyParameters.IsDefault) { return _lazyParameters.Length; } return GetParameterList().ParameterCount; } } public sealed override ImmutableArray<ParameterSymbol> Parameters { get { LazyMethodChecks(); return _lazyParameters; } } public sealed override ImmutableArray<TypeParameterSymbol> TypeParameters { get { return ImmutableArray<TypeParameterSymbol>.Empty; } } public sealed override ImmutableArray<ImmutableArray<TypeWithAnnotations>> GetTypeParameterConstraintTypes() => ImmutableArray<ImmutableArray<TypeWithAnnotations>>.Empty; public sealed override ImmutableArray<TypeParameterConstraintKind> GetTypeParameterConstraintKinds() => ImmutableArray<TypeParameterConstraintKind>.Empty; public sealed override TypeWithAnnotations ReturnTypeWithAnnotations { get { LazyMethodChecks(); return _lazyReturnType; } } public sealed override ImmutableArray<CustomModifier> RefCustomModifiers => []; public sealed override string Name { get { return this.IsStatic ? WellKnownMemberNames.StaticConstructorName : WellKnownMemberNames.InstanceConstructorName; } } internal sealed override OneOrMany<SyntaxList<AttributeListSyntax>> GetReturnTypeAttributeDeclarations() { // constructors can't have return type attributes return OneOrMany.Create(default(SyntaxList<AttributeListSyntax>)); } internal sealed override bool GenerateDebugInfo { get { return true; } } internal sealed override int CalculateLocalSyntaxOffset(int position, SyntaxTree tree) { Debug.Assert(position >= 0 && tree != null); TextSpan span; // local/lambda/closure defined within the body of the constructor: var ctorSyntax = (CSharpSyntaxNode)syntaxReferenceOpt.GetSyntax(); if (tree == ctorSyntax.SyntaxTree) { if (IsWithinExpressionOrBlockBody(position, out int offset)) { return offset; } // closure in ctor initializer lifting its parameter(s) spans the constructor declaration: if (position == ctorSyntax.SpanStart) { // Use a constant that is distinct from any other syntax offset. // -1 works since a field initializer and a constructor declaration header can't squeeze into a single character. return -1; } } // lambdas in ctor initializer: int ctorInitializerLength; var ctorInitializer = GetInitializer(); if (tree == ctorInitializer?.SyntaxTree) { span = ctorInitializer.Span; ctorInitializerLength = span.Length; if (span.Contains(position)) { return -ctorInitializerLength + (position - span.Start); } } else { ctorInitializerLength = 0; } // lambdas in field/property initializers: int syntaxOffset; var containingType = (SourceNamedTypeSymbol)this.ContainingType; if (containingType.TryCalculateSyntaxOffsetOfPositionInInitializer(position, tree, this.IsStatic, ctorInitializerLength, out syntaxOffset)) { return syntaxOffset; } // we haven't found the constructor part that declares the variable: throw ExceptionUtilities.Unreachable(); } internal abstract override bool IsNullableAnalysisEnabled(); protected abstract CSharpSyntaxNode GetInitializer(); protected abstract bool IsWithinExpressionOrBlockBody(int position, out int offset); #nullable enable protected sealed override bool HasSetsRequiredMembersImpl => GetEarlyDecodedWellKnownAttributeData()?.HasSetsRequiredMembersAttribute == true; internal override (CSharpAttributeData?, BoundAttribute?) EarlyDecodeWellKnownAttribute(ref EarlyDecodeWellKnownAttributeArguments<EarlyWellKnownAttributeBinder, NamedTypeSymbol, AttributeSyntax, AttributeLocation> arguments) { if (arguments.SymbolPart == AttributeLocation.None) { if (CSharpAttributeData.IsTargetEarlyAttribute(arguments.AttributeType, arguments.AttributeSyntax, AttributeDescription.SetsRequiredMembersAttribute)) { var earlyData = arguments.GetOrCreateData<MethodEarlyWellKnownAttributeData>(); earlyData.HasSetsRequiredMembersAttribute = true; if (ContainingType.IsWellKnownSetsRequiredMembersAttribute()) { // Avoid a binding cycle for this scenario. return (null, null); } var (attributeData, boundAttribute) = arguments.Binder.GetAttribute(arguments.AttributeSyntax, arguments.AttributeType, beforeAttributePartBound: null, afterAttributePartBound: null, out bool hasAnyDiagnostics); if (!hasAnyDiagnostics) { return (attributeData, boundAttribute); } else { return (null, null); } } } return base.EarlyDecodeWellKnownAttribute(ref arguments); } } }