Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix crash, and offer "declare as nullable" for tuple fields #46437

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1046,6 +1046,85 @@ await TestMissingInRegularAndScriptAsync(
class Program
{
string [|s|], s2 = ""hello"";
}", parameters: s_nullableFeature);
}

[Fact]
[WorkItem(46354, "https://github.com/dotnet/roslyn/issues/46354")]
davidwengier marked this conversation as resolved.
Show resolved Hide resolved
public async Task FixTupleFieldAssignment()
{
await TestInRegularAndScript1Async(
@"#nullable enable
class Program
{
static void F1((string, string?) t)
{
if (t.Item2 == null) return;
t.Item1 = [|null|];
}
}",
@"#nullable enable
class Program
{
static void F1((string?, string?) t)
{
if (t.Item2 == null) return;
t.Item1 = null;
}
}", parameters: s_nullableFeature);
}

[Fact]
[WorkItem(46354, "https://github.com/dotnet/roslyn/issues/46354")]
public async Task FixTupleNamedFieldAssignment()
{
await TestInRegularAndScript1Async(
@"#nullable enable
class Program
{
static void F1((string Foo, string? Bar) t)
{
if (t.Bar == null) return;
t.Foo = [|null|];
}
}",
@"#nullable enable
class Program
{
static void F1((string? Foo, string? Bar) t)
{
if (t.Bar == null) return;
t.Foo = null;
}
}", parameters: s_nullableFeature);
}

[Fact]
[WorkItem(46354, "https://github.com/dotnet/roslyn/issues/46354")]
public async Task FixTupleGenericFieldAssignment()
{
await TestInRegularAndScript1Async(
@"#nullable enable
class Program
{
static void F1<T>((T, T?) t) where T : class
{
if (t.Item2 == null) return;
t.Item1 = [|null|];

var (a, b) = t;
}
}",
@"#nullable enable
class Program
{
static void F1<T>((T?, T?) t) where T : class
{
if (t.Item2 == null) return;
t.Item1 = null;

var (a, b) = t;
}
}", parameters: s_nullableFeature);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,8 @@ declarator.Parent is VariableDeclarationSyntax declaration &&
{
return TryGetParameterTypeSyntax(parameter);
}
else if (symbol is IFieldSymbol field)
// implicitly declared fields don't have DeclaringSyntaxReferences so filter them out
davidwengier marked this conversation as resolved.
Show resolved Hide resolved
else if (symbol is IFieldSymbol { IsImplicitlyDeclared: false } field)
{
var syntax = field.DeclaringSyntaxReferences[0].GetSyntax();
if (syntax is VariableDeclaratorSyntax declarator &&
Expand All @@ -228,6 +229,24 @@ declarator.Parent is VariableDeclarationSyntax declaration &&
{
return declaration.Type;
}
else if (syntax is TupleElementSyntax tupleElement)
{
return tupleElement.Type;
}
}
// Assigning a tuple field, eg. foo.Item1 = null
davidwengier marked this conversation as resolved.
Show resolved Hide resolved
else if (symbol is IFieldSymbol { CorrespondingTupleField: IFieldSymbol tupleField })
{
// the tupleField won't have DeclaringSyntaxReferences because it's implicitly declared, otherwise it
// would have fallen into the branch above. We can use the Locations instead, if there is one and it's in source
if (tupleField.Locations is { Length: 1 } &&
tupleField.Locations[0] is { IsInSource: true } location)
{
if (location.FindNode(default) is TupleElementSyntax tupleElement)
{
return tupleElement.Type;
}
}
}
else if (symbol is IPropertySymbol property)
{
Expand Down