internal IType ObtainTypeReference(ICliMetadataTypeDefinitionTableRow typeIdentity) { if (CliCommon.IsSpecialModule(typeIdentity)) { return(null); } IType result; lock (this.metadataTypeCache) { if (!metadataTypeCache.TryGetValue(typeIdentity, out result)) { var refAssem = this.manager.GetRelativeAssembly(typeIdentity.MetadataRoot); if (CliCommon.IsBaseObject(this.manager, typeIdentity)) { result = new CliClassType(refAssem, typeIdentity); } else if ((typeIdentity.TypeAttributes & TypeAttributes.Interface) == TypeAttributes.Interface && (typeIdentity.TypeAttributes & TypeAttributes.Sealed) != TypeAttributes.Sealed) { result = new CliInterfaceType(refAssem, typeIdentity); } else if (CliCommon.IsBaseObject(this.manager, typeIdentity.Extends)) { result = new CliClassType(refAssem, typeIdentity); } else if (CliCommon.IsEnum(this.manager, typeIdentity)) { //result = new CliEnumType(); result = new CliEnumType(refAssem, typeIdentity); } else if (CliCommon.IsValueType(this.manager, typeIdentity)) { result = new CliStructType(refAssem, typeIdentity); } else if (CliCommon.IsDelegate(this.manager, typeIdentity) && !CliCommon.IsBaseDelegateType(this.manager, typeIdentity)) { result = new CliDelegateType(refAssem, typeIdentity); } else { result = new CliClassType(refAssem, typeIdentity); } this.metadataTypeCache.Add(typeIdentity, result); } } return(result); }
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 * */ }); }