private static void ValidateTypeDefinitionTable(IAssembly hostAssembly, ICliMetadataRoot metadataRoot, CompilerErrorCollection resultErrorCollection, _ICliManager identityManager) { var typeDefTable = metadataRoot.TableStream.TypeDefinitionTable; if (typeDefTable == null) { return; } int maxTypeDef = typeDefTable.Count; int maxTypeRef = metadataRoot.TableStream.TypeRefTable == null ? 0 : metadataRoot.TableStream.TypeRefTable.Count; int maxTypeSpec = metadataRoot.TableStream.TypeSpecificationTable == null ? 0 : metadataRoot.TableStream.TypeSpecificationTable.Count; Parallel.ForEach(typeDefTable.ToArray(), typeDefinition => { var typeAttributes = typeDefinition.TypeAttributes; if (((int)(typeAttributes ^ (typeAttributes & (TypeAttributes)0xD77DBF))) != 0) { /* * * Flags must contain only those values specified by System.Reflection.TypeAttributes * */ resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0202a, hostAssembly, typeDefinition); } if (((typeAttributes & TypeAttributes.SequentialLayout) == TypeAttributes.SequentialLayout) && ((typeAttributes & TypeAttributes.ExplicitLayout) == TypeAttributes.SequentialLayout)) { /* * * Sequential Layout and Explicit Layout cannot be set together. * */ resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0202b, hostAssembly, typeDefinition); } if (((typeAttributes & TypeAttributes.AutoClass) == TypeAttributes.AutoClass) && ((typeAttributes & TypeAttributes.UnicodeClass) == TypeAttributes.UnicodeClass)) { /* * * UnicodeClass and AutoClass flags cannot be set together. * */ resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0202c, hostAssembly, typeDefinition); } if ((typeAttributes & TypeAttributes.HasSecurity) == TypeAttributes.HasSecurity) { if (!(CheckForDeclSecurityRow(metadataRoot, typeDefinition) || CheckForSecuritySuppressionAttribute(metadataRoot, typeDefTable, typeDefinition))) { /* * * If HasSecurity is set, then the type must contain at least one * DeclSecurity row, or a custom attribute called * SuppressUnmanagedCodeSecurityAttribute. * */ resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0202d, hostAssembly, typeDefinition); } if ((typeAttributes & TypeAttributes.Interface) == TypeAttributes.Interface) { /* * * Interfaces are allowed to have the HasSecurity flag set; however, * the security system ignores any permission requests attached to * that interface. * */ resultErrorCollection.ModelWarning(CliWarningsAndErrors.CliMetadata0202g, hostAssembly, typeDefinition); } } else if (CheckForDeclSecurityRow(metadataRoot, typeDefinition)) { /* * * If this type owns one (or more) DeclSecurity rows, then the HasSecurity * flag must be set. * */ resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0202e, hostAssembly, typeDefinition); } else if (CheckForSecuritySuppressionAttribute(metadataRoot, typeDefTable, typeDefinition)) { /* * * If this type has a custom attribute called SuppressUnmanagedCodeSecurityAttribute, * then the HasSecurity flag must be set. * */ resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0202f, hostAssembly, typeDefinition); } if (string.IsNullOrEmpty(typeDefinition.Name)) { /* * * Name shall index a non-empty string in the String Heap. * */ resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0203, hostAssembly, typeDefinition); } string name = typeDefinition.Name, @namespace = typeDefinition.Namespace; int maxIndex = 0; switch (typeDefinition.ExtendsSource) { case CliMetadataTypeDefOrRefTag.TypeDefinition: maxIndex = maxTypeDef; break; case CliMetadataTypeDefOrRefTag.TypeReference: maxIndex = maxTypeRef; break; case CliMetadataTypeDefOrRefTag.TypeSpecification: maxIndex = maxTypeSpec; break; } /* * * If the index is beyond the allowed ranges, don't even check the * 'Extends' part as it'll yield an exception. * * * The exception being if there's no actual reference in the first place, * when the source is a type def and the index is zero. * */ if (!(typeDefinition.ExtendsSource == CliMetadataTypeDefOrRefTag.TypeDefinition && typeDefinition.ExtendsIndex == 0) && (1 > typeDefinition.ExtendsIndex || typeDefinition.ExtendsIndex > maxIndex)) { resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0211a, hostAssembly, typeDefinition); } else if (typeDefinition.Extends == null && (typeAttributes & TypeAttributes.Interface) != TypeAttributes.Interface) { if (!(CliCommon.IsSpecialModule(typeDefinition) || CliCommon.IsBaseObject(identityManager, typeDefinition))) { /* * * Every class (with exception to System.Object and the special class * <Module>) shall extend one, and only one, other Class - so Extends * is for a Class shall be non-null. * */ resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0208, hostAssembly, typeDefinition); } } else if (typeDefinition.Extends != null && name == "Object" && @namespace == "System" && typeDefinition.DeclaringType == null) { /* * * System.Object must have an extends value of null. * */ resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0209, hostAssembly, typeDefinition); } else if (name == "ValueType" && @namespace == "System" && typeDefinition.DeclaringType == null) { if (!CliCommon.IsBaseObject(identityManager, typeDefinition.Extends)) { /* * * System.ValueType must have an extends value of System.Object * */ resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0210, hostAssembly, typeDefinition); } } else if (typeDefinition.Extends != null) { var extendsDef = identityManager.ResolveScope(typeDefinition.Extends); if (extendsDef != null) { var events = extendsDef.Events; if (CliCommon.IsValueType(identityManager, extendsDef) || ((extendsDef.TypeAttributes & TypeAttributes.Interface) == TypeAttributes.Interface)) { resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0211b, hostAssembly, typeDefinition, extendsDef); } if ((extendsDef.TypeAttributes & TypeAttributes.Sealed) == TypeAttributes.Sealed) { resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0211c, hostAssembly, typeDefinition, extendsDef); } List <ICliMetadataTypeDefinitionTableRow> extendsTable = new List <ICliMetadataTypeDefinitionTableRow>(); ICliMetadataTypeDefinitionTableRow current = typeDefinition; while (current != null) { if (extendsTable.Contains(current)) { /* * * A class shall not extend itself, or any of its children (i.e., * its derived classes), because this will introduce loops in the * hierarchy tree. * */ resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0212, hostAssembly, typeDefinition); break; } extendsTable.Add(current); current = identityManager.ResolveScope(current.Extends); } } } /* * * ToDo: Add code here to check the name identifier against CLS rules. * Warning CliMetadata0204 * */ if (typeDefinition.NamespaceIndex != 0 && typeDefinition.Namespace == string.Empty) { /* * * If non-null, Namespace shall index a non-empty string in the * String Heap. * */ resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0206, hostAssembly, typeDefinition); } /* * * ToDo: Add code here to check the namespace identifier against CLS rules. * Warning CliMetadata0207 * */ }); }
private static void ValidateTypeReferenceTable(IAssembly hostAssembly, ICliMetadataRoot metadataRoot, CompilerErrorCollection resultErrorCollection) { var typeRefTable = metadataRoot.TableStream.TypeRefTable; if (typeRefTable != null) { Parallel.ForEach(typeRefTable.ToArray(), typeRef => { var @namespace = typeRef.Namespace; string fullName = null; if (@namespace == null) { fullName = typeRef.Name; } else { fullName = string.Format("{0}.{1}", @namespace, typeRef.Name); } switch (typeRef.ResolutionScope) { case CliMetadataResolutionScopeTag.Module: if (typeRef.Source == null) { var exportedTypeTable = metadataRoot.TableStream.ExportedTypeTable; if (exportedTypeTable == null) { /* * * When resolution scope is null, there shall be an * ExportedType table row for this type (fullName). * */ resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0101a, hostAssembly, typeRef, new string[] { fullName }); } var exportedType = (from eType in exportedTypeTable where eType.NamespaceIndex == typeRef.NamespaceIndex && eType.NameIndex == typeRef.NameIndex select eType).FirstOrDefault(); if (exportedType == null) { /* * * When resolution scope is null, there shall be an * ExportedType table row for this type (fullName). * */ resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0101a, hostAssembly, metadataRoot, new string[] { fullName }); } } else { /* * * When resolution scope is a module token, the type referenced (fullName) * should be defined within the current module; though, this should not * occur in a CLI ("Compressed Metadata") module. * */ resultErrorCollection.ModelWarning(CliWarningsAndErrors.CliMetadata0101d, hostAssembly, typeRef, new string[] { fullName }); } break; case CliMetadataResolutionScopeTag.ModuleReference: var moduleRef = (ICliMetadataModuleReferenceTableRow)typeRef.Source; if (!hostAssembly.Modules.ContainsKey(TypeSystemIdentifiers.GetDeclarationIdentifier(moduleRef.Name))) { /* * * When resolution scope is a moduleref token, the target type (fullName) * is defined in another module within the same assembly. * */ resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0101c, hostAssembly, typeRef, new string[] { fullName }); } break; case CliMetadataResolutionScopeTag.AssemblyReference: var assemblyReference = (ICliMetadataAssemblyRefTableRow)typeRef.Source; var assemblyUniqueId = CliCommon.GetAssemblyUniqueIdentifier(assemblyReference).Item2; if (assemblyUniqueId == hostAssembly.UniqueIdentifier) { /* * * When resolution scope is an assemblyref, the type referenced (fullName) * should be defined within another assembly other than the current * module's assembly. * */ resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0101e, hostAssembly, typeRef, new string[] { fullName }); } else if (!hostAssembly.References.ContainsKey(assemblyUniqueId)) { hostAssembly.References.ContainsKey(assemblyUniqueId); /* * * When resolution scope is an assemblyref, the type referenced (fullName) * should be defined within another assembly (assemblyUniqueId) which * cannot be found. * */ resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0101f, hostAssembly, typeRef, new string[] { fullName, assemblyUniqueId.ToString() }); } break; case CliMetadataResolutionScopeTag.TypeReference: break; default: break; } if (typeRef.NameIndex == 0 || typeRef.Name == string.Empty) { /* * * Name shall index a non-empty string within the StringHeap. * */ resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0102, hostAssembly, typeRef); } if (typeRef.NamespaceIndex > 0 && typeRef.Namespace == string.Empty) { /* * * Namespace shall index a non-empty string if not null. * */ resultErrorCollection.ModelError(CliWarningsAndErrors.CliMetadata0104, hostAssembly, typeRef); } }); } }