| File: PEWriter\MetadataVisitor.cs | Web Access |
| Project: src\roslyn\src\Compilers\Core\Portable\Microsoft.CodeAnalysis.csproj (Microsoft.CodeAnalysis) |
// 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.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeGen; using Microsoft.CodeAnalysis.Emit; using Microsoft.CodeAnalysis.Emit.EditAndContinue; namespace Microsoft.Cci { /// <summary> /// A visitor base class that traverses the object model in depth first, left to right order. /// </summary> internal abstract class MetadataVisitor { public readonly EmitContext Context; public MetadataVisitor(EmitContext context) { this.Context = context; } public virtual void Visit(IArrayTypeReference arrayTypeReference) { this.Visit(arrayTypeReference.GetElementType(Context)); } public void Visit(IEnumerable<IAssemblyReference> assemblyReferences) { foreach (IAssemblyReference assemblyReference in assemblyReferences) { this.Visit((IUnitReference)assemblyReference); } } public virtual void Visit(IAssemblyReference assemblyReference) { } public void Visit(IEnumerable<ICustomAttribute> customAttributes) { foreach (ICustomAttribute customAttribute in customAttributes) { this.Visit(customAttribute); } } public virtual void Visit(ICustomAttribute customAttribute) { IMethodReference constructor = customAttribute.Constructor(Context, reportDiagnostics: false); if (constructor is null) { return; } this.Visit(customAttribute.GetArguments(Context)); this.Visit(constructor); this.Visit(customAttribute.GetNamedArguments(Context)); } public void Visit(ImmutableArray<ICustomModifier> customModifiers) { foreach (ICustomModifier customModifier in customModifiers) { this.Visit(customModifier); } } public virtual void Visit(ICustomModifier customModifier) { this.Visit(customModifier.GetModifier(Context)); } public void Visit(IEnumerable<IEventDefinition> events) { foreach (IEventDefinition eventDef in events) { this.Visit((ITypeDefinitionMember)eventDef); } } public virtual void Visit(IEventDefinition eventDefinition) { this.Visit(eventDefinition.GetAccessors(Context)); this.Visit(eventDefinition.GetType(Context)); } public void Visit(IEnumerable<IFieldDefinition> fields) { foreach (IFieldDefinition field in fields) { this.Visit((ITypeDefinitionMember)field); } } public virtual void Visit(IFieldDefinition fieldDefinition) { var constant = fieldDefinition.GetCompileTimeValue(Context); var marshalling = fieldDefinition.MarshallingInformation; Debug.Assert((constant != null) == fieldDefinition.IsCompileTimeConstant); Debug.Assert((marshalling != null || !fieldDefinition.MarshallingDescriptor.IsDefaultOrEmpty) == fieldDefinition.IsMarshalledExplicitly); if (constant != null) { this.Visit((IMetadataExpression)constant); } if (marshalling != null) { // Note, we are not visiting MarshallingDescriptor. It is used only for // NoPia embedded/local types and VB Dev11 simply copies the bits without // cracking them. this.Visit(marshalling); } this.Visit(fieldDefinition.RefCustomModifiers); this.Visit(fieldDefinition.GetType(Context)); } public virtual void Visit(IFieldReference fieldReference) { this.Visit((ITypeMemberReference)fieldReference); } public void Visit(IEnumerable<IFileReference> fileReferences) { foreach (IFileReference fileReference in fileReferences) { this.Visit(fileReference); } } public virtual void Visit(IFileReference fileReference) { } public virtual void Visit(IGenericMethodInstanceReference genericMethodInstanceReference) { } public void Visit(IEnumerable<IGenericMethodParameter> genericParameters) { foreach (IGenericMethodParameter genericParameter in genericParameters) { this.Visit((IGenericParameter)genericParameter); } } public virtual void Visit(IGenericMethodParameter genericMethodParameter) { } public virtual void Visit(IGenericMethodParameterReference genericMethodParameterReference) { } public virtual void Visit(IGenericParameter genericParameter) { this.Visit(genericParameter.GetAttributes(Context)); this.Visit(genericParameter.GetConstraints(Context)); genericParameter.Dispatch(this); } public abstract void Visit(IGenericTypeInstanceReference genericTypeInstanceReference); public void Visit(IEnumerable<IGenericParameter> genericParameters) { foreach (IGenericTypeParameter genericParameter in genericParameters) { this.Visit((IGenericParameter)genericParameter); } } public virtual void Visit(IGenericTypeParameter genericTypeParameter) { } public virtual void Visit(IGenericTypeParameterReference genericTypeParameterReference) { } public virtual void Visit(IGlobalFieldDefinition globalFieldDefinition) { this.Visit((IFieldDefinition)globalFieldDefinition); } public virtual void Visit(IGlobalMethodDefinition globalMethodDefinition) { this.Visit((IMethodDefinition)globalMethodDefinition); } public void Visit(ImmutableArray<ILocalDefinition> localDefinitions) { foreach (ILocalDefinition localDefinition in localDefinitions) { this.Visit(localDefinition); } } public virtual void Visit(ILocalDefinition localDefinition) { this.Visit(localDefinition.CustomModifiers); this.Visit(localDefinition.Type); } public virtual void Visit(IMarshallingInformation marshallingInformation) { throw ExceptionUtilities.Unreachable(); } public virtual void Visit(MetadataConstant constant) { } public virtual void Visit(MetadataCreateArray createArray) { this.Visit(createArray.ElementType); this.Visit(createArray.Elements); } public void Visit(IEnumerable<IMetadataExpression> expressions) { foreach (IMetadataExpression expression in expressions) { this.Visit(expression); } } public virtual void Visit(IMetadataExpression expression) { this.Visit(expression.Type); expression.Dispatch(this); } public void Visit(IEnumerable<IMetadataNamedArgument> namedArguments) { foreach (IMetadataNamedArgument namedArgument in namedArguments) { this.Visit((IMetadataExpression)namedArgument); } } public virtual void Visit(IMetadataNamedArgument namedArgument) { this.Visit(namedArgument.ArgumentValue); } public virtual void Visit(MetadataTypeOf typeOf) { if (typeOf.TypeToGet != null) { this.Visit(typeOf.TypeToGet); } } public virtual void Visit(IMethodBody methodBody) { foreach (var scope in methodBody.LocalScopes) { this.Visit(scope.Constants); } this.Visit(methodBody.LocalVariables); //this.Visit(methodBody.Operations); //in Roslyn we don't break out each instruction as it's own operation. this.Visit(methodBody.ExceptionRegions); } public void Visit(IEnumerable<IMethodDefinition> methods) { foreach (IMethodDefinition method in methods) { this.Visit((ITypeDefinitionMember)method); } } public virtual void Visit(IMethodDefinition method) { // Only visit signature components for EnC-deleted methods (generic parameters and attributes are not emitted). bool signatureOnly = method.IsEncDeleted; // Deletes of PE methods should not be visited since their signature is reused from the deleted PE symbol. if (signatureOnly && method is DeletedPEMethodDefinition { MetadataSignatureHandle.IsNil: false }) { return; } if (!signatureOnly) { this.Visit(method.GetReturnValueAttributes(Context)); } this.Visit(method.RefCustomModifiers); this.Visit(method.ReturnValueCustomModifiers); if (!signatureOnly && method.HasDeclarativeSecurity) { this.Visit(method.SecurityAttributes); } if (!signatureOnly && method.GenericParameterCount > 0) { this.Visit(method.GenericParameters); } this.Visit(method.GetType(Context)); this.Visit(method.Parameters); if (!signatureOnly && method.IsPlatformInvoke) { this.Visit(method.PlatformInvokeData); } } public void Visit(IEnumerable<MethodImplementation> methodImplementations) { foreach (MethodImplementation methodImplementation in methodImplementations) { this.Visit(methodImplementation); } } public virtual void Visit(MethodImplementation methodImplementation) { this.Visit(methodImplementation.ImplementedMethod); this.Visit(methodImplementation.ImplementingMethod); } public void Visit(IEnumerable<IMethodReference> methodReferences) { foreach (IMethodReference methodReference in methodReferences) { this.Visit(methodReference); } } public virtual void Visit(IMethodReference methodReference) { IGenericMethodInstanceReference? genericMethodInstanceReference = methodReference.AsGenericMethodInstanceReference; if (genericMethodInstanceReference != null) { this.Visit(genericMethodInstanceReference); } else { this.Visit((ITypeMemberReference)methodReference); } } public virtual void Visit(IModifiedTypeReference modifiedTypeReference) { this.Visit(modifiedTypeReference.CustomModifiers); this.Visit(modifiedTypeReference.UnmodifiedType); } public abstract void Visit(CommonPEModuleBuilder module); public void Visit(IEnumerable<IModuleReference> moduleReferences) { foreach (IModuleReference moduleReference in moduleReferences) { this.Visit((IUnitReference)moduleReference); } } public virtual void Visit(IModuleReference moduleReference) { } public void Visit(IEnumerable<INamedTypeDefinition> types) { foreach (INamedTypeDefinition type in types) { this.Visit(type); } } public virtual void Visit(INamespaceTypeDefinition namespaceTypeDefinition) { } public virtual void Visit(INamespaceTypeReference namespaceTypeReference) { } public void VisitNestedTypes(IEnumerable<INamedTypeDefinition> nestedTypes) { foreach (ITypeDefinitionMember nestedType in nestedTypes) { this.Visit(nestedType); } } public virtual void Visit(INestedTypeDefinition nestedTypeDefinition) { } public virtual void Visit(INestedTypeReference nestedTypeReference) { this.Visit(nestedTypeReference.GetContainingType(Context)); } public void Visit(ImmutableArray<ExceptionHandlerRegion> exceptionRegions) { foreach (ExceptionHandlerRegion region in exceptionRegions) { this.Visit(region); } } public virtual void Visit(ExceptionHandlerRegion exceptionRegion) { var exceptionType = exceptionRegion.ExceptionType; if (exceptionType != null) { this.Visit(exceptionType); } } public void Visit(ImmutableArray<IParameterDefinition> parameters) { foreach (IParameterDefinition parameter in parameters) { this.Visit(parameter); } } public virtual void Visit(IParameterDefinition parameterDefinition) { var marshalling = parameterDefinition.MarshallingInformation; Debug.Assert((marshalling != null || !parameterDefinition.MarshallingDescriptor.IsDefaultOrEmpty) == parameterDefinition.IsMarshalledExplicitly); if (!parameterDefinition.IsEncDeleted) { this.Visit(parameterDefinition.GetAttributes(Context)); } this.Visit(parameterDefinition.RefCustomModifiers); this.Visit(parameterDefinition.CustomModifiers); MetadataConstant? defaultValue = parameterDefinition.GetDefaultValue(Context); if (defaultValue != null) { this.Visit((IMetadataExpression)defaultValue); } if (marshalling != null) { // Note, we are not visiting MarshallingDescriptor. It is used only for // NoPia embedded/local types and VB Dev11 simply copies the bits without // cracking them. this.Visit(marshalling); } this.Visit(parameterDefinition.GetType(Context)); } public void Visit(ImmutableArray<IParameterTypeInformation> parameterTypeInformations) { foreach (IParameterTypeInformation parameterTypeInformation in parameterTypeInformations) { this.Visit(parameterTypeInformation); } } public virtual void Visit(IParameterTypeInformation parameterTypeInformation) { this.Visit(parameterTypeInformation.RefCustomModifiers); this.Visit(parameterTypeInformation.CustomModifiers); this.Visit(parameterTypeInformation.GetType(Context)); } public virtual void Visit(IPlatformInvokeInformation platformInvokeInformation) { } public virtual void Visit(IPointerTypeReference pointerTypeReference) { this.Visit(pointerTypeReference.GetTargetType(Context)); } public virtual void Visit(IFunctionPointerTypeReference functionPointerTypeReference) { this.Visit(functionPointerTypeReference.Signature.RefCustomModifiers); this.Visit(functionPointerTypeReference.Signature.ReturnValueCustomModifiers); this.Visit(functionPointerTypeReference.Signature.GetType(Context)); foreach (var param in functionPointerTypeReference.Signature.GetParameters(Context)) { this.Visit(param); } } public void Visit(IEnumerable<IPropertyDefinition> properties) { foreach (IPropertyDefinition property in properties) { this.Visit((ITypeDefinitionMember)property); } } public virtual void Visit(IPropertyDefinition propertyDefinition) { this.Visit(propertyDefinition.GetAccessors(Context)); this.Visit(propertyDefinition.Parameters); } public void Visit(IEnumerable<ManagedResource> resources) { foreach (var resource in resources) { this.Visit(resource); } } public virtual void Visit(ManagedResource resource) { } public virtual void Visit(SecurityAttribute securityAttribute) { this.Visit(securityAttribute.Attribute); } public void Visit(IEnumerable<SecurityAttribute> securityAttributes) { foreach (SecurityAttribute securityAttribute in securityAttributes) { this.Visit(securityAttribute); } } public void Visit(IEnumerable<ITypeDefinitionMember> typeMembers) { foreach (ITypeDefinitionMember typeMember in typeMembers) { this.Visit(typeMember); } } public void Visit(IEnumerable<ITypeDefinition> types) { foreach (ITypeDefinition type in types) { this.Visit(type); } } public abstract void Visit(ITypeDefinition typeDefinition); public virtual void Visit(ITypeDefinitionMember typeMember) { ITypeDefinition? nestedType = typeMember as INestedTypeDefinition; if (nestedType != null) { this.Visit(nestedType); } else { this.Visit(typeMember.GetAttributes(Context)); typeMember.Dispatch(this); } } public virtual void Visit(ITypeMemberReference typeMemberReference) { if (typeMemberReference.AsDefinition(Context) == null) { this.Visit(typeMemberReference.GetAttributes(Context)); // In principle, references can have attributes that are distinct from the definitions they refer to. } } public void Visit(IEnumerable<ITypeReference> typeReferences) { foreach (ITypeReference typeReference in typeReferences) { this.Visit(typeReference); } } public void Visit(IEnumerable<TypeReferenceWithAttributes> typeRefsWithAttributes) { foreach (var typeRefWithAttributes in typeRefsWithAttributes) { this.Visit(typeRefWithAttributes.TypeRef); this.Visit(typeRefWithAttributes.Attributes); } } public virtual void Visit(ITypeReference typeReference) { this.DispatchAsReference(typeReference); } /// <summary> /// Use this routine, rather than ITypeReference.Dispatch, to call the appropriate derived overload of an ITypeReference. /// The former routine will call Visit(INamespaceTypeDefinition) rather than Visit(INamespaceTypeReference), etc., /// in the case where a definition is used as a reference to itself. /// </summary> /// <param name="typeReference">A reference to a type definition. Note that a type definition can serve as a reference to itself.</param> protected void DispatchAsReference(ITypeReference typeReference) { INamespaceTypeReference? namespaceTypeReference = typeReference.AsNamespaceTypeReference; if (namespaceTypeReference != null) { this.Visit(namespaceTypeReference); return; } IGenericTypeInstanceReference? genericTypeInstanceReference = typeReference.AsGenericTypeInstanceReference; if (genericTypeInstanceReference != null) { this.Visit(genericTypeInstanceReference); return; } INestedTypeReference? nestedTypeReference = typeReference.AsNestedTypeReference; if (nestedTypeReference != null) { this.Visit(nestedTypeReference); return; } IArrayTypeReference? arrayTypeReference = typeReference as IArrayTypeReference; if (arrayTypeReference != null) { this.Visit(arrayTypeReference); return; } IGenericTypeParameterReference? genericTypeParameterReference = typeReference.AsGenericTypeParameterReference; if (genericTypeParameterReference != null) { this.Visit(genericTypeParameterReference); return; } IGenericMethodParameterReference? genericMethodParameterReference = typeReference.AsGenericMethodParameterReference; if (genericMethodParameterReference != null) { this.Visit(genericMethodParameterReference); return; } IPointerTypeReference? pointerTypeReference = typeReference as IPointerTypeReference; if (pointerTypeReference != null) { this.Visit(pointerTypeReference); return; } IFunctionPointerTypeReference? functionPointerTypeReference = typeReference as IFunctionPointerTypeReference; if (functionPointerTypeReference != null) { this.Visit(functionPointerTypeReference); return; } IModifiedTypeReference? modifiedTypeReference = typeReference as IModifiedTypeReference; if (modifiedTypeReference != null) { this.Visit(modifiedTypeReference); return; } } public void Visit(IEnumerable<IUnitReference> unitReferences) { foreach (IUnitReference unitReference in unitReferences) { this.Visit(unitReference); } } public virtual void Visit(IUnitReference unitReference) { this.DispatchAsReference(unitReference); } /// <summary> /// Use this routine, rather than IUnitReference.Dispatch, to call the appropriate derived overload of an IUnitReference. /// The former routine will call Visit(IAssembly) rather than Visit(IAssemblyReference), etc. /// in the case where a definition is used as the reference to itself. /// </summary> /// <param name="unitReference">A reference to a unit. Note that a unit can serve as a reference to itself.</param> private void DispatchAsReference(IUnitReference unitReference) { IAssemblyReference? assemblyReference = unitReference as IAssemblyReference; if (assemblyReference != null) { this.Visit(assemblyReference); return; } IModuleReference? moduleReference = unitReference as IModuleReference; if (moduleReference != null) { this.Visit(moduleReference); return; } } public virtual void Visit(IWin32Resource win32Resource) { } } }