Skip to content

"Generate Equals" should ignore indexers and setter-only properties#25700

Merged
DustinCampbell merged 8 commits intodotnet:masterfrom
Neme12:generateEqualsIndexers
Apr 14, 2018
Merged

"Generate Equals" should ignore indexers and setter-only properties#25700
DustinCampbell merged 8 commits intodotnet:masterfrom
Neme12:generateEqualsIndexers

Conversation

@Neme12
Copy link
Copy Markdown
Contributor

@Neme12 Neme12 commented Mar 24, 2018

fixes #25690
fixes #25707

@Neme12
Copy link
Copy Markdown
Contributor Author

Neme12 commented Mar 25, 2018

@CyrusNajmabadi Would you take a quick look at this? Thanks


<WorkItem(25690, "https://github.com/dotnet/roslyn/issues/25690")>
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateEqualsAndGetHashCode)>
Public Async Function TestWithDialogNoIndexer() As Task
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

note: this is not an indexer for VB, it's a parameterized property. To make an indexer, you need to use "default property". I would consider adding a test for both cases.

Copy link
Copy Markdown
Contributor Author

@Neme12 Neme12 Mar 25, 2018

Choose a reason for hiding this comment

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

ok, will add test

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 think i've seen this referred to as an "indexer property" in the docs

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.

Internally, we've always called them "parameterized properties". Indexers use the "Default" keyword.

@Neme12 Neme12 changed the title "Generate Equals" should not treat indexers as properties "Generate Equals" should ignore indexers and setter-only properties Mar 25, 2018
@Neme12
Copy link
Copy Markdown
Contributor Author

Neme12 commented Mar 25, 2018

@CyrusNajmabadi I made other changes to fix one more issue, you might want to review again.

IsWritableFieldOrProperty(symbol);
=> !symbol.IsStatic &&
(symbol is IFieldSymbol field && IsViableField(field) && !field.IsConst ||
symbol is IPropertySymbol property && IsViableProperty(property) && property.IsWritableInConstructor());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

this mix of &&'s and ||'s is confusing. Please extract into helper and parenthesize to keep precedence clear. In general, we prefer expressions that are uniform with &&'s or ||'s.

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 thought about this for a while and found it hard to extract common code between IsWritableInstanceFieldOrProperty and IsReadableInstanceFieldOrProperty. They use the same logic for whether the field/property is "viable" but they also need to do more checks that are still specific to each type. Basically one method would check the type and some condition, and the other one would check the type again for another condition. So I don't know what to do there.

Copy link
Copy Markdown
Contributor

@CyrusNajmabadi CyrusNajmabadi Mar 26, 2018

Choose a reason for hiding this comment

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

IsWritableInstanceFieldOrProperty

IsReadableInstanceFieldOrProperty

Based on the name, it sounds like they can reuse whatever computes if this is an InstanceFieldOrProperty

Then you can have code that checks if it's Readable or Writable.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I thought about this for a while and found it hard to extract common code

Right now the mixing of precedence operators is confusing here. Please at least parenthesize for clarity. Also, to prevent mixing and matching of operators, just make this a full body method. THis is complex enough that collapsing into an expression is harder to understand.

Copy link
Copy Markdown
Contributor Author

@Neme12 Neme12 Mar 26, 2018

Choose a reason for hiding this comment

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

Based on the name, it sounds like they can reuse whatever computes if this is an InstanceFieldOrProperty

Yes. But then you'd still have another method for IsWritableInstanceFieldOrProperty which would have the same structure - it needs to check writability based on whether the symbol is a field or a property. So the code reuse would actually reuse some things but duplicate other things, and introduce unnecessary type checks after we already did the same check before.

Copy link
Copy Markdown
Contributor

@CyrusNajmabadi CyrusNajmabadi left a comment

Choose a reason for hiding this comment

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

Please refactor the complex expressions to give precedence to clarity.

@Neme12
Copy link
Copy Markdown
Contributor Author

Neme12 commented Mar 26, 2018

to give precedence to clarity.

interesting way to phrase things 😃

{
switch (symbol)
{
case IFieldSymbol field when IsViableField(field): return true;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

can you not just do: case IFieldSymbol field: return IsViableField(field);? It seems much simpler than having 'when' and a boolean.

switch (symbol)
{
case IFieldSymbol field when IsViableField(field): return true;
case IPropertySymbol property when IsViableProperty(property): return !property.IsWriteOnly;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

same issue here. no need for 'when'. just merge its condition into the actual return statement.

Copy link
Copy Markdown
Contributor Author

@Neme12 Neme12 Mar 27, 2018

Choose a reason for hiding this comment

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

I found this a little nicer than having && inside each case but ok

=> !symbol.IsStatic &&
(symbol is IFieldSymbol field && IsViableField(field) && !field.IsConst ||
symbol is IPropertySymbol property && IsViableProperty(property) && property.IsWritableInConstructor());
=> !symbol.IsStatic && IsWritableFieldOrProperty(symbol);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

these two methods are very readable. thank you :)

Copy link
Copy Markdown
Contributor

@CyrusNajmabadi CyrusNajmabadi left a comment

Choose a reason for hiding this comment

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

Thanks for the change. LGTM.

@Neme12
Copy link
Copy Markdown
Contributor Author

Neme12 commented Mar 29, 2018

retest windows_debug_vs-integration_prtest please

@Neme12
Copy link
Copy Markdown
Contributor Author

Neme12 commented Mar 29, 2018

retest windows_release_vs-integration_prtest please

@jcouv jcouv added Area-IDE Community The pull request was submitted by a contributor who is not a Microsoft employee. labels Mar 30, 2018
@Neme12
Copy link
Copy Markdown
Contributor Author

Neme12 commented Apr 11, 2018

retest windows_release_unit32_prtest please

1 similar comment
@Neme12
Copy link
Copy Markdown
Contributor Author

Neme12 commented Apr 12, 2018

retest windows_release_unit32_prtest please

Copy link
Copy Markdown
Member

@DustinCampbell DustinCampbell left a comment

Choose a reason for hiding this comment

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

LGTM

@DustinCampbell
Copy link
Copy Markdown
Member

@dotnet-bot retest windows_release_unit64_prtest please

@DustinCampbell
Copy link
Copy Markdown
Member

@dotnet-bot retest this please

@Neme12
Copy link
Copy Markdown
Contributor Author

Neme12 commented Apr 12, 2018

retest windows_debug_unit32_prtest please

@DustinCampbell
Copy link
Copy Markdown
Member

@dotnet-bot retest this please

@Neme12
Copy link
Copy Markdown
Contributor Author

Neme12 commented Apr 12, 2018

I think some of those tests are stuck. I have this on another PR as well and retesting doesn't help.

@DustinCampbell
Copy link
Copy Markdown
Member

Yeah, @jaredpar just sent email internally about it. The Jenkins machines are stuck, but it's being looked at.

@Neme12
Copy link
Copy Markdown
Contributor Author

Neme12 commented Apr 13, 2018

retest windows_debug_spanish_unit32_prtest please

@Neme12
Copy link
Copy Markdown
Contributor Author

Neme12 commented Apr 13, 2018

retest windows_release_vs-integration_prtest please

@Neme12
Copy link
Copy Markdown
Contributor Author

Neme12 commented Apr 13, 2018

retest windows_debug_spanish_unit32_prtest please

1 similar comment
@Neme12
Copy link
Copy Markdown
Contributor Author

Neme12 commented Apr 13, 2018

retest windows_debug_spanish_unit32_prtest please

@DustinCampbell
Copy link
Copy Markdown
Member

@jaredpar: Is the windows_debug_spanish_unit32_prtest flaky at the moment? We've run it a few times, but we keep getting back, "xunit produced no error output but had exit code 1"

@jaredpar
Copy link
Copy Markdown
Member

jaredpar commented Apr 13, 2018

@DustinCampbell looks like the EE tests are just faky in general. Seen this in a few logs


Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator.UnitTests.DebuggerTypeProxyAttributeTests.GenericTypeWithGenericTypeArgument
System.Reflection.TargetInvocationException: Se produjo una excepción en el destino de la invocación.
System.AccessViolationException: Intento de leer o escribir en la memoria protegida. A menudo, esto indica que hay otra memoria dañada.

@DustinCampbell
Copy link
Copy Markdown
Member

OK to merge?

@jaredpar
Copy link
Copy Markdown
Member

It's fine by me.

@DustinCampbell
Copy link
Copy Markdown
Member

Great! @Neme12: Thanks very much for your contributions!

@DustinCampbell DustinCampbell merged commit cce6b0e into dotnet:master Apr 14, 2018
@Neme12
Copy link
Copy Markdown
Contributor Author

Neme12 commented Apr 14, 2018

Thanks, I still have 12 other PRs if you're interested 😄

@Neme12 Neme12 deleted the generateEqualsIndexers branch April 14, 2018 11:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area-IDE Community The pull request was submitted by a contributor who is not a Microsoft employee.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

"Generate Equals" refactorings should not include set-only properties "Generate Equals" refactorings produce non-compiling code when using indexers

5 participants