GithubHelp home page GithubHelp logo

codemodsquad / astx Goto Github PK

View Code? Open in Web Editor NEW
85.0 4.0 6.0 2.85 MB

Super powerful structural search and replace for JavaScript and TypeScript to automate your refactoring

License: MIT License

JavaScript 1.73% TypeScript 98.27%
codemod refactor refactoring javascript typescript astx automated find match matching

astx's People

Contributors

cebamps avatar jedwards1211 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

astx's Issues

'import { Button, ...$rest } from "blah"' causes errors

$ npx [email protected] -f 'import { Button, ...$rest } from "blah"' **/*.tsx
SyntaxError: `import` can only be used in `import()` or `import.meta`. (1:1)
    at instantiate (.../@babel/parser/lib/index.js:72:32)
    at constructor (.../@babel/parser/lib/index.js:366:12)
    at TypeScriptParserMixin.raise (.../@babel/parser/lib/index.js:3453:19)
    at TypeScriptParserMixin.parseExprAtom (.../@babel/parser/lib/index.js:13065:16)
    at TypeScriptParserMixin.parseExprAtom (.../@babel/parser/lib/index.js:8174:20)
    at TypeScriptParserMixin.parseExprSubscripts (.../@babel/parser/lib/index.js:12785:23)
    at TypeScriptParserMixin.parseUpdate (.../@babel/parser/lib/index.js:12764:21)
    at TypeScriptParserMixin.parseMaybeUnary (.../@babel/parser/lib/index.js:12734:23)
    at TypeScriptParserMixin.parseMaybeUnary (.../@babel/parser/lib/index.js:10933:20)
    at TypeScriptParserMixin.parseMaybeUnaryOrPrivate (.../@babel/parser/lib/index.js:12525:61)

Babel complains about the parser

Hello again ๐Ÿ˜„

When you try to use any parser that is not the default, in my case flow, I get the following error from babel:

SyntaxError: This experimental syntax requires enabling one of the following parser plugin(s): 'flow, typescript' (16:7)
    at Parser._raise (/Users/danielo/mega/trabajo/GIT/pento/Pento/client/node_modules/@babel/parser/lib/index.js:810:17)
    at Parser.raiseWithData (/Users/danielo/mega/trabajo/GIT/pento/Pento/client/node_modules/@babel/parser/lib/index.js:803:17)
    at Parser.expectOnePlugin (/Users/danielo/mega/trabajo/GIT/pento/Pento/client/node_modules/@babel/parser/lib/index.js:9982:18)
    at Parser.isExportDefaultSpecifier (/Users/danielo/mega/trabajo/GIT/pento/Pento/client/node_modules/@babel/parser/lib/index.js:13785:16)
    at Parser.maybeParseExportDefaultSpecifier (/Users/danielo/mega/trabajo/GIT/pento/Pento/client/node_modules/@babel/parser/lib/index.js:13686:14)
    at Parser.parseExport (/Users/danielo/mega/trabajo/GIT/pento/Pento/client/node_modules/@babel/parser/lib/index.js:13639:29)
    at Parser.parseStatementContent (/Users/danielo/mega/trabajo/GIT/pento/Pento/client/node_modules/@babel/parser/lib/index.js:12657:27)
    at Parser.parseStatement (/Users/danielo/mega/trabajo/GIT/pento/Pento/client/node_modules/@babel/parser/lib/index.js:12551:17)
    at Parser.parseBlockOrModuleBlockBody (/Users/danielo/mega/trabajo/GIT/pento/Pento/client/node_modules/@babel/parser/lib/index.js:13140:25)
    at Parser.parseBlockBody (/Users/danielo/mega/trabajo/GIT/pento/Pento/client/node_modules/@babel/parser/lib/index.js:13131:10)

I'm using your CLI like this:

npx astx --parser=flow ./src/

How can I "activate" such plugins?

Unexpected error

I'm using 2.0.0-beta.5. If I have this file.js

module.exports = () => {
  return global.rules.find(
    (rule) =>
      typeof rule.loader === 'string' && /babel-loader/.test(rule.loader)
  )
}

And run this bash script

#!/usr/bin/env bash

read -r -d '' find <<'EOF'
module.exports = () => {
  $$functionBody
}
EOF

read -r -d '' replace <<'EOF'
module.exports = {
  fn() {
    $$functionBody
  }
}
EOF

astx -y -f "$find" -r "$replace" file.js

I get this error

==========================================
file.js
==========================================
TypeError: Cannot read property 'raw' of undefined
    at genericPrintNoParens (/path/to/astx/lib/node_modules/astx/node_modules/recast/lib/printer.js:677:47)
    at genericPrint (/path/to/astx/lib/node_modules/astx/node_modules/recast/lib/printer.js:123:30)
    at print (/path/to/astx/lib/node_modules/astx/node_modules/recast/lib/printer.js:77:15)
    at /path/to/astx/lib/node_modules/astx/node_modules/recast/lib/printer.js:49:41
    at Object.printComments (/path/to/astx/lib/node_modules/astx/node_modules/recast/lib/comments.js:281:22)
    at print (/path/to/astx/lib/node_modules/astx/node_modules/recast/lib/printer.js:55:31)
    at /path/to/astx/lib/node_modules/astx/node_modules/recast/lib/printer.js:49:41
    at FastPath.call (/path/to/astx/lib/node_modules/astx/node_modules/recast/lib/fast-path.js:125:18)
    at genericPrintNoParens (/path/to/astx/lib/node_modules/astx/node_modules/recast/lib/printer.js:200:29)
    at genericPrint (/path/to/astx/lib/node_modules/astx/node_modules/recast/lib/printer.js:123:30)
0 files changed
0 files unchanged
1 file errored```

VSCode extension?

Hello.
I think this tool is the best thing since sliced bread. However, it is a bit unconfrotable to have to install it globally and then run it from the command line.
I think an VSCode extension wrapping this library will be awesome.
I am not sure if it will be worth wrapping this entire library or just cherry pick some components. For example, things that are not going to be needed are:

  • command line
  • ability to read files
  • ability to execute astx files

So maybe it is possible to leverage the power of astx as a separate package?

Allow bypassing the confirmation prompt?

I'm about to update a hundred files in a large repo, is there any way to bypass the confirmation prompt (via a -y flag or similar) so that it just applies the changes to all files, that I can then review later, en masse?

find and replace within submatches has no effect

This testcase demonstrates the issue

import { TransformOptions } from '../../src'
import { astxTestcase } from '../astxTestcase'

astxTestcase({
  file: __filename,
  input: `
class Connection extends Model<ConnectionAttributes, ConnectionInitAttributes> {
  declare Channels: Array<ConnectionChannel>;
  static Channels: Association.HasMany<
    Connection,
    ConnectionChannelAttributes,
    ConnectionChannelInitAttributes,
    ConnectionChannel
  > = null
}    
  `,
  astx: ({ astx }: TransformOptions): void => {
    for (const {
      $$body,
    } of astx.find`class $C extends Model<$$A> { $$body }`()) {
      $$body.find`class X { /**/ static $a: Association.HasMany<$$p> = $Maybe($i)}`()
        // this replace has no effect
        .replace`class X { /**/ declare static $a: any; }`()
    }
  },
  expected: `
class Connection extends Model<ConnectionAttributes, ConnectionInitAttributes> {
  declare Channels: Array<ConnectionChannel>;
  declare static Channels: any;
}    
  `,
})

when to use astx codemod engine?

great work @jedwards1211 here.

which use cases cannot be handled by astx?
have you heard about semgrep? (they have data flow analysis, and built on top of tree-sitter)
also grit.io is building some awesome stuff. their pattern language reminded of your work.

at intuita, we are building a community of codemod champions like you. would love to have you there and exchange notes.
also if interested, we can chat about adding astx support to our codemod.studio (we have visual codemod builder and some LLM helpers to build codemods faster)

TypeError: Received an unexpected value [object Array]

Repro instructions:

cat <<EOF >auction_test.ts && npx astx --parser ts \
  -f 'setFakeServerHandler(() => Promise.resolve($response));' \
  -r 'const fakeServerHandler = jasmine.createSpy<FakeServerHandler>("fakeServerHandler"); fakeServerHandler.withArgs(jasmine.objectContaining<FakeRequest>({url: new URL(biddingLogicUrl1)})).and.resolveTo($response);' \
  auction_test.ts
setFakeServerHandler(() =>
  Promise.resolve({
    headers: javaScriptHeaders,
    body: [
      "function generateBid() {",
      "  return { bid: 0.03, render: 'about:blank#1' };",
      "}",
    ].join("\n"),
  })
);
EOF

Full output:

npx: installed 291 in 16.171s
==========================================
auction_test.ts
==========================================
TypeError: Received an unexpected value [object Array]
    at fromAST (/home/taymon/.npm/_npx/3832/lib/node_modules/astx/node_modules/jscodeshift/src/core.js:70:9)
    at core (/home/taymon/.npm/_npx/3832/lib/node_modules/astx/node_modules/jscodeshift/src/core.js:45:5)
    at /home/taymon/.npm/_npx/3832/lib/node_modules/astx/replace.js:196:44
    at MatchArray.map (<anonymous>)
    at generateReplacements (/home/taymon/.npm/_npx/3832/lib/node_modules/astx/replace.js:183:18)
    at replaceMatches (/home/taymon/.npm/_npx/3832/lib/node_modules/astx/replace.js:205:22)
    at MatchArray.replace (/home/taymon/.npm/_npx/3832/lib/node_modules/astx/Astx.js:75:37)
    at transformFn (/home/taymon/.npm/_npx/3832/lib/node_modules/astx/runTransformOnFile.js:133:50)
    at _callee2$ (/home/taymon/.npm/_npx/3832/lib/node_modules/astx/runTransformOnFile.js:156:35)
    at tryCatch (/home/taymon/.npm/_npx/3832/lib/node_modules/astx/node_modules/regenerator-runtime/runtime.js:63:40)
0 files changed
0 files unchanged
1 file errored

Duplicate code appearing in output

I'm not sure if this is a bug or if I'm just using it incorrectly, but if I have

test.js

/* eslint-disable no-console */

const testLib = require('test-lib')

const funcOne = (foo) => {
  console.log('foo', foo)
  return testLib(foo)
}

const funcTwo = (bar) => {
  console.log('bar', bar)
  return testLib(bar)
}

module.exports = (on, config) => {
  on('event', () => {
    funcOne(config.foo)
    funcTwo(config.bar)
  })
}

const json = {
  "foo": 123,
  "bar": true
}

astx.js

exports.find = `
$$header
module.exports = (on, config) => {
  $$functionBody
}
const json = { $$json }
`

exports.replace = `
const { func } = require('some-module')

$$header

module.exports = func({
  $$json,
  events: {
    setupEvents(on, config) {
      $$functionBody
    }
  }
})
`

The output of astx -y test.js is this (everything before module.exports from the source file seems to be at the top of the output)

/* eslint-disable no-console */

const testLib = require('test-lib')

const funcOne = (foo) => {
  console.log('foo', foo)
  return testLib(foo)
}

const funcTwo = (bar) => {
  console.log('bar', bar)
  return testLib(bar)
}

const {
  func
} = require("some-module");

/* eslint-disable no-console */
const testLib = require("test-lib");

const funcOne = foo => {
  console.log("foo", foo);
  return testLib(foo);
};

const funcTwo = bar => {
  console.log("bar", bar);
  return testLib(bar);
};

module.exports = func({
  "foo": 123,
  "bar": true,
  events: {
    setupEvents(on, config) {
      on("event", () => {
        funcOne(config.foo);
        funcTwo(config.bar);
      });
    }
  }
});

But I was expecting something more like this:

const {
  func
} = require("some-module");

/* eslint-disable no-console */
const testLib = require("test-lib");

const funcOne = foo => {
  console.log("foo", foo);
  return testLib(foo);
};

const funcTwo = bar => {
  console.log("bar", bar);
  return testLib(bar);
};

module.exports = func({
  "foo": 123,
  "bar": true,
  events: {
    setupEvents(on, config) {
      on("event", () => {
        funcOne(config.foo);
        funcTwo(config.bar);
      });
    }
  }
});

Distributed app looks to have incorrect compilation

Hello.
Thanks for this great project.
I noticed that the compiled output of this package has a problem on it. Despite it is using the requireInterop helper, it still tries to access the default exported property, which is not required:

// getfieldNames.js
function addFieldNames(type) {
  var fieldNames = _astTypes["default"].getFieldNames({
    type: type
  });

That throws an exception because prop default does not exist.
I tested on node 14.
Changing it to this makes it work:

// getfieldNames.js
function addFieldNames(type) {
  var fieldNames = _astTypes.getFieldNames({
    type: type
  });

is the CLI supposed to read ts-config.json and or babel configs?

Hello
Today I tried running the cli on a typescript project, and I'm getting type errors on some features that are not the standard. For example imports rather than requires, type imports, etc.
Is the cli supposed to find the ts-config.json/babelrc ? If not, is it possible to provide it? I took a look at the code and doesn't seem to be an option for this.

Regards

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.