/// <summary> /// Checks if an applied attribute with the given attributeType matches the namespace name and type name of the given early attribute's description /// and the attribute description has a signature with parameter count equal to the given attribute syntax's argument list count. /// NOTE: We don't allow early decoded attributes to have optional parameters. /// </summary> internal static bool IsTargetEarlyAttribute(NamedTypeSymbol attributeType, AttributeSyntax attributeSyntax, AttributeDescription description) { Debug.Assert(!attributeType.IsErrorType()); int argumentCount = (attributeSyntax.ArgumentList != null) ? attributeSyntax.ArgumentList.Arguments.Count((arg) => arg.NameEquals == null) : 0; return(AttributeData.IsTargetEarlyAttribute(attributeType, argumentCount, description)); }
protected SubstitutedNamedTypeSymbol(Symbol newContainer, TypeMap map, NamedTypeSymbol originalDefinition, NamedTypeSymbol constructedFrom = null, bool unbound = false) : base(originalDefinition) { Debug.Assert(originalDefinition.IsDefinition); Debug.Assert(!originalDefinition.IsErrorType()); _newContainer = newContainer; _inputMap = map; _unbound = unbound; // if we're substituting to create a new unconstructed type as a member of a constructed type, // then we must alpha rename the type parameters. if ((object)constructedFrom != null) { Debug.Assert(ReferenceEquals(constructedFrom.ConstructedFrom, constructedFrom)); _lazyTypeParameters = constructedFrom.TypeParameters; _lazyMap = map; } }
/// <summary> /// Lookup member declaration in predefined CorLib type in this Assembly. Only valid if this /// assembly is the Cor Library /// </summary> internal override Symbol GetDeclaredSpecialTypeMember(SpecialMember member) { #if DEBUG foreach (var module in this.Modules) { Debug.Assert(module.GetReferencedAssemblies().Length == 0); } #endif if (_lazySpecialTypeMembers == null || ReferenceEquals(_lazySpecialTypeMembers[(int)member], ErrorTypeSymbol.UnknownResultType)) { if (_lazySpecialTypeMembers == null) { var specialTypeMembers = new Symbol[(int)SpecialMember.Count]; for (int i = 0; i < specialTypeMembers.Length; i++) { specialTypeMembers[i] = ErrorTypeSymbol.UnknownResultType; } Interlocked.CompareExchange(ref _lazySpecialTypeMembers, specialTypeMembers, null); } var descriptor = SpecialMembers.GetDescriptor(member); NamedTypeSymbol type = GetDeclaredSpecialType((SpecialType)descriptor.DeclaringTypeId); Symbol result = null; if (!type.IsErrorType()) { result = CSharpCompilation.GetRuntimeMember(type, ref descriptor, CSharpCompilation.SpecialMembersSignatureComparer.Instance, accessWithinOpt: null); } Interlocked.CompareExchange(ref _lazySpecialTypeMembers[(int)member], result, ErrorTypeSymbol.UnknownResultType); } return(_lazySpecialTypeMembers[(int)member]); }
/// <summary> /// Resolves <see cref="System.Type"/> to a <see cref="TypeSymbol"/> available in this assembly /// its referenced assemblies. /// </summary> /// <param name="type">The type to resolve.</param> /// <param name="includeReferences">Use referenced assemblies for resolution.</param> /// <returns>The resolved symbol if successful or null on failure.</returns> internal TypeSymbol GetTypeByReflectionType(Type type, bool includeReferences) { System.Reflection.TypeInfo typeInfo = type.GetTypeInfo(); Debug.Assert(!typeInfo.IsByRef); // not supported (we don't accept open types as submission results nor host types): Debug.Assert(!typeInfo.ContainsGenericParameters); if (typeInfo.IsArray) { TypeSymbol symbol = GetTypeByReflectionType(typeInfo.GetElementType(), includeReferences); if ((object)symbol == null) { return(null); } int rank = typeInfo.GetArrayRank(); if (rank != 1) { throw new NotSupportedException($"An array of rank {rank} is not supported in stark via reflection"); } return(ArrayTypeSymbol.CreateArray(this, TypeSymbolWithAnnotations.Create(symbol))); } else if (typeInfo.IsPointer) { TypeSymbol symbol = GetTypeByReflectionType(typeInfo.GetElementType(), includeReferences); if ((object)symbol == null) { return(null); } return(new PointerTypeSymbol(TypeSymbolWithAnnotations.Create(symbol))); } else if (typeInfo.DeclaringType != null) { Debug.Assert(!typeInfo.IsArray); // consolidated generic arguments (includes arguments of all declaring types): Type[] genericArguments = typeInfo.GenericTypeArguments; int typeArgumentIndex = 0; var currentTypeInfo = typeInfo.IsGenericType ? typeInfo.GetGenericTypeDefinition().GetTypeInfo() : typeInfo; var nestedTypes = ArrayBuilder <System.Reflection.TypeInfo> .GetInstance(); while (true) { Debug.Assert(currentTypeInfo.IsGenericTypeDefinition || !currentTypeInfo.IsGenericType); nestedTypes.Add(currentTypeInfo); if (currentTypeInfo.DeclaringType == null) { break; } currentTypeInfo = currentTypeInfo.DeclaringType.GetTypeInfo(); } int i = nestedTypes.Count - 1; var symbol = (NamedTypeSymbol)GetTypeByReflectionType(nestedTypes[i].AsType(), includeReferences); if ((object)symbol == null) { return(null); } while (--i >= 0) { int forcedArity = nestedTypes[i].GenericTypeParameters.Length - nestedTypes[i + 1].GenericTypeParameters.Length; MetadataTypeName mdName = MetadataTypeName.FromTypeName(nestedTypes[i].Name, forcedArity: forcedArity); symbol = symbol.LookupMetadataType(ref mdName); if ((object)symbol == null || symbol.IsErrorType()) { return(null); } symbol = ApplyGenericArguments(symbol, genericArguments, ref typeArgumentIndex, includeReferences); if ((object)symbol == null) { return(null); } } nestedTypes.Free(); Debug.Assert(typeArgumentIndex == genericArguments.Length); return(symbol); } else { AssemblyIdentity assemblyId = AssemblyIdentity.FromAssemblyDefinition(typeInfo.Assembly); MetadataTypeName mdName = MetadataTypeName.FromNamespaceAndTypeName( typeInfo.Namespace ?? string.Empty, typeInfo.Name, forcedArity: typeInfo.GenericTypeArguments.Length); NamedTypeSymbol symbol = GetTopLevelTypeByMetadataName(ref mdName, assemblyId, includeReferences, isWellKnownType: false, conflicts: out var _); if ((object)symbol == null || symbol.IsErrorType()) { return(null); } int typeArgumentIndex = 0; Type[] genericArguments = typeInfo.GenericTypeArguments; symbol = ApplyGenericArguments(symbol, genericArguments, ref typeArgumentIndex, includeReferences); Debug.Assert(typeArgumentIndex == genericArguments.Length); return(symbol); } }
/// <summary> /// Lookup a top level type referenced from metadata, names should be /// compared case-sensitively. Detect cycles during lookup. /// </summary> /// <param name="emittedName"> /// Full type name, possibly with generic name mangling. /// </param> /// <param name="visitedAssemblies"> /// List of assemblies lookup has already visited (since type forwarding can introduce cycles). /// </param> /// <param name="digThroughForwardedTypes"> /// Take forwarded types into account. /// </param> internal sealed override NamedTypeSymbol LookupTopLevelMetadataTypeWithCycleDetection(ref MetadataTypeName emittedName, ConsList <AssemblySymbol> visitedAssemblies, bool digThroughForwardedTypes) { NamedTypeSymbol result = null; // This is a cache similar to the one used by MetaImport::GetTypeByName in native // compiler. The difference is that native compiler pre-populates the cache when it // loads types. Here we are populating the cache only with things we looked for, so that // next time we are looking for the same thing, the lookup is fast. This cache also // takes care of TypeForwarders. Gives about 8% win on subsequent lookups in some // scenarios. // // CONSIDER !!! // // However, it is questionable how often subsequent lookup by name is going to happen. // Currently it doesn't happen for TypeDef tokens at all, for TypeRef tokens, the // lookup by name is done once and the result is cached. So, multiple lookups by name // for the same type are going to happen only in these cases: // 1) Resolving GetType() in attribute application, type is encoded by name. // 2) TypeRef token isn't reused within the same module, i.e. multiple TypeRefs point to // the same type. // 3) Different Module refers to the same type, lookup once per Module (with exception of #2). // 4) Multitargeting - retargeting the type to a different version of assembly result = LookupTopLevelMetadataTypeInCache(ref emittedName); if ((object)result != null) { // We only cache result equivalent to digging through type forwarders, which // might produce an forwarder specific ErrorTypeSymbol. We don't want to // return that error symbol, unless digThroughForwardedTypes is true. if (digThroughForwardedTypes || (!result.IsErrorType() && (object)result.ContainingAssembly == (object)this)) { return(result); } // According to the cache, the type wasn't found, or isn't declared in this assembly (forwarded). return(new MissingMetadataTypeSymbol.TopLevel(this.Modules[0], ref emittedName)); } else { // Now we will look for the type in each module of the assembly and pick the first type // we find, this is what native VB compiler does. var modules = this.Modules; var count = modules.Length; var i = 0; result = modules[i].LookupTopLevelMetadataType(ref emittedName); if (result is MissingMetadataTypeSymbol) { for (i = 1; i < count; i++) { var newResult = modules[i].LookupTopLevelMetadataType(ref emittedName); // Hold on to the first missing type result, unless we found the type. if (!(newResult is MissingMetadataTypeSymbol)) { result = newResult; break; } } } bool foundMatchInThisAssembly = (i < count); Debug.Assert(!foundMatchInThisAssembly || (object)result.ContainingAssembly == (object)this); if (!foundMatchInThisAssembly && digThroughForwardedTypes) { // We didn't find the type System.Diagnostics.Debug.Assert(result is MissingMetadataTypeSymbol); NamedTypeSymbol forwarded = TryLookupForwardedMetadataTypeWithCycleDetection(ref emittedName, visitedAssemblies); if ((object)forwarded != null) { result = forwarded; } } System.Diagnostics.Debug.Assert((object)result != null); // Add result of the lookup into the cache if (digThroughForwardedTypes || foundMatchInThisAssembly) { CacheTopLevelMetadataType(ref emittedName, result); } return(result); } }