diff --git a/.all-contributorsrc b/.all-contributorsrc new file mode 100644 index 00000000..3ee65ba1 --- /dev/null +++ b/.all-contributorsrc @@ -0,0 +1,25 @@ +{ + "projectName": "cairo-lint", + "projectOwner": "keep-starknet-strange", + "repoType": "github", + "repoHost": "https://github.com", + "files": [ + "README.md" + ], + "imageSize": 100, + "commit": true, + "commitConvention": "angular", + "contributors": [ + { + "login": "0xLucqs", + "name": "0xLucqs", + "avatar_url": "https://avatars.githubusercontent.com/u/70894690?v=4", + "profile": "https://github.com/0xLucqs", + "contributions": [ + "code" + ] + } + ], + "contributorsPerLine": 7, + "linkToUsage": false +} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..6de8ec16 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,27 @@ +on: [push, pull_request] + +name: Test + +jobs: + test: + name: Test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Get corelib + run: git clone -b lucas/multiline_diag https://github.com/0xLucqs/cairo + + - name: Install toolchain + run: rustup show + + - uses: Swatinem/rust-cache@v2 + + - name: Run cargo clippy + run: cargo clippy -- -D warnings + + - name: Run cargo test + run: CORELIB_PATH="$(pwd)/cairo/corelib/src" cargo test + + - name: Run cargo fmt + run: rustup toolchain install nightly && rustup component add --toolchain nightly-x86_64-unknown-linux-gnu rustfmt && cargo +nightly fmt -- --check diff --git a/.gitignore b/.gitignore index eb5a316c..54088d57 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ target +.DS_Store diff --git a/Cargo.lock b/Cargo.lock index b0d23f72..e3d46352 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -187,6 +187,7 @@ checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "cairo-lang-casm" version = "2.7.0" +source = "git+https://github.com/0xLucqs/cairo?branch=lucas/multiline_diag#11f8a1979834e39f4a79cc9d3a2707017b46e1fa" dependencies = [ "cairo-lang-utils", "indoc", @@ -199,6 +200,7 @@ dependencies = [ [[package]] name = "cairo-lang-compiler" version = "2.7.0" +source = "git+https://github.com/0xLucqs/cairo?branch=lucas/multiline_diag#11f8a1979834e39f4a79cc9d3a2707017b46e1fa" dependencies = [ "anyhow", "cairo-lang-defs", @@ -222,6 +224,7 @@ dependencies = [ [[package]] name = "cairo-lang-debug" version = "2.7.0" +source = "git+https://github.com/0xLucqs/cairo?branch=lucas/multiline_diag#11f8a1979834e39f4a79cc9d3a2707017b46e1fa" dependencies = [ "cairo-lang-utils", ] @@ -229,6 +232,7 @@ dependencies = [ [[package]] name = "cairo-lang-defs" version = "2.7.0" +source = "git+https://github.com/0xLucqs/cairo?branch=lucas/multiline_diag#11f8a1979834e39f4a79cc9d3a2707017b46e1fa" dependencies = [ "cairo-lang-debug", "cairo-lang-diagnostics", @@ -244,6 +248,7 @@ dependencies = [ [[package]] name = "cairo-lang-diagnostics" version = "2.7.0" +source = "git+https://github.com/0xLucqs/cairo?branch=lucas/multiline_diag#11f8a1979834e39f4a79cc9d3a2707017b46e1fa" dependencies = [ "cairo-lang-debug", "cairo-lang-filesystem", @@ -254,6 +259,7 @@ dependencies = [ [[package]] name = "cairo-lang-doc" version = "2.7.0" +source = "git+https://github.com/0xLucqs/cairo?branch=lucas/multiline_diag#11f8a1979834e39f4a79cc9d3a2707017b46e1fa" dependencies = [ "cairo-lang-defs", "cairo-lang-formatter", @@ -267,6 +273,7 @@ dependencies = [ [[package]] name = "cairo-lang-eq-solver" version = "2.7.0" +source = "git+https://github.com/0xLucqs/cairo?branch=lucas/multiline_diag#11f8a1979834e39f4a79cc9d3a2707017b46e1fa" dependencies = [ "cairo-lang-utils", "good_lp", @@ -275,6 +282,7 @@ dependencies = [ [[package]] name = "cairo-lang-filesystem" version = "2.7.0" +source = "git+https://github.com/0xLucqs/cairo?branch=lucas/multiline_diag#11f8a1979834e39f4a79cc9d3a2707017b46e1fa" dependencies = [ "cairo-lang-debug", "cairo-lang-utils", @@ -287,6 +295,7 @@ dependencies = [ [[package]] name = "cairo-lang-formatter" version = "2.7.0" +source = "git+https://github.com/0xLucqs/cairo?branch=lucas/multiline_diag#11f8a1979834e39f4a79cc9d3a2707017b46e1fa" dependencies = [ "anyhow", "cairo-lang-diagnostics", @@ -306,6 +315,7 @@ dependencies = [ [[package]] name = "cairo-lang-language-server" version = "2.7.0" +source = "git+https://github.com/0xLucqs/cairo?branch=lucas/multiline_diag#11f8a1979834e39f4a79cc9d3a2707017b46e1fa" dependencies = [ "anyhow", "cairo-lang-compiler", @@ -340,6 +350,7 @@ dependencies = [ [[package]] name = "cairo-lang-lowering" version = "2.7.0" +source = "git+https://github.com/0xLucqs/cairo?branch=lucas/multiline_diag#11f8a1979834e39f4a79cc9d3a2707017b46e1fa" dependencies = [ "cairo-lang-debug", "cairo-lang-defs", @@ -362,6 +373,7 @@ dependencies = [ [[package]] name = "cairo-lang-parser" version = "2.7.0" +source = "git+https://github.com/0xLucqs/cairo?branch=lucas/multiline_diag#11f8a1979834e39f4a79cc9d3a2707017b46e1fa" dependencies = [ "cairo-lang-diagnostics", "cairo-lang-filesystem", @@ -380,6 +392,7 @@ dependencies = [ [[package]] name = "cairo-lang-plugins" version = "2.7.0" +source = "git+https://github.com/0xLucqs/cairo?branch=lucas/multiline_diag#11f8a1979834e39f4a79cc9d3a2707017b46e1fa" dependencies = [ "cairo-lang-defs", "cairo-lang-diagnostics", @@ -397,6 +410,7 @@ dependencies = [ [[package]] name = "cairo-lang-proc-macros" version = "2.7.0" +source = "git+https://github.com/0xLucqs/cairo?branch=lucas/multiline_diag#11f8a1979834e39f4a79cc9d3a2707017b46e1fa" dependencies = [ "cairo-lang-debug", "quote", @@ -406,6 +420,7 @@ dependencies = [ [[package]] name = "cairo-lang-project" version = "2.7.0" +source = "git+https://github.com/0xLucqs/cairo?branch=lucas/multiline_diag#11f8a1979834e39f4a79cc9d3a2707017b46e1fa" dependencies = [ "cairo-lang-filesystem", "cairo-lang-utils", @@ -418,6 +433,7 @@ dependencies = [ [[package]] name = "cairo-lang-semantic" version = "2.7.0" +source = "git+https://github.com/0xLucqs/cairo?branch=lucas/multiline_diag#11f8a1979834e39f4a79cc9d3a2707017b46e1fa" dependencies = [ "cairo-lang-debug", "cairo-lang-defs", @@ -442,6 +458,7 @@ dependencies = [ [[package]] name = "cairo-lang-sierra" version = "2.7.0" +source = "git+https://github.com/0xLucqs/cairo?branch=lucas/multiline_diag#11f8a1979834e39f4a79cc9d3a2707017b46e1fa" dependencies = [ "anyhow", "cairo-lang-utils", @@ -467,6 +484,7 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-ap-change" version = "2.7.0" +source = "git+https://github.com/0xLucqs/cairo?branch=lucas/multiline_diag#11f8a1979834e39f4a79cc9d3a2707017b46e1fa" dependencies = [ "cairo-lang-eq-solver", "cairo-lang-sierra", @@ -481,6 +499,7 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-gas" version = "2.7.0" +source = "git+https://github.com/0xLucqs/cairo?branch=lucas/multiline_diag#11f8a1979834e39f4a79cc9d3a2707017b46e1fa" dependencies = [ "cairo-lang-eq-solver", "cairo-lang-sierra", @@ -495,6 +514,7 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-generator" version = "2.7.0" +source = "git+https://github.com/0xLucqs/cairo?branch=lucas/multiline_diag#11f8a1979834e39f4a79cc9d3a2707017b46e1fa" dependencies = [ "cairo-lang-debug", "cairo-lang-defs", @@ -517,6 +537,7 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-to-casm" version = "2.7.0" +source = "git+https://github.com/0xLucqs/cairo?branch=lucas/multiline_diag#11f8a1979834e39f4a79cc9d3a2707017b46e1fa" dependencies = [ "assert_matches", "cairo-lang-casm", @@ -536,6 +557,7 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-type-size" version = "2.7.0" +source = "git+https://github.com/0xLucqs/cairo?branch=lucas/multiline_diag#11f8a1979834e39f4a79cc9d3a2707017b46e1fa" dependencies = [ "cairo-lang-sierra", "cairo-lang-utils", @@ -544,6 +566,7 @@ dependencies = [ [[package]] name = "cairo-lang-starknet" version = "2.7.0" +source = "git+https://github.com/0xLucqs/cairo?branch=lucas/multiline_diag#11f8a1979834e39f4a79cc9d3a2707017b46e1fa" dependencies = [ "anyhow", "cairo-lang-compiler", @@ -572,6 +595,7 @@ dependencies = [ [[package]] name = "cairo-lang-starknet-classes" version = "2.7.0" +source = "git+https://github.com/0xLucqs/cairo?branch=lucas/multiline_diag#11f8a1979834e39f4a79cc9d3a2707017b46e1fa" dependencies = [ "cairo-lang-casm", "cairo-lang-sierra", @@ -593,6 +617,7 @@ dependencies = [ [[package]] name = "cairo-lang-syntax" version = "2.7.0" +source = "git+https://github.com/0xLucqs/cairo?branch=lucas/multiline_diag#11f8a1979834e39f4a79cc9d3a2707017b46e1fa" dependencies = [ "cairo-lang-debug", "cairo-lang-filesystem", @@ -607,6 +632,7 @@ dependencies = [ [[package]] name = "cairo-lang-syntax-codegen" version = "2.7.0" +source = "git+https://github.com/0xLucqs/cairo?branch=lucas/multiline_diag#11f8a1979834e39f4a79cc9d3a2707017b46e1fa" dependencies = [ "genco", "xshell", @@ -615,6 +641,7 @@ dependencies = [ [[package]] name = "cairo-lang-test-plugin" version = "2.7.0" +source = "git+https://github.com/0xLucqs/cairo?branch=lucas/multiline_diag#11f8a1979834e39f4a79cc9d3a2707017b46e1fa" dependencies = [ "anyhow", "cairo-lang-compiler", @@ -640,6 +667,7 @@ dependencies = [ [[package]] name = "cairo-lang-test-utils" version = "2.7.0" +source = "git+https://github.com/0xLucqs/cairo?branch=lucas/multiline_diag#11f8a1979834e39f4a79cc9d3a2707017b46e1fa" dependencies = [ "cairo-lang-formatter", "cairo-lang-utils", @@ -651,6 +679,7 @@ dependencies = [ [[package]] name = "cairo-lang-utils" version = "2.7.0" +source = "git+https://github.com/0xLucqs/cairo?branch=lucas/multiline_diag#11f8a1979834e39f4a79cc9d3a2707017b46e1fa" dependencies = [ "hashbrown 0.14.5", "indexmap 2.3.0", @@ -661,6 +690,63 @@ dependencies = [ "serde", ] +[[package]] +name = "cairo-lint" +version = "0.1.0" +dependencies = [ + "cairo-lang-compiler", + "cairo-lang-defs", + "cairo-lang-diagnostics", + "cairo-lang-filesystem", + "cairo-lang-language-server", + "cairo-lang-lowering", + "cairo-lang-parser", + "cairo-lang-semantic", + "cairo-lang-syntax", + "cairo-lang-test-plugin", + "cairo-lang-utils", + "salsa", +] + +[[package]] +name = "cairo-lint-core" +version = "0.1.0" +dependencies = [ + "cairo-lang-compiler", + "cairo-lang-defs", + "cairo-lang-diagnostics", + "cairo-lang-filesystem", + "cairo-lang-language-server", + "cairo-lang-lowering", + "cairo-lang-parser", + "cairo-lang-semantic", + "cairo-lang-syntax", + "cairo-lang-test-plugin", + "cairo-lang-test-utils", + "cairo-lang-utils", + "cairo-lint-test-utils", + "ctor", + "indoc", + "paste", + "pretty_assertions", + "salsa", + "test-case", +] + +[[package]] +name = "cairo-lint-test-utils" +version = "0.1.0" +dependencies = [ + "cairo-lang-defs", + "cairo-lang-diagnostics", + "cairo-lang-filesystem", + "cairo-lang-semantic", + "cairo-lang-test-utils", + "cairo-lang-utils", + "cairo-lint-core", + "paste", +] + [[package]] name = "camino" version = "1.1.7" @@ -777,6 +863,16 @@ dependencies = [ "typenum", ] +[[package]] +name = "ctor" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f" +dependencies = [ + "quote", + "syn 2.0.72", +] + [[package]] name = "dashmap" version = "5.5.3" @@ -1544,6 +1640,12 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + [[package]] name = "path-clean" version = "1.0.1" @@ -2456,46 +2558,6 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" -[[package]] -name = "unretardify" -version = "0.1.0" -dependencies = [ - "cairo-lang-compiler", - "cairo-lang-defs", - "cairo-lang-diagnostics", - "cairo-lang-filesystem", - "cairo-lang-language-server", - "cairo-lang-lowering", - "cairo-lang-parser", - "cairo-lang-semantic", - "cairo-lang-syntax", - "cairo-lang-test-plugin", - "cairo-lang-utils", - "salsa", -] - -[[package]] -name = "unretardify-core" -version = "0.1.0" -dependencies = [ - "cairo-lang-compiler", - "cairo-lang-defs", - "cairo-lang-diagnostics", - "cairo-lang-filesystem", - "cairo-lang-language-server", - "cairo-lang-lowering", - "cairo-lang-parser", - "cairo-lang-semantic", - "cairo-lang-syntax", - "cairo-lang-test-plugin", - "cairo-lang-test-utils", - "cairo-lang-utils", - "indoc", - "pretty_assertions", - "salsa", - "test-case", -] - [[package]] name = "url" version = "2.5.2" diff --git a/Cargo.toml b/Cargo.toml index b6bf2cd0..16a57864 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,28 +1,30 @@ [workspace] resolver = "2" -members = ["crates/unretardify-cli", "crates/unretardify-core"] +members = ["crates/cairo-lint-cli", "crates/cairo-lint-core", "crates/cairo-lint-test-utils"] [workspace.package] version = "0.1.0" edition = "2021" -repository = "https://github.com/keep-starknet-strange/unretardify" +repository = "https://github.com/keep-starknet-strange/cairo-lint" license = "Apache-2.0" license-file = "LICENSE" [workspace.dependencies] -cairo-lang-compiler = { path = "../cairo/crates/cairo-lang-compiler" } -cairo-lang-parser = { path = "../cairo/crates/cairo-lang-parser" } -cairo-lang-utils = { path = "../cairo/crates/cairo-lang-utils" } -cairo-lang-semantic = { path = "../cairo/crates/cairo-lang-semantic" } -cairo-lang-filesystem = { path = "../cairo/crates/cairo-lang-filesystem" } -cairo-lang-diagnostics = { path = "../cairo/crates/cairo-lang-diagnostics" } -cairo-lang-test-plugin = { path = "../cairo/crates/cairo-lang-test-plugin" } -cairo-lang-lowering = { path = "../cairo/crates/cairo-lang-lowering" } -cairo-lang-syntax = { path = "../cairo/crates/cairo-lang-syntax" } -cairo-lang-defs = { path = "../cairo/crates/cairo-lang-defs" } -cairo-lang-test-utils = { path = "../cairo/crates/cairo-lang-test-utils" } -cairo-lang-language-server = { path = "../cairo/crates/cairo-lang-language-server" } +cairo-lang-compiler = { git = "https://github.com/0xLucqs/cairo", branch = "lucas/multiline_diag" } +cairo-lang-parser = { git = "https://github.com/0xLucqs/cairo", branch = "lucas/multiline_diag" } +cairo-lang-utils = { git = "https://github.com/0xLucqs/cairo", branch = "lucas/multiline_diag" } +cairo-lang-semantic = { git = "https://github.com/0xLucqs/cairo", branch = "lucas/multiline_diag" } +cairo-lang-filesystem = { git = "https://github.com/0xLucqs/cairo", branch = "lucas/multiline_diag" } +cairo-lang-diagnostics = { git = "https://github.com/0xLucqs/cairo", branch = "lucas/multiline_diag" } +cairo-lang-test-plugin = { git = "https://github.com/0xLucqs/cairo", branch = "lucas/multiline_diag" } +cairo-lang-lowering = { git = "https://github.com/0xLucqs/cairo", branch = "lucas/multiline_diag" } +cairo-lang-syntax = { git = "https://github.com/0xLucqs/cairo", branch = "lucas/multiline_diag" } +cairo-lang-defs = { git = "https://github.com/0xLucqs/cairo", branch = "lucas/multiline_diag" } +cairo-lang-test-utils = { git = "https://github.com/0xLucqs/cairo", branch = "lucas/multiline_diag" } +cairo-lang-language-server = { git = "https://github.com/0xLucqs/cairo", branch = "lucas/multiline_diag" } salsa = "0.16.1" indoc = "2" test-case = "3.0" pretty_assertions = "1.4.0" +ctor = "0.2.8" +paste = "1.0.15" diff --git a/README.md b/README.md new file mode 100644 index 00000000..7041a252 --- /dev/null +++ b/README.md @@ -0,0 +1,77 @@ +![](./resources/img/logo.jpg) + +
+

+ cairo-lint +
+ +[![Check Workflow Status](https://github.com/keep-starknet-strange/snos/actions/workflows/check.yml/badge.svg)](https://github.com/keep-starknet-strange/snos/actions/workflows/check.yml) +[![Telegram](https://img.shields.io/badge/telegram-cairo-lint-blue.svg?logo=telegram)](https://t.me/cairo-lint) + +[![Exploration_Team](https://img.shields.io/badge/Exploration_Team-29296E.svg?&style=for-the-badge&logo=data:image/svg%2bxml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIGlkPSJhIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxODEgMTgxIj48ZGVmcz48c3R5bGU+LmJ7ZmlsbDojZmZmO308L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iYiIgZD0iTTE3Ni43Niw4OC4xOGwtMzYtMzcuNDNjLTEuMzMtMS40OC0zLjQxLTIuMDQtNS4zMS0xLjQybC0xMC42MiwyLjk4LTEyLjk1LDMuNjNoLjc4YzUuMTQtNC41Nyw5LjktOS41NSwxNC4yNS0xNC44OSwxLjY4LTEuNjgsMS44MS0yLjcyLDAtNC4yN0w5Mi40NSwuNzZxLTEuOTQtMS4wNC00LjAxLC4xM2MtMTIuMDQsMTIuNDMtMjMuODMsMjQuNzQtMzYsMzcuNjktMS4yLDEuNDUtMS41LDMuNDQtLjc4LDUuMThsNC4yNywxNi41OGMwLDIuNzIsMS40Miw1LjU3LDIuMDcsOC4yOS00LjczLTUuNjEtOS43NC0xMC45Ny0xNS4wMi0xNi4wNi0xLjY4LTEuODEtMi41OS0xLjgxLTQuNCwwTDQuMzksODguMDVjLTEuNjgsMi4zMy0xLjgxLDIuMzMsMCw0LjUzbDM1Ljg3LDM3LjNjMS4zNiwxLjUzLDMuNSwyLjEsNS40NCwxLjQybDExLjQtMy4xMSwxMi45NS0zLjYzdi45MWMtNS4yOSw0LjE3LTEwLjIyLDguNzYtMTQuNzYsMTMuNzNxLTMuNjMsMi45OC0uNzgsNS4zMWwzMy40MSwzNC44NGMyLjIsMi4yLDIuOTgsMi4yLDUuMTgsMGwzNS40OC0zNy4xN2MxLjU5LTEuMzgsMi4xNi0zLjYsMS40Mi01LjU3LTEuNjgtNi4wOS0zLjI0LTEyLjMtNC43OS0xOC4zOS0uNzQtMi4yNy0xLjIyLTQuNjItMS40Mi02Ljk5LDQuMyw1LjkzLDkuMDcsMTEuNTIsMTQuMjUsMTYuNzEsMS42OCwxLjY4LDIuNzIsMS42OCw0LjQsMGwzNC4zMi0zNS43NHExLjU1LTEuODEsMC00LjAxWm0tNzIuMjYsMTUuMTVjLTMuMTEtLjc4LTYuMDktMS41NS05LjE5LTIuNTktMS43OC0uMzQtMy42MSwuMy00Ljc5LDEuNjhsLTEyLjk1LDEzLjg2Yy0uNzYsLjg1LTEuNDUsMS43Ni0yLjA3LDIuNzJoLS42NWMxLjMtNS4zMSwyLjcyLTEwLjYyLDQuMDEtMTUuOGwxLjY4LTYuNzNjLjg0LTIuMTgsLjE1LTQuNjUtMS42OC02LjA5bC0xMi45NS0xNC4xMmMtLjY0LS40NS0xLjE0LTEuMDgtMS40Mi0xLjgxbDE5LjA0LDUuMTgsMi41OSwuNzhjMi4wNCwuNzYsNC4zMywuMTQsNS43LTEuNTVsMTIuOTUtMTQuMzhzLjc4LTEuMDQsMS42OC0xLjE3Yy0xLjgxLDYuNi0yLjk4LDE0LjEyLTUuNDQsMjAuNDYtMS4wOCwyLjk2LS4wOCw2LjI4LDIuNDYsOC4xNiw0LjI3LDQuMTQsOC4yOSw4LjU1LDEyLjk1LDEyLjk1LDAsMCwxLjMsLjkxLDEuNDIsMi4wN2wtMTMuMzQtMy42M1oiLz48L3N2Zz4=)](https://github.com/keep-starknet-strange) + +

+
+ +A collection of lints to catch common mistakes and improve your [Cairo](https://github.com/starkware-libs/cairo) code. + +## Usage + +cairo-lint can either be used as a library or as a standalone binary. It can either just detect or fix the detected +problems. + +## Contributors + + + + + + + + + + +
0xLucqs
0xLucqs

💻
+ + + + + + +## Contributing + +**[Join the telegram group](t.me/cairo-lint)** + +To run the tests you'll need to provide the path to the cairo corelib (at some point this should be automated but we're +not there yet). + +```sh +CORELIB_PATH="/path/to/corelibe" cargo test +``` + +Each lint should have its own tests and should be extensive. To create a new test for a lint you need to create a file +in the [test_files folder](./crates/cairo-lint-core/tests/test_files/) and should be named as your lint. The file +should have this format: + +```txt +//! > Test name + +//! > cairo_code +fn main() { + let a: Option = Option::Some(1); +} +``` + +Then in the [test file](crates/cairo-lint-core/tests/tests.rs) declare your lint like so: + +```rs +test_file!(if_let, "Test name"); +``` + +The first argument is the lint name (also the file name) and the other ones are the test names. After that you can run + +``` +FIX_TESTS=1 cargo test -p cairo-lint-core +``` + +This will generate the expected values in your test file. Make sure it is correct. diff --git a/crates/unretardify-cli/Cargo.toml b/crates/cairo-lint-cli/Cargo.toml similarity index 96% rename from crates/unretardify-cli/Cargo.toml rename to crates/cairo-lint-cli/Cargo.toml index e5618379..b2acb5e4 100644 --- a/crates/unretardify-cli/Cargo.toml +++ b/crates/cairo-lint-cli/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "unretardify" +name = "cairo-lint" version.workspace = true edition.workspace = true repository.workspace = true diff --git a/crates/unretardify-cli/src/main.rs b/crates/cairo-lint-cli/src/main.rs similarity index 100% rename from crates/unretardify-cli/src/main.rs rename to crates/cairo-lint-cli/src/main.rs diff --git a/crates/unretardify-core/Cargo.toml b/crates/cairo-lint-core/Cargo.toml similarity index 84% rename from crates/unretardify-core/Cargo.toml rename to crates/cairo-lint-core/Cargo.toml index c4b2542d..e922c2d5 100644 --- a/crates/unretardify-core/Cargo.toml +++ b/crates/cairo-lint-core/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "unretardify-core" +name = "cairo-lint-core" version.workspace = true edition.workspace = true repository.workspace = true @@ -25,3 +25,6 @@ indoc.workspace = true cairo-lang-test-utils.workspace = true test-case.workspace = true pretty_assertions.workspace = true +ctor.workspace = true +cairo-lint-test-utils = { path = "../cairo-lint-test-utils" } +paste.workspace = true diff --git a/crates/unretardify-core/src/db.rs b/crates/cairo-lint-core/src/db.rs similarity index 97% rename from crates/unretardify-core/src/db.rs rename to crates/cairo-lint-core/src/db.rs index eff7cb64..b82a8ab0 100644 --- a/crates/unretardify-core/src/db.rs +++ b/crates/cairo-lint-core/src/db.rs @@ -11,7 +11,7 @@ use cairo_lang_syntax::node::db::{SyntaxDatabase, SyntaxGroup}; use cairo_lang_test_plugin::test_plugin_suite; use cairo_lang_utils::Upcast; -use crate::plugin::unretardify_plugin_suite; +use crate::plugin::cairo_lint_plugin_suite; /// The Cairo compiler Salsa database tailored for language server usage. #[salsa::database(DefsDatabase, FilesDatabase, LoweringDatabase, ParserDatabase, SemanticDatabase, SyntaxDatabase)] @@ -22,7 +22,7 @@ impl AnalysisDatabase { pub fn new() -> Self { let mut db = Self { storage: Default::default() }; - let plugin_suite = [get_default_plugin_suite(), test_plugin_suite(), unretardify_plugin_suite()] + let plugin_suite = [get_default_plugin_suite(), test_plugin_suite(), cairo_lint_plugin_suite()] .into_iter() .fold(PluginSuite::default(), |mut acc, suite| { acc.add(suite); diff --git a/crates/cairo-lint-core/src/fix.rs b/crates/cairo-lint-core/src/fix.rs new file mode 100644 index 00000000..b3970fab --- /dev/null +++ b/crates/cairo-lint-core/src/fix.rs @@ -0,0 +1,67 @@ +use cairo_lang_defs::plugin::PluginDiagnostic; +use cairo_lang_filesystem::span::TextSpan; +use cairo_lang_semantic::diagnostic::SemanticDiagnosticKind; +use cairo_lang_semantic::SemanticDiagnostic; +use cairo_lang_syntax::node::ast::{ExprMatch, Pattern}; +use cairo_lang_syntax::node::db::SyntaxGroup; +use cairo_lang_syntax::node::{SyntaxNode, TypedSyntaxNode}; +use cairo_lang_utils::Upcast; + +use crate::db::AnalysisDatabase; +use crate::plugin::{diagnostic_kind_from_message, RetardationKind}; + +#[derive(Default)] +pub struct Fix { + pub span: TextSpan, + pub suggestion: String, +} + +pub fn fix_semantic_diagnostic(db: &AnalysisDatabase, diag: &SemanticDiagnostic) -> String { + match diag.kind { + SemanticDiagnosticKind::UnusedVariable => { + format!("_{}", diag.stable_location.syntax_node(db.upcast()).get_text(db.upcast())) + } + SemanticDiagnosticKind::PluginDiagnostic(ref diag) => Fixer.fix_plugin_diagnostic(db, diag), + _ => "".to_owned(), + } +} + +#[derive(Default)] +pub struct Fixer; +impl Fixer { + pub fn fix_if_let(&self, db: &dyn SyntaxGroup, node: SyntaxNode) -> String { + let match_expr = ExprMatch::from_syntax_node(db, node.clone()); + let arms = match_expr.arms(db).elements(db); + let first_arm = &arms[0]; + let second_arm = &arms[1]; + let (pattern, first_expr) = + match (&first_arm.patterns(db).elements(db)[0], &second_arm.patterns(db).elements(db)[0]) { + (Pattern::Underscore(_), Pattern::Enum(pat)) => { + (&pat.as_syntax_node().get_text_without_trivia(db), second_arm) + } + (Pattern::Enum(pat), Pattern::Underscore(_)) => { + (&pat.as_syntax_node().get_text_without_trivia(db), first_arm) + } + (Pattern::Underscore(_), Pattern::Struct(pat)) => { + (&pat.as_syntax_node().get_text_without_trivia(db), second_arm) + } + (Pattern::Struct(pat), Pattern::Underscore(_)) => { + (&pat.as_syntax_node().get_text_without_trivia(db), first_arm) + } + (_, _) => panic!("Incorrect diagnostic"), + }; + format!( + "{}if let {} = {} {{ {} }}", + node.get_text(db).chars().take_while(|c| c.is_whitespace()).collect::(), + pattern, + match_expr.expr(db).as_syntax_node().get_text(db), + first_expr.expression(db).as_syntax_node().get_text_without_trivia(db), + ) + } + pub fn fix_plugin_diagnostic(&self, db: &AnalysisDatabase, diag: &PluginDiagnostic) -> String { + match diagnostic_kind_from_message(&diag.message) { + RetardationKind::IfLet => self.fix_if_let(db, diag.stable_ptr.lookup(db.upcast())), + _ => "".to_owned(), + } + } +} diff --git a/crates/unretardify-core/src/lib.rs b/crates/cairo-lint-core/src/lib.rs similarity index 100% rename from crates/unretardify-core/src/lib.rs rename to crates/cairo-lint-core/src/lib.rs diff --git a/crates/cairo-lint-core/src/plugin.rs b/crates/cairo-lint-core/src/plugin.rs new file mode 100644 index 00000000..b17557cd --- /dev/null +++ b/crates/cairo-lint-core/src/plugin.rs @@ -0,0 +1,130 @@ +use std::ops::Deref; + +use cairo_lang_defs::ids::{ModuleId, ModuleItemId}; +use cairo_lang_defs::plugin::PluginDiagnostic; +use cairo_lang_diagnostics::Severity; +use cairo_lang_semantic::db::SemanticGroup; +use cairo_lang_semantic::plugin::{AnalyzerPlugin, PluginSuite}; +use cairo_lang_syntax::node::ast::{Expr, ExprMatch, Pattern, Statement}; +use cairo_lang_syntax::node::db::SyntaxGroup; +use cairo_lang_syntax::node::kind::SyntaxKind; +use cairo_lang_syntax::node::{TypedStablePtr, TypedSyntaxNode}; + +pub fn cairo_lint_plugin_suite() -> PluginSuite { + let mut suite = PluginSuite::default(); + suite.add_analyzer_plugin::(); + suite +} +#[derive(Debug, Default)] +pub struct IsRetarded; + +#[derive(Debug, PartialEq)] +pub enum RetardationKind { + IfLet, + If, + Unknown, +} + +pub fn diagnostic_kind_from_message(message: &str) -> RetardationKind { + match message { + IsRetarded::IF_LET => RetardationKind::IfLet, + IsRetarded::IF => RetardationKind::If, + _ => RetardationKind::Unknown, + } +} + +impl IsRetarded { + const IF_LET: &'static str = + "you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`"; + const IF: &'static str = "you seem to be trying to use `match` for an equality check. Consider using `if`"; + + pub fn check_match(&self, db: &dyn SyntaxGroup, match_expr: &ExprMatch, diagnostics: &mut Vec) { + let arms = match_expr.arms(db).deref().elements(db); + let mut is_single_armed = false; + let mut is_destructuring = false; + if arms.len() == 2 { + for arm in arms { + let patterns = arm.patterns(db).elements(db); + match patterns[0].clone() { + Pattern::Underscore(_) => { + let tuple_expr = match arm.expression(db) { + Expr::Block(block_expr) => { + let statements = block_expr.statements(db).elements(db); + if statements.len() == 1 { + match &statements[0] { + Statement::Expr(statement_expr) => { + if let Expr::Tuple(tuple_expr) = statement_expr.expr(db) { + Some(tuple_expr) + } else { + None + } + } + _ => None, + } + } else { + None + } + } + Expr::Tuple(tuple_expr) => Some(tuple_expr), + _ => None, + }; + is_single_armed = tuple_expr.is_some_and(|list| list.expressions(db).elements(db).is_empty()); + } + + Pattern::Enum(pat) => { + is_destructuring = !pat.pattern(db).as_syntax_node().get_text(db).is_empty(); + } + Pattern::Struct(pat) => { + is_destructuring = !pat.as_syntax_node().get_text(db).is_empty(); + } + _ => (), + }; + } + }; + match (is_single_armed, is_destructuring) { + (true, false) => diagnostics.push(PluginDiagnostic { + stable_ptr: match_expr.stable_ptr().untyped(), + message: Self::IF.to_string(), + severity: Severity::Warning, + }), + (true, true) => diagnostics.push(PluginDiagnostic { + stable_ptr: match_expr.stable_ptr().untyped(), + message: Self::IF_LET.to_string(), + severity: Severity::Warning, + }), + (_, _) => (), + } + } +} + +impl AnalyzerPlugin for IsRetarded { + fn diagnostics(&self, db: &dyn SemanticGroup, module_id: ModuleId) -> Vec { + let mut diags = Vec::new(); + let Ok(items) = db.module_items(module_id) else { + return diags; + }; + for item in items.iter() { + match item { + ModuleItemId::FreeFunction(func_id) => { + // + let func = db.module_free_function_by_id(*func_id).unwrap().unwrap(); + let descendants = func.as_syntax_node().descendants(db.upcast()); + for descendant in descendants.into_iter() { + match descendant.kind(db.upcast()) { + SyntaxKind::ExprMatch => self.check_match( + db.upcast(), + &ExprMatch::from_syntax_node(db.upcast(), descendant), + &mut diags, + ), + SyntaxKind::ItemExternFunction => (), + _ => (), + } + } + } + ModuleItemId::ExternFunction(_) => (), + _ => (), + } + } + diags + } +} diff --git a/crates/cairo-lint-core/tests/test_files/if_let b/crates/cairo-lint-core/tests/test_files/if_let new file mode 100644 index 00000000..792f4480 --- /dev/null +++ b/crates/cairo-lint-core/tests/test_files/if_let @@ -0,0 +1,53 @@ +//! > simple if let + +//! > cairo_code +fn main() { + let variable = Option::Some(1_felt252); + match variable { + Option::Some(a) => println!("{a}"), + _ => (), + }; +} + +//! > diagnostics +warning: Plugin diagnostic: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` + --> lib.cairo:3:2 +\ match variable { +| Option::Some(a) => println!("{a}"), +| _ => (), +| } +|___^ + +//! > fixed +fn main() { + let variable = Option::Some(1_felt252); + if let Option::Some(a) = variable { println!("{a}") }; +} + +//! > ========================================================================== + +//! > simple if let with scope + +//! > cairo_code +fn main() { + let variable = Option::Some(1_felt252); + match variable { + Option::Some(a) => println!("{a}"), + _ => { () }, + }; +} + +//! > diagnostics +warning: Plugin diagnostic: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` + --> lib.cairo:3:2 +\ match variable { +| Option::Some(a) => println!("{a}"), +| _ => { () }, +| } +|___^ + +//! > fixed +fn main() { + let variable = Option::Some(1_felt252); + if let Option::Some(a) = variable { println!("{a}") }; +} diff --git a/crates/unretardify-core/tests/test_files/unused_variables b/crates/cairo-lint-core/tests/test_files/unused_variables similarity index 57% rename from crates/unretardify-core/tests/test_files/unused_variables rename to crates/cairo-lint-core/tests/test_files/unused_variables index 3385259e..bd801c6c 100644 --- a/crates/unretardify-core/tests/test_files/unused_variables +++ b/crates/cairo-lint-core/tests/test_files/unused_variables @@ -3,8 +3,6 @@ //! > cairo_code fn main() { let a: Option = Option::Some(1); - let b = 2; - let c = 2; } //! > diagnostics @@ -13,19 +11,34 @@ warning[E0001]: Unused variable. Consider ignoring by prefixing with `_`. let a: Option = Option::Some(1); ^ +//! > fixed +fn main() { + let _a: Option = Option::Some(1); +} + +//! > ========================================================================== + +//! > two unused variable + +//! > cairo_code +fn main() { + let a: Option = Option::Some(1); + let b = 1; +} + +//! > diagnostics warning[E0001]: Unused variable. Consider ignoring by prefixing with `_`. - --> lib.cairo:3:9 - let b = 2; + --> lib.cairo:2:9 + let a: Option = Option::Some(1); ^ warning[E0001]: Unused variable. Consider ignoring by prefixing with `_`. - --> lib.cairo:4:9 - let c = 2; + --> lib.cairo:3:9 + let b = 1; ^ //! > fixed fn main() { let _a: Option = Option::Some(1); - let _b = 2; - let _c = 2; + let _b = 1; } diff --git a/crates/cairo-lint-core/tests/tests.rs b/crates/cairo-lint-core/tests/tests.rs new file mode 100644 index 00000000..6ddde794 --- /dev/null +++ b/crates/cairo-lint-core/tests/tests.rs @@ -0,0 +1,19 @@ +use std::cmp::Reverse; +use std::path::Path; +use std::sync::{LazyLock, Mutex}; + +use cairo_lang_semantic::test_utils::setup_test_crate; +use cairo_lang_test_utils::parse_test_file::{dump_to_test_file, parse_test_file, Test}; +use cairo_lang_utils::ordered_hash_map::OrderedHashMap; +use cairo_lang_utils::Upcast; +use cairo_lint_core::db::AnalysisDatabase; +use cairo_lint_core::fix::{fix_semantic_diagnostic, Fix}; +use cairo_lint_test_utils::{get_diags, test_file, Tests}; +use ctor::dtor; +use paste::paste; +use pretty_assertions::assert_eq; +use test_case::test_case; + +test_file!(unused_variables, "one unused variable", "two unused variable"); + +test_file!(if_let, "simple if let", "simple if let with scope"); diff --git a/crates/cairo-lint-core/tests/utils.rs b/crates/cairo-lint-core/tests/utils.rs new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/crates/cairo-lint-core/tests/utils.rs @@ -0,0 +1 @@ + diff --git a/crates/cairo-lint-test-utils/Cargo.toml b/crates/cairo-lint-test-utils/Cargo.toml new file mode 100644 index 00000000..0344cacc --- /dev/null +++ b/crates/cairo-lint-test-utils/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "cairo-lint-test-utils" +version.workspace = true +edition.workspace = true +repository.workspace = true +license.workspace = true +license-file.workspace = true + +[dependencies] +cairo-lang-utils.workspace = true +cairo-lang-test-utils.workspace = true +cairo-lang-filesystem.workspace = true +cairo-lang-diagnostics.workspace = true +cairo-lang-semantic.workspace = true +cairo-lang-defs.workspace = true +cairo-lint-core = { path = "../cairo-lint-core" } +paste.workspace = true diff --git a/crates/cairo-lint-test-utils/src/lib.rs b/crates/cairo-lint-test-utils/src/lib.rs new file mode 100644 index 00000000..856f5884 --- /dev/null +++ b/crates/cairo-lint-test-utils/src/lib.rs @@ -0,0 +1,91 @@ +use std::path::PathBuf; + +use cairo_lang_defs::db::DefsGroup; +use cairo_lang_defs::ids::ModuleId; +use cairo_lang_diagnostics::Diagnostics; +use cairo_lang_filesystem::db::{init_dev_corelib, FilesGroup}; +use cairo_lang_filesystem::ids::{CrateId, FileLongId}; +use cairo_lang_semantic::db::SemanticGroup; +use cairo_lang_semantic::SemanticDiagnostic; +use cairo_lang_test_utils::parse_test_file::Test; +use cairo_lang_utils::ordered_hash_map::OrderedHashMap; +use cairo_lang_utils::LookupIntern; +use cairo_lint_core::db::AnalysisDatabase; + +pub struct Tests { + pub tests: OrderedHashMap, + pub should_fix: bool, +} +pub fn get_diags(crate_id: CrateId, db: &mut AnalysisDatabase) -> Vec> { + init_dev_corelib(db, PathBuf::from(std::env::var("CORELIB_PATH").unwrap())); + let mut diagnostics = Vec::new(); + let module_file = db.module_main_file(ModuleId::CrateRoot(crate_id)).unwrap(); + if db.file_content(module_file).is_none() { + match module_file.lookup_intern(db) { + FileLongId::OnDisk(_path) => {} + FileLongId::Virtual(_) => panic!("Missing virtual file."), + } + } + + for module_id in &*db.crate_modules(crate_id) { + diagnostics.push(db.module_semantic_diagnostics(*module_id).unwrap()); + } + diagnostics +} +#[macro_export] +macro_rules! test_file { + ($file_path:ident, $($test_name:expr),*) => { + + paste ! { + + const []: &str = concat!("tests/test_files/", stringify!($file_path)); + static []: LazyLock> = + LazyLock::new(|| parse_test_file(Path::new([])).unwrap()); + static []: LazyLock> = + LazyLock::new(|| Mutex::new(Tests { tests: OrderedHashMap::default(), should_fix: false })); + + + #[dtor] + fn []() { + let val = [].lock().unwrap(); + if val.should_fix { + dump_to_test_file(val.tests.clone(), []).unwrap(); + } + } + + $(#[test_case($test_name; $test_name)])* + fn $file_path(test_name: &str) { + let test = & [][test_name]; + let is_fix_mode = std::env::var("FIX_TESTS") == Ok("1".into()); + let mut file = test.attributes["cairo_code"].clone(); + let mut db = AnalysisDatabase::new(); + let mut fixes = Vec::new(); + + let diags = get_diags(setup_test_crate(db.upcast(), &file), &mut db); + for diag in diags.iter().flat_map(|diags| diags.get_all()) { + let fix = fix_semantic_diagnostic(&db, &diag); + if !fix.is_empty() { + let span = diag.stable_location.syntax_node(db.upcast()).span(db.upcast()); + fixes.push(Fix { span, suggestion: fix }); + } + } + fixes.sort_by_key(|v| Reverse(v.span.start)); + for fix in fixes.iter() { + file.replace_range(fix.span.to_str_range(), &fix.suggestion); + } + let formatted_diags = + diags.into_iter().map(|diag| diag.format(db.upcast())).collect::().trim().to_string(); + if is_fix_mode { + let mut new_test = test.clone(); + new_test.attributes.insert("diagnostics".to_string(), formatted_diags.clone()); + new_test.attributes.insert("fixed".to_string(), file.clone()); + let mut new_tests = [].lock().unwrap(); + new_tests.should_fix = true; + new_tests.tests.insert(test_name.to_string(), new_test); + } + assert_eq!(formatted_diags, test.attributes["diagnostics"]); + assert_eq!(file, test.attributes["fixed"]); + } + } + }; +} diff --git a/crates/unretardify-core/src/fix.rs b/crates/unretardify-core/src/fix.rs deleted file mode 100644 index cca5f010..00000000 --- a/crates/unretardify-core/src/fix.rs +++ /dev/null @@ -1,22 +0,0 @@ -use cairo_lang_semantic::diagnostic::SemanticDiagnosticKind; -use cairo_lang_semantic::SemanticDiagnostic; -use cairo_lang_utils::Upcast; - -use crate::db::AnalysisDatabase; - -#[derive(Default)] -pub struct Fix { - pub start: u32, - pub end: u32, - pub suggestion: String, -} -pub fn fix_semantic_diagnostic(db: &AnalysisDatabase, diag: &SemanticDiagnostic) -> String { - // diag.stable_location.syntax_node(db.upcast()).green_node(db.upcast()).details - match diag.kind { - SemanticDiagnosticKind::UnusedVariable => { - format!("_{}", diag.stable_location.syntax_node(db.upcast()).get_text(db.upcast())) - } - - _ => "".to_owned(), - } -} diff --git a/crates/unretardify-core/src/plugin.rs b/crates/unretardify-core/src/plugin.rs deleted file mode 100644 index d5d33b91..00000000 --- a/crates/unretardify-core/src/plugin.rs +++ /dev/null @@ -1,85 +0,0 @@ -use std::ops::Deref; - -use cairo_lang_defs::ids::{ModuleId, ModuleItemId}; -use cairo_lang_defs::plugin::PluginDiagnostic; -use cairo_lang_semantic::db::SemanticGroup; -use cairo_lang_semantic::plugin::{AnalyzerPlugin, PluginSuite}; -use cairo_lang_syntax::node::ast::{ExprMatch, Pattern}; -use cairo_lang_syntax::node::db::SyntaxGroup; -use cairo_lang_syntax::node::kind::SyntaxKind; -use cairo_lang_syntax::node::{TypedStablePtr, TypedSyntaxNode}; - -pub fn unretardify_plugin_suite() -> PluginSuite { - let mut suite = PluginSuite::default(); - suite.add_analyzer_plugin::(); - suite -} -#[derive(Debug, Default)] -pub struct IsRetarded; - -impl IsRetarded { - pub fn check_match(&self, db: &dyn SyntaxGroup, match_expr: &ExprMatch, diagnostics: &mut Vec) { - let arms = match_expr.arms(db).deref().elements(db); - let mut is_single_armed = false; - let mut is_destructuring = false; - if arms.len() == 2 { - for arm in arms { - let patterns = arm.patterns(db).elements(db); - if let Pattern::Underscore(_term_underscore) = patterns[0].clone() { - is_single_armed = true; - } else if let Pattern::Enum(pat) = patterns[0].clone() { - is_destructuring = !pat.pattern(db).as_syntax_node().get_text(db).is_empty(); - } else { - println!("Patterns: {:?}", patterns); - } - } - }; - match (is_single_armed, is_destructuring) { - (true, false) => diagnostics.push(PluginDiagnostic { - stable_ptr: match_expr.stable_ptr().untyped(), - message: "you seem to be trying to use `match` for an equality check. Consider using `if`".to_string(), - severity: cairo_lang_diagnostics::Severity::Warning, - }), - (true, true) => diagnostics.push(PluginDiagnostic { - stable_ptr: match_expr.stable_ptr().untyped(), - message: "you seem to be trying to use `match` for destructuring a single pattern. Consider using `if \ - let`" - .to_string(), - severity: cairo_lang_diagnostics::Severity::Warning, - }), - (_, _) => (), - } - } -} - -impl AnalyzerPlugin for IsRetarded { - fn diagnostics(&self, db: &dyn SemanticGroup, module_id: ModuleId) -> Vec { - let mut diags = Vec::new(); - let Ok(items) = db.module_items(module_id) else { - return diags; - }; - for item in items.iter() { - match item { - ModuleItemId::FreeFunction(func_id) => { - // - let func = db.module_free_function_by_id(*func_id).unwrap().unwrap(); - let descendants = func.as_syntax_node().descendants(db.upcast()); - for descendant in descendants.into_iter() { - match descendant.kind(db.upcast()) { - SyntaxKind::ExprMatch => self.check_match( - db.upcast(), - &ExprMatch::from_syntax_node(db.upcast(), descendant), - &mut diags, - ), - SyntaxKind::ItemExternFunction => (), - _ => (), - } - } - } - ModuleItemId::ExternFunction(_) => (), - _ => (), - } - } - diags - } -} diff --git a/crates/unretardify-core/tests/unused_variables.rs b/crates/unretardify-core/tests/unused_variables.rs deleted file mode 100644 index 65d0252d..00000000 --- a/crates/unretardify-core/tests/unused_variables.rs +++ /dev/null @@ -1,74 +0,0 @@ -use std::path::{Path, PathBuf}; -use std::sync::LazyLock; - -use cairo_lang_defs::db::DefsGroup; -use cairo_lang_defs::ids::ModuleId; -use cairo_lang_diagnostics::Diagnostics; -use cairo_lang_filesystem::db::{init_dev_corelib, FilesGroup}; -use cairo_lang_filesystem::ids::{CrateId, FileLongId}; -use cairo_lang_semantic::db::SemanticGroup; -use cairo_lang_semantic::test_utils::setup_test_crate; -use cairo_lang_semantic::SemanticDiagnostic; -use cairo_lang_test_utils::parse_test_file::{dump_to_test_file, parse_test_file, Test}; -use cairo_lang_utils::ordered_hash_map::OrderedHashMap; -use cairo_lang_utils::{LookupIntern, Upcast}; -use pretty_assertions::assert_eq; -use test_case::test_case; -use unretardify_core::db::AnalysisDatabase; -use unretardify_core::fix::{fix_semantic_diagnostic, Fix}; - -const TEST_FILENAME: &str = "tests/unused_variables/unused_variables"; -static PARSED_TEST_FILE: LazyLock> = - LazyLock::new(|| parse_test_file(Path::new(TEST_FILENAME)).unwrap()); - -fn get_diags(crate_id: CrateId, db: &mut AnalysisDatabase) -> Vec> { - init_dev_corelib(db, PathBuf::from("/Users/lucas/cairo/corelib/src")); - let mut diagnostics = Vec::new(); - let module_file = db.module_main_file(ModuleId::CrateRoot(crate_id)).unwrap(); - if db.file_content(module_file).is_none() { - match module_file.lookup_intern(db) { - FileLongId::OnDisk(_path) => {} - FileLongId::Virtual(_) => panic!("Missing virtual file."), - } - } - - for module_id in &*db.crate_modules(crate_id) { - diagnostics.push(db.module_semantic_diagnostics(*module_id).unwrap()); - } - diagnostics -} - -#[test_case("one unused variable"; "1 unused variable")] -fn test_unused_variable(test_name: &str) { - let test = &PARSED_TEST_FILE[test_name]; - let is_fix_mode = std::env::var("FIX_TESTS") == Ok("1".into()); - let mut file = test.attributes["cairo_code"].clone(); - let mut db = AnalysisDatabase::new(); - let mut fixes = Vec::new(); - - let diags = get_diags(setup_test_crate(db.upcast(), &file), &mut db); - for diag in diags.iter().flat_map(|diags| diags.get_all()) { - let fix = fix_semantic_diagnostic(&db, &diag); - if !fix.is_empty() { - let span = diag.stable_location.syntax_node(db.upcast()).span(db.upcast()); - fixes.push(Fix { start: span.start.to_u32(), end: span.end.to_u32(), suggestion: fix }); - } - } - let mut offset = 0; - fixes.sort_by_key(|v| v.start); - for fix in fixes.iter() { - file.replace_range(offset + fix.start as usize..offset + fix.end as usize, &fix.suggestion); - offset += fix.suggestion.len() - (fix.end - fix.start) as usize; - } - let formatted_diags = diags.into_iter().map(|diag| diag.format(db.upcast())).collect::().trim().to_string(); - if is_fix_mode { - let mut new_test = test.clone(); - new_test.attributes.insert("diagnostics".to_string(), formatted_diags.clone()); - new_test.attributes.insert("fixed".to_string(), file.clone()); - let mut new_tests = PARSED_TEST_FILE.clone(); - new_tests.insert(test_name.to_string(), new_test); - dump_to_test_file(new_tests, TEST_FILENAME).unwrap(); - } - assert_eq!(formatted_diags, test.attributes["diagnostics"]); - assert_eq!(file, test.attributes["fixed"]); -} diff --git a/resources/img/logo.jpg b/resources/img/logo.jpg new file mode 100644 index 00000000..71d20561 Binary files /dev/null and b/resources/img/logo.jpg differ