提交 449e6730 编写于 作者: J Jason Malinowski

Fix up the rest of the C# TypeInferrer to wrap with nullability

上级 5f528109
......@@ -110,6 +110,14 @@ public async Task TestVariableDeclarator2()
@"var q = [|Goo()|];", "global::System.Object");
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestVariableDeclaratorNullableReferenceType()
{
await TestInMethodAsync(
@"#nullable enable
string? q = [|Goo()|];", "global::System.String?");
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestCoalesce1()
{
......@@ -140,6 +148,17 @@ public async Task TestCoalesce4()
@"var q = [|Goo()|] ?? string.Empty;", "global::System.String", testPosition: false);
}
// This is skipped for now. This is a case where we know we can unilaterally mark the reference type as nullable, as long as the user has #nullable enable on.
// But right now there's no compiler API to know if it is, so we have to skip this. Once there is an API, we'll have it always return a nullable reference type
// and we'll remove the ? if it's in a non-nullable context no differently than we always generate types fully qualified and then clean up based on context.
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/36101"), Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestCoalesceInNullableEnabled()
{
await TestInMethodAsync(
@"#nullable enable
var q = [|Goo()|] ?? string.Empty;", "global::System.String?", testPosition: false);
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestBinaryExpression1()
{
......@@ -704,6 +723,17 @@ public async Task TestReturnInMethod()
}", "global::System.Int32");
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestReturnInMethodNullableReference()
{
await TestInClassAsync(
@"#nullable enable
string? M()
{
return [|Goo()|];
}", "global::System.String?");
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestReturnInVoidMethod()
{
......@@ -724,6 +754,16 @@ public async Task TestReturnInAsyncTaskOfTMethod()
}", "global::System.Int32");
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestReturnInAsyncTaskOfTMethodNestedNullability()
{
await TestInClassAsync(
@"async System.Threading.Tasks.Task<string?> M()
{
return [|Goo()|];
}", "global::System.String?");
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestReturnInAsyncTaskMethod()
{
......@@ -777,6 +817,20 @@ public async Task TestReturnInPropertyGetter()
}", "global::System.Int32");
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestReturnInPropertyGetterNullableReference()
{
await TestInClassAsync(
@"#nullable enable
string? P
{
get
{
return [|Goo()|];
}
}", "global::System.String?");
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestReturnInPropertySetter()
{
......@@ -803,6 +857,20 @@ public async Task TestReturnInIndexerGetter()
}", "global::System.Int32");
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestReturnInIndexerGetterNullableReference()
{
await TestInClassAsync(
@"#nullable enable
string? this[int i]
{
get
{
return [|Goo()|];
}
}", "global::System.String?");
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestReturnInIndexerSetter()
{
......@@ -857,6 +925,20 @@ int F()
}", "global::System.Int32");
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestReturnInLocalFunctionNullableReference()
{
await TestInClassAsync(
@"#nullable enable
void M()
{
string? F()
{
return [|Goo()|];
}
}", "global::System.String?");
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestReturnInAsyncTaskOfTLocalFunction()
{
......@@ -932,6 +1014,15 @@ public async Task TestExpressionBodiedAsyncTaskOfTMethod()
@"async System.Threading.Tasks.Task<int> M() => [|Goo()|];", "global::System.Int32");
}
[WorkItem(27647, "https://github.com/dotnet/roslyn/issues/27647")]
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestExpressionBodiedAsyncTaskOfTMethodNullableReference()
{
await TestInClassAsync(
@"#nullable enable
async System.Threading.Tasks.Task<string?> M() => [|Goo()|];", "global::System.String?");
}
[WorkItem(27647, "https://github.com/dotnet/roslyn/issues/27647")]
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestExpressionBodiedAsyncTaskMethod()
......@@ -1079,6 +1170,26 @@ class C
await TestAsync(markup, "global::System.Int32");
}
[Theory, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
[InlineData("IEnumerable")]
[InlineData("IEnumerator")]
[InlineData("InvalidGenericType")]
public async Task TestYieldReturnInMethodNullableReference(string returnTypeName)
{
var markup =
$@"#nullable enable
using System.Collections.Generic;
class C
{{
{returnTypeName}<string?> M()
{{
yield return [|abc|]
}}
}}";
await TestAsync(markup, "global::System.String?");
}
[Theory, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
[InlineData("IAsyncEnumerable")]
[InlineData("IAsyncEnumerator")]
......@@ -1202,6 +1313,17 @@ public async Task TestReturnInParenthesizedLambda()
};", "global::System.Int32");
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestReturnInLambdaWithNullableReturn()
{
await TestInMethodAsync(
@"#nullable enable
System.Func<string, string?> f = s =>
{
return [|Goo()|];
};", "global::System.String?");
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestReturnInAnonymousMethod()
{
......@@ -1212,6 +1334,17 @@ public async Task TestReturnInAnonymousMethod()
};", "global::System.Int32");
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestReturnInAnonymousMethodWithNullableReturn()
{
await TestInMethodAsync(
@"#nullable enable
System.Func<string?> f = delegate ()
{
return [|Goo()|];
};", "global::System.String?");
}
[WorkItem(4486, "https://github.com/dotnet/roslyn/issues/4486")]
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestReturnInAsyncTaskOfTSimpleLambda()
......@@ -1245,6 +1378,17 @@ public async Task TestReturnInAsyncTaskOfTAnonymousMethod()
};", "global::System.Int32");
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestReturnInAsyncTaskOfTAnonymousMethodWithNullableReference()
{
await TestInMethodAsync(
@"#nullable enable
System.Func<System.Threading.Tasks.Task<string?>> f = async delegate ()
{
return [|Goo()|];
};", "global::System.String?");
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestReturnInAsyncTaskSimpleLambda()
{
......@@ -1334,6 +1478,14 @@ public async Task TestAsyncTaskOfTSimpleLambda()
@"System.Func<string, System.Threading.Tasks.Task<int>> f = async s => [|Goo()|];", "global::System.Int32");
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestAsyncTaskOfTSimpleLambdaWithNullableReturn()
{
await TestInMethodAsync(
@"#nullable enable
System.Func<string, System.Threading.Tasks.Task<string?>> f = async s => [|Goo()|];", "global::System.String?");
}
[WorkItem(30232, "https://github.com/dotnet/roslyn/issues/30232")]
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestAsyncTaskOfTParenthesizedLambda()
......@@ -1438,6 +1590,15 @@ public async Task TestFor3()
await TestInMethodAsync(@"for (var i = [|Goo()|]; ; ) { }", "global::System.Int32");
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestForNullableReference()
{
await TestInMethodAsync(
@"#nullable enable
for (string? s = [|Goo()|]; ; ) { }", "global::System.String?");
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestUsing1()
{
......@@ -1462,6 +1623,14 @@ public async Task TestForEach()
await TestInMethodAsync(@"foreach (int v in [|Goo()|]) { }", "global::System.Collections.Generic.IEnumerable<global::System.Int32>");
}
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/36046"), Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestForEachNullableElements()
{
await TestInMethodAsync(
@"#nullable enable
foreach (string? v in [|Goo()|]) { }", "global::System.Collections.Generic.IEnumerable<global::System.String?>");
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestPrefixExpression1()
{
......@@ -1577,6 +1746,18 @@ public async Task TestMethodCall5()
void Bar(int i, string s);", "global::System.String");
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestMethodCallNullableReference()
{
await TestInClassAsync(
@"void M()
{
Bar([|Goo()|]);
}
void Bar(string? s);", "global::System.String?");
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestConstructorCall1()
{
......@@ -1591,7 +1772,9 @@ public async Task TestConstructorCall2()
@"void M()
{
new C([|Goo()|]);
} C(int i)
}
C(int i)
{
}", "global::System.Int32");
}
......@@ -1603,7 +1786,9 @@ public async Task TestConstructorCall3()
@"void M()
{
new C([|Goo()|]);
} C()
}
C()
{
}", "global::System.Object");
}
......@@ -1615,7 +1800,9 @@ public async Task TestConstructorCall4()
@"void M()
{
new C([|Goo()|]);
} C(int i, string s)
}
C(int i, string s)
{
}", "global::System.Int32");
}
......@@ -1627,11 +1814,29 @@ public async Task TestConstructorCall5()
@"void M()
{
new C(s: [|Goo()|]);
} C(int i, string s)
}
C(int i, string s)
{
}", "global::System.String");
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestConstructorCallNullableParameter()
{
await TestInClassAsync(
@"#nullable enable
void M()
{
new C([|Goo()|]);
}
C(string? s)
{
}", "global::System.String?");
}
[WorkItem(858112, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/858112")]
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestThisConstructorInitializer1()
......@@ -1658,6 +1863,20 @@ public MyClass(int x, string y) : this(5, [|test|])
}", "global::System.String");
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestThisConstructorInitializerNullableParameter()
{
await TestAsync(
@"#nullable enable
class MyClass
{
public MyClass(string? y) : this([|test|])
{
}
}", "global::System.String?");
}
[WorkItem(858112, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/858112")]
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestBaseConstructorInitializer()
......@@ -1678,6 +1897,27 @@ public D() : base([|test|])
}", "global::System.Int32");
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestBaseConstructorInitializerNullableParameter()
{
await TestAsync(
@"#nullable enable
class B
{
public B(string? x)
{
}
}
class D : B
{
public D() : base([|test|])
{
}
}", "global::System.String?");
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestIndexAccess1()
{
......@@ -1696,27 +1936,25 @@ public async Task TestIndexerCall1()
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestIndexerCall2()
{
// Update this when binding of indexers is working.
await TestInClassAsync(
@"void M()
{
this[[|Goo()|]];
}
int this[int i] { get; }", "global::System.Int32");
int this[long i] { get; }", "global::System.Int64");
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestIndexerCall3()
{
// Update this when binding of indexers is working.
await TestInClassAsync(
@"void M()
{
this[[|Goo()|]];
this[42, [|Goo()|]];
}
int this[int i, string s] { get; }", "global::System.Int32");
int this[int i, string s] { get; }", "global::System.String");
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
......@@ -1804,6 +2042,27 @@ void M()
await TestAsync(text, "global::System.Object");
}
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/32459")]
public async Task TestArrayInitializerInImplicitArrayCreationInferredAsNullable()
{
var text =
@"#nullable enable
using System.Collections.Generic;
class C
{
void M()
{
var a = new[] { Bar(), [|Goo()|] };
}
object? Bar() { return null; }
}";
await TestAsync(text, "global::System.Object?");
}
[Fact]
public async Task TestArrayInitializerInEqualsValueClauseSimple()
{
......@@ -1840,6 +2099,25 @@ void M()
await TestAsync(text, "global::System.Int32");
}
[Fact]
public async Task TestArrayInitializerInEqualsValueClauseNullableElement()
{
var text =
@"#nullable enable
using System.Collections.Generic;
class C
{
void M()
{
string?[] a = { [|Goo()|] };
}
}";
await TestAsync(text, "global::System.String?");
}
[Fact]
[WorkItem(529480, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529480")]
[Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
......@@ -1859,6 +2137,26 @@ void M()
await TestAsync(text, "global::System.Int32");
}
[Fact]
[Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestCollectionInitializerNullableElement()
{
var text =
@"#nullable enable
using System.Collections.Generic;
class C
{
void M()
{
new List<string?>() { [|Goo()|] };
}
}";
await TestAsync(text, "global::System.String?");
}
[Fact]
[WorkItem(529480, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529480")]
[Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
......@@ -1974,6 +2272,30 @@ public System.Collections.IEnumerator GetEnumerator()
await TestAsync(text, "global::System.String");
}
[Fact]
[Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestCustomCollectionInitializerAddMethodWithNullableParameter()
{
var text =
@"class C : System.Collections.IEnumerable
{
void M()
{
var x = new C() { { ""test"", [|s|] } };
}
void Add(int i) { }
void Add(string s, string? s2) { }
public System.Collections.IEnumerator GetEnumerator()
{
throw new System.NotImplementedException();
}
}";
await TestAsync(text, "global::System.String?");
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestArrayInference1()
{
......@@ -2104,6 +2426,24 @@ void M()
await TestAsync(text, "global::System.Int32");
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestInsideLambdaNullableReturn()
{
var text =
@"#nullable enable
using System;
class C
{
void M()
{
Func<int, string?> f = i => [|here|]
}
}";
await TestAsync(text, "global::System.String?");
}
[WorkItem(539813, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539813")]
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestPointer1()
......@@ -2168,6 +2508,24 @@ void M()
await TestAsync(text, "global::System.Threading.Tasks.Task<global::System.Int32>");
}
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/36046"), Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestAwaitTaskOfTNullableValue()
{
var text =
@"#nullable enable
using System.Threading.Tasks;
class C
{
void M()
{
string? x = await [|Goo()|];
}
}";
await TestAsync(text, "global::System.Threading.Tasks.Task<global::System.String?>");
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
[WorkItem(553584, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/553584")]
public async Task TestAwaitTaskOfTaskOfT()
......@@ -2649,6 +3007,13 @@ public async Task TestDeconstruction2()
@"(int i, _) = [||]", "(global::System.Int32 i, global::System.Object _)", testNode: false);
}
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/36047"), Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestDeconstructionWithNullableElement()
{
await TestInMethodAsync(
@"[|(string? s, _)|] =", "(global::System.String? s, global::System.Object _)", testPosition: false);
}
[WorkItem(13402, "https://github.com/dotnet/roslyn/issues/13402")]
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
public async Task TestObjectCreationBeforeBlock()
......
......@@ -326,8 +326,7 @@ private IEnumerable<TypeInferenceInfo> InferTypeInAnonymousObjectCreation(Anonym
if (types.Any(t => t is INamedTypeSymbol))
{
return types.OfType<INamedTypeSymbol>().SelectMany(t =>
GetCollectionElementType(t,
parameterIndex: 0));
GetCollectionElementType(t));
}
}
......@@ -343,7 +342,7 @@ private IEnumerable<TypeInferenceInfo> InferTypeInAnonymousObjectCreation(Anonym
return parentTypes.Select(typeInfo => typeInfo.InferredType)
.OfType<INamedTypeSymbol>()
.Where(namedType => namedType.IsTupleType && index < namedType.TupleElements.Length)
.Select(tupleType => new TypeInferenceInfo(tupleType.TupleElements[index].Type));
.Select(tupleType => new TypeInferenceInfo(tupleType.TupleElements[index].Type.WithNullability(tupleType.TupleElements[index].NullableAnnotation)));
}
private IEnumerable<TypeInferenceInfo> InferTypeInAttributeArgument(AttributeArgumentSyntax argument, SyntaxToken? previousToken = null, ArgumentSyntax argumentOpt = null)
......@@ -715,7 +714,7 @@ private void DetermineTypeParameterMapping(ITypeSymbol inferredType, ITypeSymbol
{
var matchingNameParameters = parameterizedSymbols.SelectMany(m => m)
.Where(p => p.Name == name)
.Select(p => new TypeInferenceInfo(p.Type, p.IsParams));
.Select(p => new TypeInferenceInfo(p.Type.WithNullability(p.NullableAnnotation), p.IsParams));
return matchingNameParameters;
}
......@@ -729,7 +728,7 @@ private void DetermineTypeParameterMapping(ITypeSymbol inferredType, ITypeSymbol
if (index < parameterSet.Length)
{
var parameter = parameterSet[index];
var info = new TypeInferenceInfo(parameter.Type, parameter.IsParams);
var info = new TypeInferenceInfo(parameter.Type.WithNullability(parameter.NullableAnnotation), parameter.IsParams);
allParameters.Add(info);
if (parameter.RefKind == refKind)
......@@ -803,8 +802,8 @@ private IEnumerable<TypeInferenceInfo> InferTypeInArrayType(ArrayTypeSyntax arra
var currentTypes = InferTypes(arrayType);
for (var i = 0; i < arrayType.RankSpecifiers.Count; i++)
{
currentTypes = currentTypes.WhereAsArray(c => c.InferredType is IArrayTypeSymbol)
.SelectAsArray(c => new TypeInferenceInfo(((IArrayTypeSymbol)c.InferredType).ElementType));
currentTypes = currentTypes.Select(t => t.InferredType).OfType<IArrayTypeSymbol>()
.SelectAsArray(a => new TypeInferenceInfo(a.ElementType.WithNullability(a.ElementNullableAnnotation)));
}
return currentTypes;
}
......@@ -1086,9 +1085,10 @@ private IEnumerable<TypeInferenceInfo> InferTypeInCatchFilterClause(CatchFilterC
return CreateResult(SpecialType.System_Object);
}
// TODO: mark the reference case with a ? once we can check if we're within a nullable context
// (tracked by https://github.com/dotnet/roslyn/issues/36101)
return rightTypes
.Select(x => x.InferredType.IsValueType
// TODO: pass the nullability to Construct once https://github.com/dotnet/roslyn/issues/36046 is fixed
? new TypeInferenceInfo(this.Compilation.GetSpecialType(SpecialType.System_Nullable_T).Construct(x.InferredType.WithoutNullability())) // Goo() ?? 0
: x); // Goo() ?? ""
}
......@@ -1166,7 +1166,7 @@ private IEnumerable<TypeInferenceInfo> InferTypeInEqualsValueClause(EqualsValueC
{
if (SemanticModel.GetDeclaredSymbol(equalsValue.Parent, CancellationToken) is IParameterSymbol parameter)
{
return CreateResult(parameter.Type);
return CreateResult(parameter.Type.WithNullability(parameter.NullableAnnotation));
}
}
......@@ -1178,7 +1178,7 @@ private IEnumerable<TypeInferenceInfo> InferTypeInPropertyDeclaration(PropertyDe
Debug.Assert(propertyDeclaration?.Type != null, "Property type should never be null");
var typeInfo = SemanticModel.GetTypeInfo(propertyDeclaration.Type);
return CreateResult(typeInfo.Type);
return CreateResult(typeInfo.Type.WithNullability(typeInfo.Nullability.Annotation));
}
private IEnumerable<TypeInferenceInfo> InferTypeInExpressionStatement(ExpressionStatementSyntax expressionStatement, SyntaxToken? previousToken = null)
......@@ -1270,7 +1270,7 @@ private IEnumerable<TypeInferenceInfo> InferTypeInImplicitArrayCreation(Implicit
var addMethodParameterTypes = addMethodSymbols
.Cast<IMethodSymbol>()
.Where(a => a.Parameters.Length == initializerExpression.Expressions.Count)
.Select(a => new TypeInferenceInfo(a.Parameters.ElementAtOrDefault(parameterIndex)?.Type))
.Select(a => new TypeInferenceInfo(a.Parameters.ElementAtOrDefault(parameterIndex)?.Type?.WithNullability(a.Parameters[parameterIndex].NullableAnnotation)))
.Where(t => t.InferredType != null);
if (addMethodParameterTypes.Any())
......@@ -1288,7 +1288,7 @@ private IEnumerable<TypeInferenceInfo> InferTypeInImplicitArrayCreation(Implicit
var addMethodParameterTypes = addMethodSymbols
.Cast<IMethodSymbol>()
.Where(a => a.Parameters.Length == 1)
.Select(a => new TypeInferenceInfo(a.Parameters[0].Type));
.Select(a => new TypeInferenceInfo(a.Parameters[0].Type.WithNullability(a.Parameters[0].NullableAnnotation)));
if (addMethodParameterTypes.Any())
{
......@@ -1320,7 +1320,7 @@ private IEnumerable<TypeInferenceInfo> InferTypeInImplicitArrayCreation(Implicit
// look at the siblings of this expression and use their type instead.
var arrayTypes = this.InferTypes((ExpressionSyntax)initializerExpression.Parent);
var elementTypes = arrayTypes.OfType<IArrayTypeSymbol>().Select(a => new TypeInferenceInfo(a.ElementType)).Where(IsUsableTypeFunc);
var elementTypes = arrayTypes.OfType<IArrayTypeSymbol>().Select(a => new TypeInferenceInfo(a.ElementType.WithNullability(a.ElementNullableAnnotation))).Where(IsUsableTypeFunc);
if (elementTypes.Any())
{
......@@ -1347,7 +1347,7 @@ private IEnumerable<TypeInferenceInfo> InferTypeInImplicitArrayCreation(Implicit
if (types.Any(t => t is IArrayTypeSymbol))
{
return types.OfType<IArrayTypeSymbol>().Select(t => new TypeInferenceInfo(t.ElementType));
return types.OfType<IArrayTypeSymbol>().Select(t => new TypeInferenceInfo(t.ElementType.WithNullability(t.ElementNullableAnnotation)));
}
}
else if (initializerExpression.IsParentKind(SyntaxKind.ArrayCreationExpression))
......@@ -1358,7 +1358,7 @@ private IEnumerable<TypeInferenceInfo> InferTypeInImplicitArrayCreation(Implicit
if (types.Any(t => t is IArrayTypeSymbol))
{
return types.OfType<IArrayTypeSymbol>().Select(t => new TypeInferenceInfo(t.ElementType));
return types.OfType<IArrayTypeSymbol>().Select(t => new TypeInferenceInfo(t.ElementType.WithNullability(t.ElementNullableAnnotation)));
}
}
else if (initializerExpression.IsParentKind(SyntaxKind.ObjectCreationExpression))
......@@ -1371,7 +1371,7 @@ private IEnumerable<TypeInferenceInfo> InferTypeInImplicitArrayCreation(Implicit
if (types.Any(t => t is INamedTypeSymbol))
{
return types.OfType<INamedTypeSymbol>().SelectMany(t =>
GetCollectionElementType(t, parameterIndex: 0));
GetCollectionElementType(t));
}
}
else if (initializerExpression.IsParentKind(SyntaxKind.SimpleAssignmentExpression))
......@@ -1381,7 +1381,7 @@ private IEnumerable<TypeInferenceInfo> InferTypeInImplicitArrayCreation(Implicit
if (expressionOpt != null)
{
var addMethodSymbols = SemanticModel.GetCollectionInitializerSymbolInfo(expressionOpt).GetAllSymbols();
var addMethodParameterTypes = addMethodSymbols.Select(a => new TypeInferenceInfo(((IMethodSymbol)a).Parameters[0].Type));
var addMethodParameterTypes = addMethodSymbols.Select(m => ((IMethodSymbol)m).Parameters[0]).Select(p => new TypeInferenceInfo(p.Type.WithNullability(p.NullableAnnotation)));
if (addMethodParameterTypes.Any())
{
return addMethodParameterTypes;
......@@ -1399,7 +1399,7 @@ private IEnumerable<TypeInferenceInfo> InferTypeInImplicitArrayCreation(Implicit
: initializerExpression.Expressions.IndexOf(expressionOpt);
return types.OfType<INamedTypeSymbol>().SelectMany(t =>
GetCollectionElementType(t, 0));
GetCollectionElementType(t));
}
}
......@@ -1442,10 +1442,10 @@ private IEnumerable<TypeInferenceInfo> InferTypeInRecursivePattern(RecursivePatt
switch (symbol)
{
case IFieldSymbol field:
result.Add(new TypeInferenceInfo(field.Type));
result.Add(new TypeInferenceInfo(field.Type.WithNullability(field.NullableAnnotation)));
break;
case IPropertySymbol property:
result.Add(new TypeInferenceInfo(property.Type));
result.Add(new TypeInferenceInfo(property.Type.WithNullability(property.NullableAnnotation)));
break;
}
}
......@@ -1488,7 +1488,8 @@ private IEnumerable<TypeInferenceInfo> GetTypesForRecursivePattern(RecursivePatt
// if it's of the for "X (...)" then just infer 'X' as the type.
if (recursivePattern.Type != null)
{
return CreateResult(SemanticModel.GetTypeInfo(recursivePattern).ConvertedType);
var typeInfo = SemanticModel.GetTypeInfo(recursivePattern);
return CreateResult(typeInfo.ConvertedType.WithNullability(typeInfo.ConvertedNullability.Annotation));
}
// If it's of the form (...) then infer that the type should be a
......@@ -1584,7 +1585,7 @@ private IEnumerable<TypeInferenceInfo> InferTypeInMemberDeclarator(AnonymousObje
return types.Where(t => t.InferredType.IsAnonymousType())
.SelectMany(t => t.InferredType.GetValidAnonymousTypeProperties()
.Where(p => p.Name == memberDeclarator.NameEquals.Name.Identifier.ValueText)
.Select(p => new TypeInferenceInfo(p.Type)));
.Select(p => new TypeInferenceInfo(p.Type.WithNullability(p.NullableAnnotation))));
}
return SpecializedCollections.EmptyEnumerable<TypeInferenceInfo>();
......@@ -1894,33 +1895,15 @@ private IEnumerable<TypeInferenceInfo> InferTypeInYieldStatement(YieldStatementS
var declaration = yieldStatement.FirstAncestorOrSelf<SyntaxNode>(n => n.IsReturnableConstruct());
var memberSymbol = GetDeclaredMemberSymbolFromOriginalSemanticModel(declaration);
var memberType = GetMemberType(memberSymbol, out _);
var memberType = memberSymbol.GetMemberType();
// We don't care what the type is, as long as it has 1 type argument. This will work for IEnumerable, IEnumerator,
// IAsyncEnumerable, IAsyncEnumerator and it's also good for error recovery in case there is a missing using.
return memberType is INamedTypeSymbol namedType && namedType.TypeArguments.Length == 1
? SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(namedType.TypeArguments[0]))
? SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(namedType.TypeArguments[0].WithNullability(namedType.TypeArgumentsNullableAnnotations[0])))
: SpecializedCollections.EmptyEnumerable<TypeInferenceInfo>();
}
private static ITypeSymbol GetMemberType(ISymbol memberSymbol, out bool isAsync)
{
isAsync = false;
switch (memberSymbol)
{
case IMethodSymbol method:
isAsync = method.IsAsync;
return method.ReturnType;
case IPropertySymbol property:
return property.Type;
case IFieldSymbol field:
return field.Type;
}
return null;
}
private IEnumerable<TypeInferenceInfo> InferTypeInRefExpression(RefExpressionSyntax refExpression)
=> InferTypes(refExpression);
......@@ -1967,7 +1950,8 @@ private IEnumerable<TypeInferenceInfo> InferTypeInMethodLikeDeclaration(SyntaxNo
// `declaration` can be a base-method member, property, accessor or local function
var symbol = GetDeclaredMemberSymbolFromOriginalSemanticModel(declaration);
var type = GetMemberType(symbol, out var isAsync);
var type = symbol.GetMemberType();
var isAsync = symbol is IMethodSymbol methodSymbol && methodSymbol.IsAsync;
return type != null
? SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(UnwrapTaskLike(type, isAsync)))
......@@ -2247,16 +2231,16 @@ private IEnumerable<TypeInferenceInfo> InferTypeInWhileStatement(WhileStatementS
return CreateResult(SpecialType.System_Boolean);
}
private IEnumerable<TypeInferenceInfo> GetCollectionElementType(INamedTypeSymbol type, int parameterIndex)
private IEnumerable<TypeInferenceInfo> GetCollectionElementType(INamedTypeSymbol type)
{
if (type != null)
{
var parameters = type.GetAllTypeArguments();
var parameters = type.TypeArguments;
var elementType = parameters.ElementAtOrDefault(parameterIndex);
var elementType = parameters.ElementAtOrDefault(0);
if (elementType != null)
{
return SpecializedCollections.SingletonCollection(new TypeInferenceInfo(elementType));
return SpecializedCollections.SingletonCollection(new TypeInferenceInfo(elementType.WithNullability(type.TypeArgumentsNullableAnnotations[0])));
}
}
......
......@@ -337,16 +337,16 @@ public static bool IsWriteableFieldOrProperty(this ISymbol symbol)
public static ITypeSymbol GetMemberType(this ISymbol symbol)
{
switch (symbol.Kind)
switch (symbol)
{
case SymbolKind.Field:
return ((IFieldSymbol)symbol).Type;
case SymbolKind.Property:
return ((IPropertySymbol)symbol).Type;
case SymbolKind.Method:
return ((IMethodSymbol)symbol).ReturnType;
case SymbolKind.Event:
return ((IEventSymbol)symbol).Type;
case IFieldSymbol fieldSymbol:
return fieldSymbol.Type.WithNullability(fieldSymbol.NullableAnnotation);
case IPropertySymbol propertySymbol:
return propertySymbol.Type.WithNullability(propertySymbol.NullableAnnotation);
case IMethodSymbol methodSymbol:
return methodSymbol.ReturnType.WithNullability(methodSymbol.ReturnNullableAnnotation);
case IEventSymbol eventSymbol:
return eventSymbol.Type.WithNullability(eventSymbol.NullableAnnotation);
}
return null;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册