提交 603dca70 编写于 作者: J jonas echterhoff 提交者: Charles Stoner

Attempted fix for correctly reporting error CS1069 when using implicit namespaces (#30244)

上级 1dcdc28a
......@@ -2054,7 +2054,6 @@ private CSDiagnosticInfo NotFound(SyntaxNode where, string simpleName, int arity
// as a type forwarder. We'll look for type forwarders in the containing and
// referenced assemblies and report more specific diagnostics if they are found.
AssemblySymbol forwardedToAssembly;
string fullName;
// for attributes, suggest both, but not for verbatim name
if (options.IsAttributeTypeLookup() && !options.IsVerbatimNameAttributeTypeLookup())
......@@ -2079,17 +2078,9 @@ private CSDiagnosticInfo NotFound(SyntaxNode where, string simpleName, int arity
{
Debug.Assert(qualifierOpt.IsNamespace);
bool qualifierIsCompilationGlobalNamespace = ReferenceEquals(qualifierOpt, Compilation.GlobalNamespace);
fullName = MetadataHelpers.ComposeAritySuffixedMetadataName(simpleName, arity);
if (!qualifierIsCompilationGlobalNamespace)
{
fullName = qualifierOpt.ToDisplayString(SymbolDisplayFormat.QualifiedNameOnlyFormat) + "." + fullName;
}
forwardedToAssembly = GetForwardedToAssembly(fullName, arity, diagnostics, location);
if (qualifierIsCompilationGlobalNamespace)
forwardedToAssembly = GetForwardedToAssembly(simpleName, arity, ref qualifierOpt, diagnostics, location);
if (ReferenceEquals(qualifierOpt, Compilation.GlobalNamespace))
{
Debug.Assert(aliasOpt == null || aliasOpt == SyntaxFacts.GetText(SyntaxKind.GlobalKeyword));
return (object)forwardedToAssembly == null
......@@ -2125,31 +2116,73 @@ private CSDiagnosticInfo NotFound(SyntaxNode where, string simpleName, int arity
return diagnostics.Add(code, location);
}
fullName = MetadataHelpers.ComposeAritySuffixedMetadataName(simpleName, arity);
forwardedToAssembly = GetForwardedToAssembly(fullName, arity, diagnostics, location);
forwardedToAssembly = GetForwardedToAssembly(simpleName, arity, ref qualifierOpt, diagnostics, location);
if ((object)forwardedToAssembly != null)
{
return qualifierOpt == null
? diagnostics.Add(ErrorCode.ERR_SingleTypeNameNotFoundFwd, location, whereText, forwardedToAssembly)
: diagnostics.Add(ErrorCode.ERR_DottedTypeNameNotFoundInNSFwd, location, whereText, qualifierOpt, forwardedToAssembly);
}
return diagnostics.Add(ErrorCode.ERR_SingleTypeNameNotFound, location, whereText);
}
protected virtual AssemblySymbol GetForwardedToAssemblyInUsingNamespaces(string metadataName, ref NamespaceOrTypeSymbol qualifierOpt, DiagnosticBag diagnostics, Location location)
{
return Next?.GetForwardedToAssemblyInUsingNamespaces(metadataName, ref qualifierOpt, diagnostics, location);
}
protected AssemblySymbol GetForwardedToAssembly(string fullName, DiagnosticBag diagnostics, Location location)
{
var metadataName = MetadataTypeName.FromFullName(fullName);
foreach (var referencedAssembly in
Compilation.Assembly.Modules[0].GetReferencedAssemblySymbols())
{
var forwardedType =
referencedAssembly.TryLookupForwardedMetadataType(ref metadataName);
if ((object)forwardedType != null)
{
if (forwardedType.Kind == SymbolKind.ErrorType)
{
DiagnosticInfo diagInfo = ((ErrorTypeSymbol)forwardedType).ErrorInfo;
if (diagInfo.Code == (int)ErrorCode.ERR_CycleInTypeForwarder)
{
Debug.Assert((object)forwardedType.ContainingAssembly != null, "How did we find a cycle if there was no forwarding?");
diagnostics.Add(ErrorCode.ERR_CycleInTypeForwarder, location, fullName, forwardedType.ContainingAssembly.Name);
}
else if (diagInfo.Code == (int)ErrorCode.ERR_TypeForwardedToMultipleAssemblies)
{
diagnostics.Add(diagInfo, location);
return null; // Cannot determine a suitable forwarding assembly
}
}
return forwardedType.ContainingAssembly;
}
}
return (object)forwardedToAssembly == null
? diagnostics.Add(ErrorCode.ERR_SingleTypeNameNotFound, location, whereText)
: diagnostics.Add(ErrorCode.ERR_SingleTypeNameNotFoundFwd, location, whereText, forwardedToAssembly);
return null;
}
/// <summary>
/// Look for a type forwarder for the given type in the containing assembly and any referenced assemblies.
/// If one is found, search again in the target assembly. Return the last assembly in the chain.
/// </summary>
/// <param name="fullName">The metadata name of the (potentially) forwarded type, including the arity (if non-zero).</param>
/// <param name="name">The name of the (potentially) forwarded type.</param>
/// <param name="arity">The arity of the forwarded type.</param>
/// <param name="qualifierOpt">The namespace of the potentially forwarded type. If none is provided, will
/// try Usings of the current import for eligible namespaces and return the namespace of the found forwarder,
/// if any.</param>
/// <param name="diagnostics">Will be used to report non-fatal errors during look up.</param>
/// <param name="location">Location to report errors on.</param>
/// <returns></returns>
/// <returns>Returns the Assembly to which the type is forwarded, or null if none is found.</returns>
/// <remarks>
/// Since this method is intended to be used for error reporting, it stops as soon as it finds
/// any type forwarder (or an error to report). It does not check other assemblies for consistency or better results.
/// </remarks>
private AssemblySymbol GetForwardedToAssembly(string fullName, int arity, DiagnosticBag diagnostics, Location location)
protected AssemblySymbol GetForwardedToAssembly(string name, int arity, ref NamespaceOrTypeSymbol qualifierOpt, DiagnosticBag diagnostics, Location location)
{
Debug.Assert(arity == 0 || fullName.EndsWith("`" + arity, StringComparison.Ordinal));
// If we are in the process of binding assembly level attributes, we might get into an infinite cycle
// if any of the referenced assemblies forwards type to this assembly. Since forwarded types
// are specified through assembly level attributes, an attempt to resolve the forwarded type
......@@ -2182,41 +2215,17 @@ private AssemblySymbol GetForwardedToAssembly(string fullName, int arity, Diagno
// NOTE: This won't work if the type isn't using CLS-style generic naming (i.e. `arity), but this code is
// only intended to improve diagnostic messages, so false negatives in corner cases aren't a big deal.
var metadataName = MetadataTypeName.FromFullName(fullName, useCLSCompliantNameArityEncoding: true, forcedArity: arity);
var containingAssembly = this.Compilation.Assembly;
// This method is only called after lookup has failed, so the containing (source!) assembly can't
// have a forwarder to another assembly.
NamedTypeSymbol forwardedType = null;
foreach (var referencedAssembly in containingAssembly.Modules[0].GetReferencedAssemblySymbols())
var metadataName = MetadataHelpers.ComposeAritySuffixedMetadataName(name, arity);
var fullMetadataName = MetadataHelpers.BuildQualifiedName(qualifierOpt?.ToDisplayString(SymbolDisplayFormat.QualifiedNameOnlyFormat), metadataName);
var result = GetForwardedToAssembly(fullMetadataName, diagnostics, location);
if ((object)result != null)
{
forwardedType = referencedAssembly.TryLookupForwardedMetadataType(ref metadataName);
if ((object)forwardedType != null)
{
break;
}
return result;
}
if ((object)forwardedType != null)
if ((object)qualifierOpt == null)
{
if (forwardedType.Kind == SymbolKind.ErrorType)
{
DiagnosticInfo diagInfo = ((ErrorTypeSymbol)forwardedType).ErrorInfo;
if (diagInfo.Code == (int)ErrorCode.ERR_CycleInTypeForwarder)
{
Debug.Assert((object)forwardedType.ContainingAssembly != null, "How did we find a cycle if there was no forwarding?");
diagnostics.Add(ErrorCode.ERR_CycleInTypeForwarder, location, fullName, forwardedType.ContainingAssembly.Name);
}
else if (diagInfo.Code == (int)ErrorCode.ERR_TypeForwardedToMultipleAssemblies)
{
diagnostics.Add(diagInfo, location);
return null; // Cannot determine a suitable forwarding assembly
}
}
return forwardedType.ContainingAssembly;
return GetForwardedToAssemblyInUsingNamespaces(metadataName, ref qualifierOpt, diagnostics, location);
}
return null;
......
......@@ -96,6 +96,37 @@ internal override Imports GetImports(ConsList<Symbol> basesBeingResolved)
return _lazyImports;
}
/// <summary>
/// Look for a type forwarder for the given type in any referenced assemblies, checking any using namespaces in
/// the current imports.
/// </summary>
/// <param name="name">The metadata name of the (potentially) forwarded type, without qualifiers.</param>
/// <param name="qualifierOpt">Will be used to return the namespace of the found forwarder,
/// if any.</param>
/// <param name="diagnostics">Will be used to report non-fatal errors during look up.</param>
/// <param name="location">Location to report errors on.</param>
/// <returns>Returns the Assembly to which the type is forwarded, or null if none is found.</returns>
/// <remarks>
/// Since this method is intended to be used for error reporting, it stops as soon as it finds
/// any type forwarder (or an error to report). It does not check other assemblies for consistency or better results.
/// </remarks>
protected override AssemblySymbol GetForwardedToAssemblyInUsingNamespaces(string name, ref NamespaceOrTypeSymbol qualifierOpt, DiagnosticBag diagnostics, Location location)
{
var imports = GetImports(basesBeingResolved: null);
foreach (var typeOrNamespace in imports.Usings)
{
var fullName = typeOrNamespace.NamespaceOrType + "." + name;
var result = GetForwardedToAssembly(fullName, diagnostics, location);
if (result != null)
{
qualifierOpt = typeOrNamespace.NamespaceOrType;
return result;
}
}
return base.GetForwardedToAssemblyInUsingNamespaces(name, ref qualifierOpt, diagnostics, location);
}
internal override ImportChain ImportChain
{
get
......
......@@ -936,15 +936,48 @@ static void Main()
var ref1 = CompileIL(il1, prependDefaultHeader: false);
CreateCompilation(csharp, new[] { ref1 }).VerifyDiagnostics(
// (8,21): error CS0246: The type or namespace name 'Forwarded' could not be found (are you missing a using directive or an assembly reference?)
// (8,21): error CS1069: The type name 'Forwarded' could not be found in the namespace 'Namespace'. This type has been forwarded to assembly 'pe2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' Consider adding a reference to that assembly.
// var f = new Forwarded();
Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Forwarded").WithArguments("Forwarded"),
Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNSFwd, "Forwarded").WithArguments("Forwarded", "Namespace", "pe2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"),
// (2,1): info CS8019: Unnecessary using directive.
// using Namespace;
Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using Namespace;"));
}
[Fact]
public void LookupMissingForwardedGenericTypeImplicitNamespace()
{
var il1 = @"
.assembly extern pe2 { }
.assembly pe1 { }
// We'd like to report this diagnostic, but the dev cost is too high.
// (8,21): error CS1069: The type name 'Forwarded' could not be found in the namespace 'Namespace'. This type has been forwarded to assembly 'pe2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' Consider adding a reference to that assembly.
.class extern forwarder Namespace.Forwarded`1
{
.assembly extern pe2
}
";
var csharp = @"
using Namespace;
class Test
{
static void Main()
{
var f = new Forwarded<int>();
}
}
";
var ref1 = CompileIL(il1, prependDefaultHeader: false);
CreateCompilation(csharp, new[] { ref1 }).VerifyDiagnostics(
// (8,21): error CS1069: The type name 'Forwarded<>' could not be found in the namespace 'Namespace'. This type has been forwarded to assembly 'pe2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' Consider adding a reference to that assembly.
// var f = new Forwarded<int>();
Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNSFwd, "Forwarded<int>").WithArguments("Forwarded<>", "Namespace", "pe2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"),
// (2,1): info CS8019: Unnecessary using directive.
// using Namespace;
Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using Namespace;"));
}
[Fact]
......@@ -969,6 +1002,21 @@ public void NamespacesOnlyMentionedInForwarders()
{
.assembly extern pe2
}
.class extern forwarder T4`1
{
.assembly extern pe2
}
.class extern forwarder Ns.T5`1
{
.assembly extern pe2
}
.class extern forwarder Ns.Ms.T6`1
{
.assembly extern pe2
}
";
var csharp = @"
......@@ -979,10 +1027,15 @@ class Test
Ns.Ms.T2 P2 { get; set; }
Ns.Ms.Ls.T3 P3 { get; set; }
Nope P4 { get; set; }
Ns.Nope P5 { get; set; }
Ns.Ms.Nope P6 { get; set; }
Ns.Ms.Ls.Nope P7 { get; set; }
T4<int> P4 { get; set; }
Ns.T5<int> P5 { get; set; }
Ns.Ms.T6<int> P6 { get; set; }
Ns.Ms.Ls.T7<int> P7 { get; set; }
Nope P8 { get; set; }
Ns.Nope P9 { get; set; }
Ns.Ms.Nope P10 { get; set; }
Ns.Ms.Ls.Nope P11 { get; set; }
}
";
......@@ -1003,23 +1056,35 @@ class Test
// (7,11): error CS0234: The type or namespace name 'Ls' does not exist in the namespace 'Ns.Ms' (are you missing an assembly reference?)
// Ns.Ms.Ls.T3 P3 { get; set; }
Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNS, "Ls").WithArguments("Ls", "Ns.Ms"),
// (9,5): error CS0246: The type or namespace name 'Nope' could not be found (are you missing a using directive or an assembly reference?)
// Nope P4 { get; set; }
// (9,5): error CS1070: The type name 'T4<>' could not be found. This type has been forwarded to assembly 'pe2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. Consider adding a reference to that assembly.
// T4<int> P4 { get; set; }
Diagnostic(ErrorCode.ERR_SingleTypeNameNotFoundFwd, "T4<int>").WithArguments("T4<>", "pe2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"),
// (10,8): error CS1069: The type name 'T5<>' could not be found in the namespace 'Ns'. This type has been forwarded to assembly 'pe2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' Consider adding a reference to that assembly.
// Ns.T5<int> P5 { get; set; }
Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNSFwd, "T5<int>").WithArguments("T5<>", "Ns", "pe2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"),
// (11,11): error CS1069: The type name 'T6<>' could not be found in the namespace 'Ns.Ms'. This type has been forwarded to assembly 'pe2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' Consider adding a reference to that assembly.
// Ns.Ms.T6<int> P6 { get; set; }
Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNSFwd, "T6<int>").WithArguments("T6<>", "Ns.Ms", "pe2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"),
// (12,11): error CS0234: The type or namespace name 'Ls' does not exist in the namespace 'Ns.Ms' (are you missing an assembly reference?)
// Ns.Ms.Ls.T7<int> P7 { get; set; }
Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNS, "Ls").WithArguments("Ls", "Ns.Ms"),
// (14,5): error CS0246: The type or namespace name 'Nope' could not be found (are you missing a using directive or an assembly reference?)
// Nope P8 { get; set; }
Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Nope").WithArguments("Nope"),
// (10,8): error CS0234: The type or namespace name 'Nope' does not exist in the namespace 'Ns' (are you missing an assembly reference?)
// Ns.Nope P5 { get; set; }
// (15,8): error CS0234: The type or namespace name 'Nope' does not exist in the namespace 'Ns' (are you missing an assembly reference?)
// Ns.Nope P9 { get; set; }
Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNS, "Nope").WithArguments("Nope", "Ns"),
// (11,11): error CS0234: The type or namespace name 'Nope' does not exist in the namespace 'Ns.Ms' (are you missing an assembly reference?)
// Ns.Ms.Nope P6 { get; set; }
// (16,11): error CS0234: The type or namespace name 'Nope' does not exist in the namespace 'Ns.Ms' (are you missing an assembly reference?)
// Ns.Ms.Nope P10 { get; set; }
Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNS, "Nope").WithArguments("Nope", "Ns.Ms"),
// (12,11): error CS0234: The type or namespace name 'Ls' does not exist in the namespace 'Ns.Ms' (are you missing an assembly reference?)
// Ns.Ms.Ls.Nope P7 { get; set; }
// (17,11): error CS0234: The type or namespace name 'Ls' does not exist in the namespace 'Ns.Ms' (are you missing an assembly reference?)
// Ns.Ms.Ls.Nope P11 { get; set; }
Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNS, "Ls").WithArguments("Ls", "Ns.Ms"));
var actualNamespaces = EnumerateNamespaces(compilation).Where(ns =>
!ns.StartsWith("System", StringComparison.Ordinal) &&
!ns.StartsWith("Windows", StringComparison.Ordinal) &&
!ns.StartsWith("FxResources", StringComparison.Ordinal) &&
var actualNamespaces = EnumerateNamespaces(compilation).Where(ns =>
!ns.StartsWith("System", StringComparison.Ordinal) &&
!ns.StartsWith("Windows", StringComparison.Ordinal) &&
!ns.StartsWith("FxResources", StringComparison.Ordinal) &&
!ns.StartsWith("Microsoft", StringComparison.Ordinal));
var expectedNamespaces = new[] { "Ns", "Ns.Ms" };
Assert.True(actualNamespaces.SetEquals(expectedNamespaces, EqualityComparer<string>.Default));
......@@ -1087,6 +1152,68 @@ class Test
Assert.True(actualNamespaces.SetEquals(expectedNamespaces, EqualityComparer<string>.Default));
}
[Fact]
public void NamespacesMentionedInForwardersGeneric()
{
var il1 = @"
.assembly extern pe2 { }
.assembly extern mscorlib { }
.assembly pe1 { }
.class extern forwarder N1.N2.N3.T`1
{
.assembly extern pe2
}
.class public auto ansi beforefieldinit N1.N2.T`1<U>
extends [mscorlib]System.Object
{
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
ldarg.0
call instance void [mscorlib]System.Object::.ctor()
ret
}
} // end of class N1.N2.T`1
";
var csharp = @"
namespace N1
{
class Test
{
N2.T<int> t1 { get; set; }
N2.N3.T<int> t2 { get; set; }
N1.N2.T<int> t3 { get; set; }
N1.N2.N3.T<int> t4 { get; set; }
}
}
";
var ref1 = CompileIL(il1, prependDefaultHeader: false);
var compilation = CreateCompilation(csharp, new[] { ref1 });
compilation.VerifyDiagnostics(
// (7,15): error CS1069: The type name 'T<>' could not be found in the namespace 'N1.N2.N3'. This type has been forwarded to assembly 'pe2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' Consider adding a reference to that assembly.
// N2.N3.T<int> t2 { get; set; }
Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNSFwd, "T<int>").WithArguments("T<>", "N1.N2.N3", "pe2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"),
// (9,18): error CS1069: The type name 'T<>' could not be found in the namespace 'N1.N2.N3'. This type has been forwarded to assembly 'pe2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' Consider adding a reference to that assembly.
// N1.N2.N3.T<int> t4 { get; set; }
Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNSFwd, "T<int>").WithArguments("T<>", "N1.N2.N3", "pe2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"));
var actualNamespaces = EnumerateNamespaces(compilation).Where(ns =>
!ns.StartsWith("System", StringComparison.Ordinal) &&
!ns.StartsWith("Windows", StringComparison.Ordinal) &&
!ns.StartsWith("FxResources", StringComparison.Ordinal) &&
!ns.StartsWith("Microsoft", StringComparison.Ordinal));
var expectedNamespaces = new[] { "N1", "N1.N2", "N1.N2.N3" };
Assert.True(actualNamespaces.SetEquals(expectedNamespaces, EqualityComparer<string>.Default));
}
private static IEnumerable<string> EnumerateNamespaces(CSharpCompilation compilation)
{
return EnumerateNamespaces(compilation.GlobalNamespace, "");
......@@ -1806,5 +1933,69 @@ public class MyClass { }
// var b = new B::MyNamespace.MyClass();
Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNS, "MyNamespace").WithArguments("MyNamespace", "B").WithLocation(8, 24));
}
/// <summary>
/// Aliases to forwarded types are not supported currently.
/// </summary>
[WorkItem(27375, "https://github.com/dotnet/roslyn/issues/27375")]
[Fact]
public void AliasToGenericTypeForwarder()
{
// Library v1: no forwarding.
const string sourceA1 =
@"[assembly: System.Reflection.AssemblyVersion(""1.0.0.0"")]
namespace MyNamespace
{
public class MyClass<T> { }
}";
var compA1 = CreateCompilation(sourceA1, assemblyName: "A");
var refA1 = compA1.EmitToImageReference(aliases: ImmutableArray.Create("A"));
const string sourceB1 = sourceA1;
var compB1 = CreateCompilation(sourceB1, assemblyName: "B");
var refB1 = compB1.EmitToImageReference(aliases: ImmutableArray.Create("B"));
const string sourceProgram =
@"extern alias A;
extern alias B;
class Program
{
static void Main()
{
var a = new A::MyNamespace.MyClass<int>();
var b = new B::MyNamespace.MyClass<int>();
}
}";
var comp = CreateCompilation(sourceProgram, references: new[] { refA1, refB1 });
comp.VerifyDiagnostics();
// Library v2: forwarding to implementation assembly.
const string sourceBImpl =
@"namespace MyNamespace
{
public class MyClass<T> { }
}";
var compBImpl = CreateCompilation(sourceBImpl, assemblyName: "BImpl");
var refBImpl = compBImpl.EmitToImageReference();
const string sourceB2 =
@"[assembly: System.Reflection.AssemblyVersion(""2.0.0.0"")]
[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(MyNamespace.MyClass<>))]";
var compB2 = CreateCompilation(sourceB2, references: new[] { refBImpl }, assemblyName: "B");
// Alias to PE assembly.
comp = CreateCompilation(sourceProgram, references: new[] { refA1, compB2.EmitToImageReference(aliases: ImmutableArray.Create("B")), refBImpl });
comp.VerifyDiagnostics(
// (8,36): error CS1069: The type name 'MyClass<>' could not be found in the namespace 'MyNamespace'. This type has been forwarded to assembly 'BImpl, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' Consider adding a reference to that assembly.
// var b = new B::MyNamespace.MyClass<int>();
Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNSFwd, "MyClass<int>").WithArguments("MyClass<>", "MyNamespace", "BImpl, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(8, 36));
// Alias to source assembly.
comp = CreateCompilation(sourceProgram, references: new[] { refA1, new CSharpCompilationReference(compB2, aliases: ImmutableArray.Create("B")), refBImpl });
comp.VerifyDiagnostics(
// (8,24): error CS0234: The type or namespace name 'MyNamespace' does not exist in the namespace 'B' (are you missing an assembly reference?)
// var b = new B::MyNamespace.MyClass<int>();
Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNS, "MyNamespace").WithArguments("MyNamespace", "B").WithLocation(8, 24));
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册