Skip to content

Add inline variable refactor - #54281

Merged
Maria Solano (MariaSolOs) merged 35 commits into
microsoft:mainfrom
MariaSolOs:inline-variable
Jun 13, 2023
Merged

Add inline variable refactor#54281
Maria Solano (MariaSolOs) merged 35 commits into
microsoft:mainfrom
MariaSolOs:inline-variable

Conversation

@MariaSolOs

Copy link
Copy Markdown
Contributor

Fixes#18459

@typescript-bot

Copy link
Copy Markdown
Contributor

The TypeScript team hasn't accepted the linked issue #18459. If you can get it accepted, this PR will have a better chance of being reviewed.

@MariaSolOs
Maria Solano (MariaSolOs) marked this pull request as draft May 16, 2023 22:22
@typescript-bot

Copy link
Copy Markdown
Contributor

The TypeScript team hasn't accepted the linked issue #18459. If you can get it accepted, this PR will have a better chance of being reviewed.

1 similar comment
@typescript-bot

Copy link
Copy Markdown
Contributor

The TypeScript team hasn't accepted the linked issue #18459. If you can get it accepted, this PR will have a better chance of being reviewed.

Comment threadsrc/services/refactors/inlineVariable.ts Outdated
Comment threadsrc/services/services.ts Outdated
Comment threadsrc/services/refactors/inlineVariable.ts Outdated
@MariaSolOs
Maria Solano (MariaSolOs) marked this pull request as ready for review May 22, 2023 18:52
Comment threadsrc/services/refactors/inlineVariable.ts Outdated

@mjbvzMatt Bierner (mjbvz) left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Excited to test this out!

@andrewbranchAndrew Branch (andrewbranch) left a comment

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.

I think there are a couple other invalid inlinings to consider.

  1. Type queries:
    constBar=classBar{}typeBarConstructor=typeofBar;
    typeof can only take an identifier reference.
  2. Merged type/value meanings:
    consta="hello";typea=any;typeT=a;
    There’s one symbol for a with two declarations, so Find All References might return a in type T = a as a reference, even though you wouldn’t want to inline "hello" there. The real case for merging meanings is usually more like
    // Simulate type/value duality of real class declarationsconstSomeClass=mixin(OtherClass);typeSomeClass=typeofSomeClass;
    and in those cases it seems undesirable to inline anyway. I think you can implement a simple rule that says if a symbol has more than one declaration, it can’t be inlined.

Comment threadsrc/services/refactors/inlineVariable.ts Outdated
Comment threadsrc/compiler/diagnosticMessages.json Outdated

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.

This is looking really good! The implementation is impressively small and readable and I like that each test is very focused.

Have you tried to beat this up on some more complicated real-world code? Do that if you haven’t already, and then I would also suggest having one or two kitchen-sink tests that exercise more complex cases with several references and complex expressions (multi-line function expression?)

Comment threadtests/cases/fourslash/inlineVariableExportedVariable.ts Outdated
@MariaSolOs

Copy link
Copy Markdown
ContributorAuthor

Andrew Branch (@andrewbranch) I've added a couple more tests with more complex scenarios like call expressions. LMK what you think :)

@andrewbranch

Copy link
Copy Markdown
Member

I still think inlining a multi-line expression would be good to test:

functionComponent(){constonClick/*inline me*/=()=>{console.log("clicked");};return(<buttononClick={onClick}>Dousefulthing</button>);}

@DanielRosenwasser

Copy link
Copy Markdown
Member

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.

Looks good to me, nice job 👍

@DanielRosenwasser

Copy link
Copy Markdown
Member

I SAID

TypeScript Bot (@typescript-bot) pack this
TypeScript Bot (@typescript-bot) user test tsserver
TypeScript Bot (@typescript-bot) test tsserver top100

@typescript-bot

TypeScript Bot (typescript-bot) commented May 31, 2023

Copy link
Copy Markdown
Contributor

Heya Daniel Rosenwasser (@DanielRosenwasser), I've started to run the diff-based user code test suite (tsserver) on this PR at 2f97c5c. You can monitor the build here.

Update: The results are in!

@typescript-bot

TypeScript Bot (typescript-bot) commented May 31, 2023

Copy link
Copy Markdown
Contributor

Heya Daniel Rosenwasser (@DanielRosenwasser), I've started to run the tarball bundle task on this PR at 2f97c5c. You can monitor the build here.

@typescript-bot

TypeScript Bot (typescript-bot) commented May 31, 2023

Copy link
Copy Markdown
Contributor

Heya Daniel Rosenwasser (@DanielRosenwasser), I've started to run the diff-based top-repos suite (tsserver) on this PR at 2f97c5c. You can monitor the build here.

Update: The results are in!

@DanielRosenwasser

Copy link
Copy Markdown
Member

That's what I thought.

@typescript-bot

TypeScript Bot (typescript-bot) commented May 31, 2023

Copy link
Copy Markdown
Contributor

Hey Daniel Rosenwasser (@DanielRosenwasser), I've packed this into an installable tgz. You can install it for testing by referencing it in your package.json like so:

{
"devDependencies": {
"typescript": "https://typescript.visualstudio.com/cf7ac146-d525-443c-b23c-0d58337efebc/_apis/build/builds/155242/artifacts?artifactName=tgz&fileId=20071FB31E0A3D7DF07B6D5E41FC11EFD71181FE4C4C85CE4B27E7183150EAC902&fileName=/typescript-5.2.0-insiders.20230531.tgz"
}
}

and then running npm install.


There is also a playground for this build and an npm module you can use via "typescript": "npm:@typescript-deploys/pr-build@5.2.0-pr-54281-11".;

@typescript-bot

Copy link
Copy Markdown
Contributor

Daniel Rosenwasser (@DanielRosenwasser) Here are the results of running the user test suite comparing main and refs/pull/54281/merge:

Everything looks good!

@DanielRosenwasser

Copy link
Copy Markdown
Member

Here's a fun one I just tried out:

const/**/yadda=()=>yadda;
Error: Debug Failure. False expression: Changes overlap
Verbose Debug Information: {"pos":4,"end":29} and {"pos":24,"end":29}
at c:/Users/Daniel/workspace/node_modules/typescript/lib/tsserver.js:166694:15
at mapDefined (c:/Users/Daniel/workspace/node_modules/typescript/lib/tsserver.js:2644:22)
at Object.getTextChangesFromChanges (c:/Users/Daniel/workspace/node_modules/typescript/lib/tsserver.js:166690:12)
at ChangeTracker.getChanges (c:/Users/Daniel/workspace/node_modules/typescript/lib/tsserver.js:166587:35)
at ChangeTracker.with (c:/Users/Daniel/workspace/node_modules/typescript/lib/tsserver.js:166071:20)
at Object.getEditsForAction (c:/Users/Daniel/workspace/node_modules/typescript/lib/tsserver.js:136427:60)
at Object.getEditsForRefactor (c:/Users/Daniel/workspace/node_modules/typescript/lib/tsserver.js:135605:31)
at Object.getEditsForRefactor2 [as getEditsForRefactor] (c:/Users/Daniel/workspace/node_modules/typescript/lib/tsserver.js:142982:32)
at IpcIOSession.getEditsForRefactor (c:/Users/Daniel/workspace/node_modules/typescript/lib/tsserver.js:182282:49)
at getEditsForRefactor (c:/Users/Daniel/workspace/node_modules/typescript/lib/tsserver.js:180538:43)
at c:/Users/Daniel/workspace/node_modules/typescript/lib/tsserver.js:182666:69
at IpcIOSession.executeWithRequestId (c:/Users/Daniel/workspace/node_modules/typescript/lib/tsserver.js:182658:14)
at IpcIOSession.executeCommand (c:/Users/Daniel/workspace/node_modules/typescript/lib/tsserver.js:182666:29)
at IpcIOSession.onMessage (c:/Users/Daniel/workspace/node_modules/typescript/lib/tsserver.js:182708:51)
at process.<anonymous> (c:/Users/Daniel/workspace/node_modules/typescript/lib/tsserver.js:184288:14)
at process.emit (node:events:513:28)
at emit (node:internal/child_process:958:14)
at process.processTicksAndRejections (node:internal/process/task_queues:84:21)

@MariaSolOs

Copy link
Copy Markdown
ContributorAuthor

Also, I noticed that if I request an inline at the following position

let/**/asdasd=42;letqwerty=asdasd;

the refactoring is made available, but not elsewhere on the let (e.g. l/**/et asdasd = ...).

I feel like it should either work solely on:

  1. The variable name
  2. The variable name or the variable statement keyword
  3. The entire variable statement

Daniel Rosenwasser (@DanielRosenwasser) I believe we should stick with option 1, since there would be an ambiguity about what to inline in cases like let x = 0, y = 1 with the other 2 options.

However, if I change this bit to:

if(isIdentifier(token)&&isInitializedVariable(parent)&&isVariableDeclarationInVariableStatement(parent)){

The refactor is still available in let/**/ foo = 0;, since I believe that's leading trivia that belongs to the identifier node. I think this should be fine...?

Comment threadsrc/services/refactors/inlineVariable.ts Outdated
Comment threadsrc/services/refactors/inlineVariable.ts Outdated
@DanielRosenwasser

Copy link
Copy Markdown
Member

TypeScript Bot (@typescript-bot) pack this

@typescript-bot

TypeScript Bot (typescript-bot) commented Jun 12, 2023

Copy link
Copy Markdown
Contributor

Heya Daniel Rosenwasser (@DanielRosenwasser), I've started to run the tarball bundle task on this PR at 67a5880. You can monitor the build here.

@typescript-bot

TypeScript Bot (typescript-bot) commented Jun 12, 2023

Copy link
Copy Markdown
Contributor

Hey Daniel Rosenwasser (@DanielRosenwasser), I've packed this into an installable tgz. You can install it for testing by referencing it in your package.json like so:

{
"devDependencies": {
"typescript": "https://typescript.visualstudio.com/cf7ac146-d525-443c-b23c-0d58337efebc/_apis/build/builds/155454/artifacts?artifactName=tgz&fileId=6087B18552E765F2B38E8662F37137B2540138A75BDE31954CDB44014CC8C60C02&fileName=/typescript-5.2.0-insiders.20230612.tgz"
}
}

and then running npm install.


There is also a playground for this build and an npm module you can use via "typescript": "npm:@typescript-deploys/pr-build@5.2.0-pr-54281-25".;

Comment threadsrc/services/refactors/inlineVariable.ts Outdated
@MariaSolOs
Maria Solano (MariaSolOs) merged commit 31936ea into microsoft:mainJun 13, 2023
@MariaSolOs
Maria Solano (MariaSolOs) deleted the inline-variable branch June 13, 2023 07:27
@awerlogus

Copy link
Copy Markdown

Inlining variable data changes runtime behaviour. Is it bug or design limitation?

constdata=newMap()constgetter=()=>data.get('foo')data.set('foo','bar')console.log(getter())

@microsoftMicrosoft (microsoft) locked as resolved and limited conversation to collaborators Oct 16, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

For Milestone BugPRs that fix a bug with a specific milestone

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

Inline local refactoring

7 participants

@MariaSolOs@typescript-bot@andrewbranch@DanielRosenwasser@awerlogus@mjbvz@sandersn