| File: Actions\GrammarActions.Types.Headers.cs | Web Access |
| Project: ILAssembler.csproj (ILAssembler) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Immutable; using System.Diagnostics; using System.Reflection; using Antlr4.Runtime; namespace ILAssembler; internal sealed partial class GrammarActions { internal void BeginNamespace( CILParser.NameSpaceHeadContext context, string? namespaceName, int initialSyntaxErrorCount) { if (!EnterDeclarationScope( context.Parent, !HasSyntaxErrorsSince(initialSyntaxErrorCount) && context.exception is null && namespaceName is not null)) { return; } Debug.Assert(namespaceName is not null); string? outerNamespace = _currentNamespace.PeekOrDefault(); _currentNamespace.Push( string.IsNullOrEmpty(outerNamespace) ? namespaceName : $"{outerNamespace}.{namespaceName}"); _namespaceOwners.Push(context.Parent); } internal void BeginType(CILParser.ClassHeadContext context, ClassHeaderValue value) { if (!EnterDeclarationScope(context.Parent, value.IsValid)) { return; } EntityRegistry.TypeDefinitionEntity typeDefinition = MaterializeClassHeader(context, value); _currentTypeDefinition.Push(typeDefinition); _typeOwners.Push(context.Parent); } private EntityRegistry.TypeDefinitionEntity MaterializeClassHeader( CILParser.ClassHeadContext context, ClassHeaderValue header) { (string typeNamespace, string typeName) = GetTypeDefinitionName(header.FullName); bool isNewType = false; EntityRegistry.TypeDefinitionEntity typeDefinition = _entityRegistry.GetOrCreateTypeDefinition( _currentTypeDefinition.PeekOrDefault(), typeNamespace, typeName, newTypeDefinition => { isNewType = true; InitializeTypeDefinition(context, header, newTypeDefinition); }); if (!isNewType) { MergeTypeDefinition(context, header, typeDefinition); } return typeDefinition; } private (string Namespace, string Name) GetTypeDefinitionName(string fullName) { int lastDot = fullName.LastIndexOf('.'); if (lastDot == 0) { lastDot = -1; } string typeNamespace; if (_currentTypeDefinition.Count != 0) { typeNamespace = lastDot == -1 ? string.Empty : fullName.Substring(0, lastDot); } else if (lastDot == -1) { typeNamespace = _currentNamespace.PeekOrDefault() ?? string.Empty; } else { string containingNamespace = fullName.Substring(0, lastDot); string? currentNamespace = _currentNamespace.PeekOrDefault(); typeNamespace = string.IsNullOrEmpty(currentNamespace) ? containingNamespace : $"{currentNamespace}.{containingNamespace}"; } return ( typeNamespace, lastDot == -1 ? fullName : fullName.Substring(lastDot + 1)); } private void InitializeTypeDefinition( CILParser.ClassHeadContext context, ClassHeaderValue header, EntityRegistry.TypeDefinitionEntity typeDefinition) { EntityRegistry.WellKnownBaseType? fallbackBase = _options.NoAutoInherit ? null : EntityRegistry.WellKnownBaseType.System_Object; bool requireSealed = false; TypeAttributes attributes = 0; foreach (ClassAttributeValue classAttribute in header.Attributes) { if (classAttribute.FallbackBase is not null) { fallbackBase = classAttribute.FallbackBase; } CILParser.AttributeValue<TypeAttributes> attribute = classAttribute.Attribute; if (!attribute.ShouldAppend) { attributes = attribute.Value; requireSealed = classAttribute.RequireSealed; continue; } requireSealed |= classAttribute.RequireSealed; if (attribute.Value == TypeAttributes.RTSpecialName) { continue; } attributes = ApplyAttribute(attributes, attribute); } typeDefinition.Attributes = attributes; ReportGenericParameterEncodingErrors(header.GenericParameters, context); RegisterGenericParameterNames( typeDefinition, typeDefinition.GenericParameters, header.GenericParameters); _currentTypeDefinition.Push(typeDefinition); try { MaterializeGenericParameterConstraints( typeDefinition.GenericParameters, typeDefinition.GenericParameterConstraints, header.GenericParameters); if (header.BaseType is not null) { typeDefinition.BaseType = ResolveTypeSpecification(header.BaseType); } AddInterfaceImplementations(typeDefinition, header.Interfaces); } finally { _currentTypeDefinition.Pop(); } if (typeDefinition.Attributes.HasFlag(TypeAttributes.Interface)) { fallbackBase = null; } typeDefinition.BaseType ??= _entityRegistry.ResolveImplicitBaseType(fallbackBase); if (!typeDefinition.Attributes.HasFlag(TypeAttributes.Sealed) && (requireSealed || _entityRegistry.SystemValueTypeType.Equals(typeDefinition.BaseType))) { IToken location = header.NameToken ?? context.Start; _diagnostics.Add( new Diagnostic( DiagnosticIds.UnsealedValueType, DiagnosticSeverity.Error, string.Format(DiagnosticMessageTemplates.UnsealedValueType, typeDefinition.Name), Location.From(location, _documents))); typeDefinition.Attributes |= TypeAttributes.Sealed; } } private void MergeTypeDefinition( CILParser.ClassHeadContext context, ClassHeaderValue header, EntityRegistry.TypeDefinitionEntity typeDefinition) { TypeAttributes attributes = typeDefinition.Attributes; foreach (ClassAttributeValue classAttribute in header.Attributes) { CILParser.AttributeValue<TypeAttributes> attribute = classAttribute.Attribute; if (!attribute.ShouldAppend) { attributes = attribute.Value; } else if ((attribute.Value & TypeAttributes.Interface) != 0) { attributes |= TypeAttributes.Interface | TypeAttributes.Abstract; } else { attributes |= attribute.Value; } } typeDefinition.Attributes = attributes; bool materializeConstraints = typeDefinition.GenericParameters.Count == 0; if (materializeConstraints) { ReportGenericParameterEncodingErrors(header.GenericParameters, context); RegisterGenericParameterNames( typeDefinition, typeDefinition.GenericParameters, header.GenericParameters); } _currentTypeDefinition.Push(typeDefinition); try { if (materializeConstraints) { MaterializeGenericParameterConstraints( typeDefinition.GenericParameters, typeDefinition.GenericParameterConstraints, header.GenericParameters); } if (header.BaseType is not null) { EntityRegistry.TypeEntity baseType = ResolveTypeSpecification(header.BaseType); typeDefinition.BaseType ??= baseType; } AddInterfaceImplementations(typeDefinition, header.Interfaces); } finally { _currentTypeDefinition.Pop(); } } private void AddInterfaceImplementations( EntityRegistry.TypeDefinitionEntity typeDefinition, ImmutableArray<TypeSpecificationValue> interfaces) { foreach (TypeSpecificationValue interfaceType in interfaces) { typeDefinition.InterfaceImplementations.Add( EntityRegistry.CreateUnrecordedInterfaceImplementation( typeDefinition, ResolveTypeSpecification(interfaceType))); } } }