/// <summary> /// Remove any modules that are not in the set of referenced modules. /// If there are duplicates of referenced modules, potentially differing by /// version, one instance of the highest version is kept and others dropped. /// </summary> /// <remarks> /// Binding against this reduced set of modules will not handle certain valid cases /// where binding to full set would succeed (e.g.: binding to types outside the /// referenced modules). And since duplicates are dropped, this will prevent resolving /// ambiguities between two versions of the same assembly by using aliases. Also, /// there is no attempt here to follow binding redirects or to use the CLR to determine /// which version of an assembly to prefer when there are duplicate assemblies. /// </remarks> private static void RemoveUnreferencedModules( ArrayBuilder <MetadataReference> modules, ArrayBuilder <AssemblyIdentity> identities, AssemblyIdentityComparer identityComparer, ArrayBuilder <AssemblyIdentity> referencedModules) { Debug.Assert(modules.Count == identities.Count); var referencedIndices = PooledHashSet <int> .GetInstance(); int n = identities.Count; int index; foreach (var referencedModule in referencedModules) { index = -1; for (int i = 0; i < n; i++) { var identity = identities[i]; var compareResult = identityComparer.Compare(referencedModule, identity); switch (compareResult) { case AssemblyIdentityComparer.ComparisonResult.NotEquivalent: break; case AssemblyIdentityComparer.ComparisonResult.Equivalent: case AssemblyIdentityComparer.ComparisonResult.EquivalentIgnoringVersion: if ((index < 0) || (identity.Version > identities[index].Version)) { index = i; } break; default: throw ExceptionUtilities.UnexpectedValue(compareResult); } } if (index >= 0) { referencedIndices.Add(index); } } Debug.Assert(referencedIndices.Count <= modules.Count); Debug.Assert(referencedIndices.Count <= referencedModules.Count); index = 0; for (int i = 0; i < n; i++) { if (referencedIndices.Contains(i)) { modules[index] = modules[i]; index++; } } modules.Clip(index); referencedIndices.Free(); }
private static ImmutableArray <byte> SerializeBitVector(ImmutableArray <TypedConstant> vector) { ArrayBuilder <byte> builder = ArrayBuilder <byte> .GetInstance(); int b = 0; int shift = 0; for (int i = 0; i < vector.Length; i++) { if ((bool)vector[i].Value) { b |= 1 << shift; } if (shift == 7) { builder.Add((byte)b); b = 0; shift = 0; } else { shift++; } } if (b != 0) { builder.Add((byte)b); } else { // trim trailing zeros: int lastNonZero = builder.Count - 1; while (builder[lastNonZero] == 0) { lastNonZero--; } builder.Clip(lastNonZero + 1); } return(builder.ToImmutableAndFree()); }
/// <summary> /// Remove any modules that are not in the set of referenced modules. /// If there are duplicates of referenced modules, potentially differing by /// version, one instance of the highest version is kept and others dropped. /// </summary> /// <remarks> /// Binding against this reduced set of modules will not handle certain valid cases /// where binding to full set would succeed (e.g.: binding to types outside the /// referenced modules). And since duplicates are dropped, this will prevent resolving /// ambiguities between two versions of the same assembly by using aliases. Also, /// there is no attempt here to follow binding redirects or to use the CLR to determine /// which version of an assembly to prefer when there are duplicate assemblies. /// </remarks> private static void RemoveUnreferencedModules( ArrayBuilder<MetadataReference> modules, ArrayBuilder<AssemblyIdentity> identities, AssemblyIdentityComparer identityComparer, ArrayBuilder<AssemblyIdentity> referencedModules) { Debug.Assert(modules.Count == identities.Count); var referencedIndices = PooledHashSet<int>.GetInstance(); int n = identities.Count; int index; foreach (var referencedModule in referencedModules) { index = -1; for (int i = 0; i < n; i++) { var identity = identities[i]; var compareResult = identityComparer.Compare(referencedModule, identity); switch (compareResult) { case AssemblyIdentityComparer.ComparisonResult.NotEquivalent: break; case AssemblyIdentityComparer.ComparisonResult.Equivalent: case AssemblyIdentityComparer.ComparisonResult.EquivalentIgnoringVersion: if ((index < 0) || (identity.Version > identities[index].Version)) { index = i; } break; default: throw ExceptionUtilities.UnexpectedValue(compareResult); } } if (index >= 0) { referencedIndices.Add(index); } } Debug.Assert(referencedIndices.Count <= modules.Count); Debug.Assert(referencedIndices.Count <= referencedModules.Count); index = 0; for (int i = 0; i < n; i++) { if (referencedIndices.Contains(i)) { modules[index] = modules[i]; index++; } } modules.Clip(index); referencedIndices.Free(); }