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

Add ability to underline variables in the editor that are reassigned. #51889

Merged
merged 73 commits into from
May 25, 2021

Conversation

CyrusNajmabadi
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi commented Mar 15, 2021

Some users would like to know if a variable is ever reassigned in some block of code. This is esp. relevant to them as C# lacks a way to mark local variables as 'readonly', so a manual scan of the code (or examination of FindAllReferences) is necessary.

This PR adds the ability to mark these variables (declaration and references) with an underline to clearly demarcate which are even reassignments.

A core intuition here is that this effectively acts like a classification. You can think of non-underlying variables as being 'effectively readonly', while underlined variables are 'effectively mutable'. If we had a lang-feature to make locals readonly, these are the ones that wouldn't be applicable.

For example, without reassignment:

image

But with reassignment:

image

Closes #37517

Todo:

  • VB side.
  • Exposed Tools|Option to control this
  • Tests

internal class ReassignedVariableOptions
{
public static PerLanguageOption2<bool> Underline =
new PerLanguageOption2<bool>(nameof(ReassignedVariableOptions), nameof(Underline), defaultValue: true,
Copy link
Member Author

Choose a reason for hiding this comment

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

this will likely be set to false when this is submitted. it will be an opt-in option.

@mavasani
Copy link
Contributor

mavasani commented Mar 15, 2021

So, are we underlining all reads and writes in the block if there is at least one write? Can you expand a bit more on the overall user scenario?

@davidwengier
Copy link
Contributor

This will be interesting to play with, as my gut feeling on reading the PR title was that this would underline the reassignment, and perhaps the reads after that, and I was surprised by the parameter itself being underlined. I can see the logic in that approach too though.

@mavasani
Copy link
Contributor

my gut feeling on reading the PR title was that this would underline the reassignment, and perhaps the reads after that, and I was surprised by the parameter itself being underlined

Exactly, I was surprised as well. My gut feeling on reading the PR was that we have some way to show the def-use chains so a user can look at a read and find all potential writes that can lead to it or vice versa. I would like to understand the motivation for underlying all reads and writes in the block.

@CyrusNajmabadi
Copy link
Member Author

So, are we underlining all reads and writes in the block if there is at least one write? Can you expand a bit more on the overall user scenario?

No. We are underling any variable that ever encounters a reassignment. That way the user can tell if this is an 'assigned-once' varaible, or a reassigned variable.

@CyrusNajmabadi
Copy link
Member Author

This will be interesting to play with, as my gut feeling on reading the PR title was that this would underline the reassignment, and perhaps the reads after that, and I was surprised by the parameter itself being underlined. I can see the logic in that approach too though.

If we only underline hte reassignment, it's easy to miss. The idea here is that you can immediately distinguish (from any location) if it's reassigned or not ever.

It would be akin to knowing at the decl site, if this is read-only or not.

@CyrusNajmabadi
Copy link
Member Author

I would like to understand the motivation for underlying all reads and writes in the block.

Think of it more like a classification. Non-underlined variables are effectively readonly (and could be marked as such if we ever get such a feature). Underlined variables are reassigned and thus can't be readonly.

@CyrusNajmabadi CyrusNajmabadi changed the title Add ability to underling variables in the editor that are reassigned. Add ability to underline variables in the editor that are reassigned. Mar 15, 2021
@CyrusNajmabadi
Copy link
Member Author

@genlu @sharwell This has been updated with the resolution of the IDE design meeting. Specifically, internally, this now runs through the classification codepath. Though we still need the special IDE option to enable this (as standard VS classification cannot underline things).

@sharwell
Copy link
Member

sharwell commented May 21, 2021

@CyrusNajmabadi can you describe the rules for which variables get underlined, and at which locations? We discussed many options in design review and I'm curious which one we ended up with for the PR.

Specifically, internally, this now runs through the classification codepath.

👍

@CyrusNajmabadi
Copy link
Member Author

CyrusNajmabadi commented May 22, 2021

@CyrusNajmabadi can you describe the rules for which variables get underlined, and at which locations?

Sure!

The general idea is: is this a variable that is assigned after it has already been assigned. The idea being that if we had readonly variables, would this be something the compiler would be likely to error on becuse multiple writes happen to the variable.

Once we detect this has happened for a variable, we then consider this an aspect of the variable itself (similar to how a variable is static is not). One we determine this is an aspect of the variable, then we classify that variable (the declaration and references for it) in that fashion.

@CyrusNajmabadi
Copy link
Member Author

@ryzngard it looks like:

image

@@ -15,5 +15,6 @@ internal enum TokenModifiers
{
None = 0,
Static = 1,
ReassignedVariable = 2,
Copy link
Member

Choose a reason for hiding this comment

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

there's a 'modification' SemanticTokenModifier in the LSP spec, would that be appropriate?
https://microsoft.github.io/language-server-protocol/specification#textDocument_semanticTokens

Also, @allisonchou do we need custom handling for this in the LSP client?

Copy link
Member Author

Choose a reason for hiding this comment

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

i did add some filtering for this in our LSP code (similar to how we handle 'static') :)

@CyrusNajmabadi CyrusNajmabadi merged commit f04d51c into dotnet:main May 25, 2021
@ghost ghost added this to the Next milestone May 25, 2021
@CyrusNajmabadi CyrusNajmabadi deleted the underlingVariables branch May 25, 2021 05:27
@RikkiGibson RikkiGibson modified the milestones: Next, 17.0.P2 Jun 29, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Need Update
Development

Successfully merging this pull request may close these issues.

Indicate mutable members in editor.
10 participants