提交 7e879484 编写于 作者: T Tomas Matousek

Transitive #r

上级 03d11f2a
......@@ -337,6 +337,9 @@ private bool CreateAndSetSourceAssemblyFullBind(CSharpCompilation compilation)
BoundInputAssembly[] bindingResult = Bind(
explicitAssemblyData,
modules,
references,
referenceMap,
compilation.Options.MetadataReferenceResolver,
compilation.Options.MetadataImportOptions,
out allAssemblyData,
......
......@@ -2182,15 +2182,19 @@ public void MissingAssemblyResolution1()
var bRef = CreateCompilationWithMscorlib("public class B { }", assemblyName: "B").EmitToImageReference();
var aRef = CreateCompilationWithMscorlib("public class A : B { }", new[] { bRef }, assemblyName: "A").EmitToImageReference();
var c = CreateCompilationWithMscorlib("public class C : A { }", new[] { aRef },
TestOptions.ReleaseDll.WithMetadataReferenceResolver(new TestMissingMetadataReferenceResolver(new Dictionary<string, MetadataReference>
{
{ "B", bRef }
})));
var resolver = new TestMissingMetadataReferenceResolver(new Dictionary<string, MetadataReference>
{
{ "B", bRef }
});
var c = CreateCompilationWithMscorlib("public class C : A { }", new[] { aRef }, TestOptions.ReleaseDll.WithMetadataReferenceResolver(resolver));
c.VerifyEmitDiagnostics();
Assert.Equal("B", ((AssemblySymbol)c.GetAssemblyOrModuleSymbol(bRef)).Name);
resolver.VerifyResolutionAttempts(
"A -> B, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
}
[Fact]
......@@ -2200,6 +2204,11 @@ public void MissingAssemblyResolution_Aliases()
var bRef = CreateCompilationWithMscorlib("public class B { }", assemblyName: "B").EmitToImageReference();
var aRef = CreateCompilationWithMscorlib("public class A : B { }", new[] { bRef }, assemblyName: "A").EmitToImageReference();
var resolver = new TestMissingMetadataReferenceResolver(new Dictionary<string, MetadataReference>
{
{ "B", bRef.WithAliases(ImmutableArray.Create("X")) }
});
var c = CreateCompilationWithMscorlib(@"
extern alias X;
......@@ -2207,13 +2216,12 @@ public class C : A
{
X::B F() => null;
}
", new[] { aRef },
TestOptions.ReleaseDll.WithMetadataReferenceResolver(new TestMissingMetadataReferenceResolver(new Dictionary<string, MetadataReference>
{
{ "B", bRef.WithAliases(ImmutableArray.Create("X")) }
})));
", new[] { aRef }, TestOptions.ReleaseDll.WithMetadataReferenceResolver(resolver));
c.VerifyEmitDiagnostics();
resolver.VerifyResolutionAttempts(
"A -> B, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
}
[Fact]
......@@ -2231,6 +2239,12 @@ public void MissingAssemblyResolution_AliasesMerge()
var b3RefX = b3Ref.WithAliases(ImmutableArray.Create("X"));
var b3RefY = b3Ref.WithAliases(ImmutableArray.Create("Y"));
var resolver = new TestMissingMetadataReferenceResolver(new Dictionary<string, MetadataReference>
{
{ "B, 1.0.0.0", b3RefX },
{ "B, 2.0.0.0", b3RefY },
});
var c = CreateCompilationWithMscorlib(@"
extern alias X;
extern alias Y;
......@@ -2240,11 +2254,7 @@ public class C : A
X::B F() => new Y::B();
}
", new[] { aRef, dRef },
TestOptions.ReleaseDll.WithMetadataReferenceResolver(new TestMissingMetadataReferenceResolver(new Dictionary<string, MetadataReference>
{
{ "B, 1.0.0.0", b3RefX },
{ "B, 2.0.0.0", b3RefY },
})));
TestOptions.ReleaseDll.WithMetadataReferenceResolver(resolver));
c.VerifyEmitDiagnostics(
// (5,18): warning CS1701: Assuming assembly reference
......@@ -2256,6 +2266,10 @@ public class C : A
Assert.Equal("B", ((AssemblySymbol)c.GetAssemblyOrModuleSymbol(b3RefY)).Name);
Assert.Null(c.GetAssemblyOrModuleSymbol(b3RefX));
resolver.VerifyResolutionAttempts(
"D -> B, Version=2.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2",
"A -> B, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2");
}
[Fact]
......@@ -2271,16 +2285,22 @@ public void MissingAssemblyResolution_WeakIdentities1()
var aRef = CreateCompilationWithMscorlib(@"public interface A : B { }", new[] { b1Ref }, assemblyName: "A").EmitToImageReference();
var dRef = CreateCompilationWithMscorlib(@"public interface D : B { }", new[] { b2Ref }, assemblyName: "D").EmitToImageReference();
var resolver = new TestMissingMetadataReferenceResolver(new Dictionary<string, MetadataReference>
{
{ "B, 1.0.0.0", b1Ref },
{ "B, 2.0.0.0", b2Ref },
});
var c = CreateCompilationWithMscorlib(@"public interface C : A, D { }", new[] { aRef, dRef },
TestOptions.ReleaseDll.WithMetadataReferenceResolver(new TestMissingMetadataReferenceResolver(new Dictionary<string, MetadataReference>
{
{ "B, 1.0.0.0", b1Ref },
{ "B, 2.0.0.0", b2Ref },
})));
TestOptions.ReleaseDll.WithMetadataReferenceResolver(resolver));
c.VerifyEmitDiagnostics(
// error CS1704: An assembly with the same simple name 'B' has already been imported. Try removing one of the references (e.g. 'B') or sign them to enable side-by-side.
Diagnostic(ErrorCode.ERR_DuplicateImportSimple).WithArguments("B", "B"));
resolver.VerifyResolutionAttempts(
"D -> B, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null",
"A -> B, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
}
[Fact]
......@@ -2296,16 +2316,22 @@ public void MissingAssemblyResolution_WeakIdentities2()
var aRef = CreateCompilationWithMscorlib(@"public interface A : B { }", new[] { b1Ref }, assemblyName: "A").EmitToImageReference();
var dRef = CreateCompilationWithMscorlib(@"public interface D : B { }", new[] { b2Ref }, assemblyName: "D").EmitToImageReference();
var resolver = new TestMissingMetadataReferenceResolver(new Dictionary<string, MetadataReference>
{
{ "B, 1.0.0.0", b3Ref },
{ "B, 2.0.0.0", b4Ref },
});
var c = CreateCompilationWithMscorlib(@"public interface C : A, D { }", new[] { aRef, dRef },
TestOptions.ReleaseDll.WithMetadataReferenceResolver(new TestMissingMetadataReferenceResolver(new Dictionary<string, MetadataReference>
{
{ "B, 1.0.0.0", b3Ref },
{ "B, 2.0.0.0", b4Ref },
})));
TestOptions.ReleaseDll.WithMetadataReferenceResolver(resolver));
c.VerifyEmitDiagnostics(
// error CS1704: An assembly with the same simple name 'B' has already been imported. Try removing one of the references (e.g. 'B') or sign them to enable side-by-side.
Diagnostic(ErrorCode.ERR_DuplicateImportSimple).WithArguments("B", "B"));
resolver.VerifyResolutionAttempts(
"D -> B, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null",
"A -> B, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
}
[Fact]
......@@ -2322,8 +2348,7 @@ public void MissingAssemblyResolution_None()
TestOptions.ReleaseDll.WithMetadataReferenceResolver(resolver));
c.VerifyDiagnostics();
Assert.Equal(0, resolver.ResolutionAttempts.Count);
resolver.VerifyResolutionAttempts();
}
[Fact]
......@@ -2342,7 +2367,8 @@ public void MissingAssemblyResolution_ActualMissing()
// (1,18): error CS0012: The type 'D' is defined in an assembly that is not referenced. You must add a reference to assembly 'D, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
Diagnostic(ErrorCode.ERR_NoTypeDef, "C").WithArguments("D", "D, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"));
Assert.Equal(1, resolver.ResolutionAttempts.Count);
resolver.VerifyResolutionAttempts(
"A -> D, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
}
/// <summary>
......@@ -2369,7 +2395,8 @@ public void MissingAssemblyResolution_MissingDueToResolutionMismatch()
// (1,18): error CS0012: The type 'D' is defined in an assembly that is not referenced. You must add a reference to assembly 'B, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
Diagnostic(ErrorCode.ERR_NoTypeDef, "C").WithArguments("D", "B, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"));
Assert.Equal(1, resolver.ResolutionAttempts.Count);
resolver.VerifyResolutionAttempts(
"A -> B, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
}
[Fact]
......@@ -2392,7 +2419,9 @@ public void MissingAssemblyResolution_Multiple()
c.VerifyEmitDiagnostics();
Assert.Equal("D", ((AssemblySymbol)c.GetAssemblyOrModuleSymbol(dRef)).Name);
Assert.Equal(1, resolver.ResolutionAttempts.Count);
resolver.VerifyResolutionAttempts(
"B -> D, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
}
[Fact]
......@@ -2423,6 +2452,11 @@ public void MissingAssemblyResolution_Modules()
Assert.Equal("B", ((AssemblySymbol)c.GetAssemblyOrModuleSymbol(bRef)).Name);
Assert.Equal("D", ((AssemblySymbol)c.GetAssemblyOrModuleSymbol(dRef)).Name);
// We don't resolve one assembly reference identity twice, even if the requesting definition is different.
resolver.VerifyResolutionAttempts(
"A -> D, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null",
"M.netmodule -> B, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
}
/// <summary>
......@@ -2457,13 +2491,13 @@ public void MissingAssemblyResolution_BindingToForExplicitReference1()
"B, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2", "A",
"B, Version=3.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2", "B"));
Assert.Equal(0, resolver.ResolutionAttempts.Count);
Assert.Equal(
"B, Version=3.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2",
((AssemblySymbol)c.GetAssemblyOrModuleSymbol(b3Ref)).Identity.GetDisplayName());
Assert.Null((AssemblySymbol)c.GetAssemblyOrModuleSymbol(b2Ref));
resolver.VerifyResolutionAttempts();
}
/// <summary>
......@@ -2520,7 +2554,9 @@ public void MissingAssemblyResolution_BindingToExplicitReference_WorseVersion()
"B, Version=2.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2",
"B", "B, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2"));
Assert.Equal(2, resolverC.ResolutionAttempts.Count);
resolverC.VerifyResolutionAttempts(
"A -> D, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2",
"A -> E, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2");
}
/// <summary>
......@@ -2573,7 +2609,9 @@ public void MissingAssemblyResolution_BindingToExplicitReference_BetterVersion()
"B, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2", "E",
"B, Version=2.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2", "B"));
Assert.Equal(2, resolverC.ResolutionAttempts.Count);
resolverC.VerifyResolutionAttempts(
"A -> D, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2",
"A -> E, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2");
}
[Fact]
......@@ -2614,6 +2652,12 @@ public void MissingAssemblyResolution_BindingToImplicitReference1()
Assert.Equal(
"B, Version=2.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2",
((AssemblySymbol)c.GetAssemblyOrModuleSymbol(b2Ref)).Identity.GetDisplayName());
resolverC.VerifyResolutionAttempts(
"A -> D, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2",
"A -> B, Version=2.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2",
"A -> E, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2",
"A -> B, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2");
}
[Fact]
......@@ -2667,8 +2711,6 @@ public void MissingAssemblyResolution_BindingToImplicitReference2()
"B, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2", "E",
"B, Version=3.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2", "B"));
Assert.Equal(4, resolverC.ResolutionAttempts.Count);
AssertEx.Equal(new[]
{
"mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
......@@ -2678,6 +2720,12 @@ public void MissingAssemblyResolution_BindingToImplicitReference2()
"E, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2",
"B, Version=3.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2"
}, c.GetBoundReferenceManager().ReferencedAssemblies.Select(a => a.Identity.GetDisplayName()));
resolverC.VerifyResolutionAttempts(
"A -> D, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2",
"A -> B, Version=2.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2",
"A -> E, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2",
"A -> B, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2");
}
}
}
......@@ -15,7 +15,7 @@ public abstract class MetadataReferenceResolver
public abstract ImmutableArray<PortableExecutableReference> ResolveReference(string reference, string baseFilePath, MetadataReferenceProperties properties);
/// <summary>
/// True to instruct the compiler to invoke <see cref="ResolveMissingAssembly(AssemblyIdentity)"/> for each assembly reference that
/// True to instruct the compiler to invoke <see cref="ResolveMissingAssembly(MetadataReference, AssemblyIdentity)"/> for each assembly reference that
/// doesn't match any of the assemblies explicitly referenced by the <see cref="Compilation"/> (via <see cref="Compilation.ExternalReferences"/>, or #r directives.
/// </summary>
public virtual bool ResolveMissingAssemblies => false;
......@@ -23,8 +23,9 @@ public abstract class MetadataReferenceResolver
/// <summary>
/// Resolves a missing assembly reference.
/// </summary>
/// <param name="identity">Identity of the assembly reference.</param>
/// <param name="definition">The metadata definition (assembly or module) that declares assembly reference <paramref name="referenceIdentity"/> in its list of dependencies.</param>
/// <param name="referenceIdentity">Identity of the assembly reference that couldn't be resolved against metadata references explicitly specified to in the compilation.</param>
/// <returns>Resolved reference or null if the identity can't be resolved.</returns>
public virtual PortableExecutableReference ResolveMissingAssembly(AssemblyIdentity identity) => null;
public virtual PortableExecutableReference ResolveMissingAssembly(MetadataReference definition, AssemblyIdentity referenceIdentity) => null;
}
}
......@@ -63,5 +63,5 @@ static Microsoft.CodeAnalysis.Diagnostics.Telemetry.AnalyzerTelemetry.GetAnalyze
static Microsoft.CodeAnalysis.SyntaxNodeExtensions.NormalizeWhitespace<TNode>(this TNode node, string indentation = " ", string eol = "\r\n", bool elasticTrivia = false) -> TNode
static Microsoft.CodeAnalysis.SyntaxNodeExtensions.NormalizeWhitespace<TNode>(this TNode node, string indentation, bool elasticTrivia) -> TNode
virtual Microsoft.CodeAnalysis.MetadataReferenceResolver.ResolveMissingAssemblies.get -> bool
virtual Microsoft.CodeAnalysis.MetadataReferenceResolver.ResolveMissingAssembly(Microsoft.CodeAnalysis.AssemblyIdentity identity) -> Microsoft.CodeAnalysis.PortableExecutableReference
virtual Microsoft.CodeAnalysis.MetadataReferenceResolver.ResolveMissingAssembly(Microsoft.CodeAnalysis.MetadataReference definition, Microsoft.CodeAnalysis.AssemblyIdentity referenceIdentity) -> Microsoft.CodeAnalysis.PortableExecutableReference
virtual Microsoft.CodeAnalysis.SourceReferenceResolver.ReadText(string resolvedPath) -> Microsoft.CodeAnalysis.Text.SourceText
\ No newline at end of file
......@@ -26,6 +26,16 @@ internal partial class CommonReferenceManager<TCompilation, TAssemblySymbol>
/// An array of <see cref="AssemblyData"/> objects describing assemblies, for which this method should
/// resolve references and find suitable AssemblySymbols. The first slot contains the assembly being built.
/// </param>
/// <param name="explicitModules">
/// An array of <see cref="PEModule"/> objects describing standalone modules referenced by the compilation.
/// </param>
/// <param name="explicitReferences">
/// An array of references passed to the compilation and resolved from #r directives.
/// May contain references that were skipped during resolution (they don't have a corresponding explicit assmebly).
/// </param>
/// <param name="explicitReferenceMap">
/// Maps index to <paramref name="explicitReferences"/> to an index of a resolved assembly or module in <paramref name="explicitAssemblies"/> or modules.
/// </param>
/// <param name="resolverOpt">
/// Reference resolver used to look up missing assemblies.
/// </param>
......@@ -66,6 +76,9 @@ internal partial class CommonReferenceManager<TCompilation, TAssemblySymbol>
/// </return>
protected BoundInputAssembly[] Bind(
ImmutableArray<AssemblyData> explicitAssemblies,
ImmutableArray<PEModule> explicitModules,
ImmutableArray<MetadataReference> explicitReferences,
ImmutableArray<ResolvedReference> explicitReferenceMap,
MetadataReferenceResolver resolverOpt,
MetadataImportOptions importOptions,
out ImmutableArray<AssemblyData> allAssemblies,
......@@ -76,6 +89,7 @@ internal partial class CommonReferenceManager<TCompilation, TAssemblySymbol>
out int corLibraryIndex)
{
Debug.Assert(explicitAssemblies[0] is AssemblyDataForAssemblyBeingBuilt);
Debug.Assert(explicitReferences.Length == explicitReferenceMap.Length);
var referenceBindings = ArrayBuilder<AssemblyReferenceBinding[]>.GetInstance();
try
......@@ -89,7 +103,7 @@ internal partial class CommonReferenceManager<TCompilation, TAssemblySymbol>
if (resolverOpt?.ResolveMissingAssemblies == true)
{
ResolveAndBindMissingAssemblies(explicitAssemblies, resolverOpt, importOptions, referenceBindings, out allAssemblies, out implicitlyResolvedReferences, out implicitlyResolvedReferenceMap, resolutionDiagnostics);
ResolveAndBindMissingAssemblies(explicitAssemblies, explicitModules, explicitReferences, explicitReferenceMap, resolverOpt, importOptions, referenceBindings, out allAssemblies, out implicitlyResolvedReferences, out implicitlyResolvedReferenceMap, resolutionDiagnostics);
}
else
{
......@@ -147,6 +161,9 @@ internal partial class CommonReferenceManager<TCompilation, TAssemblySymbol>
private void ResolveAndBindMissingAssemblies(
ImmutableArray<AssemblyData> explicitAssemblies,
ImmutableArray<PEModule> explicitModules,
ImmutableArray<MetadataReference> explicitReferences,
ImmutableArray<ResolvedReference> explicitReferenceMap,
MetadataReferenceResolver resolver,
MetadataImportOptions importOptions,
[In, Out] ArrayBuilder<AssemblyReferenceBinding[]> referenceBindings,
......@@ -156,28 +173,37 @@ internal partial class CommonReferenceManager<TCompilation, TAssemblySymbol>
DiagnosticBag resolutionDiagnostics)
{
Debug.Assert(explicitAssemblies[0] is AssemblyDataForAssemblyBeingBuilt);
Debug.Assert(referenceBindings.Count == explicitAssemblies.Length);
Debug.Assert(explicitReferences.Length == explicitReferenceMap.Length);
// -1 for assembly being built:
int totalReferencedAssemblyCount = explicitAssemblies.Length - 1;
var implicitAssemblies = ArrayBuilder<AssemblyData>.GetInstance();
// tracks identities we already asked the resolver to resolve:
var requestedIdentities = PooledHashSet<AssemblyIdentity>.GetInstance();
// reference bindings of implicit assemblies, used to calculate a fixed point:
var referenceBindingsToProcess = ArrayBuilder<AssemblyReferenceBinding[]>.GetInstance();
var metadataReferencesBuilder = ArrayBuilder<MetadataReference>.GetInstance();
Dictionary<string, List<ReferencedAssemblyIdentity>> lazyResolvedReferencesBySimpleName = null;
Dictionary<MetadataReference, ArrayBuilder<string>> lazyAliasMap = null;
// metadata references and corresponding bindings of their references, used to calculate a fixed point:
var referenceBindingsToProcess = ArrayBuilder<ValueTuple<MetadataReference, ArraySegment<AssemblyReferenceBinding>>>.GetInstance();
// collect all missing identities, resolve the assemblies and bind their references against explicit definitions:
GetInitialReferenceBindingsToProcess(explicitModules, explicitReferences, explicitReferenceMap, referenceBindings, totalReferencedAssemblyCount, referenceBindingsToProcess);
try
{
// collect all missing identities, resolve the assemblies and bind their references against explicit definitions:
referenceBindingsToProcess.AddRange(referenceBindings);
while (referenceBindingsToProcess.Count > 0)
{
foreach (var binding in referenceBindingsToProcess.Pop())
var referenceAndBindings = referenceBindingsToProcess.Pop();
var requestingReference = referenceAndBindings.Item1;
var bindings = referenceAndBindings.Item2;
foreach (var binding in bindings)
{
// only attempt to resolve unbound references (regardless of version difference of the bound ones)
if (binding.IsBound)
......@@ -190,13 +216,13 @@ internal partial class CommonReferenceManager<TCompilation, TAssemblySymbol>
continue;
}
var peReference = resolver.ResolveMissingAssembly(binding.ReferenceIdentity);
if (peReference == null)
var resolvedReference = resolver.ResolveMissingAssembly(requestingReference, binding.ReferenceIdentity);
if (resolvedReference == null)
{
continue;
}
var data = ResolveMissingAssembly(binding.ReferenceIdentity, peReference, importOptions, resolutionDiagnostics);
var data = ResolveMissingAssembly(binding.ReferenceIdentity, resolvedReference, importOptions, resolutionDiagnostics);
if (data == null)
{
continue;
......@@ -208,19 +234,19 @@ internal partial class CommonReferenceManager<TCompilation, TAssemblySymbol>
// If such case occurs merge the properties (aliases) of the resulting references in the same way we do
// during initial explicit references resolution.
var existingReference = TryAddAssembly(data.Identity, peReference, resolutionDiagnostics, Location.None, ref lazyResolvedReferencesBySimpleName);
var existingReference = TryAddAssembly(data.Identity, resolvedReference, resolutionDiagnostics, Location.None, ref lazyResolvedReferencesBySimpleName);
if (existingReference != null)
{
MergeReferenceProperties(existingReference, peReference, resolutionDiagnostics, ref lazyAliasMap);
MergeReferenceProperties(existingReference, resolvedReference, resolutionDiagnostics, ref lazyAliasMap);
continue;
}
metadataReferencesBuilder.Add(peReference);
metadataReferencesBuilder.Add(resolvedReference);
implicitAssemblies.Add(data);
var referenceBinding = data.BindAssemblyReferences(explicitAssemblies, IdentityComparer);
referenceBindings.Add(referenceBinding);
referenceBindingsToProcess.Push(referenceBinding);
referenceBindingsToProcess.Push(ValueTuple.Create((MetadataReference)resolvedReference, new ArraySegment<AssemblyReferenceBinding>(referenceBinding)));
}
}
......@@ -241,7 +267,7 @@ internal partial class CommonReferenceManager<TCompilation, TAssemblySymbol>
// NB: includes the assembly being built:
int explicitAssemblyCount = explicitAssemblies.Length;
allAssemblies = explicitAssemblies.AddRange(implicitAssemblies);
for (int bindingsIndex = 0; bindingsIndex < referenceBindings.Count; bindingsIndex++)
{
var referenceBinding = referenceBindings[bindingsIndex];
......@@ -281,6 +307,77 @@ internal partial class CommonReferenceManager<TCompilation, TAssemblySymbol>
}
}
private void GetInitialReferenceBindingsToProcess(
ImmutableArray<PEModule> explicitModules,
ImmutableArray<MetadataReference> explicitReferences,
ImmutableArray<ResolvedReference> explicitReferenceMap,
ArrayBuilder<AssemblyReferenceBinding[]> referenceBindings,
int totalReferencedAssemblyCount,
[Out]ArrayBuilder<ValueTuple<MetadataReference, ArraySegment<AssemblyReferenceBinding>>> result)
{
Debug.Assert(result.Count == 0);
// maps module index to explicitReferences index
var explicitModuleToReferenceMap = CalculateModuleToReferenceMap(explicitModules, explicitReferenceMap);
// add module bindings of assembly being built:
var bindingsOfAssemblyBeingBuilt = referenceBindings[0];
int bindingIndex = totalReferencedAssemblyCount;
for (int moduleIndex = 0; moduleIndex < explicitModules.Length; moduleIndex++)
{
var moduleReference = explicitReferences[explicitModuleToReferenceMap[moduleIndex]];
var moduleBindingsCount = explicitModules[moduleIndex].ReferencedAssemblies.Length;
result.Add(ValueTuple.Create(
moduleReference,
new ArraySegment<AssemblyReferenceBinding>(bindingsOfAssemblyBeingBuilt, bindingIndex, moduleBindingsCount)));
bindingIndex += moduleBindingsCount;
}
Debug.Assert(bindingIndex == bindingsOfAssemblyBeingBuilt.Length);
// the first binding is for the assembly being built, all its references are bound or added above
for (int referenceIndex = 0; referenceIndex < explicitReferenceMap.Length; referenceIndex++)
{
var explicitReferenceMapping = explicitReferenceMap[referenceIndex];
if (explicitReferenceMapping.IsSkipped || explicitReferenceMapping.Kind == MetadataImageKind.Module)
{
continue;
}
// +1 for the assembly being built
result.Add(ValueTuple.Create(
explicitReferences[referenceIndex],
new ArraySegment<AssemblyReferenceBinding>(referenceBindings[explicitReferenceMapping.Index + 1])));
}
// we have a reference binding for each module and for each referenced assembly:
Debug.Assert(result.Count == explicitModules.Length + totalReferencedAssemblyCount);
}
private ImmutableArray<int> CalculateModuleToReferenceMap(ImmutableArray<PEModule> modules, ImmutableArray<ResolvedReference> resolvedReferences)
{
if (modules.Length == 0)
{
return ImmutableArray<int>.Empty;
}
var result = ArrayBuilder<int>.GetInstance(modules.Length);
result.ZeroInit(modules.Length);
for (int i = 0; i < resolvedReferences.Length; i++)
{
var resolvedReference = resolvedReferences[i];
if (!resolvedReference.IsSkipped && resolvedReference.Kind == MetadataImageKind.Module)
{
result[resolvedReference.Index] = i;
}
}
return result.ToImmutableAndFree();
}
private static ImmutableArray<ResolvedReference> ToResolvedAssemblyReferences(
ImmutableArray<MetadataReference> references,
Dictionary<MetadataReference, ArrayBuilder<string>> aliasMapOpt,
......
......@@ -93,7 +93,7 @@ public MetadataImageKind Kind
}
/// <summary>
/// Index into an array of assemblies or an array of modules, depending on <see cref="Kind"/>.
/// Index into an array of assemblies (not including the assembly being built) or an array of modules, depending on <see cref="Kind"/>.
/// </summary>
public int Index
{
......
......@@ -285,6 +285,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Dim allAssemblyData As ImmutableArray(Of AssemblyData) = Nothing
Dim bindingResult() As BoundInputAssembly = Bind(explicitAssemblyData,
modules,
references,
referenceMap,
compilation.Options.MetadataReferenceResolver,
compilation.Options.MetadataImportOptions,
allAssemblyData,
......
......@@ -1671,15 +1671,21 @@ End Class
' c - a -> b
Dim bRef = CreateCompilationWithMscorlib({"Public Class B : End Class"}, options:=TestOptions.ReleaseDll, assemblyName:="B").EmitToImageReference()
Dim aRef = CreateCompilationWithMscorlib({"Public Class A : Inherits B : End Class"}, {bRef}, TestOptions.ReleaseDll, assemblyName:="A").EmitToImageReference()
Dim resolver As TestMissingMetadataReferenceResolver = New TestMissingMetadataReferenceResolver(New Dictionary(Of String, MetadataReference) From
{
{"B", bRef}
})
Dim c = CreateCompilationWithMscorlib({"Public Class C : Inherits A : End Class"}, {aRef},
TestOptions.ReleaseDll.WithMetadataReferenceResolver(New TestMissingMetadataReferenceResolver(New Dictionary(Of String, MetadataReference) From
{
{"B", bRef}
})))
TestOptions.ReleaseDll.WithMetadataReferenceResolver(resolver))
c.VerifyEmitDiagnostics()
Assert.Equal("B", DirectCast(c.GetAssemblyOrModuleSymbol(bRef), AssemblySymbol).Name)
Resolver.VerifyResolutionAttempts(
"A -> B, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")
End Sub
<Fact>
......@@ -1694,12 +1700,14 @@ End Class
Dim aRef = CreateCompilationWithMscorlib({"Public Interface A : Inherits B : End Interface"}, {b1Ref}, TestOptions.ReleaseDll, assemblyName:="A").EmitToImageReference()
Dim dRef = CreateCompilationWithMscorlib({"Public Interface D : Inherits B : End Interface"}, {b2Ref}, TestOptions.ReleaseDll, assemblyName:="D").EmitToImageReference()
Dim resolver As TestMissingMetadataReferenceResolver = New TestMissingMetadataReferenceResolver(New Dictionary(Of String, MetadataReference) From
{
{"B, 1.0.0.0", b1Ref},
{"B, 2.0.0.0", b2Ref}
})
Dim c = CreateCompilationWithMscorlib({"Public Interface C : Inherits A, D : End Interface"}, {aRef, dRef},
TestOptions.ReleaseDll.WithMetadataReferenceResolver(New TestMissingMetadataReferenceResolver(New Dictionary(Of String, MetadataReference) From
{
{"B, 1.0.0.0", b1Ref},
{"B, 2.0.0.0", b2Ref}
})))
TestOptions.ReleaseDll.WithMetadataReferenceResolver(resolver))
AssertEx.Equal(
{
......@@ -1710,6 +1718,9 @@ End Class
"B, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
}, c.GetBoundReferenceManager().ReferencedAssemblies.Select(Function(a) a.Identity.GetDisplayName()))
resolver.VerifyResolutionAttempts(
"D -> B, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null",
"A -> B, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
End Sub
<Fact>
......@@ -1724,12 +1735,14 @@ End Class
Dim aRef = CreateCompilationWithMscorlib({"Public Interface A : Inherits B : End Interface"}, {b1Ref}, TestOptions.ReleaseDll, assemblyName:="A").EmitToImageReference()
Dim dRef = CreateCompilationWithMscorlib({"Public Interface D : Inherits B : End Interface"}, {b2Ref}, TestOptions.ReleaseDll, assemblyName:="D").EmitToImageReference()
Dim resolver As TestMissingMetadataReferenceResolver = New TestMissingMetadataReferenceResolver(New Dictionary(Of String, MetadataReference) From
{
{"B, 1.0.0.0", b3Ref},
{"B, 2.0.0.0", b4Ref}
})
Dim c = CreateCompilationWithMscorlib({"Public Interface C : Inherits A, D : End Interface"}, {aRef, dRef},
TestOptions.ReleaseDll.WithMetadataReferenceResolver(New TestMissingMetadataReferenceResolver(New Dictionary(Of String, MetadataReference) From
{
{"B, 1.0.0.0", b3Ref},
{"B, 2.0.0.0", b4Ref}
})))
TestOptions.ReleaseDll.WithMetadataReferenceResolver(resolver))
AssertEx.Equal(
{
......@@ -1739,6 +1752,10 @@ End Class
"B, Version=4.0.0.0, Culture=neutral, PublicKeyToken=null",
"B, Version=3.0.0.0, Culture=neutral, PublicKeyToken=null"
}, c.GetBoundReferenceManager().ReferencedAssemblies.Select(Function(a) a.Identity.GetDisplayName()))
resolver.VerifyResolutionAttempts(
"D -> B, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null",
"A -> B, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
End Sub
<Fact>
......@@ -1754,7 +1771,7 @@ End Class
TestOptions.ReleaseDll.WithMetadataReferenceResolver(resolver))
c.VerifyDiagnostics()
Assert.Equal(0, resolver.ResolutionAttempts.Count)
resolver.VerifyResolutionAttempts()
End Sub
<Fact>
......@@ -1771,7 +1788,8 @@ End Class
c.VerifyDiagnostics(
Diagnostic(ERRID.ERR_UnreferencedAssembly3, "A").WithArguments("D, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "D"))
Assert.Equal(1, resolver.ResolutionAttempts.Count)
resolver.VerifyResolutionAttempts(
"A -> D, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")
End Sub
''' <summary>
......@@ -1796,7 +1814,8 @@ End Class
c.VerifyDiagnostics(
Diagnostic(ERRID.ERR_UnreferencedAssembly3, "A").WithArguments("B, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "D"))
Assert.Equal(1, resolver.ResolutionAttempts.Count)
resolver.VerifyResolutionAttempts(
"A -> B, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")
End Sub
<Fact>
......@@ -1824,6 +1843,11 @@ End Class
c.VerifyEmitDiagnostics()
Assert.Equal("B", (DirectCast(c.GetAssemblyOrModuleSymbol(bRef), AssemblySymbol)).Name)
Assert.Equal("D", (DirectCast(c.GetAssemblyOrModuleSymbol(dRef), AssemblySymbol)).Name)
' We don't resolve one assembly reference identity twice, even if the requesting definition is different.
resolver.VerifyResolutionAttempts(
"A -> D, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null",
"M.netmodule -> B, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")
End Sub
''' <summary>
......@@ -1848,13 +1872,13 @@ End Class
c.VerifyEmitDiagnostics()
Assert.Equal(0, resolver.ResolutionAttempts.Count)
Assert.Equal(
"B, Version=3.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2",
DirectCast(c.GetAssemblyOrModuleSymbol(b3Ref), AssemblySymbol).Identity.GetDisplayName())
Assert.Null(DirectCast(c.GetAssemblyOrModuleSymbol(b2Ref), AssemblySymbol))
resolver.VerifyResolutionAttempts()
End Sub
''' <summary>
......@@ -1892,7 +1916,9 @@ End Class
c.VerifyEmitDiagnostics(
Diagnostic(ERRID.ERR_SxSIndirectRefHigherThanDirectRef3, "A").WithArguments("B", "2.0.0.0", "1.0.0.0"))
Assert.Equal(2, resolverC.ResolutionAttempts.Count)
resolverC.VerifyResolutionAttempts(
"A -> D, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2",
"A -> E, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2")
End Sub
''' <summary>
......@@ -1932,7 +1958,9 @@ End Class
c.VerifyEmitDiagnostics()
Assert.Equal(2, resolverC.ResolutionAttempts.Count)
resolverC.VerifyResolutionAttempts(
"A -> D, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2",
"A -> E, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2")
End Sub
<Fact>
......@@ -1965,7 +1993,6 @@ End Class
c.VerifyEmitDiagnostics()
Assert.Equal(4, resolverC.ResolutionAttempts.Count)
Assert.Equal(
"B, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2",
DirectCast(c.GetAssemblyOrModuleSymbol(b1Ref), AssemblySymbol).Identity.GetDisplayName())
......@@ -1973,6 +2000,12 @@ End Class
Assert.Equal(
"B, Version=2.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2",
DirectCast(c.GetAssemblyOrModuleSymbol(b2Ref), AssemblySymbol).Identity.GetDisplayName())
resolverC.VerifyResolutionAttempts(
"A -> D, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2",
"A -> E, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2",
"E -> B, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2",
"D -> B, Version=2.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2")
End Sub
<Fact>
......@@ -2014,6 +2047,12 @@ End Class
"B, Version=3.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2",
"B, Version=4.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2"
}, c.GetBoundReferenceManager().ReferencedAssemblies.Select(Function(a) a.Identity.GetDisplayName()))
resolverC.VerifyResolutionAttempts(
"A -> D, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2",
"A -> E, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2",
"E -> B, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2",
"D -> B, Version=2.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2")
End Sub
End Class
End Namespace
......@@ -6,6 +6,7 @@
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
......@@ -453,12 +454,19 @@ public void UserDefinedAssemblyResolve_InfiniteLoop()
}
[Fact]
public void AddReference_PartialName()
public void AddReference_Path()
{
Assert.False(Execute("System.Diagnostics.Process.GetCurrentProcess().HasExited"));
Assert.False(Execute("new System.Data.DataSet()"));
Assert.True(LoadReference(Assembly.Load(new AssemblyName("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")).Location));
Assert.True(Execute("new System.Data.DataSet()"));
}
Assert.True(LoadReference("System"));
Assert.True(Execute("System.Diagnostics.Process.GetCurrentProcess().HasExited"));
[Fact]
public void AddReference_PartialName()
{
Assert.False(Execute("new System.Data.DataSet()"));
Assert.True(LoadReference("System.Data"));
Assert.True(Execute("new System.Data.DataSet()"));
}
[Fact]
......@@ -476,10 +484,9 @@ public void AddReference_PartialName_LatestVersion()
[Fact]
public void AddReference_FullName()
{
Assert.False(Execute("System.Diagnostics.Process.GetCurrentProcess().HasExited"));
Assert.True(LoadReference(typeof(Process).Assembly.FullName));
Assert.True(Execute("System.Diagnostics.Process.GetCurrentProcess().HasExited"));
Assert.False(Execute("new System.Data.DataSet()"));
Assert.True(LoadReference("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"));
Assert.True(Execute("new System.Data.DataSet()"));
}
[ConditionalFact(typeof(Framework35Installed), Skip="https://github.com/dotnet/roslyn/issues/5167")]
......@@ -516,15 +523,6 @@ public void AddReference_AssemblyAlreadyLoaded()
Assert.True(result);
}
[Fact]
public void AddReference_Path()
{
Assert.False(Execute("System.Diagnostics.Process.GetCurrentProcess().HasExited"));
Assert.True(LoadReference(typeof(Process).Assembly.Location));
Assert.True(Execute("System.Diagnostics.Process.GetCurrentProcess().HasExited"));
}
// Caused by submission not inheriting references.
[Fact(Skip = "101161")]
public void AddReference_ShadowCopy()
......
......@@ -5,12 +5,15 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Scripting.CSharp;
using Microsoft.CodeAnalysis.Scripting.Hosting;
using Microsoft.CodeAnalysis.Scripting.Test;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
using TestBase = PortableTestUtils::Roslyn.Test.Utilities.TestBase;
......@@ -298,16 +301,16 @@ public async Task HostObjectBinding_DuplicateReferences()
AddReferences(typeof(C).Assembly, typeof(C).Assembly);
var s0 = await CSharpScript.RunAsync<int>("x", options, new C());
var c0 = s0.Script.GetCompilation();
// includes corlib, host type assembly by default:
AssertEx.Equal(new[]
{
typeof(object).GetTypeInfo().Assembly.Location,
typeof(C).Assembly.Location,
Assembly.Load(new AssemblyName("System.Runtime, Version=4.0.20.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")).Location, // TODO: remove
typeof(C).Assembly.Location,
typeof(C).Assembly.Location,
}, s0.Script.GetCompilation().ExternalReferences.SelectAsArray(m => m.Display));
}, c0.ExternalReferences.SelectAsArray(m => m.Display));
Assert.Equal(1, s0.ReturnValue);
......@@ -318,5 +321,46 @@ public async Task HostObjectBinding_DuplicateReferences()
");
Assert.Equal(1, s1.ReturnValue);
}
[Fact]
public async Task MissingRefrencesAutoResolution()
{
var portableLib = CSharpCompilation.Create(
"PortableLib",
new[] { SyntaxFactory.ParseSyntaxTree("public class C {}") },
new[] { SystemRuntimePP7Ref },
new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
var portableLibRef = portableLib.ToMetadataReference();
var loader = new InteractiveAssemblyLoader();
loader.RegisterDependency(Assembly.Load(portableLib.EmitToArray().ToArray()));
var s0 = await CSharpScript.Create("new C()", options: ScriptOptions.Default.AddReferences(portableLibRef), assemblyLoader: loader).RunAsync();
var c0 = s0.Script.GetCompilation();
// includes corlib, host type assembly by default:
AssertEx.Equal(new[]
{
typeof(object).GetTypeInfo().Assembly.Location,
"PortableLib"
}, c0.ExternalReferences.SelectAsArray(m => m.Display));
// System.Runtime, 4.0.0.0 depends on all the assemblies below:
AssertEx.Equal(new[]
{
"mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
"PortableLib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null",
"System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
"System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
"System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
"System.ComponentModel.Composition, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
"System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
"System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
"System.Data.SqlXml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
"System.Security, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
"System.Numerics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
}, c0.GetBoundReferenceManager().GetReferencedAssemblies().Select(a => a.Value.Identity.GetDisplayName()));
}
}
}
......@@ -25,13 +25,8 @@ public class HostModel
public class InteractiveSessionTests : TestBase
{
private static readonly Assembly s_lazySystemRuntimeAssembly;
internal static readonly Assembly SystemRuntimeAssembly = s_lazySystemRuntimeAssembly ?? (s_lazySystemRuntimeAssembly = Assembly.Load(new AssemblyName("System.Runtime, Version=4.0.20.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")));
internal static readonly Assembly HostAssembly = typeof(InteractiveSessionTests).GetTypeInfo().Assembly;
// TODO: shouldn't be needed
private static readonly ScriptOptions OptionsWithFacades = ScriptOptions.Default.AddReferences(SystemRuntimeAssembly);
#region Namespaces, Types
[Fact]
......@@ -212,7 +207,7 @@ public void AnonymousTypes_TopLevel_Empty()
[Fact]
public void Dynamic_Expando()
{
var options = OptionsWithFacades.
var options = ScriptOptions.Default.
AddReferences(
typeof(Microsoft.CSharp.RuntimeBinder.RuntimeBinderException).GetTypeInfo().Assembly,
typeof(System.Dynamic.ExpandoObject).GetTypeInfo().Assembly).
......@@ -220,7 +215,7 @@ public void Dynamic_Expando()
"System.Dynamic");
var script = CSharpScript.Create(@"
dynamic expando = new ExpandoObject();
dynamic expando = new ExpandoObject();
", options).ContinueWith(@"
expando.foo = 1;
").ContinueWith(@"
......@@ -402,7 +397,7 @@ public void CompilationChain_BasicFields()
public void CompilationChain_GlobalNamespaceAndUsings()
{
var result =
CSharpScript.Create("using InteractiveFixtures.C;", OptionsWithFacades.AddReferences(HostAssembly)).
CSharpScript.Create("using InteractiveFixtures.C;", ScriptOptions.Default.AddReferences(HostAssembly)).
ContinueWith("using InteractiveFixtures.C;").
ContinueWith("System.Environment.ProcessorCount").
EvaluateAsync().Result;
......@@ -413,7 +408,7 @@ public void CompilationChain_GlobalNamespaceAndUsings()
[Fact]
public void CompilationChain_CurrentSubmissionUsings()
{
var s0 = CSharpScript.RunAsync("", OptionsWithFacades.AddReferences(HostAssembly));
var s0 = CSharpScript.RunAsync("", ScriptOptions.Default.AddReferences(HostAssembly));
var state = s0.
ContinueWith("class X { public int foo() { return 1; } }").
......@@ -600,7 +595,7 @@ public class HostObjectWithOverrides
[Fact]
public async Task ObjectOverrides1()
{
var state0 = await CSharpScript.RunAsync("", OptionsWithFacades, new HostObjectWithOverrides());
var state0 = await CSharpScript.RunAsync("", globals: new HostObjectWithOverrides());
var state1 = await state0.ContinueWithAsync<bool>("Equals(null)");
Assert.True(state1.ReturnValue);
......@@ -615,7 +610,7 @@ public async Task ObjectOverrides1()
[Fact]
public async Task ObjectOverrides2()
{
var state0 = await CSharpScript.RunAsync("", OptionsWithFacades, new object());
var state0 = await CSharpScript.RunAsync("", globals: new object());
var state1 = await state0.ContinueWithAsync<bool>(@"
object x = 1;
object y = x;
......@@ -633,7 +628,7 @@ public async Task ObjectOverrides2()
[Fact]
public void ObjectOverrides3()
{
var state0 = CSharpScript.RunAsync("", OptionsWithFacades);
var state0 = CSharpScript.RunAsync("");
var src1 = @"
Equals(null);
......@@ -1257,7 +1252,7 @@ public void Submission_HostConversions()
// Can't use Verify() because the version number of the test dll is different in the build lab.
}
var options = OptionsWithFacades.AddReferences(HostAssembly);
var options = ScriptOptions.Default.AddReferences(HostAssembly);
var cint = CSharpScript.EvaluateAsync<C<int>>("null", options).Result;
Assert.Equal(null, cint);
......@@ -1340,7 +1335,7 @@ public void HostObjectBinding_PublicClassMembers()
{
var c = new C();
var s0 = CSharpScript.RunAsync<int>("x + Y + Z()", OptionsWithFacades, globals: c);
var s0 = CSharpScript.RunAsync<int>("x + Y + Z()", globals: c);
Assert.Equal(6, s0.Result.ReturnValue);
var s1 = s0.ContinueWith<int>("x");
......@@ -1356,7 +1351,7 @@ public void HostObjectBinding_PublicClassMembers()
public void HostObjectBinding_PublicGenericClassMembers()
{
var m = new M<string>();
var result = CSharpScript.EvaluateAsync<string>("G()", OptionsWithFacades, globals: m);
var result = CSharpScript.EvaluateAsync<string>("G()", globals: m);
Assert.Equal(null, result.Result);
}
......@@ -1365,7 +1360,7 @@ public async Task HostObjectBinding_Interface()
{
var c = new C();
var s0 = await CSharpScript.RunAsync<int>("Z()", OptionsWithFacades, c, typeof(I));
var s0 = await CSharpScript.RunAsync<int>("Z()", globals: c, globalsType: typeof(I));
Assert.Equal(3, s0.ReturnValue);
ScriptingTestHelpers.AssertCompilationError(s0, @"x + Y",
......@@ -1382,7 +1377,7 @@ public void HostObjectBinding_PrivateClass()
{
var c = new PrivateClass();
ScriptingTestHelpers.AssertCompilationError(() => CSharpScript.EvaluateAsync("Z()", OptionsWithFacades, c),
ScriptingTestHelpers.AssertCompilationError(() => CSharpScript.EvaluateAsync("Z()", globals: c),
// (1,1): error CS0122: '<Fully Qualified Name of PrivateClass>.Z()' is inaccessible due to its protection level
Diagnostic(ErrorCode.ERR_BadAccess, "Z").WithArguments(typeof(PrivateClass).FullName.Replace("+", ".") + ".Z()"));
}
......@@ -1392,7 +1387,7 @@ public void HostObjectBinding_PrivateMembers()
{
object c = new M<int>();
ScriptingTestHelpers.AssertCompilationError(() => CSharpScript.EvaluateAsync("Z()", OptionsWithFacades, c),
ScriptingTestHelpers.AssertCompilationError(() => CSharpScript.EvaluateAsync("Z()", globals: c),
// (1,1): error CS0103: The name 'z' does not exist in the current context
Diagnostic(ErrorCode.ERR_NameNotInContext, "Z").WithArguments("Z"));
}
......
......@@ -241,7 +241,6 @@ public async Task ScriptVariables_Chain()
var script =
CSharpScript.Create(
"var a = '1';",
options: ScriptOptions.Default.WithReferences(InteractiveSessionTests.SystemRuntimeAssembly),
globalsType: globals.GetType()).
ContinueWith("var b = 2u;").
ContinueWith("var a = 3m;").
......
......@@ -5,6 +5,7 @@
using System;
using System.Collections.Immutable;
using System.Diagnostics;
using System.IO;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Scripting.Hosting
......@@ -23,6 +24,7 @@ internal sealed class RuntimeMetadataReferenceResolver : MetadataReferenceResolv
internal readonly NuGetPackageResolver PackageResolver;
internal readonly GacFileResolver GacFileResolver;
private readonly Func<string, MetadataReferenceProperties, PortableExecutableReference> _fileReferenceProvider;
private static ImmutableArray<string> s_assemblyExtensions = ImmutableArray.Create(".dll", ".exe", ".winmd");
internal RuntimeMetadataReferenceResolver(
ImmutableArray<string> searchPaths,
......@@ -44,6 +46,38 @@ internal sealed class RuntimeMetadataReferenceResolver : MetadataReferenceResolv
new Func<string, MetadataReferenceProperties, PortableExecutableReference>((path, properties) => MetadataReference.CreateFromFile(path, properties));
}
public override bool ResolveMissingAssemblies => true;
public override PortableExecutableReference ResolveMissingAssembly(MetadataReference definition, AssemblyIdentity referenceIdentity)
{
// look in the GAC:
if (GacFileResolver != null && referenceIdentity.IsStrongName)
{
var path = GacFileResolver.Resolve(referenceIdentity.GetDisplayName());
if (path != null)
{
return _fileReferenceProvider(path, MetadataReferenceProperties.Assembly);
}
}
// look in the directory of the requesting definition:
var definitionPath = (definition as PortableExecutableReference)?.FilePath;
if (definitionPath != null)
{
var pathWithoutExtension = PathUtilities.CombinePathsUnchecked(PathUtilities.GetDirectoryName(definitionPath), referenceIdentity.Name);
foreach (var extension in s_assemblyExtensions)
{
var fullPath = pathWithoutExtension + extension;
if (File.Exists(fullPath))
{
return _fileReferenceProvider(fullPath, MetadataReferenceProperties.Assembly);
}
}
}
return null;
}
public override ImmutableArray<PortableExecutableReference> ResolveReference(string reference, string baseFilePath, MetadataReferenceProperties properties)
{
string packageName;
......
......@@ -199,12 +199,6 @@ public Compilation GetCompilation()
{
var globalsTypeAssembly = MetadataReference.CreateFromAssemblyInternal(GlobalsType.GetTypeInfo().Assembly);
references.Add(globalsTypeAssembly);
// TODO: remove
var systemRuntimeFacade = MetadataReference.CreateFromAssemblyInternal(
Assembly.Load(new AssemblyName("System.Runtime, Version=4.0.20.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")));
references.Add(systemRuntimeFacade);
}
if (languageRuntimeReferenceOpt != null)
......
......@@ -2,26 +2,45 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis;
using Roslyn.Utilities;
namespace Roslyn.Test.Utilities
{
internal class TestMissingMetadataReferenceResolver : MetadataReferenceResolver
{
internal struct ReferenceAndIdentity
{
public readonly MetadataReference Reference;
public readonly AssemblyIdentity Identity;
public ReferenceAndIdentity(MetadataReference reference, AssemblyIdentity identity)
{
Reference = reference;
Identity = identity;
}
public override string ToString()
{
return $"{Reference.Display} -> {Identity.GetDisplayName()}";
}
}
private readonly Dictionary<string, MetadataReference> _map;
public readonly List<AssemblyIdentity> ResolutionAttempts = new List<AssemblyIdentity>();
public readonly List<ReferenceAndIdentity> ResolutionAttempts = new List<ReferenceAndIdentity>();
public TestMissingMetadataReferenceResolver(Dictionary<string, MetadataReference> map)
{
_map = map;
}
public override PortableExecutableReference ResolveMissingAssembly(AssemblyIdentity identity)
public override PortableExecutableReference ResolveMissingAssembly(MetadataReference definition, AssemblyIdentity referenceIdentity)
{
ResolutionAttempts.Add(identity);
ResolutionAttempts.Add(new ReferenceAndIdentity(definition, referenceIdentity));
MetadataReference reference;
string nameAndVersion = identity.Name + (identity.Version != AssemblyIdentity.NullVersion ? $", {identity.Version}" : "");
string nameAndVersion = referenceIdentity.Name + (referenceIdentity.Version != AssemblyIdentity.NullVersion ? $", {referenceIdentity.Version}" : "");
return _map.TryGetValue(nameAndVersion, out reference) ? (PortableExecutableReference)reference : null;
}
......@@ -29,5 +48,10 @@ public override PortableExecutableReference ResolveMissingAssembly(AssemblyIdent
public override bool Equals(object other) => true;
public override int GetHashCode() => 1;
public override ImmutableArray<PortableExecutableReference> ResolveReference(string reference, string baseFilePath, MetadataReferenceProperties properties) => default(ImmutableArray<PortableExecutableReference>);
public void VerifyResolutionAttempts(params string[] expected)
{
AssertEx.Equal(expected, ResolutionAttempts.Select(a => a.ToString()));
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册