Skip to content

Implement FindReferences for deconstructions#22934

Merged
jcouv merged 2 commits intodotnet:post-dev15.5-contribfrom
jcouv:far-deconstruct
Nov 9, 2017
Merged

Implement FindReferences for deconstructions#22934
jcouv merged 2 commits intodotnet:post-dev15.5-contribfrom
jcouv:far-deconstruct

Conversation

@jcouv
Copy link
Member

@jcouv jcouv commented Oct 31, 2017

Implements "Find All References" for Deconstruct methods. It is similar to how FAR works on methods that participate in foreach.

Fixes #18963

From the compiler side, the change is to expose information about deconstructions (assignment/declarations and foreach) via new public APIs. Since deconstructions are not conversions in the language, but they are implemented using nested conversions (like tuple conversions) with a deconstruction method, I'm using a wrapper class around deconstruction conversion objects to abstract from the implementation.
The existing DeconstructionInfo class (which is internal) was renamed to DeconstructMethodInfo.

From the IDE side, we now keep track of whether a document uses any deconstructions (just like we do for foreach) and we can scan through a document to find all the Deconstruct method symbols that are references. That's the core of the "Find All References" implementation. (thanks Cyrus for the tips)

Note: this fix was incomplete, it was supplemented by #24223

@jcouv jcouv added this to the 15.later milestone Oct 31, 2017
@jcouv jcouv self-assigned this Oct 31, 2017
Copy link
Member Author

@jcouv jcouv Oct 31, 2017

Choose a reason for hiding this comment

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

📝 this is a bit unfortunate, but I don't expect deeply nested deconstructions. #Resolved

Copy link
Contributor

@CyrusNajmabadi CyrusNajmabadi Nov 1, 2017

Choose a reason for hiding this comment

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

I'd prefer an immutable array builder. we end up tending to have to avoid IEnumreables in pathological cases. #Resolved

@jcouv
Copy link
Member Author

jcouv commented Oct 31, 2017

@dotnet/roslyn-compiler for review. This PR provides a public API for accessing deconstruction information. See description for more details. Thanks #Resolved

@jcouv
Copy link
Member Author

jcouv commented Oct 31, 2017

@dotnet/roslyn-ide for review as well. This PR implements FindReferences for Deconstruct methods. Thanks #Resolved

Copy link
Contributor

@CyrusNajmabadi CyrusNajmabadi Nov 1, 2017

Choose a reason for hiding this comment

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

maybe GetDeconstructionMethods? #Resolved

Copy link
Contributor

@CyrusNajmabadi CyrusNajmabadi Nov 5, 2017

Choose a reason for hiding this comment

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

Also... on a personal level... i don't like having a single helper method that works on all these types. I think i'd prefer a GetAssignmentDeconstructionSymbols and GetForEachStatementDeconstructionSymbols. #Resolved

Copy link
Contributor

@CyrusNajmabadi CyrusNajmabadi Nov 1, 2017

Choose a reason for hiding this comment

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

avoid single letter foreach variable names. #Closed

Copy link
Contributor

@CyrusNajmabadi CyrusNajmabadi Nov 1, 2017

Choose a reason for hiding this comment

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

nit: => #Resolved

Copy link
Contributor

@CyrusNajmabadi CyrusNajmabadi Nov 1, 2017

Choose a reason for hiding this comment

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

need to update the 'version' of SyntaxTreeINdex. Otherwise, existing indices will not be recreated and it will look like no files contain deconstructions. #Resolved

Copy link
Member Author

Choose a reason for hiding this comment

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

Updated SerializationFormat number.


In reply to: 148396504 [](ancestors = 148396504)

Copy link
Contributor

@CyrusNajmabadi CyrusNajmabadi Nov 1, 2017

Choose a reason for hiding this comment

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

Wrong location for these tests. Look for the more declarative FindReferencesTests written in VB. #Resolved

@jcouv
Copy link
Member Author

jcouv commented Nov 3, 2017

@dotnet/roslyn-compiler for review as well (adding public API to get information about deconstructions, for IDE scenario). Thanks #Resolved

@CyrusNajmabadi
Copy link
Contributor

CyrusNajmabadi commented Nov 5, 2017

(thanks Cyrus for the tips)

You're welcome :) Can't wait to have this. It'll be super useful! #Resolved

Copy link
Contributor

@CyrusNajmabadi CyrusNajmabadi Nov 5, 2017

Choose a reason for hiding this comment

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

Same here. SyntaxFacts isn't for merging multiple nodes from the same language into the same concept. It's for providing a uniform syntactic API over VB and C#. I would prefer IsDeconstructionAssignment and IsDeconstructionForEachStatement #Resolved

Copy link
Contributor

@CyrusNajmabadi CyrusNajmabadi Nov 5, 2017

Choose a reason for hiding this comment

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

this would then become containsDestruction = containsDeconstruction || (syntaxFacts.IsDeconstructionAssignment || syntaxFacts.IsDeconstructionForEachStatement); #Resolved

@jcouv jcouv force-pushed the far-deconstruct branch 2 times, most recently from 427522d to 914c168 Compare November 6, 2017 19:19
@jcouv jcouv requested review from VSadov, agocke and sharwell November 6, 2017 19:27
Copy link
Contributor

@CyrusNajmabadi CyrusNajmabadi Nov 6, 2017

Choose a reason for hiding this comment

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

Fasscinating. This is the resultant span? I guess i'm ok with that. though i think it's strange. #Resolved

Copy link
Member

@jasonmalinowski jasonmalinowski Nov 7, 2017

Choose a reason for hiding this comment

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

Yeah, I think something a bit narrower might be wise. Consider if there are comments in the middle of that somewhere... #Resolved

Copy link
Contributor

@CyrusNajmabadi CyrusNajmabadi Nov 6, 2017

Choose a reason for hiding this comment

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

same here.. i think i would prefer either "var (x1, x2)" to be the span, or "(x1, x2)" to be hte span. or "=" to be hte span. for the foreach case, the same (except replacing "in" for "="). #Resolved

Copy link
Contributor

@CyrusNajmabadi CyrusNajmabadi Nov 6, 2017

Choose a reason for hiding this comment

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

so just to be sure. You can' thave both .Method and .Nested available at the same time? #Resolved

Copy link
Member Author

@jcouv jcouv Nov 6, 2017

Choose a reason for hiding this comment

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

Good catch. There is a bug here. Actually, if there is a .Method, there will be a .Nested. #Resolved

Copy link
Contributor

@CyrusNajmabadi CyrusNajmabadi Nov 6, 2017

Choose a reason for hiding this comment

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

nit: => #Resolved

Copy link
Contributor

@CyrusNajmabadi CyrusNajmabadi Nov 6, 2017

Choose a reason for hiding this comment

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

this location seems absolutely wacky :D #Resolved

Copy link
Contributor

@CyrusNajmabadi CyrusNajmabadi Nov 6, 2017

Choose a reason for hiding this comment

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

I am... barely ok with this :D i think it would be better to just select hte =, and the 'in' token though. But i would be open for arguments otherwise. #Resolved

Copy link
Contributor

@CyrusNajmabadi CyrusNajmabadi Nov 6, 2017

Choose a reason for hiding this comment

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

don't you always want to do this? i don't understand why you only do htis if you didn't find any deconstruction assignments. #Closed

Copy link
Contributor

@CyrusNajmabadi CyrusNajmabadi Nov 6, 2017

Choose a reason for hiding this comment

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

oh........... i see. yes. this is checking per node. so you couldn't have both. cute :) n/m then. #Closed

Copy link
Member

@jasonmalinowski jasonmalinowski Nov 7, 2017

Choose a reason for hiding this comment

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

Still worth adding a comment. I think what's throwing me off is the GetDeconstruction..Methods* name, since plural, implies that it might be doing recursive itself. Which it's not. #Resolved

@jcouv
Copy link
Member Author

jcouv commented Nov 7, 2017

Filed #23037 for updating ChangeSignature to handle Deconstruct methods. #Resolved

@jcouv
Copy link
Member Author

jcouv commented Nov 7, 2017

@dotnet/roslyn-compiler for review of the compiler portion. Thanks #Resolved

@jcouv jcouv requested a review from gafter November 7, 2017 16:33
Copy link
Contributor

@cston cston Nov 7, 2017

Choose a reason for hiding this comment

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

Hash.CombineValues calls GetHashCode() on the ImmutableArray<T> and handles IsDefault. #Resolved

Copy link
Contributor

@cston cston Nov 7, 2017

Choose a reason for hiding this comment

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

Are IEquatable<DeconstructionInfo> and Equals needed? #Closed

Copy link
Member Author

@jcouv jcouv Nov 7, 2017

Choose a reason for hiding this comment

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

I did this for consistency with ForEachDeconstructionInfo, which begs the question.
I'll check with @gafter on public API design, and if nobody objects, I'll remove IEquatable. #Closed

@jcouv
Copy link
Member Author

jcouv commented Nov 7, 2017

From discussion with Chuck and Neal, we don't need IEquatable on DeconstructionInfo yet (we're not sure why ForEachStatementInfo needed it). Removed that portion and its tendrils. #Resolved

Copy link
Contributor

@cston cston Nov 7, 2017

Choose a reason for hiding this comment

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

Gets assignment deconstruction info? #Resolved

Copy link
Contributor

@cston cston Nov 7, 2017

Choose a reason for hiding this comment

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

Gets foreach variable deconstruction info? #Resolved

Copy link
Contributor

@cston cston Nov 7, 2017

Choose a reason for hiding this comment

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

Does this throw a cast exception if the caller passes an assignment that is not a deconstruction assignment? Is that the desired behavior? #Resolved

Copy link
Member Author

Choose a reason for hiding this comment

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

Good question. It's the same behavior as GetForEachStatementInfo, but does seem wrong.
For comparison, GetAwaitExpressionInfo returns default in such cases. I'll change foreach and deconstruction methods to do the same.


In reply to: 149514253 [](ancestors = 149514253)

Copy link
Member Author

Choose a reason for hiding this comment

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

Hum, actually GetForEachStatementInfo is fine. The problem is just with assignment (which may or may not be a deconstruction).


In reply to: 149516672 [](ancestors = 149516672,149514253)

Copy link
Contributor

@cston cston left a comment

Choose a reason for hiding this comment

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

Compiler changes LGTM.

@jcouv
Copy link
Member Author

jcouv commented Nov 8, 2017

Thanks Chuck!
@dotnet/roslyn-compiler for a second review of compiler portion.

Copy link
Member

Choose a reason for hiding this comment

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

cref Conversion if that means it's a reference to the property.

Copy link
Member

Choose a reason for hiding this comment

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

This comment implies that across the summation of all the nodes, there is one node that has a Method, but I would expect two since two methods are being invoked.

Copy link
Member Author

Choose a reason for hiding this comment

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

Argh, sorry about that :-(

Copy link
Member

@jasonmalinowski jasonmalinowski Nov 8, 2017

Choose a reason for hiding this comment

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

This is an Is* method returning non-Boolean. Please revise the name. #Resolved

Copy link
Member

@jasonmalinowski jasonmalinowski left a comment

Choose a reason for hiding this comment

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

Good other than one specific question about doc comments that look like they have a typo which makes it really confusing.

Copy link
Member

@gafter gafter left a comment

Choose a reason for hiding this comment

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

API and compiler changes look good to me.

@jcouv
Copy link
Member Author

jcouv commented Nov 9, 2017

Nice, thanks!
@jasonmalinowski I've addressed the doc comment issues. Good to go?

Copy link
Member

@jasonmalinowski jasonmalinowski left a comment

Choose a reason for hiding this comment

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

The docs are so clear, even a IDE developer can understand it. Thanks!

@jcouv
Copy link
Member Author

jcouv commented Nov 9, 2017

You mean when the docs don't say the opposite of what they should ;-)
Awesome. I'll resolve conflicts and merge once green. Thanks all.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Development

Successfully merging this pull request may close these issues.

6 participants