private void ProcessAssemblyDirective(IRootingServiceProvider rootProvider, XElement assemblyElement) { var assemblyNameAttribute = assemblyElement.Attribute("Name"); if (assemblyNameAttribute == null) throw new Exception(); ModuleDesc assembly = _context.ResolveAssembly(new AssemblyName(assemblyNameAttribute.Value)); rootProvider.RootModuleMetadata(assembly, "RD.XML root"); var dynamicDegreeAttribute = assemblyElement.Attribute("Dynamic"); if (dynamicDegreeAttribute != null) { if (dynamicDegreeAttribute.Value != "Required All") throw new NotSupportedException(); foreach (TypeDesc type in ((EcmaModule)assembly).GetAllTypes()) { RootingHelpers.TryRootType(rootProvider, type, "RD.XML root"); } } foreach (var element in assemblyElement.Elements()) { switch (element.Name.LocalName) { case "Type": ProcessTypeDirective(rootProvider, assembly, element); break; default: throw new NotSupportedException(); } } }
private void ProcessTypeDirective(IRootingServiceProvider rootProvider, ModuleDesc containingModule, XElement typeElement) { var typeNameAttribute = typeElement.Attribute("Name"); if (typeNameAttribute == null) throw new Exception(); string typeName = typeNameAttribute.Value; TypeDesc type = containingModule.GetTypeByCustomAttributeTypeName(typeName); var dynamicDegreeAttribute = typeElement.Attribute("Dynamic"); if (dynamicDegreeAttribute != null) { if (dynamicDegreeAttribute.Value != "Required All") throw new NotSupportedException(); RootingHelpers.RootType(rootProvider, type, "RD.XML root"); } foreach (var element in typeElement.Elements()) { switch (element.Name.LocalName) { case "Method": ProcessMethodDirective(rootProvider, containingModule, type, element); break; default: throw new NotSupportedException(); } } }
private void ProcessMethodDirective(IRootingServiceProvider rootProvider, ModuleDesc containingModule, TypeDesc containingType, XElement methodElement) { var methodNameAttribute = methodElement.Attribute("Name"); if (methodNameAttribute == null) throw new Exception(); string methodName = methodNameAttribute.Value; MethodDesc method = containingType.GetMethod(methodName, null); var instArgs = new List<TypeDesc>(); foreach (var element in methodElement.Elements()) { switch (element.Name.LocalName) { case "GenericArgument": string instArgName = element.Attribute("Name").Value; instArgs.Add(containingModule.GetTypeByCustomAttributeTypeName(instArgName)); break; default: throw new NotSupportedException(); } } if (instArgs.Count != method.Instantiation.Length) throw new Exception(); if (instArgs.Count > 0) { var methodInst = new Instantiation(instArgs.ToArray()); method = method.MakeInstantiatedMethod(methodInst); } RootingHelpers.TryRootMethod(rootProvider, method, "RD.XML root"); }
public override void GetDependenciesDueToLdToken(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) { // In order for the RuntimeMethodHandle data structure to be usable at runtime, ensure the method // is generating metadata. if ((GetMetadataCategory(method) & MetadataCategory.Description) == MetadataCategory.Description) { dependencies = dependencies ?? new DependencyList(); dependencies.Add(factory.MethodMetadata(method.GetTypicalMethodDefinition()), "LDTOKEN method"); } // Since this is typically used for LINQ expressions, let's also make sure there's runnable code // for this available, unless this is ldtoken of something we can't generate code for // (ldtoken of an uninstantiated generic method - F# makes this). if (!method.IsGenericMethodDefinition) { var deps = dependencies ?? new DependencyList(); RootingHelpers.TryRootMethod( new RootingServiceProvider( factory, (o, reason) => deps.Add((DependencyNodeCore <NodeFactory>)o, reason)), method, "LDTOKEN method"); dependencies = deps; } }
private void ProcessTypeDirective(IRootingServiceProvider rootProvider, ModuleDesc containingModule, XElement typeElement) { var typeNameAttribute = typeElement.Attribute("Name"); if (typeNameAttribute == null) { throw new Exception("The \"Name\" attribute is required on the \"Type\" Runtime Directive."); } string typeName = typeNameAttribute.Value; TypeDesc type = containingModule.GetTypeByCustomAttributeTypeName(typeName); var dynamicDegreeAttribute = typeElement.Attribute("Dynamic"); if (dynamicDegreeAttribute != null) { if (dynamicDegreeAttribute.Value != "Required All") { throw new NotSupportedException($"\"{dynamicDegreeAttribute.Value}\" is not a supported value for the \"Dynamic\" attribute of the \"Type\" Runtime Directive. Supported values are \"Required All\"."); } RootingHelpers.RootType(rootProvider, type, "RD.XML root"); } foreach (var element in typeElement.Elements()) { switch (element.Name.LocalName) { case "Method": ProcessMethodDirective(rootProvider, containingModule, type, element); break; default: throw new NotSupportedException($"\"{element.Name.LocalName}\" is not a supported Runtime Directive."); } } }
protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type) { TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, type, "Reflectable type"); // If we don't have precise field usage information, apply policy that all fields that // are eligible to have metadata get metadata. if (!_hasPreciseFieldUsageInformation) { TypeDesc typeDefinition = type.GetTypeDefinition(); foreach (FieldDesc field in typeDefinition.GetFields()) { if ((GetMetadataCategory(field) & MetadataCategory.Description) != 0) { dependencies = dependencies ?? new DependencyList(); dependencies.Add(factory.FieldMetadata(field), "Field of a reflectable type"); } } } // If anonymous type heuristic is turned on and this is an anonymous type, make sure we have // method bodies for all properties. It's common to have anonymous types used with reflection // and it's hard to specify them in RD.XML. if ((_generationOptions & UsageBasedMetadataGenerationOptions.AnonymousTypeHeuristic) != 0) { if (type is MetadataType metadataType && metadataType.HasInstantiation && !metadataType.IsGenericDefinition && metadataType.HasCustomAttribute("System.Runtime.CompilerServices", "CompilerGeneratedAttribute") && metadataType.Name.Contains("AnonymousType")) { foreach (MethodDesc method in type.GetMethods()) { if (!method.Signature.IsStatic && method.IsSpecialName) { dependencies = dependencies ?? new DependencyList(); dependencies.Add(factory.CanonicalEntrypoint(method), "Anonymous type accessor"); } } } } // If the option was specified to root types and methods in all user assemblies, do that. if ((_generationOptions & UsageBasedMetadataGenerationOptions.FullUserAssemblyRooting) != 0) { if (type is MetadataType metadataType && !_rootAllAssembliesExaminedModules.Contains(metadataType.Module)) { _rootAllAssembliesExaminedModules.Add(metadataType.Module); if (metadataType.Module is Internal.TypeSystem.Ecma.EcmaModule ecmaModule && !FrameworkStringResourceBlockingPolicy.IsFrameworkAssembly(ecmaModule)) { dependencies = dependencies ?? new DependencyList(); var rootProvider = new RootingServiceProvider(factory, dependencies.Add); foreach (TypeDesc t in ecmaModule.GetAllTypes()) { RootingHelpers.TryRootType(rootProvider, t, "RD.XML root"); } } } } // If a type is marked [Serializable], make sure a couple things are also included. if (type.IsSerializable && !type.IsGenericDefinition) { foreach (MethodDesc method in type.GetAllMethods()) { MethodSignature signature = method.Signature; if (method.IsConstructor && signature.Length == 2 && signature[0] == _serializationInfoType /* && signature[1] is StreamingContext */) { dependencies = dependencies ?? new DependencyList(); dependencies.Add(factory.CanonicalEntrypoint(method), "Binary serialization"); } // Methods with these attributes can be called during serialization if (signature.Length == 1 && !signature.IsStatic && signature.ReturnType.IsVoid && (method.HasCustomAttribute("System.Runtime.Serialization", "OnSerializingAttribute") || method.HasCustomAttribute("System.Runtime.Serialization", "OnSerializedAttribute") || method.HasCustomAttribute("System.Runtime.Serialization", "OnDeserializingAttribute") || method.HasCustomAttribute("System.Runtime.Serialization", "OnDeserializedAttribute"))) { dependencies = dependencies ?? new DependencyList(); dependencies.Add(factory.CanonicalEntrypoint(method), "Binary serialization"); } } } // Event sources need their special nested types if (type is MetadataType mdType && mdType.HasCustomAttribute("System.Diagnostics.Tracing", "EventSourceAttribute")) { AddEventSourceSpecialTypeDependencies(ref dependencies, factory, mdType.GetNestedType("Keywords")); AddEventSourceSpecialTypeDependencies(ref dependencies, factory, mdType.GetNestedType("Tasks")); AddEventSourceSpecialTypeDependencies(ref dependencies, factory, mdType.GetNestedType("Opcodes")); void AddEventSourceSpecialTypeDependencies(ref DependencyList dependencies, NodeFactory factory, MetadataType type) { if (type != null) { const string reason = "Event source"; dependencies = dependencies ?? new DependencyList(); dependencies.Add(factory.TypeMetadata(type), reason); foreach (FieldDesc field in type.GetFields()) { if (field.IsLiteral) { dependencies.Add(factory.FieldMetadata(field), reason); } } } } } }
protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type) { TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, type, "Reflectable type"); // If we don't have precise field usage information, apply policy that all fields that // are eligible to have metadata get metadata. if (!_hasPreciseFieldUsageInformation) { TypeDesc typeDefinition = type.GetTypeDefinition(); foreach (FieldDesc field in typeDefinition.GetFields()) { if ((GetMetadataCategory(field) & MetadataCategory.Description) != 0) { dependencies = dependencies ?? new DependencyList(); dependencies.Add(factory.FieldMetadata(field), "Field of a reflectable type"); } } } MetadataType mdType = type as MetadataType; // If anonymous type heuristic is turned on and this is an anonymous type, make sure we have // method bodies for all properties. It's common to have anonymous types used with reflection // and it's hard to specify them in RD.XML. if ((_generationOptions & UsageBasedMetadataGenerationOptions.AnonymousTypeHeuristic) != 0) { if (mdType != null && mdType.HasInstantiation && !mdType.IsGenericDefinition && mdType.HasCustomAttribute("System.Runtime.CompilerServices", "CompilerGeneratedAttribute") && mdType.Name.Contains("AnonymousType")) { foreach (MethodDesc method in type.GetMethods()) { if (!method.Signature.IsStatic && method.IsSpecialName) { dependencies = dependencies ?? new DependencyList(); dependencies.Add(factory.CanonicalEntrypoint(method), "Anonymous type accessor"); } } } } ModuleDesc module = mdType?.Module; if (module != null && !_rootEntireAssembliesExaminedModules.Contains(module)) { // If the owning assembly needs to be fully compiled, do that. _rootEntireAssembliesExaminedModules.Add(module); string assemblyName = module.Assembly.GetName().Name; bool fullyRoot; string reason; if (_rootEntireAssembliesModules.Contains(assemblyName)) { // If the assembly was specified as a root on the command line, root it fullyRoot = true; reason = "Rooted from command line"; } else if (_trimmedAssemblies.Contains(assemblyName) || IsTrimmableAssembly(module)) { // If the assembly was specified as trimmed on the command line, do not root // If the assembly is marked trimmable via an attribute, do not root fullyRoot = false; reason = null; } else { // If rooting default assemblies was requested, root fullyRoot = (_generationOptions & UsageBasedMetadataGenerationOptions.RootDefaultAssemblies) != 0; reason = "Assemblies rooted from command line"; } if (fullyRoot) { dependencies = dependencies ?? new DependencyList(); var rootProvider = new RootingServiceProvider(factory, dependencies.Add); foreach (TypeDesc t in mdType.Module.GetAllTypes()) { RootingHelpers.TryRootType(rootProvider, t, reason); } } } // Event sources need their special nested types if (mdType != null && mdType.HasCustomAttribute("System.Diagnostics.Tracing", "EventSourceAttribute")) { AddEventSourceSpecialTypeDependencies(ref dependencies, factory, mdType.GetNestedType("Keywords")); AddEventSourceSpecialTypeDependencies(ref dependencies, factory, mdType.GetNestedType("Tasks")); AddEventSourceSpecialTypeDependencies(ref dependencies, factory, mdType.GetNestedType("Opcodes")); void AddEventSourceSpecialTypeDependencies(ref DependencyList dependencies, NodeFactory factory, MetadataType type) { if (type != null) { const string reason = "Event source"; dependencies = dependencies ?? new DependencyList(); dependencies.Add(factory.TypeMetadata(type), reason); foreach (FieldDesc field in type.GetFields()) { if (field.IsLiteral) { dependencies.Add(factory.FieldMetadata(field), reason); } } } } } }