File: Symbols\Metadata\PE\LoadingGenericTypeParameters.cs
Web Access
Project: src\src\Compilers\CSharp\Test\Symbol\Microsoft.CodeAnalysis.CSharp.Symbol.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.Symbol.UnitTests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
#nullable disable
 
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Test.Utilities;
using Xunit;
using Basic.Reference.Assemblies;
 
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Symbols.Metadata.PE
{
    public class LoadingGenericTypeParameters : CSharpTestBase
    {
        [Fact]
        public void Test1()
        {
            var assembly = MetadataTestHelpers.GetSymbolForReference(Net40.References.mscorlib);
            var module0 = assembly.Modules[0];
 
            var objectType = module0.GlobalNamespace.GetMembers("System").
                OfType<NamespaceSymbol>().Single().
                GetTypeMembers("Object").Single();
 
            Assert.Equal(0, objectType.Arity);
            Assert.Equal(0, objectType.TypeParameters.Length);
            Assert.Equal(0, objectType.TypeArguments().Length);
 
            assembly = MetadataTestHelpers.GetSymbolForReference(TestReferences.SymbolsTests.MDTestLib1);
            module0 = assembly.Modules[0];
 
            var varC1 = module0.GlobalNamespace.GetTypeMembers("C1").Single();
 
            Assert.Equal(1, varC1.Arity);
            Assert.Equal(1, varC1.TypeParameters.Length);
            Assert.Equal(1, varC1.TypeArguments().Length);
 
            var varC1_T = varC1.TypeParameters[0];
 
            Assert.Equal(varC1_T, varC1.TypeArguments()[0]);
 
            Assert.NotNull(varC1_T.EffectiveBaseClassNoUseSiteDiagnostics);
            Assert.Equal(assembly, varC1_T.ContainingAssembly);
            Assert.Equal(module0.GlobalNamespace, varC1_T.ContainingNamespace); // Null(C1_T.ContainingNamespace)
            Assert.Equal(varC1, varC1_T.ContainingSymbol);
            Assert.Equal(varC1, varC1_T.ContainingType);
            Assert.Equal(Accessibility.NotApplicable, varC1_T.DeclaredAccessibility);
            Assert.Equal("C1_T", varC1_T.Name);
            Assert.Equal("C1_T", varC1_T.ToTestDisplayString());
            Assert.Equal(0, varC1_T.GetMembers().Length);
            Assert.Equal(0, varC1_T.GetMembers("goo").Length);
            Assert.Equal(0, varC1_T.GetTypeMembers().Length);
            Assert.Equal(0, varC1_T.GetTypeMembers("goo").Length);
            Assert.Equal(0, varC1_T.GetTypeMembers("goo", 1).Length);
            Assert.False(varC1_T.HasConstructorConstraint);
            Assert.False(varC1_T.HasReferenceTypeConstraint);
            Assert.False(varC1_T.HasValueTypeConstraint);
            Assert.Equal(0, varC1_T.EffectiveInterfacesNoUseSiteDiagnostics.Length);
            Assert.True(varC1_T.IsDefinition);
            Assert.False(varC1_T.IsAbstract);
            Assert.False(varC1_T.IsNamespace);
            Assert.False(varC1_T.IsSealed);
            Assert.False(varC1_T.IsVirtual);
            Assert.False(varC1_T.IsOverride);
            Assert.False(varC1_T.IsStatic);
            Assert.True(varC1_T.IsType);
            Assert.Equal(SymbolKind.TypeParameter, varC1_T.Kind);
            Assert.Equal(0, varC1_T.Ordinal);
            Assert.Equal(varC1_T, varC1_T.OriginalDefinition);
            Assert.Equal(TypeKind.TypeParameter, varC1_T.TypeKind);
            Assert.Equal(VarianceKind.None, varC1_T.Variance);
            Assert.Same(module0, varC1_T.Locations.Single().MetadataModuleInternal);
            Assert.Equal(0, varC1_T.ConstraintTypes().Length);
 
            var varC2 = varC1.GetTypeMembers("C2").Single();
            Assert.Equal(1, varC2.Arity);
            Assert.Equal(1, varC2.TypeParameters.Length);
            Assert.Equal(1, varC2.TypeArguments().Length);
 
            var varC2_T = varC2.TypeParameters[0];
 
            Assert.Equal("C2_T", varC2_T.Name);
            Assert.Equal(varC2, varC2_T.ContainingType);
 
            var varC3 = varC1.GetTypeMembers("C3").Single();
            Assert.Equal(0, varC3.Arity);
            Assert.Equal(0, varC3.TypeParameters.Length);
            Assert.Equal(0, varC3.TypeArguments().Length);
 
            var varC4 = varC3.GetTypeMembers("C4").Single();
            Assert.Equal(1, varC4.Arity);
            Assert.Equal(1, varC4.TypeParameters.Length);
            Assert.Equal(1, varC4.TypeArguments().Length);
 
            var varC4_T = varC4.TypeParameters[0];
 
            Assert.Equal("C4_T", varC4_T.Name);
            Assert.Equal(varC4, varC4_T.ContainingType);
 
            var varTC2 = module0.GlobalNamespace.GetTypeMembers("TC2").Single();
 
            Assert.Equal(2, varTC2.Arity);
            Assert.Equal(2, varTC2.TypeParameters.Length);
            Assert.Equal(2, varTC2.TypeArguments().Length);
 
            var varTC2_T1 = varTC2.TypeParameters[0];
            var varTC2_T2 = varTC2.TypeParameters[1];
 
            Assert.Equal(varTC2_T1, varTC2.TypeArguments()[0]);
            Assert.Equal(varTC2_T2, varTC2.TypeArguments()[1]);
 
            Assert.Equal("TC2_T1", varTC2_T1.Name);
            Assert.Equal(varTC2, varTC2_T1.ContainingType);
            Assert.Equal(0, varTC2_T1.Ordinal);
 
            Assert.Equal("TC2_T2", varTC2_T2.Name);
            Assert.Equal(varTC2, varTC2_T2.ContainingType);
            Assert.Equal(1, varTC2_T2.Ordinal);
 
            var varC100 = module0.GlobalNamespace.GetTypeMembers("C100").Single();
            var varT = varC100.TypeParameters[0];
            Assert.False(varT.HasConstructorConstraint);
            Assert.False(varT.HasReferenceTypeConstraint);
            Assert.False(varT.HasValueTypeConstraint);
            Assert.Equal(VarianceKind.Out, varT.Variance);
 
            var varC101 = module0.GlobalNamespace.GetTypeMembers("C101").Single();
            varT = varC101.TypeParameters[0];
            Assert.False(varT.HasConstructorConstraint);
            Assert.False(varT.HasReferenceTypeConstraint);
            Assert.False(varT.HasValueTypeConstraint);
            Assert.Equal(VarianceKind.In, varT.Variance);
 
            var varC102 = module0.GlobalNamespace.GetTypeMembers("C102").Single();
            varT = varC102.TypeParameters[0];
            Assert.True(varT.HasConstructorConstraint);
            Assert.False(varT.HasReferenceTypeConstraint);
            Assert.False(varT.HasValueTypeConstraint);
            Assert.Equal(VarianceKind.None, varT.Variance);
            Assert.Equal(0, varT.ConstraintTypes().Length);
 
            var varC103 = module0.GlobalNamespace.GetTypeMembers("C103").Single();
            varT = varC103.TypeParameters[0];
            Assert.False(varT.HasConstructorConstraint);
            Assert.True(varT.HasReferenceTypeConstraint);
            Assert.False(varT.HasValueTypeConstraint);
            Assert.Equal(VarianceKind.None, varT.Variance);
            Assert.Equal(0, varT.ConstraintTypes().Length);
 
            var varC104 = module0.GlobalNamespace.GetTypeMembers("C104").Single();
            varT = varC104.TypeParameters[0];
            Assert.False(varT.HasConstructorConstraint);
            Assert.False(varT.HasReferenceTypeConstraint);
            Assert.True(varT.HasValueTypeConstraint);
            Assert.Equal(VarianceKind.None, varT.Variance);
            Assert.Equal(0, varT.ConstraintTypes().Length);
 
            var varC105 = module0.GlobalNamespace.GetTypeMembers("C105").Single();
            varT = varC105.TypeParameters[0];
            Assert.True(varT.HasConstructorConstraint);
            Assert.True(varT.HasReferenceTypeConstraint);
            Assert.False(varT.HasValueTypeConstraint);
            Assert.Equal(VarianceKind.None, varT.Variance);
 
            var varC106 = module0.GlobalNamespace.GetTypeMembers("C106").Single();
            varT = varC106.TypeParameters[0];
            Assert.True(varT.HasConstructorConstraint);
            Assert.True(varT.HasReferenceTypeConstraint);
            Assert.False(varT.HasValueTypeConstraint);
            Assert.Equal(VarianceKind.Out, varT.Variance);
 
            var varI101 = module0.GlobalNamespace.GetTypeMembers("I101").Single();
            var varI102 = module0.GlobalNamespace.GetTypeMembers("I102").Single();
 
            var varC201 = module0.GlobalNamespace.GetTypeMembers("C201").Single();
            varT = varC201.TypeParameters[0];
            Assert.Equal(1, varT.ConstraintTypes().Length);
            Assert.Same(varI101, varT.ConstraintTypes().ElementAt(0));
 
            var localC202 = module0.GlobalNamespace.GetTypeMembers("C202").Single();
            varT = localC202.TypeParameters[0];
            Assert.Equal(2, varT.ConstraintTypes().Length);
            Assert.Same(varI101, varT.ConstraintTypes().ElementAt(0));
            Assert.Same(varI102, varT.ConstraintTypes().ElementAt(1));
        }
 
        [Fact, WorkItem(619267, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/619267")]
        public void InvalidNestedArity()
        {
            // .class public C`2<T1,T2>
            // .class nested public D<S1>
            var mdRef = MetadataReference.CreateFromImage(TestResources.MetadataTests.Invalid.InvalidGenericType.AsImmutableOrNull());
            string source = "class X : C<int, int>.D { }";
            CreateCompilation(source, new[] { mdRef }).VerifyDiagnostics(
                // (2,11): error CS0648: 'C<T1, T2>.D' is a type not supported by the language
                // class X : C<int, int>.D { }
                Diagnostic(ErrorCode.ERR_BogusType, "C<int, int>.D").WithArguments("C<T1, T2>.D")
                );
        }
 
        [WorkItem(528859, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528859")]
        [Fact]
        public void InvalidNestedArity_2()
        {
            var ilSource =
@".class interface public abstract I0
{
  .class interface abstract nested public IT<T>
  {
    .class interface abstract nested public I0 { }
  }
}
.class interface public abstract IT<T>
{
  .class interface abstract nested public I0
  {
    .class interface abstract nested public I0 { }
    .class interface abstract nested public IT<T> { }
  }
  .class interface abstract nested public IT<T>
  {
    .class interface abstract nested public I0 { }
  }
  .class interface abstract nested public ITU<T, U>
  {
    .class interface abstract nested public IT<T> { }
  }
}";
            var csharpSource =
@"class C0_T : I0.IT<object> { }
class C0_T_0 : I0.IT<object>.I0 { }
class CT_0 : IT<object>.I0 { }
class CT_0_0 : IT<object>.I0.I0 { }
class CT_0_T : IT<object>.I0.IT { }
class CT_T_0 : IT<object>.IT.I0 { }
class CT_TU_T : IT<object>.ITU<int>.IT { }
";
            var compilation1 = CreateCompilationWithILAndMscorlib40(csharpSource, ilSource);
            compilation1.VerifyDiagnostics(
                // (2,7): error CS0648: 'I0.IT<T>.I0' is a type not supported by the language
                // class C0_T_0 : I0.IT<object>.I0 { }
                Diagnostic(ErrorCode.ERR_BogusType, "C0_T_0").WithArguments("I0.IT<T>.I0"),
                // (3,7): error CS0648: 'IT<T>.I0' is a type not supported by the language
                // class CT_0 : IT<object>.I0 { }
                Diagnostic(ErrorCode.ERR_BogusType, "CT_0").WithArguments("IT<T>.I0"),
                // (4,27): error CS0648: 'IT<T>.I0' is a type not supported by the language
                // class CT_0_0 : IT<object>.I0.I0 { }
                Diagnostic(ErrorCode.ERR_BogusType, "I0").WithArguments("IT<T>.I0"),
                // (4,7): error CS0648: 'IT<T>.I0.I0' is a type not supported by the language
                // class CT_0_0 : IT<object>.I0.I0 { }
                Diagnostic(ErrorCode.ERR_BogusType, "CT_0_0").WithArguments("IT<T>.I0.I0"),
                // (5,27): error CS0648: 'IT<T>.I0' is a type not supported by the language
                // class CT_0_T : IT<object>.I0.IT { }
                Diagnostic(ErrorCode.ERR_BogusType, "I0").WithArguments("IT<T>.I0"),
                // (6,7): error CS0648: 'IT<T>.IT.I0' is a type not supported by the language
                // class CT_T_0 : IT<object>.IT.I0 { }
                Diagnostic(ErrorCode.ERR_BogusType, "CT_T_0").WithArguments("IT<T>.IT.I0"),
                // (7,7): error CS0648: 'IT<T>.ITU<U>.IT' is a type not supported by the language
                // class CT_TU_T : IT<object>.ITU<int>.IT { }
                Diagnostic(ErrorCode.ERR_BogusType, "CT_TU_T").WithArguments("IT<T>.ITU<U>.IT"));
        }
    }
}