Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
747 lines (492 sloc) 20.4 KB

Changelog

All notable changes to the Abracadabra extension will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

Unreleased

3.2.1 - 2020-02-20

Fixed

  • Extract Variable didn't worked properly with empty string and special keywords. This is now fixed!
  • Extract Variable didn't worked properly for non-camel case properties. E.g. path.some_node.value would wrongly extract const { someNode } = path. Now it will correctly compute const { some_node } = path.

3.2.0 - 2020-01-30 - The Class Without an Interface 🎭

Fixed

  • Convert to Template Literal now works on JSX attributes which were not already wrapped with braces. Concretely, <MyComponent prop="test" /> will now produce <MyComponent prop={test} /> instead of failing.
  • Don't propose Convert to Template Literal on imports

Added

  • [New Refactoring] Add Braces to JSX Attribute
  • [New Refactoring] Remove Braces from JSX Attribute
  • [New Refactoring] Extract Interface (TS specific)

3.1.0 - 2020-01-14 - Keep 'em simple 🌱

Added

  • [New Refactoring] Simplify Ternary
  • [New Refactoring] Add Braces to If Statement

3.0.0 - 2019-12-19 - Finding good shortcuts is hard 🤪

Added

  • [New Refactoring] Convert to Pure Component (React specific)

Changed

  • (Breaking) So… Move Statement Up/Down keybinding was conflicting with VS Code native shortcuts on Mac OS too. It was ⌘ ⇧ ↑/↓, now it's Alt + Shift + U / D for everyone.

Extract Variable now destructures member expressions properties

Consider the following code:

console.log(session.user.address);

Before, extracting address would have produced:

const address = session.user.address;
console.log(address);

This was fine… But it could be optimized. From our own experience, we always destructure the address property after the extraction.

Thus, from now on, extracting address will produce:

const { address } = session.user;
console.log(address);

Since you end up renaming the symbol, you can provide a different name than address and it will work.

Fixed

  • Don't Convert For-Loop to ForEach if counter doesn't start from 0

2.0.0 - 2019-12-12 - A better shortcut 🛣

Changed

  • (Breaking) Changed keybinding of Move Statement Up/Down on Windows and Linux since it conflicts with VS Code native shortcuts. It was Ctrl + Shift + ↑ / ↓, now it's Alt + Shift + U / D
  • Configure Alt ↵ keybinding to trigger VS Code Quick Fixes, so it's more convenient to use the extension by default.

Convert If/Else to Ternary handles implicit else return statements

Useful when dealing with guard clauses patterns.

Consider the following code:

function calculateYear(selectedDates) {
  if (selectedDates[0].getMonth() === 0) {
    return selectedDates[0].getFullYear() - 1;
  }

  return selectedDates[0].getFullYear();
}

Before this change, you couldn't convert this to a ternary directly, since the else statement is not explicit. But it's still here. It's a typical guard clause pattern.

Now, Abracadabra will recognize this pattern and it will produce the expected code:

function calculateYear(selectedDates) {
  return selectedDates[0].getMonth() === 0
    ? selectedDates[0].getFullYear() - 1
    : selectedDates[0].getFullYear();
}

Fixed

  • Inline Variable now handles destructured "this" expressions correctly (e.g. you can inline const { id } = this.user).

1.2.1 - 2019-11-30

Fixed

  • Fix cursor position after Extract Variable that creates a shorthand on an object property that ends with a comma, so rename works
  • Stop proposing Negate Expression quick fix on single call expressions, since the negated expression is identical
  • Remove double-negations after running Negate Expression on a multi-line expression

1.2.0 - 2019-11-28 - Big head, shorthand 🦖

Changed

Extract Variable creates shorthand object properties

Consider the following code:

console.log({
  foo: "bar"
});

Before, extracting the "bar" string literal would have produced:

const extracted = "bar";
console.log({
  foo: extracted
});

This worked. But in practice, we realized that we continue modifying the code manually to get there:

const foo = "bar";
console.log({
  foo
});

So now, this is what Extract Variable will generate by default. Obviously, you'll have the capability to rename foo directly, so you can adapt the name if you want to provide another one.

We believe this will make extracting object properties even more fluid.

Fixed

  • Extract Variable won't extract type annotation as it doesn't handle them properly yet.

1.1.0 - 2019-11-21 - Keep movin' 🏃‍♀️

Changed

  • Extract Variable now extracts JSX Attributes (e.g. <Header title="Home" /> will extract "Home" if cursor is on it).
  • Extract Variable now suggest a better variable name when you extract member expressions (e.g. const name = this.props.location.name instead of const extracted = this.props.location.name).
  • Move Statements now work on object methods, class methods and class properties!

Fixed

  • Extract Variable don't suggest an invalid variable name when extracting a string starting with a number.
  • Stop jumping cursor to the end of the file when performing some refactorings. That was a regression introduced when we improve cursor scrolling on Move Statements, in v1.0.0 😅

1.0.1 - 2019-11-18

Fixed

  • Inline Variable now works correctly for destructured objects with a computed identifier (e.g. const { id } = session.users[key]).

1.0.0 - 2019-11-15 - Officially stable 🎩

Abracadabra is now stable enough to be considered v1 🎉🎩

Fixed

  • Cursor position after "Move Statements" is now more accurate.
  • VS Code now scrolls to the moved statement, so we don't loose track of it!

0.11.0 - 2019-11-13 - Refactor Barry, Refactor ⚡

Changed

Improve Quick Fixes performances

We've optimized the way we determine which refactorings can be executed at your current cursor position. This is an Abracabra key feature.

Every time you move your cursor on the code, we propose you the relevant refactorings through the VS Code Quick Fixes (aka, the lightbulb 💡). This process was taking quite some time, which was causing 2 issues:

  1. On large files (> 1000 LOC), it would take many seconds to propose you anything. This is lon. And let's be honest, legacy code we're dealing with frequently comes as large files we want to refactor.
  2. Each new refactoring was adding a bit more of computing. Today, that's around 20 refactorings. If we want to add more, we add to improve performances first, so the extension stays usable.

In short, 2 things were improved:

  1. We now only parse the code once, instead of each refactoring parsing the code again.
  2. We shortcut the refactoring execution, so we save a bunch of time on the transformation part too.

As for every performance optimization, you need to measure it or it didn't happen! Overall, here's what it looks like:

File size Execution time before Execution time after Gain
Small (70 LOC) 200ms 40ms -80%, 5 times faster
Large (2.400 LOC) 6s 350ms -94%, 17 times faster

Move Statements now handles one-liners more intuitively

Consider following code:

const user = {
  firstName: "John",
  lastName: "Doe",
  age: 24
};
const rights = { admin: false, moderator: true };

Before, if you had the cursor on admin and you tried to move the statement up, you'd have swapped the parameters:

const user = {
  firstName: "John",
  lastName: "Doe",
  age: 24
};
const rights = { moderator: true, admin: false };

But what you probably intended to do was to swap the two variable declarations. From usage, we think "Move Statements" more as something you'd like to use to move things up or down. If things are at the same line, you certainly don't expect them to move.

The behaviour was surprising, so it was improved. Now, the same operation will generate:

const rights = { admin: false, moderator: true };
const user = {
  firstName: "John",
  lastName: "Doe",
  age: 24
};

However, if your cursor is now on lastName and you move the statement down, it will still produce the following code since statements are on different lines:

const rights = { admin: false, moderator: true };
const user = {
  firstName: "John",
  age: 24,
  lastName: "Doe"
};

Noticed how it handles the trailing comma? Ok, that was already here. But it's still super neat!

0.10.0 - 2019-10-27 - Can't type this 🕺

Changed

Inline Variable now handles Type Aliases

Consider the following TypeScript code:

type Value = "one" | "many" | "none";

interface Something {
  value: Value;
}

You can now inline the Value type just like a regular variable. Inlining it will result in following code:

interface Something {
  value: "one" | "many" | "none";
}

Merge else-if is more intuitive

Consider the following nested if statements:

if (isValid) {
  doSomething();
} else {
  if (shouldDoSomething) {
    doSomethingElse();
  } else {
    if (isCorrect) {
      doAnotherThing();
    }
  }
}

If your cursor is on the nested if (shouldDoSomething) and you want to execute " Merge else-if" quick fix, then you'd expect this if to be merged with the previous one.

However, because of the nested if (isCorrect), the actual output would have been:

if (isValid) {
  doSomething();
} else {
  if (shouldDoSomething) {
    doSomethingElse();
  } else if (isCorrect) {
    doAnotherThing();
  }
}

We improved the UX to be more intuitive. So if your cursor is on if (shouldDoSomething), we'll prioritize the parent merge and the result would be:

if (isValid) {
  doSomething();
} else if (shouldDoSomething) {
  doSomethingElse();
} else {
  if (isCorrect) {
    doAnotherThing();
  }
}

Fixed

  • Extract Variable with arrays of different length now matches other occurrences correctly.

0.9.0 - 2019-10-17 - Let me guess your name 🔮

Changed

Inline Variable now handles destructured array patterns

Consider the following code:

const [firstName] = names;
console.log(firstName);

If you tried to inline firstName, it wouldn't work because destructured array patterns were not supported.

Now it would work as expected:

console.log(names[0]);

That means Inline Variable now handles all kind of destructured variables. Making it much more flexible and handy!

Extract Variable infers variable name on String Literals

Consider the following code:

console.log("Hello World!");

If you extracted "Hello World!", you would end up with the following code:

const extracted = "Hello World!";
console.log(extracted);

And you'll be renaming the extracted symbol. Which is a quick and efficient way to extract the variable.

But now, it'll try to do a bit better. Now, you'll end up with:

const helloWorld = "Hello World!";
console.log(helloWorld);

Which would make sense in that case, saving you the trouble of naming it!

Now, predicting the variable name is hard. Thus, you'll still be in "renaming mode", so it doesn't really matter if the guess is wrong. If it's correct though, it will certainly save you some more time in your refactoring, and that's the goal!

One last thing: if the inferred name is too long (> 20 characters), it will default on "extracted" because it's probably not a good name for your variable.

Fixed

  • All refactorings Quick Fixes used to appear on Windows because of EOL. Not anymore!

0.8.0 - 2019-09-22 - I see dead code 💀

Added

  • [New Refactoring] Remove Dead Code
  • [New Refactoring] Convert For-Loop to ForEach

Changed

Inline Variable now handles destructured object patterns

Consider the following code:

const { userId } = session;
messages.map(message => ({ userId }));

If you tried to inline userId, it wouldn't work because destructured object patterns were not supported.

Now it would work as expected:

messages.map(message => ({ userId: session.userId }));

Thanks to @noway for bringing this one up.

Destructured array patterns (e.g. const [userId] = session) are still not supported, but we're working on it.

Fixed

  • Convert If/Else to Ternary now preserve comments that were inside each branches.

0.7.0 - 2019-09-16 - Switch it on! 🔦

Added

  • [New Refactoring] Convert If/Else to Switch
  • [New Refactoring] Merge With Previous If Statement

Changed

Split Declaration and Initialization now handles nested declarations

Consider the following code:

const getLastName = () => {
  const lastName = "Doe";
  return lastName;
};

If your cursor is on const lastName, executing the refactoring would have produced this result before:

let getLastName;

getLastName = () => {
  let lastName;
  lastName = "Doe";
  return lastName;
};

Refactoring would have been applied to both declarations. It's valid, but probably not want you wanted to do.

Now it will produce the following, expected output:

const getLastName = () => {
  let lastName;
  lastName = "Doe";
  return lastName;
};

Fixed

  • Flip If/Else now works when both if and else branches have return statements
  • Inline Function now preserves comments as much as possible

0.6.0 - 2019-09-08 - Bubble it up 🐠

Added

  • [New Refactoring] Bubble up If Statement

Changed

Merge If Statements now handles else-ifs

Extract Variable handles Spread Elements better

Consider the following snippet:

console.log({ ...foo.bar });

Before, executing Extract Variable with the cursor of foo would have produced:

const extracted = { ...foo.bar };
console.log(extracted);

Now, you can extract the Spread Element. The result will be:

const extracted = foo.bar;
console.log({ ...extracted });

If your cursor is on the ... symbol however, you will still extract the whole thing.

0.5.0 - 2019-08-25 - Extract 'em all 🤙

Added

  • [New Refactoring] Replace Binary with Assignment

Changed

Extract Variable now handles extraction of multiple occurrences!

If the extracted variable has no other occurrence in scope, it will just perform the extraction as it does today.

But if we can find other occurrences of the variable in the scope, then it will ask you what you want to do:

  1. "Replace all N occurrences". This is the default since it's what we want to do most of the time.
  2. "Replace this occurrence only". In case you only want to extract this one.

Fixed

  • Extract Variable now works for call expressions in JSX Elements (e.g. <Button onClick={this.extractMe()} />)
  • Extract Variable now works in for statements

0.4.0 - 2019-08-18 - Here come the Guards 💂‍♀️

Changed

Flip If/Else now works better on guard clause patterns

Consider this guard clause example:

function doSomething(someData) {
  if (!isValid(someData)) {
    return;
  }

  // … rest of the code
}

Before, running Flip If/Else would have produced:

function doSomething(someData) {
  if (isValid(someData)) {
  } else {
    return;
  }

  // … rest of the code
}

Which is valid, but probably not what you had in mind.

Now, it would produce the following result:

function doSomething(someData) {
  if (isValid(someData)) {
    // … rest of the code
  }
}

Fixed

  • Inline Function now says it can't inline function with many statements to assigned call expressions
  • Inline Function now works on return statements identifiers (e.g. return inlineMe;)
  • Inline Function now works on every call expression that is:
    • assigned to a variable (e.g. const result = isValid ? inlineMe() : "default";)
    • inside another call expression (e.g. console.log(inlineMe()))
    • inside an arrow function expression (e.g. () => inlineMe())
  • Extract Variable on JSX Elements now triggers symbol rename as expected
  • Extract Variable now works on JSXTexts

0.3.0 - 2019-08-10 - Y U no use template strings? 😫

Added

  • [New refactoring] Convert to Template Literal
  • [New refactoring] Split Declaration and Initialization

Fixed

  • Don't add unnecessary braces when extracting JSX elements.
  • Don't extract arrow function expressions params.
  • Remove Redundant Else now handles nested If statements correctly.
  • Flip Ternary now handles nested ternaries correctly.
  • Flip If/Else now handles nested If statements correctly.

0.2.0 - 2019-08-05 - Let me Inline this for you 🧙‍♂️

Added

  • [New refactoring] Inline Function
  • [New refactoring] Merge If Statements

0.1.0 - 2019-07-23 - Brace(s) yourself… ❄️

Fixed

  • Inline Variable with object shorthand properties

Added

  • Move Statement Up/Down now work on object properties too
  • [New refactoring] Split If Statement
  • [New refactoring] Remove Braces from Arrow Function
  • [New refactoring] Add Braces to Arrow Function

0.0.1 - 2019-07-09 - First publication, first refactorings

Added

  • [New refactoring] Move Statement Down
  • [New refactoring] Move Statement Up
  • [New refactoring] Convert Ternary to If/Else
  • [New refactoring] Convert If/Else to Ternary
  • [New refactoring] Flip Ternary
  • [New refactoring] Flip If/Else
  • [New refactoring] Remove Redundant Else
  • [New refactoring] Negate Expression
  • [New refactoring] Inline Variable
  • [New refactoring] Extract Variable
  • [New refactoring] Rename Symbol
You can’t perform that action at this time.