wix-incubator / vscode-glean

The extension provides refactoring tools for your React codebase
MIT License
1.46k stars 56 forks source link

Import react for new component #31

Closed chiptus closed 5 years ago

chiptus commented 6 years ago

React is needed to be imported for every component, an import statement should be added to the new component file

borislit commented 6 years ago

@chiptus good point. Its a bit tricky to implement since you may be exporting the component into an existing file. Ill try implementing this ASAP

chiptus commented 6 years ago

can look for the import statement, or otherwise if importing to existing file, don't add the statement

borislit commented 6 years ago

@chiptus yep. Also various version of import need to be taken into account. For example, Typescript users usually do import * as React from 'react' while babel users do a regular default import.

@chiptus wanna do a PR? Ill be glad to help

williamluke4 commented 5 years ago

It would also be nice to import dependences of the extracted code :) If I have time ill start playing around with this

hyphaene commented 5 years ago

I'm also interested in this, I can also participate to the PR if needed.

borislit commented 5 years ago

I love the initiative! Ill be super glad to help out and point you guys in the right direction. I'd start here: https://github.com/wix/vscode-glean/blob/7d6791f9595bb9be4e5619f566c7c67276599d87/src/code-actions.ts#L25

This is baiscally the implementation of the "extract to component" refactoring, and the part where extracted component is added to the target file

williamluke4 commented 5 years ago

Managed to get a prototype working. This does not import React but finds the required imports from the source file. Relative imports will not work yet

code-actions.ts

    await appendSelectedTextToFile(selectionProccessingResult, filePath);
    await prependImportsToFileIfNeeded(selectionProccessingResult, filePath);

    const destinationImports: string = getImports(selectionProccessingResult.text);
    prependTextToFile(destinationImports, filePath);

get-imports.ts

import { jsxToAst } from "./modules/jsx";
import { allText } from "./editor";
import traverse from "@babel/traverse";
import { File } from "@babel/types";
import { transformFromAstSync } from "@babel/core";

export default function getImports(code: string): string {
  let imports: Array<string> = [];
  let sourceAst: File = jsxToAst(allText());
  sourceAst.program.body = sourceAst.program.body.filter(bodyItem => bodyItem.type === "ImportDeclaration");

  const visitor = {
    JSXIdentifier(path) {
      console.log(path);
      console.log(path.node.type);
      if(path.container.type === "JSXOpeningElement") {
        imports = [...imports, path.node.name];
      }
    }
  };

  const ast: File = jsxToAst(code);

  traverse(ast, visitor);

  sourceAst.program.body = sourceAst.program.body.filter(imp => {
    imp.specifiers = imp.specifiers.filter(spec => imports.includes(spec.local.name));
    if(imp.specifiers.length > 0) { return true; }
    return false;
  });
  const importsFromSource: string = transformFromAstSync(sourceAst).code;
  return importsFromSource;
}
borislit commented 5 years ago

@williamluke4 Thanks alot! Im having a bit of a hectic week. Ill have look at it ASAP

borislit commented 5 years ago

@williamluke4 i havent forgotten about this! Its been a bit hectic. Ill get to reviewing this week! Thank you!

borislit commented 5 years ago

hey @williamluke4, we are back in business :) Can you please create a branch? AFAIK, you want to import all missing imports, not just React?

borislit commented 5 years ago

BTW, there are several nuances that we needed take into account: When Glean creates a stateful component, it extends Component. So we need to check if there is already an existing import and either add to it (in case the file already contain another component) or add a new one @williamluke4

williamluke4 commented 5 years ago

Hey @borislit Will have a go this evening

borislit commented 5 years ago

@williamluke4 can you create a branch/fork?