Skip to content

Update 'use coalece assignment' fixer to support additional common use case.#62191

Merged
CyrusNajmabadi merged 4 commits intodotnet:mainfrom
CyrusNajmabadi:useCoalesce
Jun 28, 2022
Merged

Update 'use coalece assignment' fixer to support additional common use case.#62191
CyrusNajmabadi merged 4 commits intodotnet:mainfrom
CyrusNajmabadi:useCoalesce

Conversation

@CyrusNajmabadi
Copy link
Copy Markdown
Contributor

@CyrusNajmabadi CyrusNajmabadi commented Jun 28, 2022

Fixes #32985
Fixes #54974

else
{
var coalesce = coalesceOrIfStatement;
// changing from `x ?? (x = y)` to `x ??= y` can change the type. Specifically,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

easier to read this with whitespace off.

{
private static string s_goo;
private static string Goo => s_goo [||]?? (s_goo = new string('c', 42));
private static string Goo => s_goo [|??|] (s_goo = new string('c', 42));
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

switched to new test harness. the new one is stricter about the test inputs, so a lot of existing tests are updated to be correct in that regard.

{
private static string s_goo;
private static string Goo => s_goo [||]?? s_goo = new string('c', 42);
private static string Goo => {|CS0131:s_goo ?? s_goo|} = new string('c', 42);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you need to specify the diagnostic in certain cases but not others?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because the original code is invalid C#. the test is testing that. the new test harness requires you to be explicit htat you know it's invalid code by putting in these markers. it helps prevent tests that are accidentally testing bogus code unintentionally.

{
// Before
o ??= new C(); // After
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really thorough tests 😄

Copy link
Copy Markdown
Member

@akhera99 akhera99 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me!

@CyrusNajmabadi CyrusNajmabadi enabled auto-merge June 28, 2022 18:29
@CyrusNajmabadi CyrusNajmabadi merged commit 623b7ed into dotnet:main Jun 28, 2022
@ghost ghost added this to the Next milestone Jun 28, 2022
? assignmentTemp
: null;

return whenTrue != null && assignment != null;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just return assignment != null?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i liked the clarity :)

// System.String. Even though `==` is overloaded, it has the same semantics as ReferenceEquals(null) so
// it's safe to convert.
var symbol = semanticModel.GetSymbolInfo(binaryExpression, cancellationToken).Symbol;
if (symbol is null || !symbol.IsUserDefinedOperator() || symbol.ContainingType.SpecialType == SpecialType.System_String)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

null check looks unnecessary? The extension method will return false if symbol is null:

public static bool IsUserDefinedOperator([NotNullWhen(returnValue: true)] this ISymbol? symbol)
=> (symbol as IMethodSymbol)?.MethodKind == MethodKind.UserDefinedOperator;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's not an && it's an ||.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the null checked is removed and symbol is null, then symbol.IsUserDefinedOperator will return false, then the ! will make it true and hence the whole expression will be true, which matches the current behavior. The null check just makes it more clear, I think?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fair point :) i'm ok either way.

@RikkiGibson RikkiGibson modified the milestones: Next, 17.3 P3 Jun 28, 2022
@CyrusNajmabadi CyrusNajmabadi deleted the useCoalesce branch June 28, 2022 20:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Detect if (x == null) x = ... and offer to convert to x ??= ... Support if pattern in "use null coalescing assignment" refactoring

4 participants