未验证 提交 25c439ca 编写于 作者: C Charles Stoner 提交者: GitHub

Return `null` rather than `this` from INamedTypeSymbol.TupleUnderlyingType (#41828)

Fixes #41702
上级 cb5d3a4d
......@@ -450,12 +450,12 @@ private void AddAnonymousTypeName(INamedTypeSymbol symbol)
/// <returns></returns>
private bool CanUseTupleSyntax(INamedTypeSymbol tupleSymbol)
{
INamedTypeSymbol currentUnderlying = tupleSymbol.TupleUnderlyingType;
if (containsModopt(tupleSymbol))
{
return false;
}
INamedTypeSymbol currentUnderlying = GetTupleUnderlyingTypeOrSelf(tupleSymbol);
if (currentUnderlying.Arity <= 1)
{
return false;
......@@ -473,12 +473,11 @@ private bool CanUseTupleSyntax(INamedTypeSymbol tupleSymbol)
return false;
}
currentUnderlying = tupleSymbol.TupleUnderlyingType;
currentUnderlying = GetTupleUnderlyingTypeOrSelf(tupleSymbol);
}
return true;
bool containsModopt(INamedTypeSymbol symbol)
{
NamedTypeSymbol underlyingTypeSymbol = (symbol as Symbols.PublicModel.NamedTypeSymbol)?.UnderlyingNamedTypeSymbol;
......@@ -492,6 +491,11 @@ bool containsModopt(INamedTypeSymbol symbol)
}
}
private static INamedTypeSymbol GetTupleUnderlyingTypeOrSelf(INamedTypeSymbol type)
{
return type.TupleUnderlyingType ?? type;
}
private static bool HasNonDefaultTupleElements(INamedTypeSymbol tupleSymbol)
{
return tupleSymbol.TupleElements.Any(e => !e.IsDefaultTupleElement());
......
......@@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
namespace Microsoft.CodeAnalysis.CSharp.Symbols.PublicModel
{
......@@ -162,14 +163,18 @@ ImmutableArray<IFieldSymbol> INamedTypeSymbol.TupleElements
}
/// <summary>
/// If this is a tuple type symbol, returns the symbol for its underlying type.
/// If this is a tuple type with element names, returns the symbol for the tuple type without names.
/// Otherwise, returns null.
/// </summary>
INamedTypeSymbol INamedTypeSymbol.TupleUnderlyingType
{
get
{
return UnderlyingNamedTypeSymbol.TupleUnderlyingType.GetPublicSymbol();
var type = UnderlyingNamedTypeSymbol;
var tupleUnderlyingType = type.TupleUnderlyingType;
return type.Equals(tupleUnderlyingType, TypeCompareKind.ConsiderEverything) ?
null :
tupleUnderlyingType.GetPublicSymbol();
}
}
......
......@@ -16,6 +16,7 @@
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
using Xunit;
using static TestResources.NetFX.ValueTuple;
......@@ -5816,7 +5817,8 @@ public struct ValueTuple
var vt0 = comp.GetWellKnownType(WellKnownType.System_ValueTuple);
var tupleWithoutNames = comp.CreateTupleTypeSymbol(vt0, ImmutableArray<string>.Empty);
Assert.True(tupleWithoutNames.IsTupleType);
Assert.Equal(SymbolKind.NamedType, tupleWithoutNames.TupleUnderlyingType.Kind);
Assert.Equal(SymbolKind.NamedType, tupleWithoutNames.Kind);
Assert.Null(tupleWithoutNames.TupleUnderlyingType);
Assert.Equal("System.ValueTuple", tupleWithoutNames.ToTestDisplayString());
Assert.True(GetTupleElementNames(tupleWithoutNames).IsDefault);
Assert.Empty(ElementTypeNames(tupleWithoutNames));
......@@ -5873,7 +5875,8 @@ public void CreateTupleTypeSymbol_WithValueTuple()
Assert.Same(vt2, ((Symbols.PublicModel.NamedTypeSymbol)tupleWithoutNames).UnderlyingNamedTypeSymbol);
Assert.True(tupleWithoutNames.IsTupleType);
Assert.Equal(SymbolKind.NamedType, tupleWithoutNames.TupleUnderlyingType.Kind);
Assert.Equal(SymbolKind.NamedType, tupleWithoutNames.Kind);
Assert.Null(tupleWithoutNames.TupleUnderlyingType);
Assert.Equal("(System.Int32, System.String)", tupleWithoutNames.ToTestDisplayString());
Assert.True(GetTupleElementNames(tupleWithoutNames).IsDefault);
Assert.Equal(new[] { "System.Int32", "System.String" }, ElementTypeNames(tupleWithoutNames));
......@@ -5950,7 +5953,8 @@ public void CreateTupleTypeSymbol_NoNames()
var tupleWithoutNames = comp.CreateTupleTypeSymbol(vt2, default(ImmutableArray<string>));
Assert.True(tupleWithoutNames.IsTupleType);
Assert.Equal(SymbolKind.ErrorType, tupleWithoutNames.TupleUnderlyingType.Kind);
Assert.Equal(SymbolKind.ErrorType, tupleWithoutNames.Kind);
Assert.Null(tupleWithoutNames.TupleUnderlyingType);
Assert.Equal("(System.Int32, System.String)[missing]", tupleWithoutNames.ToTestDisplayString());
Assert.True(GetTupleElementNames(tupleWithoutNames).IsDefault);
Assert.Equal(new[] { "System.Int32", "System.String" }, ElementTypeNames(tupleWithoutNames));
......@@ -6631,7 +6635,8 @@ public void CreateTupleTypeSymbol_UnderlyingType_DefaultArgs_01()
}";
var comp = (Compilation)CreateCompilation(source);
var tuple1 = (INamedTypeSymbol)((IFieldSymbol)comp.GetMember("Program.F")).Type;
var underlyingType = tuple1.TupleUnderlyingType;
Assert.Null(tuple1.TupleUnderlyingType);
var underlyingType = tuple1;
var tuple2 = comp.CreateTupleTypeSymbol(underlyingType);
Assert.True(tuple1.Equals(tuple2, TypeCompareKind.ConsiderEverything));
......@@ -6672,7 +6677,8 @@ public void CreateTupleTypeSymbol_UnderlyingType_DefaultArgs_02()
}";
var comp = (Compilation)CreateCompilation(source);
var tuple1 = (INamedTypeSymbol)((IFieldSymbol)comp.GetMember("Program.F")).Type;
var underlyingType = tuple1.TupleUnderlyingType;
Assert.Null(tuple1.TupleUnderlyingType);
var underlyingType = tuple1;
var tuple2 = comp.CreateTupleTypeSymbol(underlyingType);
Assert.True(tuple1.Equals(tuple2, TypeCompareKind.ConsiderEverything));
......@@ -6789,7 +6795,8 @@ public void CreateTupleTypeSymbol_UnderlyingType_WithNullableAnnotations_01()
}";
var comp = CreateCompilation(source);
var tuple1 = (INamedTypeSymbol)((FieldSymbol)comp.GetMember("Program.F")).GetPublicSymbol().Type;
var underlyingType = tuple1.TupleUnderlyingType;
Assert.Null(tuple1.TupleUnderlyingType);
var underlyingType = tuple1;
var tuple2 = comp.CreateTupleTypeSymbol(underlyingType, elementNullableAnnotations: default);
Assert.True(tuple1.Equals(tuple2, TypeCompareKind.ConsiderEverything));
......@@ -16100,7 +16107,7 @@ void M()
Assert.True(xSymbol.IsTupleType);
Assert.Equal("(System.Int32, System.Int32)[missing]", xSymbol.ToTestDisplayString());
Assert.True(xSymbol.TupleUnderlyingType.IsErrorType());
Assert.Null(xSymbol.TupleUnderlyingType);
Assert.True(xSymbol.IsErrorType());
Assert.True(xSymbol.IsReferenceType);
......@@ -18506,10 +18513,10 @@ public void ClassifyConversionImplicit03u()
ITypeSymbol stringType = comp.GetSpecialType(SpecialType.System_String);
ITypeSymbol objectType = comp.GetSpecialType(SpecialType.System_Object);
var int_string1 = tupleComp1.CreateTupleTypeSymbol(ImmutableArray.Create(intType, stringType)).TupleUnderlyingType;
var int_string1 = tupleComp1.CreateTupleTypeSymbol(ImmutableArray.Create(intType, stringType));
var int_string2 = tupleComp2.CreateTupleTypeSymbol(ImmutableArray.Create(intType, stringType));
var int_object = tupleComp1.CreateTupleTypeSymbol(ImmutableArray.Create(intType, objectType));
Assert.Null(int_string1.TupleUnderlyingType);
Assert.Equal(ConversionKind.ImplicitTuple, comp.ClassifyConversion(int_string1, int_string2).Kind);
Assert.Equal(ConversionKind.ImplicitTuple, comp.ClassifyConversion(int_string2, int_string1).Kind);
......@@ -18531,10 +18538,11 @@ public void ClassifyConversionImplicit03uu()
ITypeSymbol stringType = comp.GetSpecialType(SpecialType.System_String);
ITypeSymbol objectType = comp.GetSpecialType(SpecialType.System_Object);
var int_string1 = tupleComp1.CreateTupleTypeSymbol(ImmutableArray.Create(intType, stringType)).TupleUnderlyingType;
var int_string2 = tupleComp2.CreateTupleTypeSymbol(ImmutableArray.Create(intType, stringType)).TupleUnderlyingType;
var int_string1 = tupleComp1.CreateTupleTypeSymbol(ImmutableArray.Create(intType, stringType));
var int_string2 = tupleComp2.CreateTupleTypeSymbol(ImmutableArray.Create(intType, stringType));
var int_object = tupleComp1.CreateTupleTypeSymbol(ImmutableArray.Create(intType, objectType));
Assert.Null(int_string1.TupleUnderlyingType);
Assert.Null(int_string2.TupleUnderlyingType);
Assert.Equal(ConversionKind.ImplicitTuple, comp.ClassifyConversion(int_string1, int_string2).Kind);
Assert.Equal(ConversionKind.ImplicitTuple, comp.ClassifyConversion(int_string2, int_string1).Kind);
......@@ -18556,10 +18564,12 @@ public void ClassifyConversionImplicit03uuu()
ITypeSymbol stringType = comp.GetSpecialType(SpecialType.System_String);
ITypeSymbol objectType = comp.GetSpecialType(SpecialType.System_Object);
var int_string1 = tupleComp1.CreateTupleTypeSymbol(ImmutableArray.Create(intType, stringType)).TupleUnderlyingType;
var int_string2 = tupleComp2.CreateTupleTypeSymbol(ImmutableArray.Create(intType, stringType)).TupleUnderlyingType;
var int_object = tupleComp1.CreateTupleTypeSymbol(ImmutableArray.Create(intType, objectType)).TupleUnderlyingType;
var int_string1 = tupleComp1.CreateTupleTypeSymbol(ImmutableArray.Create(intType, stringType));
var int_string2 = tupleComp2.CreateTupleTypeSymbol(ImmutableArray.Create(intType, stringType));
var int_object = tupleComp1.CreateTupleTypeSymbol(ImmutableArray.Create(intType, objectType));
Assert.Null(int_string1.TupleUnderlyingType);
Assert.Null(int_string2.TupleUnderlyingType);
Assert.Null(int_object.TupleUnderlyingType);
Assert.Equal(ConversionKind.ImplicitTuple, comp.ClassifyConversion(int_string1, int_string2).Kind);
Assert.Equal(ConversionKind.ImplicitTuple, comp.ClassifyConversion(int_string2, int_string1).Kind);
......@@ -26579,5 +26589,136 @@ public static void Main()
var comp6 = CreateCompilation(source2, targetFramework: TargetFramework.Mscorlib46, options: TestOptions.DebugExe, references: comp1ImageRef);
CompileAndVerify(comp6, expectedOutput: "123");
}
[Fact]
[WorkItem(41702, "https://github.com/dotnet/roslyn/issues/41702")]
public void TupleUnderlyingType_FromCSharp()
{
var source =
@"#pragma warning disable 169
class Program
{
static System.ValueTuple F0;
static (int, int) F1;
static (int A, int B) F2;
static (object, object, object, object, object, object, object, object) F3;
static (object, object B, object, object D, object, object F, object, object H) F4;
}";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics();
var containingType = comp.GlobalNamespace.GetTypeMembers("Program").Single();
VerifyTypeFromCSharp((NamedTypeSymbol)((FieldSymbol)containingType.GetMembers("F0").Single()).Type, TupleUnderlyingTypeValue.Same, TupleUnderlyingTypeValue.Null, TupleUnderlyingTypeValue.Same, TupleUnderlyingTypeValue.Null, "System.ValueTuple", "()");
VerifyTypeFromCSharp((NamedTypeSymbol)((FieldSymbol)containingType.GetMembers("F1").Single()).Type, TupleUnderlyingTypeValue.Same, TupleUnderlyingTypeValue.Null, TupleUnderlyingTypeValue.Same, TupleUnderlyingTypeValue.Null, "(System.Int32, System.Int32)", "(System.Int32, System.Int32)");
VerifyTypeFromCSharp((NamedTypeSymbol)((FieldSymbol)containingType.GetMembers("F2").Single()).Type, TupleUnderlyingTypeValue.Distinct, TupleUnderlyingTypeValue.Distinct, TupleUnderlyingTypeValue.Same, TupleUnderlyingTypeValue.Null, "(System.Int32 A, System.Int32 B)", "(A As System.Int32, B As System.Int32)");
VerifyTypeFromCSharp((NamedTypeSymbol)((FieldSymbol)containingType.GetMembers("F3").Single()).Type, TupleUnderlyingTypeValue.Same, TupleUnderlyingTypeValue.Null, TupleUnderlyingTypeValue.Null, TupleUnderlyingTypeValue.Null, "(System.Object, System.Object, System.Object, System.Object, System.Object, System.Object, System.Object, System.Object)", "(System.Object, System.Object, System.Object, System.Object, System.Object, System.Object, System.Object, System.Object)");
VerifyTypeFromCSharp((NamedTypeSymbol)((FieldSymbol)containingType.GetMembers("F4").Single()).Type, TupleUnderlyingTypeValue.Distinct, TupleUnderlyingTypeValue.Distinct, TupleUnderlyingTypeValue.Null, TupleUnderlyingTypeValue.Null, "(System.Object, System.Object B, System.Object, System.Object D, System.Object, System.Object F, System.Object, System.Object H)", "(System.Object, B As System.Object, System.Object, D As System.Object, System.Object, F As System.Object, System.Object, H As System.Object)");
}
[Fact]
[WorkItem(41702, "https://github.com/dotnet/roslyn/issues/41702")]
public void TupleUnderlyingType_FromVisualBasic()
{
var source =
@"Class Program
Private F0 As System.ValueTuple
Private F1 As (Integer, Integer)
Private F2 As (A As Integer, B As Integer)
Private F3 As (Object, Object, Object, Object, Object, Object, Object, Object)
Private F4 As (Object, B As Object, Object, D As Object, Object, F As Object, Object, H As Object)
End Class";
var comp = CreateVisualBasicCompilation(source, referencedAssemblies: TargetFrameworkUtil.GetReferences(TargetFramework.Standard));
comp.VerifyDiagnostics();
var containingType = comp.GlobalNamespace.GetTypeMembers("Program").Single();
VerifyTypeFromVisualBasic((INamedTypeSymbol)((IFieldSymbol)containingType.GetMembers("F0").Single()).Type, TupleUnderlyingTypeValue.Null, "System.ValueTuple", "System.ValueTuple");
VerifyTypeFromVisualBasic((INamedTypeSymbol)((IFieldSymbol)containingType.GetMembers("F1").Single()).Type, TupleUnderlyingTypeValue.Distinct, "(System.Int32, System.Int32)", "(System.Int32, System.Int32)");
VerifyTypeFromVisualBasic((INamedTypeSymbol)((IFieldSymbol)containingType.GetMembers("F2").Single()).Type, TupleUnderlyingTypeValue.Distinct, "(System.Int32 A, System.Int32 B)", "(A As System.Int32, B As System.Int32)");
VerifyTypeFromVisualBasic((INamedTypeSymbol)((IFieldSymbol)containingType.GetMembers("F3").Single()).Type, TupleUnderlyingTypeValue.Distinct, "(System.Object, System.Object, System.Object, System.Object, System.Object, System.Object, System.Object, System.Object)", "(System.Object, System.Object, System.Object, System.Object, System.Object, System.Object, System.Object, System.Object)");
VerifyTypeFromVisualBasic((INamedTypeSymbol)((IFieldSymbol)containingType.GetMembers("F4").Single()).Type, TupleUnderlyingTypeValue.Distinct, "(System.Object, System.Object B, System.Object, System.Object D, System.Object, System.Object F, System.Object, System.Object H)", "(System.Object, B As System.Object, System.Object, D As System.Object, System.Object, F As System.Object, System.Object, H As System.Object)");
}
private enum TupleUnderlyingTypeValue
{
Null,
Distinct,
Same
}
private static void VerifyTypeFromCSharp(
NamedTypeSymbol type,
TupleUnderlyingTypeValue expectedInternalValue,
TupleUnderlyingTypeValue expectedPublicValue,
TupleUnderlyingTypeValue definitionInternalValue,
TupleUnderlyingTypeValue definitionPublicValue,
string expectedCSharp,
string expectedVisualBasic)
{
VerifyDisplay(type.GetPublicSymbol(), expectedCSharp, expectedVisualBasic);
VerifyInternalType(type, expectedInternalValue);
VerifyPublicType(type.GetPublicSymbol(), expectedPublicValue);
type = type.OriginalDefinition;
VerifyInternalType(type, definitionInternalValue);
VerifyPublicType(type.GetPublicSymbol(), definitionPublicValue);
}
private static void VerifyTypeFromVisualBasic(
INamedTypeSymbol type,
TupleUnderlyingTypeValue expectedValue,
string expectedCSharp,
string expectedVisualBasic)
{
VerifyDisplay(type, expectedCSharp, expectedVisualBasic);
VerifyPublicType(type, expectedValue);
VerifyPublicType(type.OriginalDefinition, expectedValue);
}
private static void VerifyDisplay(INamedTypeSymbol type, string expectedCSharp, string expectedVisualBasic)
{
Assert.Equal(expectedCSharp, CSharp.SymbolDisplay.ToDisplayString(type, SymbolDisplayFormat.TestFormat));
Assert.Equal(expectedVisualBasic, VisualBasic.SymbolDisplay.ToDisplayString(type, SymbolDisplayFormat.TestFormat));
}
private static void VerifyInternalType(NamedTypeSymbol type, TupleUnderlyingTypeValue expectedValue)
{
var underlyingType = type.TupleUnderlyingType;
switch (expectedValue)
{
case TupleUnderlyingTypeValue.Null:
Assert.Null(underlyingType);
break;
case TupleUnderlyingTypeValue.Distinct:
Assert.NotEqual(type, underlyingType);
Assert.True(type.Equals(underlyingType, TypeCompareKind.AllIgnoreOptions));
Assert.False(type.Equals(underlyingType, TypeCompareKind.ConsiderEverything));
VerifyInternalType(underlyingType, TupleUnderlyingTypeValue.Same);
break;
case TupleUnderlyingTypeValue.Same:
Assert.Equal(type, underlyingType);
Assert.True(type.Equals(underlyingType, TypeCompareKind.ConsiderEverything));
break;
default:
throw ExceptionUtilities.UnexpectedValue(expectedValue);
}
}
private static void VerifyPublicType(INamedTypeSymbol type, TupleUnderlyingTypeValue expectedValue)
{
var underlyingType = type.TupleUnderlyingType;
switch (expectedValue)
{
case TupleUnderlyingTypeValue.Null:
Assert.Null(underlyingType);
break;
case TupleUnderlyingTypeValue.Distinct:
Assert.NotEqual(type, underlyingType);
Assert.False(type.Equals(underlyingType, SymbolEqualityComparer.Default));
Assert.False(type.Equals(underlyingType, SymbolEqualityComparer.ConsiderEverything));
VerifyPublicType(underlyingType, TupleUnderlyingTypeValue.Null);
break;
default:
throw ExceptionUtilities.UnexpectedValue(expectedValue);
}
}
}
}
......@@ -167,7 +167,7 @@ public interface INamedTypeSymbol : ITypeSymbol
bool MightContainExtensionMethods { get; }
/// <summary>
/// If this is a tuple type symbol, returns the symbol for its underlying type (ie. without element names).
/// If this is a tuple type with element names, returns the symbol for the tuple type without names.
/// Otherwise, returns null.
/// The type argument corresponding to the type of the extension field (VT[8].Rest),
/// which is at the 8th (one based) position is always a symbol for another tuple,
......
......@@ -330,7 +330,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
''' <param name="tupleSymbol"></param>
''' <returns></returns>
Private Shared Function CanUseTupleTypeName(tupleSymbol As INamedTypeSymbol) As Boolean
Dim currentUnderlying As INamedTypeSymbol = tupleSymbol.TupleUnderlyingType
Dim currentUnderlying As INamedTypeSymbol = GetTupleUnderlyingTypeOrSelf(tupleSymbol)
If currentUnderlying.Arity = 1 Then
Return False
......@@ -344,12 +344,16 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return False
End If
currentUnderlying = tupleSymbol.TupleUnderlyingType
currentUnderlying = GetTupleUnderlyingTypeOrSelf(tupleSymbol)
End While
Return True
End Function
Private Shared Function GetTupleUnderlyingTypeOrSelf(tupleSymbol As INamedTypeSymbol) As INamedTypeSymbol
Return If(tupleSymbol.TupleUnderlyingType, tupleSymbol)
End Function
Private Shared Function HasNonDefaultTupleElements(tupleSymbol As INamedTypeSymbol) As Boolean
Return tupleSymbol.TupleElements.Any(Function(e) Not e.IsDefaultTupleElement)
End Function
......
......@@ -22944,6 +22944,112 @@ End Class
CompileAndVerify(comp6, expectedOutput:="123")
End Sub
<Fact>
<WorkItem(41702, "https://github.com/dotnet/roslyn/issues/41702")>
Public Sub TupleUnderlyingType_FromCSharp()
Dim source =
"#pragma warning disable 169
class Program
{
static System.ValueTuple F0;
static (int, int) F1;
static (int A, int B) F2;
static (object, object, object, object, object, object, object, object) F3;
static (object, object B, object, object D, object, object F, object, object H) F4;
}"
Dim comp = CreateCSharpCompilation(source, referencedAssemblies:=TargetFrameworkUtil.GetReferences(TargetFramework.Standard))
comp.VerifyDiagnostics()
Dim containingType = comp.GlobalNamespace.GetTypeMembers("Program").Single()
VerifyTypeFromCSharp(DirectCast(DirectCast(containingType.GetMembers("F0").Single(), IFieldSymbol).Type, INamedTypeSymbol), TupleUnderlyingTypeValue.Nothing, "System.ValueTuple", "()")
VerifyTypeFromCSharp(DirectCast(DirectCast(containingType.GetMembers("F1").Single(), IFieldSymbol).Type, INamedTypeSymbol), TupleUnderlyingTypeValue.Nothing, "(System.Int32, System.Int32)", "(System.Int32, System.Int32)")
VerifyTypeFromCSharp(DirectCast(DirectCast(containingType.GetMembers("F2").Single(), IFieldSymbol).Type, INamedTypeSymbol), TupleUnderlyingTypeValue.Distinct, "(System.Int32 A, System.Int32 B)", "(A As System.Int32, B As System.Int32)")
VerifyTypeFromCSharp(DirectCast(DirectCast(containingType.GetMembers("F3").Single(), IFieldSymbol).Type, INamedTypeSymbol), TupleUnderlyingTypeValue.Nothing, "(System.Object, System.Object, System.Object, System.Object, System.Object, System.Object, System.Object, System.Object)", "(System.Object, System.Object, System.Object, System.Object, System.Object, System.Object, System.Object, System.Object)")
VerifyTypeFromCSharp(DirectCast(DirectCast(containingType.GetMembers("F4").Single(), IFieldSymbol).Type, INamedTypeSymbol), TupleUnderlyingTypeValue.Distinct, "(System.Object, System.Object B, System.Object, System.Object D, System.Object, System.Object F, System.Object, System.Object H)", "(System.Object, B As System.Object, System.Object, D As System.Object, System.Object, F As System.Object, System.Object, H As System.Object)")
End Sub
<Fact>
<WorkItem(41702, "https://github.com/dotnet/roslyn/issues/41702")>
Public Sub TupleUnderlyingType_FromVisualBasic()
Dim source =
"Class Program
Private F0 As System.ValueTuple
Private F1 As (Integer, Integer)
Private F2 As (A As Integer, B As Integer)
Private F3 As (Object, Object, Object, Object, Object, Object, Object, Object)
Private F4 As (Object, B As Object, Object, D As Object, Object, F As Object, Object, H As Object)
End Class"
Dim comp = CreateCompilation(source)
comp.AssertNoDiagnostics()
Dim containingType = comp.GlobalNamespace.GetTypeMembers("Program").Single()
VerifyTypeFromVisualBasic(DirectCast(DirectCast(containingType.GetMembers("F0").Single(), FieldSymbol).Type, NamedTypeSymbol), TupleUnderlyingTypeValue.Nothing, "System.ValueTuple", "System.ValueTuple")
VerifyTypeFromVisualBasic(DirectCast(DirectCast(containingType.GetMembers("F1").Single(), FieldSymbol).Type, NamedTypeSymbol), TupleUnderlyingTypeValue.Distinct, "(System.Int32, System.Int32)", "(System.Int32, System.Int32)")
VerifyTypeFromVisualBasic(DirectCast(DirectCast(containingType.GetMembers("F2").Single(), FieldSymbol).Type, NamedTypeSymbol), TupleUnderlyingTypeValue.Distinct, "(System.Int32 A, System.Int32 B)", "(A As System.Int32, B As System.Int32)")
VerifyTypeFromVisualBasic(DirectCast(DirectCast(containingType.GetMembers("F3").Single(), FieldSymbol).Type, NamedTypeSymbol), TupleUnderlyingTypeValue.Distinct, "(System.Object, System.Object, System.Object, System.Object, System.Object, System.Object, System.Object, System.Object)", "(System.Object, System.Object, System.Object, System.Object, System.Object, System.Object, System.Object, System.Object)")
VerifyTypeFromVisualBasic(DirectCast(DirectCast(containingType.GetMembers("F4").Single(), FieldSymbol).Type, NamedTypeSymbol), TupleUnderlyingTypeValue.Distinct, "(System.Object, System.Object B, System.Object, System.Object D, System.Object, System.Object F, System.Object, System.Object H)", "(System.Object, B As System.Object, System.Object, D As System.Object, System.Object, F As System.Object, System.Object, H As System.Object)")
End Sub
Private Enum TupleUnderlyingTypeValue
[Nothing]
Distinct
Same
End Enum
Private Shared Sub VerifyTypeFromCSharp(type As INamedTypeSymbol, expectedValue As TupleUnderlyingTypeValue, expectedCSharp As String, expectedVisualBasic As String)
VerifyDisplay(type, expectedCSharp, expectedVisualBasic)
VerifyPublicType(type, expectedValue)
VerifyPublicType(type.OriginalDefinition, TupleUnderlyingTypeValue.Nothing)
End Sub
Private Shared Sub VerifyTypeFromVisualBasic(type As NamedTypeSymbol, expectedValue As TupleUnderlyingTypeValue, expectedCSharp As String, expectedVisualBasic As String)
VerifyDisplay(type, expectedCSharp, expectedVisualBasic)
VerifyInternalType(type, expectedValue)
VerifyPublicType(type, expectedValue)
type = type.OriginalDefinition
VerifyInternalType(type, expectedValue)
VerifyPublicType(type, expectedValue)
End Sub
Private Shared Sub VerifyDisplay(type As INamedTypeSymbol, expectedCSharp As String, expectedVisualBasic As String)
Assert.Equal(expectedCSharp, CSharp.SymbolDisplay.ToDisplayString(type, SymbolDisplayFormat.TestFormat))
Assert.Equal(expectedVisualBasic, VisualBasic.SymbolDisplay.ToDisplayString(type, SymbolDisplayFormat.TestFormat))
End Sub
Private Shared Sub VerifyInternalType(type As NamedTypeSymbol, expectedValue As TupleUnderlyingTypeValue)
Dim underlyingType = type.TupleUnderlyingType
Select Case expectedValue
Case TupleUnderlyingTypeValue.Nothing
Assert.Null(underlyingType)
Case TupleUnderlyingTypeValue.Distinct
Assert.NotEqual(type, underlyingType)
Assert.False(type.Equals(underlyingType, TypeCompareKind.AllIgnoreOptions))
Assert.False(type.Equals(underlyingType, TypeCompareKind.ConsiderEverything))
VerifyPublicType(underlyingType, expectedValue:=TupleUnderlyingTypeValue.Nothing)
Case Else
Throw ExceptionUtilities.UnexpectedValue(expectedValue)
End Select
End Sub
Private Shared Sub VerifyPublicType(type As INamedTypeSymbol, expectedValue As TupleUnderlyingTypeValue)
Dim underlyingType = type.TupleUnderlyingType
Select Case expectedValue
Case TupleUnderlyingTypeValue.Nothing
Assert.Null(underlyingType)
Case TupleUnderlyingTypeValue.Distinct
Assert.NotEqual(type, underlyingType)
Assert.False(type.Equals(underlyingType, SymbolEqualityComparer.Default))
Assert.False(type.Equals(underlyingType, SymbolEqualityComparer.ConsiderEverything))
VerifyPublicType(underlyingType, expectedValue:=TupleUnderlyingTypeValue.Nothing)
Case Else
Throw ExceptionUtilities.UnexpectedValue(expectedValue)
End Select
End Sub
End Class
End Namespace
......
......@@ -422,7 +422,7 @@ public override object VisitNamedType(INamedTypeSymbol namedTypeSymbol)
WriteType(SymbolKeyType.ErrorType);
ErrorTypeSymbolKey.Create(namedTypeSymbol, this);
}
else if (namedTypeSymbol.IsTupleType && namedTypeSymbol.TupleUnderlyingType != namedTypeSymbol)
else if (namedTypeSymbol.IsTupleType && namedTypeSymbol.TupleUnderlyingType is INamedTypeSymbol underlyingType && underlyingType != namedTypeSymbol)
{
// A tuple is a named type with some added information
// We only need to store this extra information if there is some
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册