{"id":13499228,"url":"https://github.com/google/rerast","last_synced_at":"2025-03-29T04:30:46.657Z","repository":{"id":26471221,"uuid":"108958823","full_name":"google/rerast","owner":"google","description":"A tool for transforming Rust code using rules","archived":true,"fork":false,"pushed_at":"2023-06-04T20:35:28.000Z","size":494,"stargazers_count":712,"open_issues_count":9,"forks_count":40,"subscribers_count":23,"default_branch":"master","last_synced_at":"2024-08-08T22:37:16.442Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/google.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2017-10-31T07:14:09.000Z","updated_at":"2024-08-07T19:57:42.000Z","dependencies_parsed_at":"2022-07-28T21:09:20.809Z","dependency_job_id":"429278a7-98df-48d0-a03d-ef5df61acd59","html_url":"https://github.com/google/rerast","commit_stats":{"total_commits":227,"total_committers":11,"mean_commits":"20.636363636363637","dds":0.06607929515418498,"last_synced_commit":"927a3817f49a606a5bad0bfc7d30733e2fba6d31"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/google%2Frerast","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/google%2Frerast/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/google%2Frerast/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/google%2Frerast/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/google","download_url":"https://codeload.github.com/google/rerast/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":222456044,"owners_count":16987585,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T22:00:31.098Z","updated_at":"2024-10-31T17:31:40.065Z","avatar_url":"https://github.com/google.png","language":"Rust","funding_links":[],"categories":["Write code to change code","Rust","Libraries/Tools for refactoring"],"sub_categories":["rust","Debian"],"readme":"# Rerast\n\nRerast is a search/replace tool for Rust code using rules. A rule consists of a\nsearch pattern, a replacement and possibly some placeholders that can appear in\nboth the search pattern and the replacement. Matching is done on syntax, not on\ntext, so formatting doesn't matter. Placeholders are typed and must match the\ntype found in the code for the rule to apply.\n\nRerast is deprecated. We suggest using the [Structured Search\nReplace](https://rust-analyzer.github.io/manual.html#structural-seach-and-replace) feature available\nin rust-analyzer. It is available either in vscode or from the command line (and possibly also vim).\nIf you are missing any particular feature that Rerast supported (or didn't), please comment on [this\nissue](https://github.com/rust-analyzer/rust-analyzer/issues/3186).\n\nIf you'd like to still use Rerast, we suggest using Rerast version 0.1.88 with Rust version\nnightly-2020-02-27. There are a few newer version of Rerast, but there are some broken features in\nthe newer versions.\n\n## Installation\n\n```sh\nrustup toolchain add nightly-2020-02-27\nrustup component add --toolchain nightly-2020-02-27 rustc-dev\ncargo +nightly-2020-02-27 install --version 0.1.88 rerast\n```\n\n## Usage\n\nBasic operations can be performed entirely from the command line\n```sh\ncargo +nightly-2020-02-27 rerast --placeholders 'a: i32' --search 'a + 1' --replace_with 'a - 1' --diff\n```\n\nAlternatively you can put your rule in a Rust file\n```rust\nfn rule1(a: i32) {\n  replace!(a + 1 =\u003e a - 1);\n}\n```\nthen use\n\n```sh\ncargo +nightly-2020-02-27 rerast --rules_file=my_rules.rs\n```\nPutting your rules in a file is required if you want to apply multiple rules at once.\n\nIf you'd like to actually update your files, that can be done as follows:\n\n```sh\ncargo +nightly-2020-02-27 rerast --placeholders 'a: i32' --search 'a + 1' --replace_with 'a - 1' --force --backup\n```\n\nYou can control which compilation roots rerast will inject the rule into using the `--file` argument, e.g.:\n\n```sh\ncargo +nightly-2020-02-27 rerast --rules_file=my_rules.rs --targets tests --file tests/testsuite/main.rs --diff\n```\n\nHere's a more complex example\n\n```rust\nuse std::rc::Rc;\nfn rule1\u003cT\u003e(r: Rc\u003cT\u003e) {\n  replace!(r.clone() =\u003e Rc::clone(\u0026r))\n}\n```\n\nHere we're replacing calls to the clone() method on an Rc\u003cT\u003e with the more explicit way of cloning\nan Rc - via Rc::clone.\n\n\"r\" is a placeholder which will match any expression of the type specified. The name of the function\n\"rule1\" is not currently used for anything. In future it may be possible to selectively\nenable/disable rules by specifying their name, so it's probably a good idea to put a slightly\ndescriptive name here. Similarly, comments placed before the function may in the future be displayed\nto users when the rule matches. This is not yet implemented.\n\nA function can contain multiple invocations of the replace! macro, with earlier rules taking precedence.\nThis is useful if you want to do several replacements that make use of the same placeholders or if you want\nto handle certain special patterns first, ahead of a more general match.\n\nBesides replace! there are several other replacement macros that can be used:\n\n* replace\\_pattern! - this replaces patterns. e.g. \u0026Some(a). Such a pattern might appear in a match\n  arm or if let. Irrefutable patterns (those that are guaranteed to always match) can also be\n  matched within let statements and function arguments.\n* replace\\_type! - this replaces types. It's currently a bit limited in that it doesn't support\n  placeholders. Also note, if your type is just a trait you should consider using\n  replace\\_trait\\_ref! instead, since trait references can appear in contexts where types cannot -\n  specifically generic bounds and where clauses.\n* replace\\_trait\\_ref! - this replaces references to the named trait\n\nReplacing statements is currently disabled pending a good use-case.\n\n## Matching macro invocations\n\nMacro invocations can be matched so long as they expand to code that can be matched. Note however\nthat a macro invocation will not match against the equivalent code, nor the invocation of a\ndifferent, but identical macro. This is intentional. When verifying a match, we check that the same\nsequence of expansions was followed. Also note, that if a macro expands to something different every\ntime it is invoked, it will never match. println! is an example of such a macro, since it generates\na constant that is referenced from the expanded code and every invocation references a different\nconstant.\n\n## Order of operations\n\nSuppose you're replacing foo(a, b) with a \u0026\u0026 !b. Depending on what the placeholders end up matching\nand what context the entire expression is in, there may be need for extra parenthesis. For example\nif the matched code was !foo(x == 1, y == 2), if we didn't add any parenthesis, we'd end up with !x\n== 1 \u0026\u0026 !y == 2 which clearly isn't correct. Rerast detects this and adds parenthesis as needed in\norder to preserve the order or precedence found in the replacement. This would give !(x == 1 \u0026\u0026 !(y\n== 2)).\n\n## Formatting of code\n\nNo reformatting of code is currently done. Unmatched code will not be affected. Replacement code is\nproduced by copying the replacement code from the rule and splicing in any matched patterns. In\nfuture, we may adjust identation for multi-line replacements. Running rustfmt afterwards is probably\na good idea since some identation and line lengths may not be ideal.\n\n## Recursive and overlapping matches\n\nThe first matched rule wins. When some code is matched, no later rules will be applied to that\ncode. However, code matched to placeholders will be searched for further matches to all rules.\n\n## Automatically determining a rule from a source code change\n\nIf you're about to make a change multiple times throughout your source code and you're using git,\nyou can commit (or stage) your changes, make one edit then run:\n\n```sh\ncargo +nightly-2020-02-27 rerast --replay_git --diff\n```\n\nThis will locate the changed expression in your project (of which there should be only one) then try\nto determine a rule that would have produced this change. It will print the rule, then apply it to\nyour project. If you are happy with the changes, you can run again with --force to apply them, or\nyou could copy the printed rule into a .rs file and apply it with --rules_file.\n\n* The rule produced will use placeholders to the maximum extent possible. i.e. wherever a\n  subexpression is found in both the old and the new code, it will be replaced with a placeholder.\n* This only works for changed expressions at the moment, not for statements, types, patterns etc.\n* Your code must be able to compile both with and without the change.\n\n## Limitations\n\n* Use statements are not yet updated, so depending on your rule, may need to be updated after the\n  rule is applied. This should eventually be fixed, there just wasn't time before release and it's\n  kind of tricky.\n* Your code must be able to compile for this to work.\n* The replacement code must also compile.  This means rerast is better at replacing a deprecated API\n  usage with its non-deprecated equivalent than dealing with breaking changes.  Often the best\n  workaround is to create a new API temporarily.\n* Code within rustdoc is not yet processed and matched.\n* Conditional code that disabled with a cfg attribute isn't matched. It's suggested to enable all\n  features if possible when running so that as much code can be checked as possible.\n* replace_type! doesn't yet support placeholders.\n* Probably many bugs and missing features. Please feel free to file bugs / feature requests.\n\n## Known issues\n\n* If you have integration tests (a \"tests\" directory) in your project, you might\n  be no matches. Not sure why. This started from nightly-2020-04-10. You might\n  be able to work around this issue by passing `--targets ''` to cargo rerast.\n  Unfortunately then you won't get matches in non-integration tests (i.e.\n  cfg(test)). Alternatively you could install an older version of rust and the\n  corresponding rerast version.\n* Using `?` in the replacement is currently broken. This broke I think in\n  February 2020. Something changed with spans.\n\n## More examples\nSee the [Rerast Cookbook](COOKBOOK.md) for more examples.\n\n## Groups\n* [Users group](https://groups.google.com/forum/#!forum/rerast-users)\n* [Developers group](https://groups.google.com/forum/#!forum/rerast-dev)\n\n## Questions?\nFeel free to just file an issue on github.\n\n## Authors\n\nSee Cargo.toml\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md)\n\n## Code of conduct\n\nThis project defers to the [Rust code of conduct](https://www.rust-lang.org/en-US/conduct.html). If\nyou feel someone is not adhering to the code of conduct in relation to this project, please contact\nDavid Lattimore. My email address is in Cargo.toml.\n\n## Disclaimer\n\nThis is not an official Google product. It's released by Google only because the (original) author\nhappens to work there.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgoogle%2Frerast","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgoogle%2Frerast","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgoogle%2Frerast/lists"}