Giter VIP home page Giter VIP logo

ast-grep's Introduction

ast-grep

coverage badge Discord Repology Badge Badge GitHub Sponsors

ast-grep(sg)

ast-grep(sg) is a CLI tool for code structural search, lint, and rewriting.

Introduction

ast-grep is an AST-based tool to search code by pattern code. Think it as your old-friend grep but it matches AST nodes instead of text. You can write patterns as if you are writing ordinary code. It will match all code that has the same syntactical structure. You can use $ sign + upper case letters as wildcard, e.g. $MATCH, to match any single AST node. Think it as REGEX dot ., except it is not textual.

Try the online playground for a taste!

Demo

demo

See more screenshots on the website.

Installation

You can install it from npm, pip, cargo, homebrew, scoop or MacPorts!

npm install --global @ast-grep/cli
pip install ast-grep-cli
cargo install ast-grep

# install via homebrew, thank @henryhchchc
brew install ast-grep

# install via scoop, thank @brian6932
scoop install main/ast-grep

# install via MacPorts
sudo port install ast-grep

Or you can build ast-grep from source. You need install rustup, clone the repository and then

cargo install --path ./crates/cli

Packages are available on other platforms too.

Command line usage example

ast-grep has following form.

sg --pattern 'var code = $PATTERN' --rewrite 'let code = new $PATTERN' --lang ts

Example

sg -p '$A && $A()' -l ts -r '$A?.()'
sg -p 'new Zodios($URL,  $CONF as const,)' -l ts -r 'new Zodios($URL, $CONF)' -i

Sponsor

Sponsors

If you find ast-grep interesting and useful for your work, please buy me a coffee so I can spend more time on the project!

Feature Highlight

ast-grep's core is an algorithm to search and replace code based on abstract syntax tree produced by tree-sitter. It can help you to do lightweight static analysis and massive scale code manipulation in an intuitive way.

Key highlights:

  • An intuitive pattern to find and replace AST. ast-grep's pattern looks like ordinary code you would write every day (you could say the pattern is isomorphic to code).

  • jQuery like API for AST traversal and manipulation.

  • YAML configuration to write new linting rules or code modification.

  • Written in compiled language, with tree-sitter based parsing and utilizing multiple cores.

  • Beautiful command line interface :)

ast-grep's vision is to democratize abstract syntax tree magic and to liberate one from cumbersome AST programming!

  • If you are an open source library author, ast-grep can help your library users adopt breaking changes more easily.
  • if you are a tech lead in your team, ast-grep can help you enforce code best practice tailored to your business need.
  • If you are a security researcher, ast-grep can help you write rules much faster.

ast-grep's People

Contributors

akx avatar alexzhang1030 avatar gautamprikshit1 avatar herbygillot avatar herringtondarkholme avatar hpmaxi avatar huygn avatar icp1994 avatar iwanabethatguy avatar jubalh avatar liby avatar liushuyu avatar luismeyer95 avatar manzt avatar mkatychev avatar moushicheng avatar nomyfan avatar obreitwi avatar pd4d10 avatar philiptaron avatar ppppqp avatar renovate[bot] avatar siguremo avatar sooniter avatar ssshuai1999 avatar stevenlove avatar suyanhanx avatar sxzz avatar tstrijdhorst avatar yyytbd 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

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

ast-grep's Issues

Additional languages

I would be really interested in using this tool with C# (.cs) code, any chance you can add it to the list of supported languages?
It has a treesitter parser: https://github.com/tree-sitter/tree-sitter-c-sharp
A C# identifier is not allowed to start with $ so it'd work great (makes me wonder... how do you handle that in JS, where $ is a valid identifier?)

I would also love if ast-grep could work with TS/JS code that is inside Vue SFC .vue files, but that might be more difficult as you'd need a .vue SFC parser to extract the <script> block(s) and figure out their lang attribute...

munmap_chunk(): invalid pointer

I followed the quick start guide but got the following:

$ cargo install ast-grep
...
$ cd /tmp
$ git clone [email protected]:microsoft/TypeScript.git --depth 1
...
$ cd TypeScript
$ sg -p '$PROP && $PROP()' -l ts .
./tests/cases/conformance/types/namedTypes/optionalMethods.ts
17|    let g1 = x.g && x.g();
44|    let g1 = x.g && x.g();
46|    let h1 = x.h && x.h();
munmap_chunk(): invalid pointer
[1]    25462 IOT instruction (core dumped)  sg -p '$PROP && $PROP()' -l ts .

Searching in src/ works fine:

$ sg -p '$PROP && $PROP()' -l ts src
src/services/services.ts
1541|    documentRegistry: DocumentRegistry = createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory()),
2190|        const customTransformers = host.getCustomTransformers && host.getCustomTransformers();
src/services/stringCompletions.ts
596|    const ignoreCase = !(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames());
659|    const ignoreCase = !(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames());
src/services/shims.ts
1395|                this.documentRegistry = createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory());
src/tsserver/nodeServer.ts
949|                    (os.homedir && os.homedir()) ||
974|        const homePath = (os.homedir && os.homedir()) ||
src/compiler/moduleSpecifiers.ts
936|    const globalTypingsCacheLocation = host.getGlobalTypingsCacheLocation && host.getGlobalTypingsCacheLocation();
src/harness/harnessIO.ts
174|        tryEnableSourceMapsForHost: () => ts.sys.tryEnableSourceMapsForHost && ts.sys.tryEnableSourceMapsForHost(),
175|        getMemoryUsage: () => ts.sys.getMemoryUsage && ts.sys.getMemoryUsage(),

Info

$ cargo install ast-grep  # no `sg --version` flag?
    Updating crates.io index
     Ignored package `ast-grep v0.1.11` is already installed, use --force to override
$ rustc --version
rustc 1.65.0 (897e37553 2022-11-02)
$ neofetch
            .-/+oossssoo+/-.               schneider@lenovo
        `:+ssssssssssssssssss+:`           ----------------
      -+ssssssssssssssssssyyssss+-         OS: Ubuntu 22.10 x86_64
    .ossssssssssssssssssdMMMNysssso.       Host: 80R0 Lenovo G50-80
   /ssssssssssshdmmNNmmyNMMMMhssssss/      Kernel: 5.19.0-26-generic
  +ssssssssshmydMMMMMMMNddddyssssssss+     Uptime: 58 mins
 /sssssssshNMMMyhhyyyyhmNMMMNhssssssss/    Packages: 2940 (dpkg), 14 (snap)
.ssssssssdMMMNhsssssssssshNMMMdssssssss.   Shell: zsh 5.9
+sssshhhyNMMNyssssssssssssyNMMMysssssss+   Resolution: 1440x900
ossyNMMMNyMMhsssssssssssssshmmmhssssssso   DE: GNOME 43.0
ossyNMMMNyMMhsssssssssssssshmmmhssssssso   WM: Mutter
+sssshhhyNMMNyssssssssssssyNMMMysssssss+   WM Theme: Adwaita
.ssssssssdMMMNhsssssssssshNMMMdssssssss.   Theme: Yaru-dark [GTK2/3]
 /sssssssshNMMMyhhyyyyhdNMMMNhssssssss/    Icons: Yaru-dark [GTK2/3]
  +sssssssssdmydMMMMMMMMddddyssssssss+     Terminal: tmux
   /ssssssssssshdmNNNNmyNMMMMhssssss/      CPU: Intel i7-5500U (4) @ 3.000GHz
    .ossssssssssssssssssdMMMNysssso.       GPU: Intel HD Graphics 5500
      -+sssssssssssssssssyyyssss+-         Memory: 3603MiB / 7864MiB

Find functions without return type

Good afternoon, this is such an interesting project with huge potential!

I want to write a rule which finds functions without a return type. For example, this code would trigger an error:

const foo = () => {
	return 1;
}

While this code would not:

const foo = (): int => {
	return 1;
}

The TS playground for the latter function looks like this:

image

My first thought was to make a rule which matches arrow_function (easy..) but when it comes time to find a missing value, I hit a wall.

Any suggestions or direction? This was my latest rule:

id: empty-return-type
message: Must supply a return type to a function
severity: warning
language: TypeScript
rule:
  all:
    - not: # doesn't work - matches all ast nodes except a type annotation. 
        kind: type_annotation
    - inside:
        any:
          - kind: arrow_function
          # TODO Insert more function types here

Please take care and thank you for reading.

Complex examples

I have the following Rust code:

patterns = match config.include.clone() {
    Some(patterns) => patterns,
    None => Vec::from([cwd
        .join("**/*.toml")
        .normalize()
        .to_string_lossy()
        .into_owned()]),
};

And I want to replace with this:

patterns = config.include.clone().unwrap_or_else(|| {
    Vec::from([cwd
        .join("**/*.toml")
        .normalize()
        .to_string_lossy()
        .into_owned()])
})

I tried to do it with this command:

sg -p '$A match { Some($X) => $X, None => $N, }' -r '$A.unwrap_or_else($N)' --lang rust

But it can't match pattern. How can I solve it? Also, maybe it would be better if README has examples with this complex types of AST nodes.

[CLI] The description of `--interactive` is missing in `OPTIONS`

Hi, @HerringtonDarkholme I'm digging into the source code.

When i run sg --help

USAGE:
    sg.exe [OPTIONS] --pattern <PATTERN> --lang <LANG> [PATH]

ARGS:
    <PATH>    The path whose descendent files are to be explored [default: .]

OPTIONS:
        --debug-query          Print query pattern's tree-sitter AST
    -h, --help                 Print help information
        --hidden               Include hidden files in search
    -i, --interactive
    -l, --lang <LANG>          The language of the pattern query
    -p, --pattern <PATTERN>    AST pattern to match
    -r, --rewrite <REWRITE>    String to replace the matched AST node

The -i, --interactive line is missing description.

If you don't mind, I can try adding a description like this:
Start an interactive session

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Rate-Limited

These updates are currently rate-limited. Click on a checkbox below to force their creation now.

  • chore(deps): update dependency @napi-rs/cli to v2.18.2
  • chore(deps): update dependency @types/node to v20.12.7
  • chore(deps): update dependency typescript to v5.4.5
  • chore(deps): update rust crate anyhow to 1.0.82
  • chore(deps): update rust crate napi-build to 2.1.3
  • chore(deps): update rust crate thiserror to 1.0.59
  • fix(deps): update dependency @swc/core to v1.4.16
  • fix(deps): update rust crate clap_complete to 4.5.2
  • fix(deps): update rust crate napi to 2.16.4
  • fix(deps): update rust crate napi-derive to 2.16.3
  • fix(deps): update rust crate pyo3 to 0.21.2
  • fix(deps): update rust crate serde_json to 1.0.116
  • fix(deps): update rust crate toml_edit to 0.22.12
  • chore(deps): update robinraju/release-downloader action to v1.10
  • fix(deps): update rust crate tree-sitter-elixir to 0.2.0
  • fix(deps): update rust crate tree-sitter-java to 0.21.0
  • fix(deps): update rust crate tree-sitter-json to 0.21.0
  • 🔐 Create all rate-limited PRs at once 🔐

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Ignored or Blocked

These are blocked by an existing closed PR and will not be recreated unless you click a checkbox below.

Detected dependencies

cargo
Cargo.toml
  • bit-set 0.5.3
  • ignore 0.4.22
  • regex 1.10.4
  • serde 1.0
  • tree-sitter 0.9.2
  • thiserror 1.0.58
  • schemars 0.8.16
  • anyhow 1.0.81
benches/Cargo.toml
  • criterion 0.5
crates/cli/Cargo.toml
  • ansi_term 0.12
  • atty 0.2.14
  • clap 4.5.4
  • codespan-reporting 0.11.1
  • crossterm 0.27.0
  • inquire 0.7.4
  • num_cpus 1.16.0
  • serde_json 1.0.115
  • serde_yaml 0.9.33
  • similar 2.5.0
  • tokio 1
  • clap_complete 4.5.1
  • assert_cmd 2.0.14
  • predicates 3.1.0
  • tempfile 3.10.1
crates/config/Cargo.toml
  • globset 0.4.14
  • serde_yaml 0.9.33
  • tree-sitter-typescript 0.20.5
crates/core/Cargo.toml
  • tree-sitter-typescript 0.20.5
crates/dynamic/Cargo.toml
  • libloading 0.8
  • tree-sitter-native 0.20.10
crates/language/Cargo.toml
  • tree-sitter-bash 0.20.5
  • tree-sitter-c 0.20.8
  • tree-sitter-cpp 0.20.5
  • tree-sitter-c-sharp 0.20.0
  • tree-sitter-css 0.20.0
  • tree-sitter-dart 0.0.3
  • tree-sitter-elixir 0.1.1
  • tree-sitter-go 0.20.0
  • tree-sitter-html 0.20.0
  • tree-sitter-java 0.20.2
  • tree-sitter-javascript 0.20.4
  • tree-sitter-json 0.20.2
  • tree-sitter-kotlin 0.3.5
  • tree-sitter-lua 0.0.19
  • tree-sitter-php 0.22.2
  • tree-sitter-python 0.20.4
  • tree-sitter-ruby 0.20.1
  • tree-sitter-rust 0.20.4
  • tree-sitter-scala 0.20.3
  • tree-sitter-swift 0.4.3
  • tree-sitter-typescript 0.20.5
crates/lsp/Cargo.toml
  • serde_json 1.0.115
  • dashmap 5.5.3
  • tower-lsp 0.20.0
  • tokio 1
crates/napi/Cargo.toml
  • napi 2.16.1
  • napi-derive 2.16.1
  • tree-sitter-typescript 0.20.5
  • tree-sitter-html 0.20.0
  • tree-sitter-javascript 0.20.4
  • tree-sitter-css 0.20.0
  • serde_json 1.0.115
  • napi-build 2.1.2
crates/pyo3/Cargo.toml
  • pyo3 0.21.1
  • pythonize 0.21.1
xtask/Cargo.toml
  • serde_json 1.0.115
  • toml_edit 0.22.9
github-actions
.github/workflows/coverage.yaml
  • actions/checkout v4
  • codecov/codecov-action v4
  • actions/checkout v4
  • actions-rs/toolchain v1
  • actions/cache v4
.github/workflows/napi.yml
  • actions/checkout v4
  • actions/setup-node v4
  • actions-rs/toolchain v1
  • actions/cache v4
  • actions/cache v4
  • actions/setup-node v4
  • addnab/docker-run-action v3
  • actions/upload-artifact v3
  • actions/checkout v4
  • actions/setup-node v4
  • actions/cache v4
  • actions/download-artifact v3
  • ubuntu 20.04
.github/workflows/pyo3.yml
  • actions/checkout v4
  • actions/setup-python v5
  • PyO3/maturin-action v1
  • actions/upload-artifact v3
  • actions/checkout v4
  • actions/setup-python v5
  • PyO3/maturin-action v1
  • actions/upload-artifact v3
  • actions/checkout v4
  • actions/setup-python v5
  • PyO3/maturin-action v1
  • actions/upload-artifact v3
  • actions/checkout v4
  • PyO3/maturin-action v1
  • actions/upload-artifact v3
  • actions/download-artifact v3
  • PyO3/maturin-action v1
  • ubuntu 20.04
.github/workflows/pypi.yml
  • actions/checkout v4
  • actions/setup-python v5
  • PyO3/maturin-action v1
  • actions/upload-artifact v3
  • actions/checkout v4
  • actions/setup-python v5
  • PyO3/maturin-action v1
  • actions/upload-artifact v3
  • actions/checkout v4
  • actions/setup-python v5
  • PyO3/maturin-action v1
  • actions/upload-artifact v3
  • actions/checkout v4
  • actions/setup-python v5
  • PyO3/maturin-action v1
  • actions/upload-artifact v3
  • actions/checkout v4
  • actions/setup-python v5
  • PyO3/maturin-action v1
  • actions/upload-artifact v3
  • actions/download-artifact v3
  • ubuntu 20.04
.github/workflows/release.yml
  • actions/checkout v4
  • katyo/publish-crates v2
  • actions/checkout v4
  • taiki-e/create-gh-release-action v1
  • actions/checkout v4
  • taiki-e/upload-rust-binary-action v1
  • actions/checkout v4
  • actions/setup-node v4
  • robinraju/release-downloader v1.9
  • heinrichreimer/action-github-changelog-generator v2.4
  • ubuntu 20.04
  • ubuntu 20.04
  • ubuntu 20.04
  • ubuntu 20.04
npm
benches/package.json
  • @babel/core 7.24.4
  • @babel/plugin-syntax-typescript 7.24.1
  • @oxidation-compiler/napi 0.2.0
  • @swc/core 1.4.12
  • benny 3.7.1
  • tree-sitter 0.20.6
  • tree-sitter-typescript 0.20.5
  • typescript 5.4.4
  • @types/babel__core 7.20.5
  • @types/node 20.12.5
  • prettier 3.2.5
  • ts-node 10.9.2
crates/napi/npm/darwin-arm64/package.json
  • node >= 10
crates/napi/npm/darwin-x64/package.json
  • node >= 10
crates/napi/npm/linux-arm64-gnu/package.json
  • node >= 10
crates/napi/npm/linux-x64-gnu/package.json
  • node >= 10
crates/napi/npm/linux-x64-musl/package.json
  • node >= 10
crates/napi/npm/win32-arm64-msvc/package.json
  • node >= 10
crates/napi/npm/win32-ia32-msvc/package.json
  • node >= 10
crates/napi/npm/win32-x64-msvc/package.json
  • node >= 10
crates/napi/package.json
  • @napi-rs/cli 2.18.0
  • ava 6.1.2
  • chalk 5.3.0
  • ts-node 10.9.2
  • typescript 5.4.4
  • node >= 10
npm/package.json
  • detect-libc 2.0.3
  • @ast-grep/cli-win32-arm64-msvc 0.20.5
  • @ast-grep/cli-win32-ia32-msvc 0.20.5
  • @ast-grep/cli-win32-x64-msvc 0.20.5
  • @ast-grep/cli-darwin-arm64 0.20.5
  • @ast-grep/cli-darwin-x64 0.20.5
  • @ast-grep/cli-linux-arm64-gnu 0.20.5
  • @ast-grep/cli-linux-x64-gnu 0.20.5
  • node >= 12.0.0
npm/platforms/darwin-arm64/package.json
  • node >= 10
npm/platforms/darwin-x64/package.json
  • node >= 10
npm/platforms/linux-arm64-gnu/package.json
  • node >= 10
npm/platforms/linux-x64-gnu/package.json
  • node >= 10
npm/platforms/win32-arm64-msvc/package.json
  • node >= 10
npm/platforms/win32-ia32-msvc/package.json
  • node >= 10
npm/platforms/win32-x64-msvc/package.json
  • node >= 10
pep621
crates/pyo3/pyproject.toml
  • test/pytest >= 7
  • maturin >=1.1,<2.0
pyproject.toml
  • maturin >=1.1,<2.0

  • Check this box to trigger a request for Renovate to run again on this repository

--version flag?

I observed it is lacking when I submitted #109. It would be useful to have one.

Add a LICENSE

I wanted to package ast-grep for Homebrew and Nixpkgs, but I can't without a license.

[insufficient information] cannot install @ast-grep/cli

I look forward to trying this someday when I can install it! If this is working for anyone else, I'll come back with more details. For now, I have to run so it's just a friendly heads up. I'm on a MBP (intel) Monterey 12.6, fish shell, node 16.17.0, npm 8.15.0.

Thanks! Good luck!

Command name alias: ast-grep and sg

The cli command name sg is already taken by a shadow tools command

NAME
sg - execute command as different group ID

Cf. https://github.com/shadow-maint/shadow

It is installed by default in /usr/bin/sg at least on arch-linux.

Weirdly npm install -g @ast-grep/cli didn’t even install the cli in ~/.local/bin for me (I have prefix=~/.local configured for npm). Maybe that is also due to the name collision.

I actually like the pattern of .g for grep commands. Pitty that ag is already taken.
How about cg for code-grep?

scan command panics

When I run sg scan anywhere, it imediately fails with the following error:

thread 'main' panicked at 'called Result::unwrap() on an Err value: Os { code: 2, kind: NotFound, message: "No such file or directory" }', crates/cli/src/config.rs:8:48

The rust backtrace does not produce anything useful.

Playground: Add rewriting suppot to playground

Currently, I am writing automation for my Vue project and due to AST headache, I am using REGEX to replace the content.

I found ast-grep and it looks promising ❤️

One thing missing in playground compared to CLI mode is rewriting. Can you please add it so someone can just paste and try it before running on CLI?

P.S. It will be great if you add more examples to docs

Using ast-grep as a library

Awesome project! I'm interested in potentially using ast-grep as the foundation for Ruff's plugin system (some discussion in astral-sh/ruff#283).

What I'm envisioning: users express custom lint rules via the ast-grep YAML syntax; Ruff picks up those rules, parses + executes them via ast-grep, and includes the surfaced messages + fixes in its own output abstractions.

Before I dig in, I wanted to see if (1) this kind of use-case is within-scope for ast-grep, (2) if it's possible now or depends on future work, and (3) if you had any pointers on how to get started (I know the API docs are a work-in-progress so any tips would be appreciated).

Change output colors?

How can I change the output colors sg gives me? The current ones seem pretty unusable for me,

Screenshot from 2022-12-11 12-12-12

I think the issue here is that I'm using a light font color, which doesn't contrast well with the pink/light green highlights. Maybe related to #2?

Docs for TS API?

I am using TS project to modify my source code.

Can you please add docs on TS API?

Thanks :)

[refactor] use mspc for non-interactive output

At the moment we use stdout lock for printing matches. This is slow and the actual matching is single threaded.
So using mspc is performance-wise equivalent to current implementation.

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.