Coder Social home page Coder Social logo

refactoring-codemods's Introduction

refactoring-codemods

Quest for IDE refactoring support within JavaScript via jscodeshift codemods.

Refactoring a large JavaScript codebase is no fun. Moving files around, renaming files or renaming exported functions simply breaks all dependents import/require paths, and is a huge pain to correct. Simple search and replace is NOT a good solution.

Codemods to the rescue ๐Ÿš€ With the power of an AST we can determine which files in our project have previously depended on either the rename/moved file or renamed export, and automatically update the dependent code.

Three transforms are provided as low-level AST transforms for achieve either a file rename/move or a file export rename.

The API of this library is designed to be integrated with an IDE that leverages these transforms to update user code transparently.

Install

Install codemods via npm:

> yarn add refactoring-codemods

Transforms

import-declaration-transform

Fix all dependent import/require paths when a file has been renamed/moved.

Call this transform on your source/test files and all dependents import/require paths will be updated to match the new file name/location.

Note: prevFilePath and nextFilePath are absolute

> jscodeshift \
  -t import-declaration-transform \
  fileA fileB \
  --prevFilePath=/Users/jurassix/example/bar.js \
  --nextFilePath=/Users/jurassix/example/new/path/to/bar.js

Example:

import foo from './bar';

becomes

import foo from './new/path/to/bar';

import-relative-transform

Fix all relative import/require paths when a file has been renamed/moved.

Call this transform on the single file that is being moved to a new location and all relative import/require paths will be updated to match the new file name/location.

Note: prevFilePath and nextFilePath are absolute

> jscodeshift \
  -t import-relative-transform \
  bar.js \
  --prevFilePath=/Users/jurassix/example/old/path/to/bar.js \
  --nextFilePath=/Users/jurassix/example/new/path/to/bar.js

Example:

import foo from '../../foo';

becomes

import foo from '../../../../old/path/foo';

import-specifier-transform

Fix all dependent import/require variables when a file export been renamed.

Call this transform on your source/test files and all dependents import/require variables will be updated to match the new file export name.

Note: declarationFilePath is absolute

> jscodeshift \
  -t import-specifier-transform \
  fileA fileB \
  --prevSpecifier=foo \
  --nextSpecifier=fooPrime \
  --declarationFilePath=/Users/jurassix/example/bar.js

Example:

import foo from './bar';

foo();

becomes

import fooPrime from './bar';

fooPrime();

Contribute

Build

> yarn build

Run tests

> yarn test

refactoring-codemods's People

Contributors

ahutchings avatar jspaine avatar jurassix avatar rstacruz avatar tnrich avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

refactoring-codemods's Issues

import-declaration-transform breaks imports in index.js files

Given the following minimal test case:

$> find directory
directory
directory/index.js
directory/subdir
directory/subdir/fileA.js
$> cat directory/index.js
import Foo from './subdir/fileA';
$> cat directory/subdir/fileA.js
const Foo = 1;

export default Foo;

Then I run the following command:

$> ./node_modules/.bin/jscodeshift \
--transform ./node_modules/refactoring-codemods/lib/transformers/import-declaration-transform.js \
test-refactor/directory/index.js test-refactor/directory/subdir/fileA.js \
--prevFilePath=/Users/filip/path/to/test-refactor/directory/subdir/fileA.js \
--nextFilePath=/Users/filip/path/to/test-refactor/
Processing 2 files...
Spawning 2 workers...
Sending 1 files to free worker...
Sending 1 files to free worker...
All done.
Results:
0 errors
1 unmodified
0 skipped
1 ok
Time elapsed: 1.613seconds

The resulting file change in directory/index.js is the following:

diff --git a/directory/index.js b/directory/index.js
index 5343b73..3c20f74 100644
--- a/directory/index.js
+++ b/directory/index.js
@@ -1 +1 @@
-import Foo from './subdir/fileA';
+import Foo from "..";

which is invalid.

I was expecting the result to be

diff --git a/directory/index.js b/directory/index.js
index 5343b73..3c20f74 100644
--- a/directory/index.js
+++ b/directory/index.js
@@ -1 +1 @@
-import Foo from './subdir/fileA';
+import Foo from "../otherdirectory/subdir/fileA";

Versions I'm using:

$> cat node_modules/jscodeshift/package.json|grep version
  "version": "0.3.30"
$> cat node_modules/refactoring-codemods/package.json |grep version
  "version": "0.3.2"

Exporting non-string literal values causes error

It seems like transforming a file that exports a non-string literal fails.

For example, transforming this file:

export const SOME_VALUE = 5;

would cause an error like

TypeError: Path must be a string. Received 5
    at assertPath (path.js:7:11)
    at resolve (path.js:1148:7)
    at .../node_modules/refactoring-codemods/lib/transformers/fileHelpers/filterMatchingPaths.js:19:69
    ...

It looks like the literal value (e.g. 5) is getting passed to path.resolve() in filterMatchingPaths.js which is what is causing the TypeError

should include exports

The following shoud be updated if isRelativePath moves and also if moving the bellow file, these relative paths should update.

export {
  default as isRelativePath,
} from './isRelativePath';

Weird behavior when filename has same name but different extention

I tried to move create-react-app App.js file and it mangled the import of App.css

Moving /App.js

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

class App extends Component {
  render() {
    return (
      <div className="App">
        <div className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h2>Welcome to React</h2>
        </div>
        <p className="App-intro">
          To get started, edit <code>src/App.js</code> and save to reload.
        </p>
      </div>
    );
  }
}

export default App;

To /components/App.js caused the following output

import React, { Component } from 'react';
import logo from '../logo.svg';
import './App';

class App extends Component {
  render() {
    return (
      <div className="App">
        <div className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h2>Welcome to React</h2>
        </div>
        <p className="App-intro">
          To get started, edit <code>src/App.js</code> and save to reload.
        </p>
      </div>
    );
  }
}

export default App;

I think the issue is inside the import-declaration-transform

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.