public AssemblyIdentityAndLocation(AssemblyIdentity identity, string location) { Debug.Assert(identity != null && location != null); this.Identity = identity; this.Location = location; }
private Assembly LoadFromPathUncheckedCore(string fullPath, AssemblyIdentity identity = null) { Debug.Assert(PathUtilities.IsAbsolute(fullPath)); // Check if we have already loaded an assembly with the same identity or from the given path. Assembly loadedAssembly = null; lock (_guard) { Assembly existingAssembly; if (_loadedAssembliesByPath.TryGetValue(fullPath, out existingAssembly)) { loadedAssembly = existingAssembly; } else { identity = identity ?? GetOrAddAssemblyIdentity(fullPath); if (identity != null && _loadedAssembliesByIdentity.TryGetValue(identity, out existingAssembly)) { loadedAssembly = existingAssembly; } } } // Otherwise, load the assembly. if (loadedAssembly == null) { loadedAssembly = LoadFromPathImpl(fullPath); } // Add the loaded assembly to both path and identity cache. return AddToCache(loadedAssembly, fullPath, identity); }
public ModuleData(AssemblyIdentity identity, OutputKind kind, ImmutableArray<byte> image, ImmutableArray<byte> pdb, bool inMemoryModule) { this.Id = new ModuleDataId(identity.Name, identity.GetDisplayName(), GetMvid(image)); this.Kind = kind; this.Image = image; this.Pdb = pdb; this.InMemoryModule = inMemoryModule; }
public override PortableExecutableReference ResolveMissingAssembly(AssemblyIdentity identity) { ResolutionAttempts.Add(identity); MetadataReference reference; string nameAndVersion = identity.Name + (identity.Version != AssemblyIdentity.NullVersion ? $", {identity.Version}" : ""); return _map.TryGetValue(nameAndVersion, out reference) ? (PortableExecutableReference)reference : null; }
public override PortableExecutableReference ResolveMissingAssembly(MetadataReference definition, AssemblyIdentity referenceIdentity) { ResolutionAttempts.Add(new ReferenceAndIdentity(definition, referenceIdentity)); MetadataReference reference; string nameAndVersion = referenceIdentity.Name + (referenceIdentity.Version != AssemblyIdentity.NullVersion ? $", {referenceIdentity.Version}" : ""); return _map.TryGetValue(nameAndVersion, out reference) ? (PortableExecutableReference)reference : null; }
public MissingAnalyzerDependency(string analyzerPath, AssemblyIdentity dependencyIdentity) { Debug.Assert(analyzerPath != null); Debug.Assert(dependencyIdentity != null); AnalyzerPath = analyzerPath; DependencyIdentity = dependencyIdentity; }
public AnalyzerDependencyConflict(AssemblyIdentity identity, string analyzerFilePath1, string analyzerFilePath2) { Debug.Assert(identity != null); Debug.Assert(analyzerFilePath1 != null); Debug.Assert(analyzerFilePath2 != null); Identity = identity; AnalyzerFilePath1 = analyzerFilePath1; AnalyzerFilePath2 = analyzerFilePath2; }
public override PortableExecutableReference ResolveMissingAssembly( MetadataReference definition, AssemblyIdentity referenceIdentity) { if (resolvedReferences.TryGetValue(referenceIdentity.Name, out var resolvedReference)) { return(resolvedReference); } resolvedReference = GetPEReference(dependencyResolver.ResolveWithoutReferences( new AssemblyName(referenceIdentity.ToString()))); resolvedReferences = resolvedReferences.Add(referenceIdentity.Name, resolvedReference); return(resolvedReference); }
public CodeActionOperation CreateAddMetadataReferenceOperation(ProjectId projectId, AssemblyIdentity assemblyIdentity) { if (projectId == null) { throw new ArgumentNullException("projectId"); } if (assemblyIdentity == null) { throw new ArgumentNullException("assemblyIdentity"); } return new AddMetadataReferenceOperation(projectId, assemblyIdentity); }
public override PortableExecutableReference ResolveMissingAssembly(MetadataReference definition, AssemblyIdentity referenceIdentity) { // resolve assemblies from the directory containing the test and from directory containing corlib string name = referenceIdentity.Name; string testDir = Path.GetDirectoryName(GetType().GetTypeInfo().Assembly.ManifestModule.FullyQualifiedName); string testDependencyAssemblyPath = Path.Combine(testDir, name + ".dll"); if (File.Exists(testDependencyAssemblyPath)) { return MetadataReference.CreateFromFile(testDependencyAssemblyPath, s_resolvedMissingAssemblyReferenceProperties); } string fxDir = Path.GetDirectoryName(typeof(object).GetTypeInfo().Assembly.ManifestModule.FullyQualifiedName); string fxAssemblyPath = Path.Combine(fxDir, name + ".dll"); if (File.Exists(fxAssemblyPath)) { return MetadataReference.CreateFromFile(fxAssemblyPath, s_resolvedMissingAssemblyReferenceProperties); } return null; }
/// <exception cref="BadImageFormatException"/> internal PEAssembly(AssemblyMetadata owner, ImmutableArray<PEModule> modules) { Debug.Assert(!modules.IsDefault); Debug.Assert(modules.Length > 0); this.identity = modules[0].ReadAssemblyIdentityOrThrow(); var refs = ArrayBuilder<AssemblyIdentity>.GetInstance(); int[] refCounts = new int[modules.Length]; for (int i = 0; i < modules.Length; i++) { ImmutableArray<AssemblyIdentity> refsForModule = modules[i].ReferencedAssemblies; refCounts[i] = refsForModule.Length; refs.AddRange(refsForModule); } this.modules = modules; this.AssemblyReferences = refs.ToImmutableAndFree(); this.ModuleReferenceCounts = refCounts.AsImmutableOrNull(); this.owner = owner; }
public void TestMissingMetadataSymbol() { AssemblyIdentity missingAssemblyId = new AssemblyIdentity("foo"); AssemblySymbol assem = new MockAssemblySymbol("banana"); ModuleSymbol module = new MissingModuleSymbol(assem, ordinal: -1); NamedTypeSymbol container = new MockNamedTypeSymbol("TestClass", Enumerable.Empty<Symbol>(), TypeKind.Class); var mms1 = new MissingMetadataTypeSymbol.TopLevel(new MissingAssemblySymbol(missingAssemblyId).Modules[0], "Elvis", "Lives", 2, true); Assert.Equal(2, mms1.Arity); Assert.Equal("Elvis", mms1.NamespaceName); Assert.Equal("Lives", mms1.Name); Assert.Equal("Elvis.Lives<,>[missing]", mms1.ToTestDisplayString()); Assert.Equal("foo", mms1.ContainingAssembly.Identity.Name); var mms2 = new MissingMetadataTypeSymbol.TopLevel(module, "Elvis.Is", "Cool", 0, true); Assert.Equal(0, mms2.Arity); Assert.Equal("Elvis.Is", mms2.NamespaceName); Assert.Equal("Cool", mms2.Name); Assert.Equal("Elvis.Is.Cool[missing]", mms2.ToTestDisplayString()); Assert.Same(assem, mms2.ContainingAssembly); // TODO: Add test for 3rd constructor. }
private static bool IsTriviallyNonRetargetable(AssemblyIdentity identity) { // Short-circuit zero-version/non-neutral culture/weak name, // which will never match retargeted identities. return identity.CultureName.Length != 0 || identity.ContentType != AssemblyContentType.Default || !identity.IsStrongName; }
private static bool IsRetargetableAssembly(AssemblyIdentity identity) { bool retargetable, portable; IsRetargetableAssembly(identity, out retargetable, out portable); return retargetable; }
public override void ReportDuplicateMetadataReferenceWeak(DiagnosticBag diagnostics, Location location, MetadataReference reference, AssemblyIdentity identity, MetadataReference equivalentReference, AssemblyIdentity equivalentIdentity) { throw new NotImplementedException(); }
/// <summary> /// Used to match AssemblyRef with AssemblyDef. /// </summary> /// <param name="definitions">Array of definition identities to match against.</param> /// <param name="reference">Reference identity to resolve.</param> /// <param name="assemblyIdentityComparer">Assembly identity comparer.</param> /// <param name="okToResolveAgainstCompilationBeingCreated"> Is it Ok to resolve reference against the compilation we are creating?</param> /// <returns> /// Returns an index the reference is bound. /// </returns> internal static AssemblyReferenceBinding ResolveReferencedAssembly( AssemblyIdentity reference, ImmutableArray <AssemblyData> definitions, AssemblyIdentityComparer assemblyIdentityComparer, bool okToResolveAgainstCompilationBeingCreated) { // Dev11 C# compiler allows the versions to not match exactly, assuming that a newer library may be used instead of an older version. // For a given reference it finds a definition with the lowest version that is higher then or equal to the reference version. // If match.Version != reference.Version a warning is reported. // definition with the lowest version higher than reference version, unless exact version found int minHigherVersionDefinition = -1; int maxLowerVersionDefinition = -1; // NB: Start at 1, since we checked 0 above. const int definitionOffset = 1; for (int i = definitionOffset; i < definitions.Length; i++) { AssemblyIdentity definition = definitions[i].Identity; switch (assemblyIdentityComparer.Compare(reference, definition)) { case AssemblyIdentityComparer.ComparisonResult.NotEquivalent: continue; case AssemblyIdentityComparer.ComparisonResult.Equivalent: return(new AssemblyReferenceBinding(reference, i)); case AssemblyIdentityComparer.ComparisonResult.EquivalentIgnoringVersion: if (reference.Version < definition.Version) { // Refers to an older assembly than we have if (minHigherVersionDefinition == -1 || definition.Version < definitions[minHigherVersionDefinition].Identity.Version) { minHigherVersionDefinition = i; } } else { Debug.Assert(reference.Version > definition.Version); // Refers to a newer assembly than we have if (maxLowerVersionDefinition == -1 || definition.Version > definitions[maxLowerVersionDefinition].Identity.Version) { maxLowerVersionDefinition = i; } } continue; } } // we haven't found definition that matches the reference if (minHigherVersionDefinition != -1) { return(new AssemblyReferenceBinding(reference, minHigherVersionDefinition, versionDifference: +1)); } if (maxLowerVersionDefinition != -1) { return(new AssemblyReferenceBinding(reference, maxLowerVersionDefinition, versionDifference: -1)); } // Handle cases where Windows.winmd is a runtime substitute for a // reference to a compile-time winmd. This is for scenarios such as a // debugger EE which constructs a compilation from the modules of // the running process where Windows.winmd loaded at runtime is a // substitute for a collection of Windows.*.winmd compile-time references. if (reference.IsWindowsComponent()) { for (int i = definitionOffset; i < definitions.Length; i++) { if (IsWindowsRuntime(definitions[i])) { return(new AssemblyReferenceBinding(reference, i)); } } } // As in the native compiler (see IMPORTER::MapAssemblyRefToAid), we compare against the // compilation (i.e. source) assembly as a last resort. We follow the native approach of // skipping the public key comparison since we have yet to compute it. if (okToResolveAgainstCompilationBeingCreated && AssemblyIdentityComparer.SimpleNameComparer.Equals(reference.Name, definitions[0].Identity.Name)) { Debug.Assert(definitions[0].Identity.PublicKeyToken.IsEmpty); return(new AssemblyReferenceBinding(reference, 0)); } return(new AssemblyReferenceBinding(reference)); }
/// <summary> /// Enumerates assemblies in the GAC returning those that match given partial name and /// architecture. /// </summary> /// <param name="partialName">Optional partial name.</param> /// <param name="architectureFilter">Optional architecture filter.</param> public static IEnumerable <AssemblyIdentity> GetAssemblyIdentities(AssemblyName partialName, Func <ProcessorArchitecture, bool> architectureFilter = null) { return(GetAssemblyIdentities(AssemblyIdentity.ToAssemblyNameObject(partialName), architectureFilter)); }
public override Assembly Load(AssemblyIdentity identity, string location = null) { if (dynamicModule != null && identity.Name == _dynamicAssemblyName.Name) { return dynamicModule.Assembly; } return assemblyLoader.Load(identity, location); }
internal TypeSymbol GetTypeSymbol(MetadataHelpers.AssemblyQualifiedTypeName fullName, out bool refersToNoPiaLocalType) { // // Section 23.3 (Custom Attributes) of CLI Spec Partition II: // // If the parameter kind is System.Type, (also, the middle line in above diagram) its value is // stored as a SerString (as defined in the previous paragraph), representing its canonical name. // The canonical name is its full type name, followed optionally by the assembly where it is defined, // its version, culture and public-key-token. If the assembly name is omitted, the CLI looks first // in the current assembly, and then in the system library (mscorlib); in these two special cases, // it is permitted to omit the assembly-name, version, culture and public-key-token. int referencedAssemblyIndex; if (fullName.AssemblyName != null) { AssemblyIdentity identity; if (!AssemblyIdentity.TryParseDisplayName(fullName.AssemblyName, out identity)) { refersToNoPiaLocalType = false; return(GetUnsupportedMetadataTypeSymbol()); } // the assembly name has to be a full name: referencedAssemblyIndex = GetIndexOfReferencedAssembly(identity); if (referencedAssemblyIndex == -1) { // In rare cases (e.g. assemblies emitted by Reflection.Emit) the identity // might be the identity of the containing assembly. The metadata spec doesn't disallow this. if (!this.IsContainingAssembly(identity)) { refersToNoPiaLocalType = false; return(GetUnsupportedMetadataTypeSymbol()); } } } else { // Use this assembly referencedAssemblyIndex = -1; } // Find the top level type Debug.Assert(MetadataHelpers.IsValidMetadataIdentifier(fullName.TopLevelType)); var mdName = MetadataTypeName.FromFullName(fullName.TopLevelType); TypeSymbol container = LookupTopLevelTypeDefSymbol(ref mdName, referencedAssemblyIndex, out refersToNoPiaLocalType); // Process any nested types if (fullName.NestedTypes != null) { if (refersToNoPiaLocalType) { // Types nested into local types are not supported. refersToNoPiaLocalType = false; return(GetUnsupportedMetadataTypeSymbol()); } for (int i = 0; i < fullName.NestedTypes.Length; i++) { Debug.Assert(MetadataHelpers.IsValidMetadataIdentifier(fullName.NestedTypes[i])); mdName = MetadataTypeName.FromTypeName(fullName.NestedTypes[i]); // Find nested type in the container container = LookupNestedTypeDefSymbol(container, ref mdName); } } // Substitute type arguments if any if (fullName.TypeArguments != null) { ImmutableArray <bool> argumentRefersToNoPiaLocalType; var typeArguments = ResolveTypeArguments(fullName.TypeArguments, out argumentRefersToNoPiaLocalType); container = SubstituteTypeParameters(container, typeArguments, argumentRefersToNoPiaLocalType); foreach (bool flag in argumentRefersToNoPiaLocalType) { if (flag) { refersToNoPiaLocalType = true; break; } } } else { container = SubstituteWithUnboundIfGeneric(container); } for (int i = 0; i < fullName.PointerCount; i++) { container = MakePointerTypeSymbol(container, ImmutableArray <ModifierInfo <TypeSymbol> > .Empty); } // Process any array type ranks if (fullName.ArrayRanks != null) { foreach (int rank in fullName.ArrayRanks) { Debug.Assert(rank >= 0); container = rank == 0 ? GetSZArrayTypeSymbol(container, default(ImmutableArray <ModifierInfo <TypeSymbol> >)) : GetMDArrayTypeSymbol(rank, container, default(ImmutableArray <ModifierInfo <TypeSymbol> >), ImmutableArray <int> .Empty, default(ImmutableArray <int>)); } } return(container); }
public virtual PortableExecutableReference?ResolveMissingAssembly(MetadataReference definition, AssemblyIdentity referenceIdentity) => null;
/// <summary> /// Given that an assembly with identity assemblyGrantingAccessIdentity granted access to assemblyWantingAccess, /// check the public keys to ensure the internals-visible-to check should succeed. This is used by both the /// C# and VB implementations as a helper to implement `bool IAssemblySymbol.GivesAccessTo(IAssemblySymbol toAssembly)`. /// </summary> internal static IVTConclusion PerformIVTCheck( this AssemblyIdentity assemblyGrantingAccessIdentity, ImmutableArray <byte> assemblyWantingAccessKey, ImmutableArray <byte> grantedToPublicKey) { // This gets a bit complicated. Let's break it down. // // First off, let's assume that the "other" assembly is GrantingAssembly.DLL, that the "this" // assembly is "WantingAssembly.DLL", and that GrantingAssembly has named WantingAssembly as a friend (that is a precondition // to calling this method). Whether we allow WantingAssembly to see internals of GrantingAssembly depends on these four factors: // // q1) Is GrantingAssembly strong-named? // q2) Did GrantingAssembly name WantingAssembly as a friend via a strong name? // q3) Is WantingAssembly strong-named? // q4) Does GrantingAssembly give a strong-name for WantingAssembly that matches our strong name? // // Before we dive into the details, we should mention two additional facts: // // * If the answer to q1 is "yes", and GrantingAssembly was compiled by a Roslyn compiler, then q2 must be "yes" also. // Strong-named GrantingAssembly must only be friends with strong-named WantingAssembly. See the blog article // http://blogs.msdn.com/b/ericlippert/archive/2009/06/04/alas-smith-and-jones.aspx // for an explanation of why this feature is desirable. // // Now, just because the compiler enforces this rule does not mean that we will never run into // a scenario where GrantingAssembly is strong-named and names WantingAssembly via a weak name. Not all assemblies // were compiled with a Roslyn compiler. We still need to deal sensibly with this situation. // We do so by ignoring the problem; if strong-named GrantingAssembly extends friendship to weak-named // WantingAssembly then we're done; any assembly named WantingAssembly is a friend of GrantingAssembly. // // Incidentally, the C# compiler produces error CS1726, ERR_FriendAssemblySNReq, and VB produces // the error VB31535, ERR_FriendAssemblyStrongNameRequired, when compiling // a strong-named GrantingAssembly that names a weak-named WantingAssembly as its friend. // // * If the answer to q1 is "no" and the answer to q3 is "yes" then we are in a situation where // strong-named WantingAssembly is referencing weak-named GrantingAssembly, which is illegal. In the dev10 compiler // we do not give an error about this until emit time. In Roslyn we have a new error, CS7029, // which we give before emit time when we detect that weak-named GrantingAssembly has given friend access // to strong-named WantingAssembly, which then references GrantingAssembly. However, we still want to give friend // access to WantingAssembly for the purposes of semantic analysis. // // Roslyn C# does not yet give an error in other circumstances whereby a strong-named assembly // references a weak-named assembly. See https://github.com/dotnet/roslyn/issues/26722 // // Let's make a chart that illustrates all the possible answers to these four questions, and // what the resulting accessibility should be: // // case q1 q2 q3 q4 Result Explanation // 1 YES YES YES YES SUCCESS GrantingAssembly has named this strong-named WantingAssembly as a friend. // 2 YES YES YES NO NO MATCH GrantingAssembly has named a different strong-named WantingAssembly as a friend. // 3 YES YES NO NO NO MATCH GrantingAssembly has named a strong-named WantingAssembly as a friend, but this WantingAssembly is weak-named. // 4 YES NO YES NO SUCCESS GrantingAssembly has improperly (*) named any WantingAssembly as its friend. But we honor its offer of friendship. // 5 YES NO NO NO SUCCESS GrantingAssembly has improperly (*) named any WantingAssembly as its friend. But we honor its offer of friendship. // 6 NO YES YES YES SUCCESS, BAD REF GrantingAssembly has named this strong-named WantingAssembly as a friend, but WantingAssembly should not be referring to a weak-named GrantingAssembly. // 7 NO YES YES NO NO MATCH GrantingAssembly has named a different strong-named WantingAssembly as a friend. // 8 NO YES NO NO NO MATCH GrantingAssembly has named a strong-named WantingAssembly as a friend, but this WantingAssembly is weak-named. // 9 NO NO YES NO SUCCESS, BAD REF GrantingAssembly has named any WantingAssembly as a friend, but WantingAssembly should not be referring to a weak-named GrantingAssembly. // 10 NO NO NO NO SUCCESS GrantingAssembly has named any WantingAssembly as its friend. // // (*) GrantingAssembly was not built with a Roslyn compiler, which would have prevented this. // // This method never returns NoRelationshipClaimed because if control got here, then we assume // (as a precondition) that GrantingAssembly named WantingAssembly as a friend somehow. bool q1 = assemblyGrantingAccessIdentity.IsStrongName; bool q2 = !grantedToPublicKey.IsDefaultOrEmpty; bool q3 = !assemblyWantingAccessKey.IsDefaultOrEmpty; bool q4 = (q2 & q3) && ByteSequenceComparer.Equals(grantedToPublicKey, assemblyWantingAccessKey); // Cases 2, 3, 7 and 8: if (q2 && !q4) { return(IVTConclusion.PublicKeyDoesntMatch); } // Cases 6 and 9: if (!q1 && q3) { return(IVTConclusion.OneSignedOneNot); } // Cases 1, 4, 5 and 10: return(IVTConclusion.Match); }
internal override bool ApplyUnificationPolicies( ref AssemblyIdentity reference, ref AssemblyIdentity definition, AssemblyIdentityParts referenceParts, out bool isDefinitionFxAssembly) { if (reference.ContentType == AssemblyContentType.Default && SimpleNameComparer.Equals(reference.Name, definition.Name) && SimpleNameComparer.Equals(reference.Name, "mscorlib")) { isDefinitionFxAssembly = true; reference = definition; return(true); } if (!reference.IsRetargetable && definition.IsRetargetable) { // Reference is not retargetable, but definition is retargetable. // Non-equivalent. isDefinitionFxAssembly = false; return(false); } // Notes: // an assembly might be both retargetable and portable // in that case retargetable table acts as an override. // Apply portability policy transforms first (e.g. rewrites references to SL assemblies to their desktop equivalents) // If the reference is partial and is missing version or PKT it is not ported. reference = Port(reference); definition = Port(definition); if (reference.IsRetargetable && !definition.IsRetargetable) { if (!AssemblyIdentity.IsFullName(referenceParts)) { isDefinitionFxAssembly = false; return(false); } // Reference needs to be retargeted before comparison, // unless it's optionally retargetable and we already match the PK bool skipRetargeting = IsOptionallyRetargetableAssembly(reference) && AssemblyIdentity.KeysEqual(reference, definition); if (!skipRetargeting) { reference = Retarget(reference); } } // At this point we are in one of the following states: // // 1) Both ref/def are not retargetable // 2) Both ref/def are retargetable // 3) Ref is retargetable (and has been retargeted) // // We can do a straight compare of ref/def at this point using the // regular rules if (reference.IsRetargetable && definition.IsRetargetable) { isDefinitionFxAssembly = IsRetargetableAssembly(definition); } else { isDefinitionFxAssembly = IsFrameworkAssembly(definition); } return(true); }
private static bool IsRetargetableAssembly(AssemblyIdentity identity) { IsRetargetableAssembly(identity, out bool retargetable, out bool portable); return(retargetable); }
/// <summary> /// Compares reference assembly identity with definition identity and returns their relationship. /// </summary> /// <param name="reference">Reference identity.</param> /// <param name="definition">Definition identity.</param> public ComparisonResult Compare(AssemblyIdentity reference, AssemblyIdentity definition) { bool unificationApplied; return(Compare(reference, null, definition, out unificationApplied, ignoreVersion: true)); }
/// <summary> /// Compares assembly reference identity with definition identity. /// </summary> /// <param name="reference">Reference assembly identity.</param> /// <param name="definition">Full assembly display name.</param> /// <returns>True if the reference identity matches the definition identity.</returns> public bool ReferenceMatchesDefinition(AssemblyIdentity reference, AssemblyIdentity definition) { bool unificationApplied; return(Compare(reference, null, definition, out unificationApplied, ignoreVersion: false) != ComparisonResult.NotEquivalent); }
private static AssemblyIdentity Retarget(AssemblyIdentity identity) { if (IsTriviallyNonRetargetable(identity)) { return identity; } FrameworkRetargetingDictionary.Value value; if (g_arRetargetPolicy.TryGetValue(identity, out value)) { return new AssemblyIdentity( value.NewName ?? identity.Name, (Version)value.NewVersion, identity.CultureName, value.NewPublicKeyToken, hasPublicKey: false, isRetargetable: identity.IsRetargetable, contentType: AssemblyContentType.Default); } return identity; }
internal override bool ApplyUnificationPolicies( ref AssemblyIdentity reference, ref AssemblyIdentity definition, AssemblyIdentityParts referenceParts, out bool isFxAssembly) { if (reference.ContentType == AssemblyContentType.Default && SimpleNameComparer.Equals(reference.Name, definition.Name) && SimpleNameComparer.Equals(reference.Name, "mscorlib")) { isFxAssembly = true; reference = definition; return true; } if (!reference.IsRetargetable && definition.IsRetargetable) { // Reference is not retargetable, but definition is retargetable. // Non-equivalent. isFxAssembly = false; return false; } // Notes: // an assembly might be both retargetable and portable // in that case retargeatable table acts as an override. // Apply portability policy transforms first (e.g. rewrites references to SL assemblies to their desktop equivalents) // If the reference is partial and is missing version or PKT it is not ported. reference = Port(reference); definition = Port(definition); if (reference.IsRetargetable && !definition.IsRetargetable) { if (!AssemblyIdentity.IsFullName(referenceParts)) { isFxAssembly = false; return false; } // Reference needs to be retargeted before comparison, // unless it's optionally retargetable and we already match the PK bool skipRetargeting = IsOptionallyRetargetableAssembly(reference) && AssemblyIdentity.KeysEqual(reference, definition); if (!skipRetargeting) { reference = Retarget(reference); } } // At this point we are in one of the following states: // // 1) Both ref/def are not retargetable // 2) Both ref/def are retargetable // 3) Ref is retargetable (and has been retargeted) // // We can do a straight compare of ref/def at this point using the // regular rules if (reference.IsRetargetable && definition.IsRetargetable) { isFxAssembly = IsRetargetableAssembly(definition); } else { isFxAssembly = IsFrameworkAssembly(definition); } return true; }
protected abstract bool IsContainingAssembly(AssemblyIdentity identity);
private static ModuleBuilder CreateDynamicModule(AssemblyBuilderAccess access, AssemblyIdentity name, string fileName) { var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(name.ToAssemblyName(), access); if (DisableJitOptimizations) { assemblyBuilder.SetCustomAttribute(new CustomAttributeBuilder( typeof(DebuggableAttribute).GetConstructor(new[] { typeof(DebuggableAttribute.DebuggingModes) }), new object[] { DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations })); } const string moduleName = "InteractiveModule"; if (access == AssemblyBuilderAccess.RunAndSave) { return assemblyBuilder.DefineDynamicModule(moduleName, fileName, emitSymbolInfo: false); } else { return assemblyBuilder.DefineDynamicModule(moduleName, emitSymbolInfo: false); } }
// Internal for testing. internal static IEnumerable <AssemblyIdentity.IAssemblyName> GetAssemblyObjects( AssemblyIdentity.IAssemblyName partialNameFilter, Func <ProcessorArchitecture, bool> architectureFilter) { IAssemblyEnum enumerator; AssemblyIdentity.IApplicationContext applicationContext = null; int hr = CreateAssemblyEnum(out enumerator, applicationContext, partialNameFilter, ASM_CACHE.GAC, IntPtr.Zero); if (hr == S_FALSE) { // no assembly found yield break; } else if (hr != S_OK) { Exception e = Marshal.GetExceptionForHR(hr); if (e is FileNotFoundException) { // invalid assembly name: yield break; } else if (e != null) { throw e; } else { // for some reason it might happen that CreateAssemblyEnum returns non-zero HR that doesn't correspond to any exception: throw new ArgumentException(CodeAnalysisResources.InvalidAssemblyName); } } while (true) { AssemblyIdentity.IAssemblyName nameObject; hr = enumerator.GetNextAssembly(out applicationContext, out nameObject, 0); if (hr != 0) { if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } break; } if (architectureFilter != null) { var assemblyArchitecture = AssemblyIdentity.GetProcessorArchitecture(nameObject); if (!architectureFilter(assemblyArchitecture)) { continue; } } yield return(nameObject); } }
public override Assembly Load(AssemblyIdentity identity, string location = null) { return Resolve(identity.Name) ?? _assemblyLoader.Load(identity, location); }
public ReferencedAssemblyIdentity(AssemblyIdentity identity, MetadataReference metadataReference) { Identity = identity; MetadataReference = metadataReference; }
private Assembly AddToCache(Assembly assembly, string fullPath, AssemblyIdentity identity) { Debug.Assert(PathUtilities.IsAbsolute(fullPath)); Debug.Assert(assembly != null); identity = AddToCache(fullPath, identity ?? AssemblyIdentity.FromAssemblyDefinition(assembly)); Debug.Assert(identity != null); lock (_guard) { // The same assembly may be loaded from two different full paths (e.g. when loaded from GAC, etc.), // or another thread might have loaded the assembly after we checked above. Assembly existingAssembly; if (_loadedAssembliesByIdentity.TryGetValue(identity, out existingAssembly)) { assembly = existingAssembly; } else { _loadedAssembliesByIdentity.Add(identity, assembly); } // An assembly file might be replaced by another file with a different identity. // Last one wins. _loadedAssembliesByPath[fullPath] = assembly; return assembly; } }
// Returns null if an assembly of an equivalent identity has not been added previously, otherwise returns the reference that added it. // - Both assembly names are strong (have keys) and are either equal or FX unified // - Both assembly names are weak (no keys) and have the same simple name. private MetadataReference TryAddAssembly(AssemblyIdentity identity, MetadataReference boundReference, DiagnosticBag diagnostics, Location location, ref Dictionary <string, List <ReferencedAssemblyIdentity> > referencesBySimpleName) { if (referencesBySimpleName == null) { referencesBySimpleName = new Dictionary <string, List <ReferencedAssemblyIdentity> >(StringComparer.OrdinalIgnoreCase); } List <ReferencedAssemblyIdentity> sameSimpleNameIdentities; string simpleName = identity.Name; if (!referencesBySimpleName.TryGetValue(simpleName, out sameSimpleNameIdentities)) { referencesBySimpleName.Add(simpleName, new List <ReferencedAssemblyIdentity> { new ReferencedAssemblyIdentity(identity, boundReference) }); return(null); } ReferencedAssemblyIdentity equivalent = default(ReferencedAssemblyIdentity); if (identity.IsStrongName) { foreach (var other in sameSimpleNameIdentities) { // only compare strong with strong (weak is never equivalent to strong and vice versa) if (other.Identity.IsStrongName && IdentityComparer.ReferenceMatchesDefinition(identity, other.Identity)) { equivalent = other; break; } } } else { foreach (var other in sameSimpleNameIdentities) { // only compare weak with weak if (!other.Identity.IsStrongName && WeakIdentityPropertiesEquivalent(identity, other.Identity)) { equivalent = other; break; } } } if (equivalent.Identity == null) { sameSimpleNameIdentities.Add(new ReferencedAssemblyIdentity(identity, boundReference)); return(null); } // equivalent found - ignore and/or report an error: if (identity.IsStrongName) { Debug.Assert(equivalent.Identity.IsStrongName); // versions migth have been unified for a Framework assembly: if (identity != equivalent.Identity) { // Dev12 C# reports an error // Dev12 VB keeps both references in the compilation and reports an ambiguity error when a symbol is used. // BREAKING CHANGE in VB: we report an error for both languages // Multiple assemblies with equivalent identity have been imported: '{0}' and '{1}'. Remove one of the duplicate references. MessageProvider.ReportDuplicateMetadataReferenceStrong(diagnostics, location, boundReference, identity, equivalent.MetadataReference, equivalent.Identity); } // If the versions match exactly we ignore duplicates w/o reporting errors while // Dev12 C# reports: // error CS1703: An assembly with the same identity '{0}' has already been imported. Try removing one of the duplicate references. // Dev12 VB reports: // Fatal error BC2000 : compiler initialization failed unexpectedly: Project already has a reference to assembly System. // A second reference to 'D:\Temp\System.dll' cannot be added. } else { Debug.Assert(!equivalent.Identity.IsStrongName); // Dev12 reports an error for all weak-named assemblies, even if the versions are the same. // We treat assemblies with the same name and version equal even if they don't have a strong name. // This change allows us to de-duplicate #r references based on identities rather than full paths, // and is closer to platforms that don't support strong names and consider name and version enough // to identify an assembly. An identity without version is considered to have version 0.0.0.0. if (identity != equivalent.Identity) { MessageProvider.ReportDuplicateMetadataReferenceWeak(diagnostics, location, boundReference, identity, equivalent.MetadataReference, equivalent.Identity); } } Debug.Assert(equivalent.MetadataReference != null); return(equivalent.MetadataReference); }
/// <summary> /// Given the identity of an assembly referenced by this module, finds /// the index of that assembly in the list of assemblies referenced by /// the current module. /// </summary> protected abstract int GetIndexOfReferencedAssembly(AssemblyIdentity identity);
private AssemblyIdentity Port(AssemblyIdentity identity) { if ( identity.IsRetargetable || !identity.IsStrongName || identity.ContentType != AssemblyContentType.Default ) { return(identity); } Version?newVersion = null; ImmutableArray <byte> newPublicKeyToken = default; var version = (AssemblyVersion)identity.Version; if ( version >= new AssemblyVersion(2, 0, 0, 0) && version <= new AssemblyVersion(5, 9, 0, 0) ) { if (identity.PublicKeyToken.SequenceEqual(s_SILVERLIGHT_PLATFORM_PUBLICKEY_STR_L)) { if (!policy.SuppressSilverlightPlatformAssembliesPortability) { if ( SimpleNameComparer.Equals(identity.Name, "System") || SimpleNameComparer.Equals(identity.Name, "System.Core") ) { newVersion = (Version)s_VER_ASSEMBLYVERSION_STR_L; newPublicKeyToken = s_ECMA_PUBLICKEY_STR_L; } } } else if (identity.PublicKeyToken.SequenceEqual(s_SILVERLIGHT_PUBLICKEY_STR_L)) { if (!policy.SuppressSilverlightLibraryAssembliesPortability) { if (SimpleNameComparer.Equals(identity.Name, "Microsoft.VisualBasic")) { newVersion = new Version(10, 0, 0, 0); newPublicKeyToken = s_MICROSOFT_PUBLICKEY_STR_L; } if ( SimpleNameComparer.Equals( identity.Name, "System.ComponentModel.Composition" ) ) { newVersion = (Version)s_VER_ASSEMBLYVERSION_STR_L; newPublicKeyToken = s_ECMA_PUBLICKEY_STR_L; } } } } if (newVersion == null) { return(identity); } return(new AssemblyIdentity( identity.Name, newVersion, identity.CultureName, newPublicKeyToken, hasPublicKey: false, isRetargetable: identity.IsRetargetable, contentType: AssemblyContentType.Default )); }
// internal for testing internal ComparisonResult Compare(AssemblyIdentity reference, string referenceDisplayName, AssemblyIdentity definition, out bool unificationApplied, bool ignoreVersion) { Debug.Assert((reference != null) ^ (referenceDisplayName != null)); unificationApplied = false; AssemblyIdentityParts parts; if (reference != null) { // fast path bool?eq = TriviallyEquivalent(reference, definition); if (eq.HasValue) { return(eq.Value ? ComparisonResult.Equivalent : ComparisonResult.NotEquivalent); } parts = AssemblyIdentityParts.Name | AssemblyIdentityParts.Version | AssemblyIdentityParts.Culture | AssemblyIdentityParts.PublicKeyToken; } else { if (!AssemblyIdentity.TryParseDisplayName(referenceDisplayName, out reference, out parts) || reference.ContentType != definition.ContentType) { return(ComparisonResult.NotEquivalent); } } Debug.Assert(reference.ContentType == definition.ContentType); bool isFxAssembly; if (!ApplyUnificationPolicies(ref reference, ref definition, parts, out isFxAssembly)) { return(ComparisonResult.NotEquivalent); } if (ReferenceEquals(reference, definition)) { return(ComparisonResult.Equivalent); } bool compareCulture = (parts & AssemblyIdentityParts.Culture) != 0; bool comparePublicKeyToken = (parts & AssemblyIdentityParts.PublicKeyOrToken) != 0; if (!definition.IsStrongName) { if (reference.IsStrongName) { return(ComparisonResult.NotEquivalent); } if (!AssemblyIdentity.IsFullName(parts)) { if (!SimpleNameComparer.Equals(reference.Name, definition.Name)) { return(ComparisonResult.NotEquivalent); } if (compareCulture && !CultureComparer.Equals(reference.CultureName, definition.CultureName)) { return(ComparisonResult.NotEquivalent); } // version is ignored return(ComparisonResult.Equivalent); } isFxAssembly = false; } if (!SimpleNameComparer.Equals(reference.Name, definition.Name)) { return(ComparisonResult.NotEquivalent); } if (compareCulture && !CultureComparer.Equals(reference.CultureName, definition.CultureName)) { return(ComparisonResult.NotEquivalent); } if (comparePublicKeyToken && !AssemblyIdentity.KeysEqual(reference, definition)) { return(ComparisonResult.NotEquivalent); } bool hasSomeVersionParts = (parts & AssemblyIdentityParts.Version) != 0; bool hasPartialVersion = (parts & AssemblyIdentityParts.Version) != AssemblyIdentityParts.Version; // If any version parts were specified then compare the versions. The comparison fails if some version parts are missing. if (definition.IsStrongName && hasSomeVersionParts && (hasPartialVersion || reference.Version != definition.Version)) { if (isFxAssembly) { unificationApplied = true; return(ComparisonResult.Equivalent); } if (ignoreVersion) { return(ComparisonResult.EquivalentIgnoringVersion); } return(ComparisonResult.NotEquivalent); } return(ComparisonResult.Equivalent); }
/// <summary> /// Returns null if an assembly of an equivalent identity has not been added previously, otherwise returns the reference that added it. /// Two identities are considered equivalent if /// - both assembly names are strong (have keys) and are either equal or FX unified /// - both assembly names are weak (no keys) and have the same simple name. /// </summary> private MetadataReference TryAddAssembly( AssemblyIdentity identity, MetadataReference reference, int assemblyIndex, DiagnosticBag diagnostics, Location location, Dictionary <string, List <ReferencedAssemblyIdentity> > referencesBySimpleName, bool supersedeLowerVersions) { var referencedAssembly = new ReferencedAssemblyIdentity(identity, reference, assemblyIndex); List <ReferencedAssemblyIdentity> sameSimpleNameIdentities; if (!referencesBySimpleName.TryGetValue(identity.Name, out sameSimpleNameIdentities)) { referencesBySimpleName.Add(identity.Name, new List <ReferencedAssemblyIdentity> { referencedAssembly }); return(null); } if (supersedeLowerVersions) { foreach (var other in sameSimpleNameIdentities) { if (identity.Version == other.Identity.Version) { return(other.Reference); } } // Keep all versions of the assembly and the first identity in the list the one with the highest version: if (sameSimpleNameIdentities[0].Identity.Version > identity.Version) { sameSimpleNameIdentities.Add(referencedAssembly); } else { sameSimpleNameIdentities.Add(sameSimpleNameIdentities[0]); sameSimpleNameIdentities[0] = referencedAssembly; } return(null); } ReferencedAssemblyIdentity equivalent = default(ReferencedAssemblyIdentity); if (identity.IsStrongName) { foreach (var other in sameSimpleNameIdentities) { // Only compare strong with strong (weak is never equivalent to strong and vice versa). // In order to eliminate duplicate references we need to try to match their identities in both directions since // ReferenceMatchesDefinition is not necessarily symmetric. // (e.g. System.Numerics.Vectors, Version=4.1+ matches System.Numerics.Vectors, Version=4.0, but not the other way around.) if (other.Identity.IsStrongName && IdentityComparer.ReferenceMatchesDefinition(identity, other.Identity) && IdentityComparer.ReferenceMatchesDefinition(other.Identity, identity)) { equivalent = other; break; } } } else { foreach (var other in sameSimpleNameIdentities) { // only compare weak with weak if (!other.Identity.IsStrongName && WeakIdentityPropertiesEquivalent(identity, other.Identity)) { equivalent = other; break; } } } if (equivalent.Identity == null) { sameSimpleNameIdentities.Add(referencedAssembly); return(null); } // equivalent found - ignore and/or report an error: if (identity.IsStrongName) { Debug.Assert(equivalent.Identity.IsStrongName); // versions might have been unified for a Framework assembly: if (identity != equivalent.Identity) { // Dev12 C# reports an error // Dev12 VB keeps both references in the compilation and reports an ambiguity error when a symbol is used. // BREAKING CHANGE in VB: we report an error for both languages // Multiple assemblies with equivalent identity have been imported: '{0}' and '{1}'. Remove one of the duplicate references. MessageProvider.ReportDuplicateMetadataReferenceStrong(diagnostics, location, reference, identity, equivalent.Reference, equivalent.Identity); } // If the versions match exactly we ignore duplicates w/o reporting errors while // Dev12 C# reports: // error CS1703: An assembly with the same identity '{0}' has already been imported. Try removing one of the duplicate references. // Dev12 VB reports: // Fatal error BC2000 : compiler initialization failed unexpectedly: Project already has a reference to assembly System. // A second reference to 'D:\Temp\System.dll' cannot be added. } else { Debug.Assert(!equivalent.Identity.IsStrongName); // Dev12 reports an error for all weak-named assemblies, even if the versions are the same. // We treat assemblies with the same name and version equal even if they don't have a strong name. // This change allows us to de-duplicate #r references based on identities rather than full paths, // and is closer to platforms that don't support strong names and consider name and version enough // to identify an assembly. An identity without version is considered to have version 0.0.0.0. if (identity != equivalent.Identity) { MessageProvider.ReportDuplicateMetadataReferenceWeak(diagnostics, location, reference, identity, equivalent.Reference, equivalent.Identity); } } Debug.Assert(equivalent.Reference != null); return(equivalent.Reference); }
public abstract void ReportDuplicateMetadataReferenceWeak(DiagnosticBag diagnostics, Location location, MetadataReference reference, AssemblyIdentity identity, MetadataReference equivalentReference, AssemblyIdentity equivalentIdentity);
/// <summary> /// Used to match AssemblyRef with AssemblyDef. /// </summary> /// <param name="definitions">Array of definition identities to match against.</param> /// <param name="definitionStartIndex">An index of the first definition to consider, <paramref name="definitions"/> preceding this index are ignored.</param> /// <param name="reference">Reference identity to resolve.</param> /// <param name="assemblyIdentityComparer">Assembly identity comparer.</param> /// <returns> /// Returns an index the reference is bound. /// </returns> internal static AssemblyReferenceBinding ResolveReferencedAssembly( AssemblyIdentity reference, ImmutableArray <AssemblyData> definitions, int definitionStartIndex, AssemblyIdentityComparer assemblyIdentityComparer) { // Dev11 C# compiler allows the versions to not match exactly, assuming that a newer library may be used instead of an older version. // For a given reference it finds a definition with the lowest version that is higher then or equal to the reference version. // If match.Version != reference.Version a warning is reported. // definition with the lowest version higher than reference version, unless exact version found int minHigherVersionDefinition = -1; int maxLowerVersionDefinition = -1; // Skip assembly being built for now; it will be considered at the very end: bool resolveAgainstAssemblyBeingBuilt = definitionStartIndex == 0; definitionStartIndex = Math.Max(definitionStartIndex, 1); for (int i = definitionStartIndex; i < definitions.Length; i++) { AssemblyIdentity definition = definitions[i].Identity; switch (assemblyIdentityComparer.Compare(reference, definition)) { case AssemblyIdentityComparer.ComparisonResult.NotEquivalent: continue; case AssemblyIdentityComparer.ComparisonResult.Equivalent: return(new AssemblyReferenceBinding(reference, i)); case AssemblyIdentityComparer.ComparisonResult.EquivalentIgnoringVersion: if (reference.Version < definition.Version) { // Refers to an older assembly than we have if (minHigherVersionDefinition == -1 || definition.Version < definitions[minHigherVersionDefinition].Identity.Version) { minHigherVersionDefinition = i; } } else { Debug.Assert(reference.Version > definition.Version); // Refers to a newer assembly than we have if (maxLowerVersionDefinition == -1 || definition.Version > definitions[maxLowerVersionDefinition].Identity.Version) { maxLowerVersionDefinition = i; } } continue; default: throw ExceptionUtilities.Unreachable; } } // we haven't found definition that matches the reference if (minHigherVersionDefinition != -1) { return(new AssemblyReferenceBinding(reference, minHigherVersionDefinition, versionDifference: +1)); } if (maxLowerVersionDefinition != -1) { return(new AssemblyReferenceBinding(reference, maxLowerVersionDefinition, versionDifference: -1)); } // Handle cases where Windows.winmd is a runtime substitute for a // reference to a compile-time winmd. This is for scenarios such as a // debugger EE which constructs a compilation from the modules of // the running process where Windows.winmd loaded at runtime is a // substitute for a collection of Windows.*.winmd compile-time references. if (reference.IsWindowsComponent()) { for (int i = definitionStartIndex; i < definitions.Length; i++) { if (definitions[i].Identity.IsWindowsRuntime()) { return(new AssemblyReferenceBinding(reference, i)); } } } // In the IDE it is possible the reference we're looking for is a // compilation reference to a source assembly. However, if the reference // is of ContentType WindowsRuntime then the compilation will never // match since all C#/VB WindowsRuntime compilations output .winmdobjs, // not .winmds, and the ContentType of a .winmdobj is Default. // If this is the case, we want to ignore the ContentType mismatch and // allow the compilation to match the reference. if (reference.ContentType == AssemblyContentType.WindowsRuntime) { for (int i = definitionStartIndex; i < definitions.Length; i++) { var definition = definitions[i].Identity; var sourceCompilation = definitions[i].SourceCompilation; if (definition.ContentType == AssemblyContentType.Default && sourceCompilation?.Options.OutputKind == OutputKind.WindowsRuntimeMetadata && AssemblyIdentityComparer.SimpleNameComparer.Equals(reference.Name, definition.Name) && reference.Version.Equals(definition.Version) && reference.IsRetargetable == definition.IsRetargetable && AssemblyIdentityComparer.CultureComparer.Equals(reference.CultureName, definition.CultureName) && AssemblyIdentity.KeysEqual(reference, definition)) { return(new AssemblyReferenceBinding(reference, i)); } } } // As in the native compiler (see IMPORTER::MapAssemblyRefToAid), we compare against the // compilation (i.e. source) assembly as a last resort. We follow the native approach of // skipping the public key comparison since we have yet to compute it. if (resolveAgainstAssemblyBeingBuilt && AssemblyIdentityComparer.SimpleNameComparer.Equals(reference.Name, definitions[0].Identity.Name)) { Debug.Assert(definitions[0].Identity.PublicKeyToken.IsEmpty); return(new AssemblyReferenceBinding(reference, 0)); } return(new AssemblyReferenceBinding(reference)); }
public AddMetadataReferenceOperation(ProjectId projectId, AssemblyIdentity assemblyIdentity) { _projectId = projectId; _assemblyIdentity = assemblyIdentity; }
internal virtual bool ApplyUnificationPolicies(ref AssemblyIdentity reference, ref AssemblyIdentity definition, AssemblyIdentityParts referenceParts, out bool isDefinitionFxAssembly) { isDefinitionFxAssembly = false; return(true); }
/// <summary> /// Returns true if the identity is a Framework 4.5 or lower assembly. /// </summary> private static bool IsFrameworkAssembly(AssemblyIdentity identity) { // Note: // FrameworkAssemblyTable::IsFrameworkAssembly returns false if culture is not neutral. // However its caller doesn't initialize the culture and hence the culture is ignored. // PrepQueryMatchData(pName, wzName, &dwSizeName, wzVersion, &dwSizeVer, wzPublicKeyToken, &dwSizePKT, NULL, NULL, NULL);. if (identity.ContentType != AssemblyContentType.Default) { return false; } FrameworkAssemblyDictionary.Value value; if (!g_arFxPolicy.TryGetValue(identity.Name, out value) || !value.PublicKeyToken.SequenceEqual(identity.PublicKeyToken)) { return false; } // build and revision numbers are ignored uint thisVersion = ((uint)identity.Version.Major << 16) | (uint)identity.Version.Minor; uint fxVersion = ((uint)value.Version.Major << 16) | (uint)value.Version.Minor; return thisVersion <= fxVersion; }
public bool ReferenceMatchesDefinition(AssemblyIdentity reference, AssemblyIdentity definition) { return(Compare(reference, referenceDisplayName: null, definition, unificationApplied: out _, ignoreVersion: false) != ComparisonResult.NotEquivalent); }
private static bool IsOptionallyRetargetableAssembly(AssemblyIdentity identity) { if (!identity.IsRetargetable) { return false; } bool retargetable, portable; IsRetargetableAssembly(identity, out retargetable, out portable); return retargetable && portable; }
public ComparisonResult Compare(AssemblyIdentity reference, AssemblyIdentity definition) { return(Compare(reference, referenceDisplayName: null, definition, unificationApplied: out _, ignoreVersion: true)); }
private static void IsRetargetableAssembly(AssemblyIdentity identity, out bool retargetable, out bool portable) { retargetable = portable = false; if (IsTriviallyNonRetargetable(identity)) { return; } FrameworkRetargetingDictionary.Value value; retargetable = g_arRetargetPolicy.TryGetValue(identity, out value); portable = value.IsPortable; }
internal ComparisonResult Compare(AssemblyIdentity?reference, string?referenceDisplayName, AssemblyIdentity definition, out bool unificationApplied, bool ignoreVersion) { Debug.Assert((reference != null) ^ (referenceDisplayName != null)); unificationApplied = false; AssemblyIdentityParts parts; if (reference != null) { // fast path bool?eq = TriviallyEquivalent(reference, definition); if (eq.HasValue) { return(eq.Value ? ComparisonResult.Equivalent : ComparisonResult.NotEquivalent); } parts = AssemblyIdentityParts.Name | AssemblyIdentityParts.Version | AssemblyIdentityParts.Culture | AssemblyIdentityParts.PublicKeyToken; } else { if (!AssemblyIdentity.TryParseDisplayName(referenceDisplayName, out reference, out parts) || reference.ContentType != definition.ContentType) { return(ComparisonResult.NotEquivalent); } } Debug.Assert(reference.ContentType == definition.ContentType); bool isDefinitionFxAssembly; if (!ApplyUnificationPolicies(ref reference, ref definition, parts, out isDefinitionFxAssembly)) { return(ComparisonResult.NotEquivalent); } if (ReferenceEquals(reference, definition)) { return(ComparisonResult.Equivalent); } bool compareCulture = (parts & AssemblyIdentityParts.Culture) != 0; bool comparePublicKeyToken = (parts & AssemblyIdentityParts.PublicKeyOrToken) != 0; if (!definition.IsStrongName) { if (reference.IsStrongName) { return(ComparisonResult.NotEquivalent); } if (!AssemblyIdentity.IsFullName(parts)) { if (!SimpleNameComparer.Equals(reference.Name, definition.Name)) { return(ComparisonResult.NotEquivalent); } if (compareCulture && !CultureComparer.Equals(reference.CultureName, definition.CultureName)) { return(ComparisonResult.NotEquivalent); } // version is ignored return(ComparisonResult.Equivalent); } isDefinitionFxAssembly = false; } if (!SimpleNameComparer.Equals(reference.Name, definition.Name)) { return(ComparisonResult.NotEquivalent); } if (compareCulture && !CultureComparer.Equals(reference.CultureName, definition.CultureName)) { return(ComparisonResult.NotEquivalent); } if (comparePublicKeyToken && !AssemblyIdentity.KeysEqual(reference, definition)) { return(ComparisonResult.NotEquivalent); } bool hasSomeVersionParts = (parts & AssemblyIdentityParts.Version) != 0; bool hasPartialVersion = (parts & AssemblyIdentityParts.Version) != AssemblyIdentityParts.Version; // If any version parts were specified then compare the versions. The comparison fails if some version parts are missing. if (definition.IsStrongName && hasSomeVersionParts && (hasPartialVersion || reference.Version != definition.Version)) { // Note: // System.Numerics.Vectors, Version=4.0 is an FX assembly // System.Numerics.Vectors, Version=4.1+ is not an FX assembly // // It seems like a bug in Fusion: it only determines whether the definition is an FX assembly // and calculates the result based upon that, regardless of whether the reference is an FX assembly or not. // We do replicate the behavior. // // As a result unification is asymmetric when comparing the above identities. if (isDefinitionFxAssembly) { unificationApplied = true; return(ComparisonResult.Equivalent); } if (ignoreVersion) { return(ComparisonResult.EquivalentIgnoringVersion); } return(ComparisonResult.NotEquivalent); } return(ComparisonResult.Equivalent); }
private AssemblyIdentity Port(AssemblyIdentity identity) { if (identity.IsRetargetable || !identity.IsStrongName || identity.ContentType != AssemblyContentType.Default) { return identity; } Version newVersion = null; ImmutableArray<byte> newPublicKeyToken = default(ImmutableArray<byte>); var version = (AssemblyVersion)identity.Version; if (version >= new AssemblyVersion(2, 0, 0, 0) && version <= new AssemblyVersion(5, 9, 0, 0)) { if (identity.PublicKeyToken.SequenceEqual(SILVERLIGHT_PLATFORM_PUBLICKEY_STR_L)) { if (!policy.SuppressSilverlightPlatformAssembliesPortability) { if (SimpleNameComparer.Equals(identity.Name, "System") || SimpleNameComparer.Equals(identity.Name, "System.Core")) { newVersion = (Version)VER_ASSEMBLYVERSION_STR_L; newPublicKeyToken = ECMA_PUBLICKEY_STR_L; } } } else if (identity.PublicKeyToken.SequenceEqual(SILVERLIGHT_PUBLICKEY_STR_L)) { if (!policy.SuppressSilverlightLibraryAssembliesPortability) { if (SimpleNameComparer.Equals(identity.Name, "Microsoft.VisualBasic")) { newVersion = new Version(10, 0, 0, 0); newPublicKeyToken = MICROSOFT_PUBLICKEY_STR_L; } if (SimpleNameComparer.Equals(identity.Name, "System.ComponentModel.Composition")) { newVersion = (Version)VER_ASSEMBLYVERSION_STR_L; newPublicKeyToken = ECMA_PUBLICKEY_STR_L; } } } } if (newVersion == null) { return identity; } return new AssemblyIdentity( identity.Name, newVersion, identity.CultureName, newPublicKeyToken, hasPublicKey: false, isRetargetable: identity.IsRetargetable, contentType: AssemblyContentType.Default); }
/// <summary> /// Parses display name filling defaults for any basic properties that are missing. /// </summary> /// <param name="displayName">Display name.</param> /// <param name="identity">A full assembly identity.</param> /// <param name="parts"> /// Parts of the assembly identity that were specified in the display name, /// or 0 if the parsing failed. /// </param> /// <returns>True if display name parsed correctly.</returns> /// <remarks> /// The simple name has to be non-empty. /// A partially specified version might be missing build and/or revision number. The default value for these is 65535. /// The default culture is neutral (<see cref="CultureName"/> is <see cref="String.Empty"/>. /// If neither public key nor token is specified the identity is considered weak. /// </remarks> /// <exception cref="ArgumentNullException"><paramref name="displayName"/> is null.</exception> public static bool TryParseDisplayName(string displayName, out AssemblyIdentity identity, out AssemblyIdentityParts parts) { // see ndp\clr\src\Binder\TextualIdentityParser.cpp, ndp\clr\src\Binder\StringLexer.cpp identity = null; parts = 0; if (displayName == null) { throw new ArgumentNullException(nameof(displayName)); } if (displayName.IndexOf('\0') >= 0) { return(false); } int position = 0; string simpleName; if (!TryParseNameToken(displayName, ref position, out simpleName)) { return(false); } var parsedParts = AssemblyIdentityParts.Name; var seen = AssemblyIdentityParts.Name; Version version = null; string culture = null; bool isRetargetable = false; var contentType = AssemblyContentType.Default; var publicKey = default(ImmutableArray <byte>); var publicKeyToken = default(ImmutableArray <byte>); while (position < displayName.Length) { // Parse ',' name '=' value if (displayName[position] != ',') { return(false); } position++; string propertyName; if (!TryParseNameToken(displayName, ref position, out propertyName)) { return(false); } if (position >= displayName.Length || displayName[position] != '=') { return(false); } position++; string propertyValue; if (!TryParseNameToken(displayName, ref position, out propertyValue)) { return(false); } // Process property if (string.Equals(propertyName, "Version", StringComparison.OrdinalIgnoreCase)) { if ((seen & AssemblyIdentityParts.Version) != 0) { return(false); } seen |= AssemblyIdentityParts.Version; if (propertyValue == "*") { continue; } ulong versionLong; AssemblyIdentityParts versionParts; if (!TryParseVersion(propertyValue, out versionLong, out versionParts)) { return(false); } version = ToVersion(versionLong); parsedParts |= versionParts; } else if (string.Equals(propertyName, "Culture", StringComparison.OrdinalIgnoreCase) || string.Equals(propertyName, "Language", StringComparison.OrdinalIgnoreCase)) { if ((seen & AssemblyIdentityParts.Culture) != 0) { return(false); } seen |= AssemblyIdentityParts.Culture; if (propertyValue == "*") { continue; } culture = string.Equals(propertyValue, InvariantCultureDisplay, StringComparison.OrdinalIgnoreCase) ? null : propertyValue; parsedParts |= AssemblyIdentityParts.Culture; } else if (string.Equals(propertyName, "PublicKey", StringComparison.OrdinalIgnoreCase)) { if ((seen & AssemblyIdentityParts.PublicKey) != 0) { return(false); } seen |= AssemblyIdentityParts.PublicKey; if (propertyValue == "*") { continue; } ImmutableArray <byte> value; if (!TryParsePublicKey(propertyValue, out value)) { return(false); } // NOTE: Fusion would also set the public key token (as derived from the public key) here. // We may need to do this as well for error cases, as Fusion would fail to parse the // assembly name if public key token calculation failed. publicKey = value; parsedParts |= AssemblyIdentityParts.PublicKey; } else if (string.Equals(propertyName, "PublicKeyToken", StringComparison.OrdinalIgnoreCase)) { if ((seen & AssemblyIdentityParts.PublicKeyToken) != 0) { return(false); } seen |= AssemblyIdentityParts.PublicKeyToken; if (propertyValue == "*") { continue; } ImmutableArray <byte> value; if (!TryParsePublicKeyToken(propertyValue, out value)) { return(false); } publicKeyToken = value; parsedParts |= AssemblyIdentityParts.PublicKeyToken; } else if (string.Equals(propertyName, "Retargetable", StringComparison.OrdinalIgnoreCase)) { if ((seen & AssemblyIdentityParts.Retargetability) != 0) { return(false); } seen |= AssemblyIdentityParts.Retargetability; if (propertyValue == "*") { continue; } if (string.Equals(propertyValue, "Yes", StringComparison.OrdinalIgnoreCase)) { isRetargetable = true; } else if (string.Equals(propertyValue, "No", StringComparison.OrdinalIgnoreCase)) { isRetargetable = false; } else { return(false); } parsedParts |= AssemblyIdentityParts.Retargetability; } else if (string.Equals(propertyName, "ContentType", StringComparison.OrdinalIgnoreCase)) { if ((seen & AssemblyIdentityParts.ContentType) != 0) { return(false); } seen |= AssemblyIdentityParts.ContentType; if (propertyValue == "*") { continue; } if (string.Equals(propertyValue, "WindowsRuntime", StringComparison.OrdinalIgnoreCase)) { contentType = AssemblyContentType.WindowsRuntime; } else { return(false); } parsedParts |= AssemblyIdentityParts.ContentType; } else { parsedParts |= AssemblyIdentityParts.Unknown; } } // incompatible values: if (isRetargetable && contentType == AssemblyContentType.WindowsRuntime) { return(false); } bool hasPublicKey = !publicKey.IsDefault; bool hasPublicKeyToken = !publicKeyToken.IsDefault; identity = new AssemblyIdentity(simpleName, version, culture, hasPublicKey ? publicKey : publicKeyToken, hasPublicKey, isRetargetable, contentType); if (hasPublicKey && hasPublicKeyToken && !identity.PublicKeyToken.SequenceEqual(publicKeyToken)) { identity = null; return(false); } parts = parsedParts; return(true); }
public AnalyzerInfo(string filePath, AssemblyIdentity identity, Guid mvid, ImmutableArray<AssemblyIdentity> references) { Path = filePath; Identity = identity; MVID = mvid; References = references; }
/// <summary> /// Parses display name filling defaults for any basic properties that are missing. /// </summary> /// <param name="displayName">Display name.</param> /// <param name="identity">A full assembly identity.</param> /// <param name="parts"> /// Parts of the assembly identity that were specified in the display name, /// or 0 if the parsing failed. /// </param> /// <returns>True if display name parsed correctly.</returns> /// <remarks> /// The simple name has to be non-empty. /// A partially specified version might be missing build and/or revision number. The default value for these is 65535. /// The default culture is neutral (<see cref="CultureName"/> is <see cref="String.Empty"/>. /// If neither public key nor token is specified the identity is considered weak. /// </remarks> /// <exception cref="ArgumentNullException"><paramref name="displayName"/> is null.</exception> public static bool TryParseDisplayName(string displayName, out AssemblyIdentity identity, out AssemblyIdentityParts parts) { // see ndp\clr\src\Binder\TextualIdentityParser.cpp, ndp\clr\src\Binder\StringLexer.cpp identity = null; parts = 0; if (displayName == null) { throw new ArgumentNullException("displayName"); } if (displayName.IndexOf('\0') >= 0) { return(false); } int position = 0; string simpleName = TryParseNameToken(displayName, ',', ref position); if (simpleName == null) { return(false); } var parsedParts = AssemblyIdentityParts.Name; var seen = AssemblyIdentityParts.Name; Version version = null; string culture = null; bool isRetargetable = false; var contentType = AssemblyContentType.Default; var publicKey = default(ImmutableArray <byte>); var publicKeyToken = default(ImmutableArray <byte>); while (position < displayName.Length) { string propertyName = TryParseNameToken(displayName, '=', ref position); if (propertyName == null) { return(false); } string propertyValue = TryParseNameToken(displayName, ',', ref position); if (propertyValue == null) { return(false); } if (string.Equals(propertyName, "Version", StringComparison.OrdinalIgnoreCase)) { if ((seen & AssemblyIdentityParts.Version) != 0) { return(false); } seen |= AssemblyIdentityParts.Version; if (propertyValue == "*") { continue; } ulong versionLong; AssemblyIdentityParts versionParts; if (!TryParseVersion(propertyValue, out versionLong, out versionParts)) { return(false); } version = ToVersion(versionLong); parsedParts |= versionParts; } else if (string.Equals(propertyName, "Culture", StringComparison.OrdinalIgnoreCase) || string.Equals(propertyName, "Language", StringComparison.OrdinalIgnoreCase)) { if ((seen & AssemblyIdentityParts.Culture) != 0) { return(false); } seen |= AssemblyIdentityParts.Culture; if (propertyValue == "*") { continue; } culture = string.Equals(propertyValue, "neutral", StringComparison.OrdinalIgnoreCase) ? null : propertyValue; parsedParts |= AssemblyIdentityParts.Culture; } else if (string.Equals(propertyName, "PublicKey", StringComparison.OrdinalIgnoreCase)) { if ((seen & AssemblyIdentityParts.PublicKey) != 0) { return(false); } seen |= AssemblyIdentityParts.PublicKey; if (propertyValue == "*") { continue; } ImmutableArray <byte> value = ParseKey(propertyValue); if (value.Length == 0) { return(false); } publicKey = value; parsedParts |= AssemblyIdentityParts.PublicKey; } else if (string.Equals(propertyName, "PublicKeyToken", StringComparison.OrdinalIgnoreCase)) { if ((seen & AssemblyIdentityParts.PublicKeyToken) != 0) { return(false); } seen |= AssemblyIdentityParts.PublicKeyToken; if (propertyValue == "*") { continue; } ImmutableArray <byte> value; if (string.Equals(propertyValue, "null", StringComparison.OrdinalIgnoreCase) || string.Equals(propertyValue, "neutral", StringComparison.OrdinalIgnoreCase)) { value = ImmutableArray.Create <byte>(); } else { value = ParseKey(propertyValue); if (value.Length != PublicKeyTokenSize) { return(false); } } publicKeyToken = value; parsedParts |= AssemblyIdentityParts.PublicKeyToken; } else if (string.Equals(propertyName, "Retargetable", StringComparison.OrdinalIgnoreCase)) { if ((seen & AssemblyIdentityParts.Retargetability) != 0) { return(false); } seen |= AssemblyIdentityParts.Retargetability; if (propertyValue == "*") { continue; } if (string.Equals(propertyValue, "Yes", StringComparison.OrdinalIgnoreCase)) { isRetargetable = true; } else if (string.Equals(propertyValue, "No", StringComparison.OrdinalIgnoreCase)) { isRetargetable = false; } else { return(false); } parsedParts |= AssemblyIdentityParts.Retargetability; } else if (string.Equals(propertyName, "ContentType", StringComparison.OrdinalIgnoreCase)) { if ((seen & AssemblyIdentityParts.ContentType) != 0) { return(false); } seen |= AssemblyIdentityParts.ContentType; if (propertyValue == "*") { continue; } if (string.Equals(propertyValue, "WindowsRuntime", StringComparison.OrdinalIgnoreCase)) { contentType = AssemblyContentType.WindowsRuntime; } else { return(false); } parsedParts |= AssemblyIdentityParts.ContentType; } else { parsedParts |= AssemblyIdentityParts.Unknown; } } // incompatible values: if (isRetargetable && contentType == AssemblyContentType.WindowsRuntime) { return(false); } bool hasPublicKey = !publicKey.IsDefault; bool hasPublicKeyToken = !publicKeyToken.IsDefault; identity = new AssemblyIdentity(simpleName, version, culture, hasPublicKey ? publicKey : publicKeyToken, hasPublicKey, isRetargetable, contentType); if (hasPublicKey && hasPublicKeyToken && !identity.PublicKeyToken.SequenceEqual(publicKeyToken)) { identity = null; return(false); } parts = parsedParts; return(true); }
internal static bool IsReservedAssemblyName(AssemblyIdentity identity) { return identity.Name.StartsWith(s_globalAssemblyNamePrefix); }
public CollectibleCodeManager(AssemblyLoader assemblyLoader, string assemblyNamePrefix) { this.assemblyLoader = assemblyLoader; _dynamicAssemblyName = new AssemblyIdentity(name: assemblyNamePrefix + "CD"); AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(Resolve); }
// Windows[.winmd] private static bool IsWindowsRuntime(AssemblyIdentity identity) { return((identity.ContentType == AssemblyContentType.WindowsRuntime) && string.Equals(identity.Name, "windows", StringComparison.OrdinalIgnoreCase)); }
internal UncollectibleCodeManager(AssemblyLoader assemblyLoader, string assemblyNamePrefix) { _assemblyLoader = assemblyLoader; _assemblyNamePrefix = assemblyNamePrefix; this.dynamicAssemblyName = new AssemblyIdentity(name: assemblyNamePrefix + "UD"); AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(Resolve); }
public ReferencedAssemblyIdentity(AssemblyIdentity identity, MetadataReference reference, int relativeAssemblyIndex) { Identity = identity; Reference = reference; RelativeAssemblyIndex = relativeAssemblyIndex; }
protected abstract bool WeakIdentityPropertiesEquivalent(AssemblyIdentity identity1, AssemblyIdentity identity2);
public bool Contains(AssemblyIdentity identity, bool allowHigherVersion = true) { TValue value; return(TryGetValue(identity, out value, allowHigherVersion)); }