Skip to content

Inline function refactoring #27070

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

Open
4 tasks done
D0nGiovanni opened this issue Sep 13, 2018 · 7 comments
Open
4 tasks done

Inline function refactoring #27070

D0nGiovanni opened this issue Sep 13, 2018 · 7 comments
Labels
Domain: Refactorings e.g. extract to constant or function, rename symbol In Discussion Not yet reached consensus Suggestion An idea for TypeScript

Comments

@D0nGiovanni
Copy link
Contributor

D0nGiovanni commented Sep 13, 2018

Search Terms

inline function method refactoring

Suggestion

I would like a refactoring that inlines a function from

1: function foo() { return 42; }
2: function bar() { const meaningOfLife = foo(); }

to

1: function bar() { const meaningOfLife = 42; }

Use Cases

This is a very common refactoring and thus widely used while cleaning up code.

Examples

In the above code sample, block 1, line 1: selecting foo, the user should be able to inline this function to every occurence and optionally delete the function definition.

In the above code sample, block 1, line 2: selecting foo, the user should be able to inline the function to this occurence, and, if it's the only one, optionally delete the function definition.

I am not sure how the option can be handled in vscode. Eclipse brings up a pop-up with the two options, but afaik vs code tries to be minimalist.

Checklist

My suggestion meets these guidelines:

  • This wouldn't change the runtime behavior of existing JavaScript code
  • This wouldn't be a breaking change in existing TypeScript / JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. new expression-level syntax)
@ghost ghost added Domain: Refactorings e.g. extract to constant or function, rename symbol Suggestion An idea for TypeScript labels Sep 13, 2018
@ghost
Copy link

ghost commented Sep 13, 2018

Related: #18459

@Kingwl
Copy link
Contributor

Kingwl commented Sep 17, 2018

The boundary of refactor seems to be difficult to determine 🤫

@hediet
Copy link
Member

hediet commented Jun 8, 2020

I think this is one of the most important (but underused) refactorings.
Many other refactorings (like rename, parameter removal/addition/reordering) can be reduced to this refactoring.

For example, if you want to reorder these parameters:

function apiFunction(arg1: string, arg2: string) {
    // ...
}

function consumerCode() {
    apiFunction("arg1", "arg2");
    apiFunction("foo", "bar");
}

... you can first rename apiFunction to apiFunction_ and delegate to a copy of apiFunction (for n consumers, manual edit complexity is O(1)):

function apiFunction(arg1: string, arg2: string) {
    // ...
}

function apiFunction_(arg1: string, arg2: string) {
    apiFunction(arg1, arg2);
}

function consumerCode() {
    apiFunction_("arg1", "arg2");
    apiFunction_("foo", "bar");
}

Now you can apply the local refactoring to apiFunction_, e.g. swapping parameter arg1 with arg2 (for n consumers, manual edit complexity is O(1)):

function apiFunction(arg2: string, arg1: string) {
    // ...
}

function apiFunction_(arg1: string, arg2: string) {
    apiFunction(arg2, arg1);
}

function consumerCode() {
    apiFunction_("arg1", "arg2");
    apiFunction_("foo", "bar");
}

And now you can inline apiFunction_ (for n consumers, manual edit complexity is O(1)):

function apiFunction(arg2: string, arg1: string) {
    // ...
}

function consumerCode() {
    apiFunction("arg2", "arg1");
    apiFunction("bar", "foo");
}

The inline refactoring is very complicated to implement though.
Local variables might need to be renamed to prevent accidental shadowing and pattern destructuring of function arguments must be supported and ideally inlined against supplied object literals.

@boyland
Copy link

boyland commented Mar 11, 2021

Yes, I miss this refactoring in VSC. I would also like inline constant expression which is even easier:

const foo = someMethodCall(...);
... foo + 100 ...

becomes

... someMethodCall(...) + 100 ...

In Opdyke's dissertation which gave a rigorous treatment of refactorings, he stressed that every refactoring has an equal and opposite refactoring: extract function has inline function as an inverse. VSC omits lots of the inverses, it seems.

@sduzair
Copy link

sduzair commented Apr 30, 2024

Looking forward to this! Coming from Uncle Bob's and Primeagen's video. This seems to be super helpful when understanding a function with many nested functions and refactoring towards better abstractions as per clean code.

@ukslim
Copy link

ukslim commented May 14, 2024

Yes, I miss this refactoring in VSC. I would also like inline constant expression which is even easier:

const foo = someMethodCall(...);
... foo + 100 ...

becomes

... someMethodCall(...) + 100 ...

This seems to already be supported as "inline variable". Cursor on the foo of foo + 100, ctrl-cmd-I (in VSC).

I do miss "inline function" though.

@ukslim
Copy link

ukslim commented May 14, 2024

The inline refactoring is very complicated to implement though. Local variables might need to be renamed to prevent accidental shadowing and pattern destructuring of function arguments must be supported and ideally inlined against supplied object literals.

I think it would be acceptable to error and refuse to perform the refactoring if variable names conflict. Refactorings should be mechanical and reversible, so "inline function" followed by "extract function" should get you back where you started. I think it's OK to expect the developer to rename some variables to unblock "inline function" .

Ideally some guidance - "cannot inline function because of conflicting identifier 'foo'"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Domain: Refactorings e.g. extract to constant or function, rename symbol In Discussion Not yet reached consensus Suggestion An idea for TypeScript
Projects
None yet
7 participants