File: Symbols\CorLibrary\CorTypes.cs
Web Access
Project: ..\..\..\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;
using System.Collections.Generic;
using System.Linq;
using Basic.Reference.Assemblies;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Symbols.CorLibrary
{
    public class CorTypes : CSharpTestBase
    {
        private static readonly SymbolDisplayFormat s_languageNameFormat = new SymbolDisplayFormat(
            typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces,
            genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters);
 
        [Fact]
        public void MissingCorLib()
        {
            var assemblies = MetadataTestHelpers.GetSymbolsForReferences(new[] { TestReferences.SymbolsTests.CorLibrary.NoMsCorLibRef });
 
            var noMsCorLibRef = assemblies[0];
 
            for (int i = 1; i <= (int)SpecialType.Count; i++)
            {
                var t = noMsCorLibRef.GetSpecialType((SpecialType)i);
                Assert.Equal((SpecialType)i, t.SpecialType);
                Assert.Equal(TypeKind.Error, t.TypeKind);
                Assert.NotNull(t.ContainingAssembly);
                Assert.Equal("<Missing Core Assembly>", t.ContainingAssembly.Identity.Name);
            }
 
            var p = noMsCorLibRef.GlobalNamespace.GetTypeMembers("I1").Single().
                GetMembers("M1").OfType<MethodSymbol>().Single().
                Parameters[0].TypeWithAnnotations;
 
            Assert.Equal(TypeKind.Error, p.Type.TypeKind);
            Assert.Equal(SpecialType.System_Int32, p.SpecialType);
        }
 
        [Fact]
        public void PresentCorLib()
        {
            var assemblies = MetadataTestHelpers.GetSymbolsForReferences(new[] { NetCoreApp.SystemRuntime });
 
            MetadataOrSourceAssemblySymbol msCorLibRef = (MetadataOrSourceAssemblySymbol)assemblies[0];
 
            var knownMissingTypes = new HashSet<int>()
            {
            };
 
            for (int i = 1; i <= (int)SpecialType.Count; i++)
            {
                var t = msCorLibRef.GetSpecialType((SpecialType)i);
                Assert.Equal((SpecialType)i, t.SpecialType);
                Assert.Same(msCorLibRef, t.ContainingAssembly);
                if (knownMissingTypes.Contains(i))
                {
                    // not present on dotnet core 3.1
                    Assert.Equal(TypeKind.Error, t.TypeKind);
                }
                else
                {
                    Assert.NotEqual(TypeKind.Error, t.TypeKind);
                }
            }
 
            Assert.False(msCorLibRef.KeepLookingForDeclaredSpecialTypes);
 
            assemblies = MetadataTestHelpers.GetSymbolsForReferences(mrefs: new[] { MetadataReference.CreateFromImage(Net50.Resources.SystemRuntime) });
 
            msCorLibRef = (MetadataOrSourceAssemblySymbol)assemblies[0];
            Assert.True(msCorLibRef.KeepLookingForDeclaredSpecialTypes);
 
            Queue<NamespaceSymbol> namespaces = new Queue<NamespaceSymbol>();
 
            namespaces.Enqueue(msCorLibRef.Modules[0].GlobalNamespace);
            int count = 0;
 
            while (namespaces.Count > 0)
            {
                foreach (var m in namespaces.Dequeue().GetMembers())
                {
                    NamespaceSymbol ns = m as NamespaceSymbol;
 
                    if (ns != null)
                    {
                        namespaces.Enqueue(ns);
                    }
                    else if (((NamedTypeSymbol)m).SpecialType != SpecialType.None)
                    {
                        count++;
                    }
 
                    if (count >= (int)SpecialType.Count)
                    {
                        Assert.False(msCorLibRef.KeepLookingForDeclaredSpecialTypes);
                    }
                }
            }
 
            Assert.Equal((int)SpecialType.Count, count + knownMissingTypes.Count);
            Assert.Equal(knownMissingTypes.Any(), msCorLibRef.KeepLookingForDeclaredSpecialTypes);
        }
 
        [Fact]
        public void FakeCorLib()
        {
            var assemblies = MetadataTestHelpers.GetSymbolsForReferences(new[] { TestReferences.SymbolsTests.CorLibrary.FakeMsCorLib.dll });
 
            MetadataOrSourceAssemblySymbol msCorLibRef = (MetadataOrSourceAssemblySymbol)assemblies[0];
 
            for (int i = 1; i <= (int)SpecialType.Count; i++)
            {
                Assert.True(msCorLibRef.KeepLookingForDeclaredSpecialTypes);
                var t = msCorLibRef.GetSpecialType((SpecialType)i);
                Assert.Equal((SpecialType)i, t.SpecialType);
 
                if (t.SpecialType == SpecialType.System_Object)
                {
                    Assert.NotEqual(TypeKind.Error, t.TypeKind);
                }
                else
                {
                    Assert.Equal(TypeKind.Error, t.TypeKind);
                    Assert.Same(msCorLibRef, t.ContainingAssembly);
                }
 
                Assert.Same(msCorLibRef, t.ContainingAssembly);
            }
 
            Assert.False(msCorLibRef.KeepLookingForDeclaredSpecialTypes);
        }
 
        [Fact]
        public void SourceCorLib()
        {
            string source = @"
namespace System
{
    public class Object
    {
    }
}
";
 
            var c1 = CSharpCompilation.Create("CorLib", syntaxTrees: new[] { Parse(source) });
 
            Assert.Same(c1.Assembly, c1.Assembly.CorLibrary);
 
            MetadataOrSourceAssemblySymbol msCorLibRef = (MetadataOrSourceAssemblySymbol)c1.Assembly;
 
            for (int i = 1; i <= (int)SpecialType.Count; i++)
            {
                if (i != (int)SpecialType.System_Object)
                {
                    Assert.True(msCorLibRef.KeepLookingForDeclaredSpecialTypes);
                    var t = c1.GetSpecialType((SpecialType)i);
                    Assert.Equal((SpecialType)i, t.SpecialType);
 
                    Assert.Equal(TypeKind.Error, t.TypeKind);
                    Assert.Same(msCorLibRef, t.ContainingAssembly);
                }
            }
 
            var system_object = msCorLibRef.Modules[0].GlobalNamespace.GetMembers("System").
                Select(m => (NamespaceSymbol)m).Single().GetTypeMembers("Object").Single();
 
            Assert.Equal(SpecialType.System_Object, system_object.SpecialType);
 
            Assert.False(msCorLibRef.KeepLookingForDeclaredSpecialTypes);
 
            Assert.Same(system_object, c1.GetSpecialType(SpecialType.System_Object));
 
            Assert.Throws<ArgumentOutOfRangeException>(() => c1.GetSpecialType(SpecialType.None));
            Assert.Throws<ArgumentOutOfRangeException>(() => c1.GetSpecialType(SpecialType.Count + 1));
        }
 
        [WorkItem(697521, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/697521")]
        [Fact]
        public void SubclassSystemArray()
        {
            var source1 = @"
namespace System
{
    public class Object
    {
    }
 
    public class Void
    {
    }
 
    public class Array : Object
    {
    }
}
";
 
            var source2 = @"
namespace System
{
    internal class ArrayContract : Array
    {
    }
}
";
 
            // Fine in corlib.
            CreateEmptyCompilation(source1 + source2).VerifyDiagnostics();
 
            // Error elsewhere.
            CreateCompilation(source2).VerifyDiagnostics(
                // (4,36): error CS0644: 'System.ArrayContract' cannot derive from special class 'System.Array'
                //     internal class ArrayContract : Array
                Diagnostic(ErrorCode.ERR_DeriveFromEnumOrValueType, "Array").WithArguments("System.ArrayContract", "System.Array"));
        }
    }
}