File: Symbols\ErrorTypeSymbolTests.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.Emit;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Symbols
{
    public class ErrorTypeSymbolTests : CSharpTestBase
    {
        [WorkItem(546143, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546143")]
        [Fact]
        public void ConstructedErrorTypes()
        {
            var source1 =
@"public class A<T>
{
    public class B<U> { }
}";
            var compilation1 = CreateCompilation(source1, assemblyName: "91AB32B7-DDDF-4E50-87EF-4E8B0A664A41");
            compilation1.VerifyDiagnostics();
            var reference1 = MetadataReference.CreateFromImage(compilation1.EmitToArray(options: new EmitOptions(metadataOnly: true)));
 
            // Binding types in source, no missing types.
            var source2 =
@"class C1<T, U> : A<T>.B<U> { }
class C2<T, U> : A<T>.B<U> { }
class C3<T> : A<T>.B<object> { }
class C4<T> : A<object>.B<T> { }
class C5 : A<object>.B<int> { }
class C6 : A<string>.B<object> { }
class C7 : A<string>.B<object> { }";
            var compilation2 = CreateCompilation(source2, references: new[] { reference1 }, assemblyName: "91AB32B7-DDDF-4E50-87EF-4E8B0A664A42");
            compilation2.VerifyDiagnostics();
            CompareConstructedErrorTypes(compilation2, missingTypes: false, fromSource: true);
            var reference2 = MetadataReference.CreateFromImage(compilation2.EmitToArray(options: new EmitOptions(metadataOnly: true)));
 
            // Loading types from metadata, no missing types.
            var source3 =
@"";
            var compilation3 = CreateCompilation(source3, references: new[] { reference1, reference2 });
            compilation3.VerifyDiagnostics();
            CompareConstructedErrorTypes(compilation3, missingTypes: false, fromSource: false);
 
            // Binding types in source, missing types, resulting inExtendedErrorTypeSymbols.
            var compilation4 = CreateCompilation(source2);
            CompareConstructedErrorTypes(compilation4, missingTypes: true, fromSource: true);
 
            // Loading types from metadata, missing types, resulting in ErrorTypeSymbols.
            var source5 =
@"";
            var compilation5 = CreateCompilation(source5, references: new[] { reference2 });
            CompareConstructedErrorTypes(compilation5, missingTypes: true, fromSource: false);
        }
 
        private void CompareConstructedErrorTypes(CSharpCompilation compilation, bool missingTypes, bool fromSource)
        {
            // Get all root types.
            var allTypes = compilation.GlobalNamespace.GetTypeMembers();
 
            // Get base class for each type named "C?".
            var types = new[] { "C1", "C2", "C3", "C4", "C5", "C6", "C7" }.Select(name => allTypes.First(t => t.Name == name).BaseType()).ToArray();
            foreach (var type in types)
            {
                var constructedFrom = type.ConstructedFrom;
                Assert.NotEqual(type, constructedFrom);
                if (missingTypes)
                {
                    Assert.True(type.IsErrorType());
                    Assert.True(constructedFrom.IsErrorType());
                    var extendedError = constructedFrom as ExtendedErrorTypeSymbol;
                    if (fromSource)
                    {
                        Assert.NotNull(extendedError);
                    }
                    else
                    {
                        Assert.Null(extendedError);
                    }
                }
                else
                {
                    Assert.False(type.IsErrorType());
                    Assert.False(constructedFrom.IsErrorType());
                }
            }
 
            // Compare pairs of types. The only error types that
            // should compare equal are C6 and C7.
            const int n = 7;
            for (int i = 0; i < n - 1; i++)
            {
                var typeA = types[i];
                for (int j = i + 1; j < n; j++)
                {
                    var typeB = types[j];
                    bool expectedEqual = (i == 5) && (j == 6);
                    Assert.Equal(TypeSymbol.Equals(typeA, typeB, TypeCompareKind.ConsiderEverything2), expectedEqual);
                }
            }
        }
 
        [WorkItem(52516, "https://github.com/dotnet/roslyn/issues/52516")]
        [Fact]
        public void ErrorInfo_01()
        {
            var error = new MissingMetadataTypeSymbol.Nested(new UnsupportedMetadataTypeSymbol(), "Test", 0, false);
            var info = error.ErrorInfo;
 
            Assert.Equal(ErrorCode.ERR_BogusType, (ErrorCode)info.Code);
            Assert.Null(error.ContainingModule);
            Assert.Null(error.ContainingAssembly);
            Assert.NotNull(error.ContainingSymbol);
        }
    }
}