Compare commits

..

33 Commits

Author SHA1 Message Date
Shunsuke Shibayama b7e78b310c Update README.md 2025-05-10 11:10:28 +09:00
Shunsuke Shibayama 83bd0ffc61 build: update version (v0.0.82) 2025-02-25 17:36:36 +09:00
Loïc Riegel f0a44bf272
Fix: checking multiple files (#126)
* fix: remove duplicates when checking multiple files

* fix: exit 1 when providing invalid file or patterns

* wip

* keep order of insertion, and works with options or flags in the middle

* alphabetical order

* remove useless type annotation

* return IndexSet directly instead of Vec

* remove .clone()
2025-02-24 17:24:27 +09:00
Shunsuke Shibayama 7871d31c93 build: update version (v0.0.81) 2025-02-22 17:56:59 +09:00
Shunsuke Shibayama 7248c00448 feat: attrs can be registered in methods other than `__init__` 2025-02-22 10:56:21 +09:00
Shunsuke Shibayama 5fb0c71a63 fix: `List` type bug 2025-02-21 21:22:13 +09:00
Shunsuke Shibayama fd4b5895f3 feat: multiple files & glob input 2025-02-21 13:24:07 +09:00
Shunsuke Shibayama 71f5da0963 build: update version (v0.0.80) 2025-02-19 01:29:57 +09:00
Shunsuke Shibayama 3003076cef Update convert.rs 2025-02-19 00:11:07 +09:00
Shunsuke Shibayama f653c3fe16 feat: add `--do-not-respect-pyi` option
With this change, by default `.pyi` file types will be respected and `.py` files will not be parsed.
2025-02-18 22:29:34 +09:00
Shunsuke Shibayama 8b9437ef7a feat: deep completion can be disabled 2025-02-09 12:41:25 +09:00
Shunsuke Shibayama b9b757d896 build: update version (v0.0.79) 2025-02-09 11:59:04 +09:00
Shunsuke Shibayama 5882f18c46 Update bug-report.yaml 2025-02-09 01:35:27 +09:00
Shunsuke Shibayama 001183db79 fix: minor bugs 2025-02-08 17:04:56 +09:00
Shunsuke Shibayama acd50996ae chore: bug_report.md -> bug_report.yaml 2025-02-06 19:14:54 +09:00
Shunsuke Shibayama 640f654b1f build: update version (v0.0.78) 2025-01-29 17:45:21 +09:00
Shunsuke Shibayama 4caac7c325 build: update deps 2025-01-29 17:37:49 +09:00
Shunsuke Shibayama 814c46996d fix: decl file generator panics 2025-01-22 02:45:16 +09:00
Shunsuke Shibayama b52b017c37 fix: decl file generation bug 2025-01-19 15:22:38 +09:00
Shunsuke Shibayama 1aa3f53d5d build: update version (v0.0.77) 2025-01-17 16:22:05 +09:00
Shunsuke Shibayama 50c7b7a252 fix: clippy warns 2025-01-17 02:58:25 +09:00
Shunsuke Shibayama 1083e2f140 fix: collection bugs 2025-01-05 00:38:40 +09:00
Shunsuke Shibayama dedfa8443b feat: support `@property` 2025-01-01 20:56:40 +09:00
Shunsuke Shibayama accd453a12 build: update version (v0.0.76) 2024-12-29 14:17:58 +09:00
Shunsuke Shibayama 9cd1846216 fix: type inference bugs 2024-12-29 14:06:12 +09:00
Shunsuke Shibayama faec281fa9 fix: type specification parsing bugs 2024-12-28 18:43:07 +09:00
Shunsuke Shibayama 0da66dceca fix: slice bug 2024-12-27 20:21:05 +09:00
Shunsuke Shibayama deb6736f9f feat: support named-expr (walrus operator) 2024-12-27 20:09:50 +09:00
Shunsuke Shibayama 2a98535d4c feat: ABC implementation check 2024-12-27 15:46:59 +09:00
Shunsuke Shibayama 233b7ee382 build: update version (v0.0.75) 2024-12-25 02:59:00 +09:00
Shunsuke Shibayama c985e798f0 build: update deps 2024-12-25 02:52:25 +09:00
Shunsuke Shibayama 088c22a84c fix: cache clearing 2024-12-25 02:44:57 +09:00
Shunsuke Shibayama 18386546b4 Update README.md 2024-12-18 09:34:53 +09:00
36 changed files with 1524 additions and 577 deletions

53
.github/ISSUE_TEMPLATE/bug-report.yaml vendored Normal file
View File

@ -0,0 +1,53 @@
name: Bug report
description: Create a report to help us improve
labels:
- bug
body:
- type: textarea
attributes:
label: "Describe the bug"
description: "A clear and concise description of what the bug is."
placeholder: "Enter a detailed description of the bug"
validations:
required: true
- type: textarea
attributes:
label: "Reproducible Code"
description: "Provide code or steps needed to reproduce the bug."
placeholder: "Enter code snippet or reproduction steps"
validations:
required: true
- type: textarea
attributes:
label: "Environment"
description: "Provide details such as OS, version, etc."
placeholder: "OS: \nVersion: "
validations:
required: true
- type: textarea
attributes:
label: "Expected behavior"
description: "A clear and concise description of what you expected to happen."
placeholder: "Enter what you expected to happen"
validations:
required: false
- type: textarea
attributes:
label: "Error log"
description: "Add error logs here. Language server errors may be logged in $ERG_PATH/els.log."
validations:
required: false
- type: textarea
attributes:
label: "Screenshots"
description: "Add screenshots to help explain your problem."
placeholder: "Provide screenshot links or instructions to attach images"
validations:
required: false
- type: textarea
attributes:
label: "Additional context"
description: "Add any other context about the problem here."
placeholder: "Enter any additional context"
validations:
required: false

View File

@ -1,26 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**Reproducible Code**
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Environment**
- OS
- Version
**Additional context**
Add any other context about the problem here.

2
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@ -0,0 +1,2 @@
# This file cannot use the extension `.yaml`.
blank_issues_enabled: false

View File

@ -0,0 +1,19 @@
name: Feature request
description: Suggest an idea for this project
labels:
- enhancement
body:
- type: textarea
attributes:
label: "Describe the feature"
description: "A clear and concise description of what the feature is."
placeholder: "Enter a detailed description of the feature"
validations:
required: true
- type: textarea
attributes:
label: "Additional context"
description: "Add any other context about the feature here."
placeholder: "Enter any additional context"
validations:
required: false

22
.github/workflows/stale-issues.yml vendored Normal file
View File

@ -0,0 +1,22 @@
name: Close inactive issues
on:
schedule:
- cron: "30 1 * * *"
jobs:
close-issues:
runs-on: ubuntu-latest
permissions:
issues: write
steps:
- uses: actions/stale@v9
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: "This issue is stale because it has been open for 60 days with no activity."
close-issue-message: "This issue was closed because it has been inactive for 14 days since being marked as stale."
stale-issue-label: "stale"
exempt-issue-labels: "bug"
days-before-issue-stale: 60
days-before-issue-close: 14
days-before-pr-stale: -1
days-before-pr-close: -1

View File

@ -6,5 +6,8 @@
"[typescript]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "biomejs.biome"
}
},
"cSpell.words": [
"indexmap"
]
}

291
Cargo.lock generated
View File

@ -31,9 +31,9 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.94"
version = "1.0.96"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7"
checksum = "6b964d184e89d9b6b67dd2715bc8e74cf3107fb2b529990c90cf517326150bf4"
[[package]]
name = "autocfg"
@ -75,15 +75,15 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.6.0"
version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
[[package]]
name = "bumpalo"
version = "3.16.0"
version = "3.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
[[package]]
name = "byteorder"
@ -93,9 +93,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cc"
version = "1.2.4"
version = "1.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9157bbaa6b165880c27a4293a474c91cdcf265cc68cc829bf10be0964a391caf"
checksum = "c736e259eea577f443d5c86c304f9f4ae0295c43f3ba05c21f1d66b5f06001af"
dependencies = [
"shlex",
]
@ -106,29 +106,31 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "convert_case"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
[[package]]
name = "crunchy"
version = "0.2.2"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929"
[[package]]
name = "derive_more"
version = "0.99.18"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce"
checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05"
dependencies = [
"derive_more-impl",
]
[[package]]
name = "derive_more-impl"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22"
dependencies = [
"convert_case",
"proc-macro2",
"quote",
"rustc_version",
"syn 2.0.90",
"syn 2.0.98",
"unicode-xid",
]
[[package]]
@ -139,7 +141,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.90",
"syn 2.0.98",
]
[[package]]
@ -150,9 +152,9 @@ checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]]
name = "els"
version = "0.1.61-nightly.4"
version = "0.1.65-nightly.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53be571fdd8299095d6ecf0bc34520a0defe6c43cf288362aeec29d773bafb4a"
checksum = "5cbf48dcb22f23c344ebcf751ba479ea2d770782826659d5ac0e341f6b971432"
dependencies = [
"erg_common",
"erg_compiler",
@ -165,10 +167,16 @@ dependencies = [
]
[[package]]
name = "erg_common"
version = "0.6.49-nightly.4"
name = "equivalent"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c298aa80c736a4ff3afa3e2efff169ae2dd519cdf52e18b7160e0c11cd10df3c"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "erg_common"
version = "0.6.53-nightly.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e712be33223eb2376056e5864c32290b592058c5ebdfaf27562e5196cb6ae74a"
dependencies = [
"backtrace-on-stack-overflow",
"erg_proc_macros",
@ -179,9 +187,9 @@ dependencies = [
[[package]]
name = "erg_compiler"
version = "0.6.49-nightly.4"
version = "0.6.53-nightly.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf43980c85b827230df246b9d1c47a650951968dcfd69304965ed48b3de8b795"
checksum = "84555ce7074c7c068f64393630add858d5b4d9ccd9c304f5c8274ddae291c58c"
dependencies = [
"erg_common",
"erg_parser",
@ -189,9 +197,9 @@ dependencies = [
[[package]]
name = "erg_parser"
version = "0.6.49-nightly.4"
version = "0.6.53-nightly.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec47955057f0875292358a8d693a4623be19b74d6c3a424d06ee8a7a67db0cd4"
checksum = "e28e444531ca109213845ff38f96e1717f26018ed7cc857e5c8fd4ff29bf3800"
dependencies = [
"erg_common",
"erg_proc_macros",
@ -200,9 +208,9 @@ dependencies = [
[[package]]
name = "erg_proc_macros"
version = "0.6.49-nightly.4"
version = "0.6.53-nightly.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "051d0db355682df902264ce06143ee69fd1090be4c3da0117845768c5e2d4718"
checksum = "dbe0c49c58f7bd9003582c725ce0050bcac6c3754f408e24793c0a29102de9ce"
dependencies = [
"quote",
"syn 1.0.109",
@ -243,6 +251,12 @@ version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
[[package]]
name = "glob"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
[[package]]
name = "hashbrown"
version = "0.14.5"
@ -252,6 +266,12 @@ dependencies = [
"ahash",
]
[[package]]
name = "hashbrown"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
[[package]]
name = "heck"
version = "0.5.0"
@ -373,7 +393,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.90",
"syn 2.0.98",
]
[[package]]
@ -397,6 +417,16 @@ dependencies = [
"icu_properties",
]
[[package]]
name = "indexmap"
version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652"
dependencies = [
"equivalent",
"hashbrown 0.15.2",
]
[[package]]
name = "is-macro"
version = "0.3.7"
@ -406,7 +436,7 @@ dependencies = [
"heck",
"proc-macro2",
"quote",
"syn 2.0.90",
"syn 2.0.98",
]
[[package]]
@ -432,9 +462,9 @@ checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553"
[[package]]
name = "libc"
version = "0.2.168"
version = "0.2.169"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d"
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
[[package]]
name = "libm"
@ -460,9 +490,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.22"
version = "0.4.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e"
[[package]]
name = "lsp-types"
@ -479,9 +509,9 @@ dependencies = [
[[package]]
name = "malachite"
version = "0.4.16"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5616515d632967cd329b6f6db96be9a03ea0b3a49cdbc45b0016803dad8a77b7"
checksum = "2fbdf9cb251732db30a7200ebb6ae5d22fe8e11397364416617d2c2cf0c51cb5"
dependencies = [
"malachite-base",
"malachite-nz",
@ -490,11 +520,11 @@ dependencies = [
[[package]]
name = "malachite-base"
version = "0.4.16"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46059721011b0458b7bd6d9179be5d0b60294281c23320c207adceaecc54d13b"
checksum = "5ea0ed76adf7defc1a92240b5c36d5368cfe9251640dcce5bd2d0b7c1fd87aeb"
dependencies = [
"hashbrown",
"hashbrown 0.14.5",
"itertools",
"libm",
"ryu",
@ -502,9 +532,9 @@ dependencies = [
[[package]]
name = "malachite-bigint"
version = "0.2.0"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17703a19c80bbdd0b7919f0f104f3b0597f7de4fc4e90a477c15366a5ba03faa"
checksum = "d149aaa2965d70381709d9df4c7ee1fc0de1c614a4efc2ee356f5e43d68749f8"
dependencies = [
"derive_more",
"malachite",
@ -515,9 +545,9 @@ dependencies = [
[[package]]
name = "malachite-nz"
version = "0.4.16"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1503b27e825cabd1c3d0ff1e95a39fb2ec9eab6fd3da6cfa41aec7091d273e78"
checksum = "34a79feebb2bc9aa7762047c8e5495269a367da6b5a90a99882a0aeeac1841f7"
dependencies = [
"itertools",
"libm",
@ -526,9 +556,9 @@ dependencies = [
[[package]]
name = "malachite-q"
version = "0.4.16"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a475503a70a3679dbe3b9b230a23622516742528ba614a7b2490f180ea9cb514"
checksum = "50f235d5747b1256b47620f5640c2a17a88c7569eebdf27cd9cb130e1a619191"
dependencies = [
"itertools",
"malachite-base",
@ -552,9 +582,9 @@ dependencies = [
[[package]]
name = "miniz_oxide"
version = "0.8.0"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1"
checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5"
dependencies = [
"adler2",
]
@ -603,18 +633,18 @@ dependencies = [
[[package]]
name = "object"
version = "0.36.5"
version = "0.36.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e"
checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
version = "1.20.2"
version = "1.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e"
[[package]]
name = "parking_lot"
@ -653,18 +683,18 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "phf"
version = "0.11.2"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078"
dependencies = [
"phf_shared",
]
[[package]]
name = "phf_codegen"
version = "0.11.2"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a"
checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a"
dependencies = [
"phf_generator",
"phf_shared",
@ -672,9 +702,9 @@ dependencies = [
[[package]]
name = "phf_generator"
version = "0.11.2"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0"
checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
dependencies = [
"phf_shared",
"rand",
@ -682,9 +712,9 @@ dependencies = [
[[package]]
name = "phf_shared"
version = "0.11.2"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b"
checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5"
dependencies = [
"siphasher",
]
@ -700,16 +730,16 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.92"
version = "1.0.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
dependencies = [
"unicode-ident",
]
[[package]]
name = "py2erg"
version = "0.0.74"
version = "0.0.82"
dependencies = [
"erg_common",
"erg_compiler",
@ -719,17 +749,19 @@ dependencies = [
[[package]]
name = "pylyzer"
version = "0.0.74"
version = "0.0.82"
dependencies = [
"els",
"erg_common",
"erg_compiler",
"glob",
"indexmap",
"pylyzer_core",
]
[[package]]
name = "pylyzer_core"
version = "0.0.74"
version = "0.0.82"
dependencies = [
"erg_common",
"erg_compiler",
@ -740,7 +772,7 @@ dependencies = [
[[package]]
name = "pylyzer_wasm"
version = "0.0.74"
version = "0.0.82"
dependencies = [
"erg_common",
"erg_compiler",
@ -750,9 +782,9 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.37"
version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
dependencies = [
"proc-macro2",
]
@ -789,11 +821,11 @@ dependencies = [
[[package]]
name = "redox_syscall"
version = "0.5.8"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834"
checksum = "82b568323e98e49e2a0899dcee453dd679fae22d69adf9b11dd508d1549b7e2f"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.8.0",
]
[[package]]
@ -808,19 +840,10 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustc_version"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
dependencies = [
"semver",
]
[[package]]
name = "rustpython-ast"
version = "0.4.0"
source = "git+https://github.com/RustPython/Parser#5e9d9853e751240b28138efd165e793a7ee5dad4"
source = "git+https://github.com/RustPython/Parser#d2f137b372ec08ce4a243564a80f8f9153c45a23"
dependencies = [
"is-macro",
"malachite-bigint",
@ -831,7 +854,7 @@ dependencies = [
[[package]]
name = "rustpython-parser"
version = "0.4.0"
source = "git+https://github.com/RustPython/Parser#5e9d9853e751240b28138efd165e793a7ee5dad4"
source = "git+https://github.com/RustPython/Parser#d2f137b372ec08ce4a243564a80f8f9153c45a23"
dependencies = [
"anyhow",
"is-macro",
@ -854,7 +877,7 @@ dependencies = [
[[package]]
name = "rustpython-parser-core"
version = "0.4.0"
source = "git+https://github.com/RustPython/Parser#5e9d9853e751240b28138efd165e793a7ee5dad4"
source = "git+https://github.com/RustPython/Parser#d2f137b372ec08ce4a243564a80f8f9153c45a23"
dependencies = [
"is-macro",
"memchr",
@ -864,17 +887,23 @@ dependencies = [
[[package]]
name = "rustpython-parser-vendored"
version = "0.4.0"
source = "git+https://github.com/RustPython/Parser#5e9d9853e751240b28138efd165e793a7ee5dad4"
source = "git+https://github.com/RustPython/Parser#d2f137b372ec08ce4a243564a80f8f9153c45a23"
dependencies = [
"memchr",
"once_cell",
]
[[package]]
name = "ryu"
version = "1.0.18"
name = "rustversion"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4"
[[package]]
name = "ryu"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd"
[[package]]
name = "scopeguard"
@ -882,37 +911,31 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "semver"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba"
[[package]]
name = "serde"
version = "1.0.216"
version = "1.0.218"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e"
checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.216"
version = "1.0.218"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e"
checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.90",
"syn 2.0.98",
]
[[package]]
name = "serde_json"
version = "1.0.133"
version = "1.0.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377"
checksum = "44f86c3acccc9c65b153fe1b85a3be07fe5515274ec9f0653b4a0875731c72a6"
dependencies = [
"itoa",
"memchr",
@ -928,7 +951,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.90",
"syn 2.0.98",
]
[[package]]
@ -939,15 +962,15 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "siphasher"
version = "0.3.11"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
[[package]]
name = "smallvec"
version = "1.13.2"
version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd"
[[package]]
name = "stable_deref_trait"
@ -974,9 +997,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.90"
version = "2.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31"
checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1"
dependencies = [
"proc-macro2",
"quote",
@ -991,7 +1014,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.90",
"syn 2.0.98",
]
[[package]]
@ -1077,9 +1100,9 @@ dependencies = [
[[package]]
name = "unicode-ident"
version = "1.0.14"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe"
[[package]]
name = "unicode-width"
@ -1162,34 +1185,35 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.99"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396"
checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
dependencies = [
"cfg-if",
"once_cell",
"rustversion",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.99"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79"
checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
dependencies = [
"bumpalo",
"log",
"proc-macro2",
"quote",
"syn 2.0.90",
"syn 2.0.98",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.99"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe"
checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@ -1197,22 +1221,25 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.99"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2"
checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.90",
"syn 2.0.98",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.99"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6"
checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
dependencies = [
"unicode-ident",
]
[[package]]
name = "windows"
@ -1245,7 +1272,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.90",
"syn 2.0.98",
]
[[package]]
@ -1256,7 +1283,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.90",
"syn 2.0.98",
]
[[package]]
@ -1374,7 +1401,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.90",
"syn 2.0.98",
"synstructure",
]
@ -1396,7 +1423,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.90",
"syn 2.0.98",
]
[[package]]
@ -1416,7 +1443,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.90",
"syn 2.0.98",
"synstructure",
]
@ -1439,5 +1466,5 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.90",
"syn 2.0.98",
]

View File

@ -17,16 +17,16 @@ members = [
]
[workspace.package]
version = "0.0.74"
version = "0.0.82"
authors = ["Shunsuke Shibayama <sbym1346@gmail.com>"]
license = "MIT OR Apache-2.0"
edition = "2021"
repository = "https://github.com/mtshiba/pylyzer"
[workspace.dependencies]
erg_common = { version = "0.6.49-nightly.4", features = ["py_compat", "els"] }
erg_compiler = { version = "0.6.49-nightly.4", features = ["py_compat", "els"] }
els = { version = "0.1.61-nightly.4", features = ["py_compat"] }
erg_common = { version = "0.6.53-nightly.5", features = ["py_compat", "els"] }
erg_compiler = { version = "0.6.53-nightly.5", features = ["py_compat", "els"] }
els = { version = "0.1.65-nightly.5", features = ["py_compat"] }
# rustpython-parser = { version = "0.3.0", features = ["all-nodes-with-ranges", "location"] }
# rustpython-ast = { version = "0.3.0", features = ["all-nodes-with-ranges", "location"] }
rustpython-parser = { git = "https://github.com/RustPython/Parser", version = "0.4.0", features = ["all-nodes-with-ranges", "location"] }
@ -45,11 +45,16 @@ pretty = ["erg_common/pretty", "pylyzer_core/pretty"]
backtrace = ["erg_common/backtrace", "els/backtrace", "pylyzer_core/backtrace"]
experimental = ["erg_common/experimental", "els/experimental", "pylyzer_core/experimental", "parallel"]
parallel = ["erg_common/parallel", "pylyzer_core/parallel"]
japanese = ["erg_common/japanese", "els/japanese"]
simplified_chinese = ["erg_common/simplified_chinese", "els/simplified_chinese"]
traditional_chinese = ["erg_common/traditional_chinese", "els/traditional_chinese"]
[dependencies]
pylyzer_core = { version = "0.0.74", path = "./crates/pylyzer_core" }
pylyzer_core = { version = "0.0.82", path = "./crates/pylyzer_core" }
erg_common = { workspace = true }
els = { workspace = true }
glob = "0.3.2"
indexmap = "2.7.1"
[dev-dependencies]
erg_compiler = { workspace = true }

View File

@ -1,5 +1,9 @@
# pylyzer ⚡
> [!IMPORTANT]
> pylyzer is now under the maintenance phase, which means that only bug fixes will be made and no new features will be added.
The author is currently cooperating with the development of [astral-sh/ty](https://github.com/astral-sh/ty). Please try that instead!
![pylyzer_logo_with_letters](https://raw.githubusercontent.com/mtshiba/pylyzer/main/images/pylyzer-logo-with-letters.png)
<a href="https://marketplace.visualstudio.com/items?itemName=pylyzer.pylyzer" target="_blank" rel="noreferrer noopener nofollow"><img src="https://img.shields.io/visual-studio-marketplace/v/pylyzer.pylyzer?style=flat&amp;label=VS%20Marketplace&amp;logo=visual-studio-code" alt="vsm-version"></a>
@ -33,6 +37,39 @@ Make sure that `cargo`/`rustc` is up-to-date, as pylyzer may be written with the
### [GitHub Releases](https://github.com/mtshiba/pylyzer/releases/latest)
## How to use
### Check a single file
```sh
pylyzer file.py
```
### Check multiple files
```sh
# glob patterns are supported
pylyzer file1.py file2.py dir/file*.py
```
### Check an entire package
If you don't specify a file path, pylyzer will automatically search for the entry point.
```sh
pylyzer
```
### Start the language server
This option is used when an LSP-aware editor requires arguments to start pylyzer.
```sh
pylyzer --server
```
For other options, check [the manual](https://mtshiba.github.io/pylyzer/options/options/).
## What is the advantage over pylint, pyright, pytype, etc.?
* Performance 🌟
@ -97,6 +134,7 @@ pylyzer converts Python ASTs to Erg ASTs and passes them to Erg's type checker.
* [x] function/method
* [x] class
* [ ] `async/await`
* [ ] user-defined abstract class
* [x] type inference
* [x] variable
* [x] operator
@ -139,15 +177,18 @@ pylyzer converts Python ASTs to Erg ASTs and passes them to Erg's type checker.
* [x] type narrowing
* [ ] others
* [ ] `collections.abc`
* [x] `Collection`
* [x] `Container`
* [x] `Generator`
* [x] `Iterable`
* [x] `Iterator`
* [x] `Mapping`
* [x] `Sequence`
* [x] `Mapping`, `MutableMapping`
* [x] `Sequence`, `MutableSequence`
* [ ] others
* [x] type assertion (`typing.cast`)
* [x] type narrowing (`is`, `isinstance`)
* [x] `pyi` (stub) files support
* [ ] glob pattern file check
* [x] glob pattern file check
* [x] type comment (`# type: ...`)
* [x] virtual environment support
* [x] package manager support

View File

@ -11,6 +11,9 @@ repository.workspace = true
[features]
debug = ["erg_compiler/debug", "erg_common/debug"]
japanese = ["erg_compiler/japanese", "erg_common/japanese"]
simplified_chinese = ["erg_compiler/simplified_chinese", "erg_common/simplified_chinese"]
traditional_chinese = ["erg_compiler/traditional_chinese", "erg_common/traditional_chinese"]
[dependencies]
rustpython-parser = { workspace = true }

View File

@ -6,18 +6,19 @@ use erg_common::dict::Dict as HashMap;
use erg_common::error::Location as ErgLocation;
use erg_common::fresh::FRESH_GEN;
use erg_common::set::Set as HashSet;
use erg_common::traits::{Locational, Stream};
use erg_common::traits::{Locational, Stream, Traversable};
use erg_common::{fmt_vec, log, set};
use erg_compiler::artifact::IncompleteArtifact;
use erg_compiler::erg_parser::ast::{
Accessor, Args, BinOp, Block, ClassAttr, ClassAttrs, ClassDef, ConstAccessor, ConstApp,
ConstArgs, ConstAttribute, ConstBinOp, ConstBlock, ConstDict, ConstExpr, ConstKeyValue,
ConstLambda, ConstList, ConstListWithLength, ConstNormalList, ConstNormalSet, ConstPosArg,
ConstSet, Decorator, Def, DefBody, DefId, DefaultParamSignature, Dict, Dummy, Expr, Identifier,
KeyValue, KwArg, Lambda, LambdaSignature, List, ListComprehension, Literal, Methods, Module,
NonDefaultParamSignature, NormalDict, NormalList, NormalRecord, NormalSet, NormalTuple,
ParamPattern, ParamTySpec, Params, PosArg, PreDeclTypeSpec, ReDef, Record, RecordAttrs, Set,
SetComprehension, Signature, SubrSignature, SubrTypeSpec, Tuple, TupleTypeSpec, TypeAscription,
Accessor, Args, BinOp, Block, ClassAttr, ClassAttrs, ClassDef, Compound, ConstAccessor,
ConstApp, ConstArgs, ConstAttribute, ConstBinOp, ConstBlock, ConstDict, ConstExpr,
ConstKeyValue, ConstLambda, ConstList, ConstListWithLength, ConstNormalList, ConstNormalSet,
ConstPosArg, ConstSet, Decorator, Def, DefBody, DefId, DefaultParamSignature, Dict,
DictComprehension, Dummy, Expr, Identifier, KeyValue, KwArg, Lambda, LambdaSignature, List,
ListComprehension, Literal, Methods, Module, NonDefaultParamSignature, NormalDict, NormalList,
NormalRecord, NormalSet, NormalTuple, ParamPattern, ParamTySpec, Params, PosArg,
PreDeclTypeSpec, ReDef, Record, RecordAttrs, Set, SetComprehension, Signature, SubrSignature,
SubrTypeSpec, Tuple, TupleTypeSpec, TypeAppArgs, TypeAppArgsKind, TypeAscription,
TypeBoundSpec, TypeBoundSpecs, TypeSpec, TypeSpecWithOp, UnaryOp, VarName, VarPattern,
VarRecordAttr, VarRecordAttrs, VarRecordPattern, VarSignature, VisModifierSpec,
};
@ -143,12 +144,26 @@ fn escape_name(name: String) -> String {
"tuple" => "GenericTuple".into(),
"type" => "Type".into(),
"ModuleType" => "GeneticModule".into(),
"MutableSequence" => "Sequence!".into(),
"MutableMapping" => "Mapping!".into(),
_ => name,
}
}
fn is_global_poly_type(name: &str) -> bool {
matches!(
name,
"list"
| "dict"
| "set"
| "tuple"
| "List"
| "Dict"
| "Tuple"
| global_unary_collections!()
| global_mutable_unary_collections!()
| global_binary_collections!()
)
}
fn quoted_symbol(sym: &str, lineno: u32, col_begin: u32) -> Token {
let col_end = col_begin + sym.chars().count() as u32;
Token {
@ -240,6 +255,7 @@ impl DefinedPlace {
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct NameInfo {
kind: NameKind,
rename: Option<String>,
defined_in: DefinedPlace,
defined_block_id: usize,
@ -249,12 +265,14 @@ pub struct NameInfo {
impl NameInfo {
pub fn new(
kind: NameKind,
rename: Option<String>,
defined_in: DefinedPlace,
defined_block_id: usize,
defined_times: usize,
) -> Self {
Self {
kind,
rename,
defined_in,
defined_block_id,
@ -319,6 +337,19 @@ pub struct BlockInfo {
pub kind: BlockKind,
}
#[derive(Debug)]
pub enum ReturnKind {
None,
Return,
Yield,
}
impl ReturnKind {
pub const fn is_none(&self) -> bool {
matches!(self, Self::None)
}
}
#[derive(Debug)]
pub struct LocalContext {
pub name: String,
@ -328,6 +359,7 @@ pub struct LocalContext {
type_vars: HashMap<String, TypeVarInfo>,
// e.g. def id(x: T) -> T: ... => appeared_types = {T}
appeared_type_names: HashSet<String>,
return_kind: ReturnKind,
}
impl LocalContext {
@ -338,6 +370,7 @@ impl LocalContext {
names: HashMap::new(),
type_vars: HashMap::new(),
appeared_type_names: HashSet::new(),
return_kind: ReturnKind::None,
}
}
}
@ -620,6 +653,15 @@ impl ASTConverter {
None
}
fn is_type_name(&self, name: &str) -> bool {
is_global_poly_type(name)
|| self
.contexts
.iter()
.rev()
.any(|ctx| ctx.names.get(name).is_some_and(|ni| ni.kind.is_class()))
}
fn define_name(&mut self, name: String, info: NameInfo) {
self.contexts.last_mut().unwrap().names.insert(name, info);
}
@ -666,6 +708,14 @@ impl ASTConverter {
&self.contexts.last().unwrap().name
}
fn cur_context(&self) -> &LocalContext {
self.contexts.last().unwrap()
}
fn cur_context_mut(&mut self) -> &mut LocalContext {
self.contexts.last_mut().unwrap()
}
fn parent_name(&self) -> &str {
&self.contexts[self.contexts.len().saturating_sub(2)].name
}
@ -708,7 +758,7 @@ impl ASTConverter {
None
};
let defined_in = DefinedPlace::Known(self.cur_namespace());
let info = NameInfo::new(rename, defined_in, self.cur_block_id(), 1);
let info = NameInfo::new(kind, rename, defined_in, self.cur_block_id(), 1);
self.define_name(String::from(name), info);
RenameKind::Let
}
@ -749,7 +799,7 @@ impl ASTConverter {
} else {
DefinedPlace::Unknown
};
let mut info = NameInfo::new(None, defined_in, cur_block_id, 0);
let mut info = NameInfo::new(NameKind::Variable, None, defined_in, cur_block_id, 0);
info.add_referrer(cur_namespace);
self.declare_name(name.clone(), info);
name
@ -991,43 +1041,56 @@ impl ASTConverter {
Lambda::new(sig, op, Block::new(body), DefId(0))
}
fn convert_ident_type_spec(&mut self, name: String, loc: PyLocation) -> TypeSpec {
fn convert_ident_type_spec(&mut self, name: String, range: PySourceRange) -> TypeSpec {
let loc = pyloc_to_ergloc(range);
let global = ConstExpr::Accessor(ConstAccessor::Local(Identifier::private_with_loc(
"global".into(),
loc,
)));
let obj = ConstExpr::Accessor(ConstAccessor::Local(Identifier::private_with_loc(
"Obj".into(),
loc,
)));
match &name[..] {
"dict" => {
let kv = ConstKeyValue::new(obj.clone(), obj.clone());
let (l, r) = Self::gen_enclosure_tokens(TokenKind::LSqBr, range);
let dict = ConstDict::new(l, r, vec![kv]);
TypeSpec::poly(
global.attr(Identifier::private_with_loc("Dict!".into(), loc)),
ConstArgs::single(ConstExpr::Dict(dict)),
)
}
"set" => TypeSpec::poly(
global.attr(Identifier::private_with_loc("Set!".into(), loc)),
ConstArgs::single(obj),
),
"tuple" => TypeSpec::poly(
global.attr(Identifier::private_with_loc("HomogenousTuple".into(), loc)),
ConstArgs::single(obj),
),
// Iterable[T] => Iterable(T), Iterable => Iterable(Obj)
global_unary_collections!() => TypeSpec::poly(
ConstExpr::Accessor(ConstAccessor::Local(Identifier::private("global".into())))
.attr(Identifier::private(name.into())),
ConstArgs::single(ConstExpr::Accessor(ConstAccessor::Local(
Identifier::private("Obj".into()),
))),
global.attr(Identifier::private_with_loc(name.into(), loc)),
ConstArgs::single(obj),
),
// MutableSequence[T] => Sequence!(T), MutableSequence => Sequence!(Obj)
global_mutable_unary_collections!() => TypeSpec::poly(
ConstExpr::Accessor(ConstAccessor::Local(Identifier::private("global".into())))
.attr(Identifier::private(
format!("{}!", name.trim_start_matches("Mutable")).into(),
)),
ConstArgs::single(ConstExpr::Accessor(ConstAccessor::Local(
Identifier::private("Obj".into()),
))),
global.attr(Identifier::private_with_loc(
format!("{}!", name.trim_start_matches("Mutable")).into(),
loc,
)),
ConstArgs::single(obj),
),
// Mapping => Mapping(Obj, Obj)
global_binary_collections!() => TypeSpec::poly(
ConstExpr::Accessor(ConstAccessor::Local(Identifier::private("global".into())))
.attr(Identifier::private(name.into())),
global.attr(Identifier::private_with_loc(name.into(), loc)),
ConstArgs::pos_only(
vec![
ConstPosArg::new(ConstExpr::Accessor(ConstAccessor::Local(
Identifier::private("Obj".into()),
))),
ConstPosArg::new(ConstExpr::Accessor(ConstAccessor::Local(
Identifier::private("Obj".into()),
))),
],
vec![ConstPosArg::new(obj.clone()), ConstPosArg::new(obj)],
None,
),
),
_ => TypeSpec::mono(self.convert_ident(name, loc)),
_ => TypeSpec::mono(self.convert_ident(name, range.start)),
}
}
@ -1040,8 +1103,7 @@ impl ASTConverter {
))
}
#[allow(clippy::only_used_in_recursion)]
fn convert_const_expr(&self, expr: ConstExpr) -> ConstExpr {
fn convert_const_expr(&mut self, expr: ConstExpr) -> ConstExpr {
match expr {
ConstExpr::UnaryOp(un) if un.op.is(TokenKind::Mutate) => *un.expr,
ConstExpr::App(app)
@ -1138,11 +1200,23 @@ impl ASTConverter {
ConstExpr::Set(ConstSet::Normal(set))
}
Some("Callable") => {
let params = match args.pos_args.remove(0).expr {
ConstExpr::List(ConstList::Normal(list)) => list.elems,
other => {
args.pos_args.insert(0, ConstPosArg::new(other));
args.clone()
let params = if args.pos_args.is_empty() {
self.errs.push(CompileError::syntax_error(
self.cfg.input.clone(),
line!() as usize,
args.loc(),
self.cur_namespace(),
"`Callable` takes an input type list and a return type".into(),
None,
));
ConstArgs::empty()
} else {
match args.pos_args.remove(0).expr {
ConstExpr::List(ConstList::Normal(list)) => list.elems,
other => {
args.pos_args.insert(0, ConstPosArg::new(other));
args.clone()
}
}
};
let non_defaults = params
@ -1172,13 +1246,25 @@ impl ASTConverter {
})
.collect();
let params = Params::new(non_defaults, None, vec![], None, None);
let ret = match args.pos_args.remove(0).expr {
ConstExpr::Lit(lit) if lit.is(TokenKind::NoneLit) => {
ConstExpr::Accessor(ConstAccessor::Local(Identifier::private(
"NoneType".into(),
)))
let ret = if args.pos_args.is_empty() {
self.errs.push(CompileError::syntax_error(
self.cfg.input.clone(),
line!() as usize,
args.loc(),
self.cur_namespace(),
"Expected a return type".into(),
None,
));
ConstExpr::Accessor(ConstAccessor::Local(Identifier::private("Any".into())))
} else {
match args.pos_args.remove(0).expr {
ConstExpr::Lit(lit) if lit.is(TokenKind::NoneLit) => {
ConstExpr::Accessor(ConstAccessor::Local(Identifier::private(
"NoneType".into(),
)))
}
other => other,
}
other => other,
};
let op = Token::dummy(TokenKind::ProcArrow, "=>");
let body = ConstBlock::new(vec![ret]);
@ -1222,6 +1308,9 @@ impl ASTConverter {
return Self::gen_dummy_type_spec(args.location());
};
let lhs = self.convert_type_spec(tuple.elts.remove(0));
if tuple.elts.is_empty() {
return lhs;
}
let rhs = self.convert_type_spec(tuple.elts.remove(0));
let mut union = TypeSpec::or(lhs, rhs);
for elem in tuple.elts {
@ -1250,10 +1339,24 @@ impl ASTConverter {
let elems = ConstArgs::new(elems, None, vec![], None, None);
TypeSpec::Enum(elems)
}
// TODO: Currently, these types are simply interpreted as inner types
"Final" | "Required" | "NotRequired" | "ReadOnly" => self.convert_type_spec(args),
// TODO: distinguish from collections.abc.Callable
"Callable" => {
let py_ast::Expr::Tuple(mut tuple) = args else {
return Self::gen_dummy_type_spec(args.location());
let mut tuple = match args {
py_ast::Expr::Tuple(tuple) if tuple.elts.len() == 2 => tuple,
_ => {
let err = CompileError::syntax_error(
self.cfg.input.clone(),
line!() as usize,
pyloc_to_ergloc(args.range()),
self.cur_namespace(),
"`Callable` takes an input type list and a return type".into(),
None,
);
self.errs.push(err);
return Self::gen_dummy_type_spec(args.location());
}
};
let params = tuple.elts.remove(0);
let mut non_defaults = vec![];
@ -1306,17 +1409,20 @@ impl ASTConverter {
TypeSpec::poly(acc, ConstArgs::pos_only(vec![elem_t], None))
}
"Mapping" | "MutableMapping" => {
let py_ast::Expr::Tuple(mut tuple) = args else {
let err = CompileError::syntax_error(
self.cfg.input.clone(),
line!() as usize,
pyloc_to_ergloc(args.range()),
self.cur_namespace(),
format!("`{name}` takes 2 types"),
None,
);
self.errs.push(err);
return Self::gen_dummy_type_spec(args.location());
let mut tuple = match args {
py_ast::Expr::Tuple(tuple) if tuple.elts.len() == 2 => tuple,
_ => {
let err = CompileError::syntax_error(
self.cfg.input.clone(),
line!() as usize,
pyloc_to_ergloc(args.range()),
self.cur_namespace(),
"`Mapping` takes 2 types".into(),
None,
);
self.errs.push(err);
return Self::gen_dummy_type_spec(args.location());
}
};
let key_t = match self.convert_expr_to_const(tuple.elts.remove(0)) {
Some(key_t) => key_t,
@ -1365,8 +1471,20 @@ impl ASTConverter {
)
}
"Dict" | "dict" => {
let py_ast::Expr::Tuple(mut tuple) = args else {
return Self::gen_dummy_type_spec(args.location());
let mut tuple = match args {
py_ast::Expr::Tuple(tuple) if tuple.elts.len() == 2 => tuple,
_ => {
let err = CompileError::syntax_error(
self.cfg.input.clone(),
line!() as usize,
pyloc_to_ergloc(args.range()),
self.cur_namespace(),
"`dict` takes 2 types".into(),
None,
);
self.errs.push(err);
return Self::gen_dummy_type_spec(args.location());
}
};
let (l_brace, r_brace) = Self::gen_enclosure_tokens(TokenKind::LBrace, tuple.range);
let key_t = match self.convert_expr_to_const(tuple.elts.remove(0)) {
@ -1414,12 +1532,27 @@ impl ASTConverter {
let tuple = TupleTypeSpec::new(Some((l.loc(), r.loc())), tys);
TypeSpec::Tuple(tuple)
}
"Set" | "set" => {
let elem_t = match self.convert_expr_to_const(args) {
Some(elem_t) => elem_t,
None => {
ConstExpr::Accessor(ConstAccessor::Local(Identifier::private("Obj".into())))
}
};
let elem_t = ConstPosArg::new(elem_t);
let global =
ConstExpr::Accessor(ConstAccessor::Local(Identifier::private("global".into())));
let acc = ConstAccessor::Attr(ConstAttribute::new(
global,
Identifier::private("Set!".into()),
));
TypeSpec::poly(acc, ConstArgs::pos_only(vec![elem_t], None))
}
_ => Self::gen_dummy_type_spec(args.location()),
}
}
fn convert_type_spec(&mut self, expr: py_ast::Expr) -> TypeSpec {
#[allow(clippy::collapsible_match)]
match expr {
py_ast::Expr::Name(name) => {
self.contexts
@ -1427,13 +1560,13 @@ impl ASTConverter {
.unwrap()
.appeared_type_names
.insert(name.id.to_string());
self.convert_ident_type_spec(name.id.to_string(), name.location())
self.convert_ident_type_spec(name.id.to_string(), name.range)
}
py_ast::Expr::Constant(cons) => {
if cons.value.is_none() {
self.convert_ident_type_spec("NoneType".into(), cons.location())
self.convert_ident_type_spec("NoneType".into(), cons.range)
} else if let Some(name) = cons.value.as_str() {
self.convert_ident_type_spec(name.into(), cons.location())
self.convert_ident_type_spec(name.into(), cons.range)
} else {
let err = CompileError::syntax_error(
self.cfg.input.clone(),
@ -1458,8 +1591,7 @@ impl ASTConverter {
global_unary_collections!()
| global_mutable_unary_collections!()
| global_binary_collections!() => {
return self
.convert_ident_type_spec(attr.attr.to_string(), attr.range.start)
return self.convert_ident_type_spec(attr.attr.to_string(), attr.range)
}
"Any" => return TypeSpec::PreDeclTy(PreDeclTypeSpec::Mono(t)),
_ => {}
@ -1720,10 +1852,9 @@ impl ASTConverter {
let rhs = self.convert_expr(*un.operand);
let (kind, cont) = match un.op {
UnOp::UAdd => (TokenKind::PrePlus, "+"),
// UnOp::Not => (TokenKind::PreBitNot, "not"),
UnOp::USub => (TokenKind::PreMinus, "-"),
UnOp::Invert => (TokenKind::PreBitNot, "~"),
_ => return Expr::Dummy(Dummy::new(None, vec![rhs])),
UnOp::Not => return Expr::Call(Identifier::public("not".into()).call1(rhs)),
};
let op = Token::from_str(kind, cont);
Expr::UnaryOp(UnaryOp::new(op, rhs))
@ -1812,8 +1943,8 @@ impl ASTConverter {
.map(|ex| PosArg::new(self.convert_expr(ex)))
.collect::<Vec<_>>();
let elems = Args::pos_only(elements, None);
Expr::Set(Set::Normal(NormalSet::new(l_brace, r_brace, elems)))
// Self::mutate_expr(set)
let set = Expr::Set(Set::Normal(NormalSet::new(l_brace, r_brace, elems)));
Self::mutate_expr(set)
}
py_ast::Expr::SetComp(comp) => {
let (l_brace, r_brace) = Self::gen_enclosure_tokens(TokenKind::LBrace, comp.range);
@ -1832,14 +1963,14 @@ impl ASTConverter {
.next()
.map(|ex| self.convert_expr(ex));
let generators = vec![(ident, iter)];
Expr::Set(Set::Comprehension(SetComprehension::new(
let set = Expr::Set(Set::Comprehension(SetComprehension::new(
l_brace,
r_brace,
Some(layout),
generators,
guard,
)))
// Self::mutate_expr(set)
)));
Self::mutate_expr(set)
}
py_ast::Expr::Dict(dict) => {
let (l_brace, r_brace) = Self::gen_enclosure_tokens(TokenKind::LBrace, dict.range);
@ -1858,6 +1989,30 @@ impl ASTConverter {
let dict = Expr::Dict(Dict::Normal(NormalDict::new(l_brace, r_brace, kvs)));
Self::mutate_expr(dict)
}
py_ast::Expr::DictComp(comp) => {
let (l_brace, r_brace) = Self::gen_enclosure_tokens(TokenKind::LBrace, comp.range);
let key = self.convert_expr(*comp.key);
let value = self.convert_expr(*comp.value);
let kv = KeyValue::new(key, value);
let generator = comp.generators.into_iter().next().unwrap();
let target = self.convert_expr(generator.target);
let Expr::Accessor(Accessor::Ident(ident)) = target else {
log!(err "unimplemented: {target}");
let loc = pyloc_to_ergloc(comp.range);
return Expr::Dummy(Dummy::new(Some(loc), vec![]));
};
let iter = self.convert_expr(generator.iter);
let guard = generator
.ifs
.into_iter()
.next()
.map(|ex| self.convert_expr(ex));
let generators = vec![(ident, iter)];
let dict = Expr::Dict(Dict::Comprehension(DictComprehension::new(
l_brace, r_brace, kv, generators, guard,
)));
Self::mutate_expr(dict)
}
py_ast::Expr::Tuple(tuple) => {
let (l, r) = Self::gen_enclosure_tokens(TokenKind::LParen, tuple.range);
let elements = tuple
@ -1870,11 +2025,25 @@ impl ASTConverter {
}
py_ast::Expr::Subscript(subs) => {
let obj = self.convert_expr(*subs.value);
// List[T] => List!(T)
if obj.get_name().is_some_and(|n| self.is_type_name(n)) {
let obj = if obj.get_name().is_some_and(|n| n == "List") {
let global = self.convert_ident("global".to_string(), subs.range.start);
Expr::from(global).attr_expr(Identifier::private("List!".into()))
} else if obj.get_name().is_some_and(|n| n == "Set") {
let global = self.convert_ident("global".to_string(), subs.range.start);
Expr::from(global).attr_expr(Identifier::private("Set!".into()))
} else {
obj
};
return obj.call1(self.convert_expr(*subs.slice));
}
let method = obj.attr_expr(
self.convert_ident("__getitem__".to_string(), subs.slice.location()),
);
method.call1(self.convert_expr(*subs.slice))
}
// [:] == [slice(None)]
// [start:] == [slice(start, None)]
// [:stop] == [slice(stop)]
// [start:stop] == [slice(start, stop)]
@ -1894,6 +2063,14 @@ impl ASTConverter {
if let Some(step) = step {
args.push_pos(PosArg::new(step));
}
if args.is_empty() {
args.push_pos(PosArg::new(Expr::Literal(Literal::new(Token::new(
TokenKind::NoneLit,
"None",
loc.row.get(),
loc.column.to_zero_indexed(),
)))));
}
let slice = self.convert_ident("slice".to_string(), loc);
slice.call(args).into()
}
@ -1937,6 +2114,34 @@ impl ASTConverter {
let stringify = self.convert_ident("str".to_string(), loc);
stringify.call1(expr).into()
}
py_ast::Expr::NamedExpr(named) => {
let loc = named.location();
let target = self.convert_expr(*named.target);
let target_pat = match &target {
Expr::Accessor(Accessor::Ident(ident)) => VarPattern::Ident(ident.clone()),
_ => {
log!(err "unimplemented: {:?}", target);
VarPattern::Ident(Identifier::private("_".into()))
}
};
let value = self.convert_expr(*named.value);
let assign = Token::new(
TokenKind::Assign,
"=",
loc.row.get(),
loc.column.to_zero_indexed(),
);
let def = Def::new(
Signature::Var(VarSignature::new(target_pat, None)),
DefBody::new(assign, Block::new(vec![value]), DefId(0)),
);
Expr::Compound(Compound::new(vec![Expr::Def(def), target]))
}
py_ast::Expr::Yield(_) => {
self.cur_context_mut().return_kind = ReturnKind::Yield;
log!(err "unimplemented: {:?}", expr);
Expr::Dummy(Dummy::new(None, vec![]))
}
_other => {
log!(err "unimplemented: {:?}", _other);
Expr::Dummy(Dummy::new(None, vec![]))
@ -1960,41 +2165,81 @@ impl ASTConverter {
Block::new(new_block)
}
fn check_init_sig(&mut self, sig: &Signature) -> Option<()> {
#[allow(clippy::result_large_err)]
fn check_init_sig(&self, sig: &Signature) -> Result<(), (bool, CompileError)> {
match sig {
Signature::Subr(subr) => {
if let Some(first) = subr.params.non_defaults.first() {
if first.inspect().map(|s| &s[..]) == Some("self") {
return Some(());
return Ok(());
}
}
self.errs.push(self_not_found_error(
self.cfg.input.clone(),
subr.loc(),
self.cur_namespace(),
));
Some(())
}
Signature::Var(var) => {
self.errs.push(init_var_error(
self.cfg.input.clone(),
var.loc(),
self.cur_namespace(),
));
None
Err((
true,
self_not_found_error(self.cfg.input.clone(), subr.loc(), self.cur_namespace()),
))
}
Signature::Var(var) => Err((
false,
init_var_error(self.cfg.input.clone(), var.loc(), self.cur_namespace()),
)),
}
}
// ```python
// def __init__(self, x: Int, y: Int, z):
// self.x = x
// self.y = y
// if True:
// self.set_z(z)
//
// def set_z(self, z):
// self.z = z
// ```
// ↓
// methods: {"set_z"}
#[allow(clippy::only_used_in_recursion)]
fn collect_called_methods(&self, expr: &Expr, methods: &mut HashSet<String>) {
expr.traverse(&mut |ex| {
if let Expr::Call(call) = ex {
match call.obj.as_ref() {
Expr::Accessor(Accessor::Ident(ident)) if ident.inspect() == "self" => {
if let Some(method_ident) = &call.attr_name {
methods.insert(method_ident.inspect().to_string());
} else {
self.collect_called_methods(&call.obj, methods);
}
}
_ => self.collect_called_methods(ex, methods),
}
} else {
self.collect_called_methods(ex, methods);
}
});
}
// def __init__(self, x: Int, y: Int, z):
// self.x = x
// self.y = y
// self.z = z
// ↓
// requirement : {x: Int, y: Int, z: Never}
// requirement : {x: Int, y: Int, z: Any}
// returns : .__call__(x: Int, y: Int, z: Obj): Self = .unreachable()
fn extract_init(&mut self, base_type: &mut Option<Expr>, init_def: Def) -> Option<Def> {
self.check_init_sig(&init_def.sig)?;
fn extract_init(
&mut self,
base_type: &mut Option<Expr>,
init_def: Def,
attrs: &[ClassAttr],
pre_check: bool,
) -> Option<Def> {
if let Err((continuable, err)) = self.check_init_sig(&init_def.sig) {
if pre_check {
self.errs.push(err);
}
if !continuable {
return None;
}
}
let l_brace = Token::new(
TokenKind::LBrace,
"{",
@ -2007,51 +2252,21 @@ impl ASTConverter {
init_def.ln_end().unwrap_or(0),
init_def.col_end().unwrap_or(0),
);
let expr = Expr::Def(init_def.clone());
let Signature::Subr(sig) = init_def.sig else {
unreachable!()
};
let mut fields = vec![];
for chunk in init_def.body.block {
#[allow(clippy::single_match)]
match chunk {
Expr::ReDef(redef) => {
let Accessor::Attr(attr) = redef.attr else {
continue;
};
// if `self.foo == ...`
if attr.obj.get_name().map(|s| &s[..]) == Some("self") {
// get attribute types
let typ = if let Some(t_spec_op) = sig
.params
.non_defaults
.iter()
.find(|&param| param.inspect() == Some(attr.ident.inspect()))
.and_then(|param| param.t_spec.as_ref())
.or_else(|| {
sig.params
.defaults
.iter()
.find(|&param| param.inspect() == Some(attr.ident.inspect()))
.and_then(|param| param.sig.t_spec.as_ref())
}) {
*t_spec_op.t_spec_as_expr.clone()
} else if let Some(typ) = redef.t_spec.map(|t_spec| t_spec.t_spec_as_expr) {
*typ
} else {
Expr::from(Accessor::Ident(Identifier::public_with_line(
DOT,
"Never".into(),
attr.obj.ln_begin().unwrap_or(0),
)))
};
let sig =
Signature::Var(VarSignature::new(VarPattern::Ident(attr.ident), None));
let body = DefBody::new(EQUAL, Block::new(vec![typ]), DefId(0));
let field_type_def = Def::new(sig, body);
fields.push(field_type_def);
self.extract_instance_attrs(&sig, &init_def.body.block, &mut fields);
let mut method_names = HashSet::new();
self.collect_called_methods(&expr, &mut method_names);
for class_attr in attrs {
if let ClassAttr::Def(def) = class_attr {
if let Signature::Subr(sig) = &def.sig {
if method_names.contains(&sig.ident.inspect()[..]) {
self.extract_instance_attrs(sig, &def.body.block, &mut fields);
}
}
_ => {}
}
}
if let Some(Expr::Record(Record::Normal(rec))) = base_type.as_mut() {
@ -2108,6 +2323,55 @@ impl ASTConverter {
Some(def)
}
fn extract_instance_attrs(&self, sig: &SubrSignature, block: &Block, fields: &mut Vec<Def>) {
for chunk in block.iter() {
if let Expr::ReDef(redef) = chunk {
let Accessor::Attr(attr) = &redef.attr else {
continue;
};
// if `self.foo == ...`
if attr.obj.get_name().map(|s| &s[..]) == Some("self")
&& fields
.iter()
.all(|field| field.sig.ident().unwrap() != &attr.ident)
{
// get attribute types
let typ = if let Some(t_spec_op) = sig
.params
.non_defaults
.iter()
.find(|&param| param.inspect() == Some(attr.ident.inspect()))
.and_then(|param| param.t_spec.as_ref())
.or_else(|| {
sig.params
.defaults
.iter()
.find(|&param| param.inspect() == Some(attr.ident.inspect()))
.and_then(|param| param.sig.t_spec.as_ref())
}) {
*t_spec_op.t_spec_as_expr.clone()
} else if let Some(typ) =
redef.t_spec.clone().map(|t_spec| t_spec.t_spec_as_expr)
{
*typ
} else {
Expr::from(Accessor::Ident(Identifier::private_with_line(
"Any".into(),
attr.obj.ln_begin().unwrap_or(0),
)))
};
let sig = Signature::Var(VarSignature::new(
VarPattern::Ident(attr.ident.clone()),
None,
));
let body = DefBody::new(EQUAL, Block::new(vec![typ]), DefId(0));
let field_type_def = Def::new(sig, body);
fields.push(field_type_def);
}
}
}
}
fn gen_default_init(&self, line: usize) -> Def {
let call_ident = Identifier::new(
VisModifierSpec::Public(ErgLocation::Unknown),
@ -2138,10 +2402,11 @@ impl ASTConverter {
&mut self,
body: Vec<py_ast::Stmt>,
inherit: bool,
class_name: Expr,
) -> (Option<Expr>, ClassAttrs) {
let mut base_type = None;
let mut attrs = vec![];
let mut init_is_defined = false;
let mut call_params_len = None;
for stmt in body {
match self.convert_statement(stmt, true) {
Expr::Def(mut def) => {
@ -2151,14 +2416,60 @@ impl ASTConverter {
.insert(Decorator(Expr::static_local("Override")));
}
}
if def
if def.sig.decorators().is_some_and(|decos| {
decos.iter().any(|deco| {
deco.expr()
.get_name()
.is_some_and(|name| name == "property")
})
}) {
// class Foo:
// @property
// def foo(self): ...
// ↓
// class Foo:
// def foo_(self): ...
// foo = Foo(*[]).foo_()
let mut args = Args::empty();
if call_params_len.as_ref().is_some_and(|&len| len >= 1) {
args.set_var_args(PosArg::new(Expr::List(List::Normal(
NormalList::new(
Token::dummy(TokenKind::LSqBr, "["),
Token::dummy(TokenKind::RSqBr, "]"),
Args::empty(),
),
))));
}
let instance = class_name.clone().call(args);
let name = def.sig.ident().unwrap().clone();
def.sig
.ident_mut()
.unwrap()
.name
.rename(format!("{} ", name.inspect()).into());
let escaped = def.sig.ident().unwrap().clone();
let call = Expr::Call(instance).method_call_expr(escaped, Args::empty());
let t_spec = def.sig.t_spec_op_mut().cloned();
let sig =
Signature::Var(VarSignature::new(VarPattern::Ident(name), t_spec));
let var_def =
Def::new(sig, DefBody::new(EQUAL, Block::new(vec![call]), DefId(0)));
attrs.push(ClassAttr::Def(def));
attrs.push(ClassAttr::Def(var_def));
} else if def
.sig
.ident()
.is_some_and(|id| &id.inspect()[..] == "__init__")
{
if let Some(call_def) = self.extract_init(&mut base_type, def) {
attrs.insert(0, ClassAttr::Def(call_def));
init_is_defined = true;
// We will generate `__init__` and determine the shape of the class at the end
// Here we just extract the signature
if let Some(call_def) =
self.extract_init(&mut base_type, def.clone(), &attrs, true)
{
if let Some(params) = call_def.sig.params() {
call_params_len = Some(params.len());
}
attrs.push(ClassAttr::Def(def));
}
} else {
attrs.push(ClassAttr::Def(def));
@ -2208,7 +2519,25 @@ impl ASTConverter {
_other => {} // TODO:
}
}
if !init_is_defined && !inherit {
let mut init = None;
for (i, attr) in attrs.iter().enumerate() {
if let ClassAttr::Def(def) = attr {
if def
.sig
.ident()
.is_some_and(|id| &id.inspect()[..] == "__init__")
{
if let Some(def) = self.extract_init(&mut base_type, def.clone(), &attrs, false)
{
init = Some((i, def));
}
}
}
}
if let Some((i, def)) = init {
attrs.remove(i);
attrs.insert(0, ClassAttr::Def(def));
} else if !inherit {
attrs.insert(0, ClassAttr::Def(self.gen_default_init(0)));
}
(base_type, ClassAttrs::new(attrs))
@ -2218,11 +2547,21 @@ impl ASTConverter {
&mut self,
ident: Identifier,
body: Vec<py_ast::Stmt>,
inherit: bool,
base: Option<py_ast::Expr>,
) -> (Option<Expr>, Vec<Methods>) {
let class = TypeSpec::mono(ident.clone());
let inherit = base.is_some();
let class = if let Some(base) = base {
let base_spec = self.convert_type_spec(base.clone());
let expr = self.convert_expr(base);
let loc = expr.loc();
let base = TypeSpecWithOp::new(COLON, base_spec, expr);
let args = TypeAppArgs::new(loc, TypeAppArgsKind::SubtypeOf(Box::new(base)), loc);
TypeSpec::type_app(TypeSpec::mono(ident.clone()), args)
} else {
TypeSpec::mono(ident.clone())
};
let class_as_expr = Expr::Accessor(Accessor::Ident(ident));
let (base_type, attrs) = self.extract_method(body, inherit);
let (base_type, attrs) = self.extract_method(body, inherit, class_as_expr.clone());
self.block_id_counter += 1;
let methods = Methods::new(
DefId(self.block_id_counter),
@ -2367,8 +2706,22 @@ impl ASTConverter {
.unwrap_or(func_def.type_params)
};
let bounds = self.get_type_bounds(type_params);
let sig = Signature::Subr(SubrSignature::new(decos, ident, bounds, params, return_t));
let mut sig =
Signature::Subr(SubrSignature::new(decos, ident, bounds, params, return_t));
let block = self.convert_block(func_def.body, BlockKind::Function);
if self.cur_context().return_kind.is_none() {
let Signature::Subr(subr) = &mut sig else {
unreachable!()
};
if subr.return_t_spec.is_none() {
let none = TypeSpecWithOp::new(
Token::dummy(TokenKind::Colon, ":"),
TypeSpec::mono(Identifier::private("NoneType".into())),
Expr::static_local("NoneType"),
);
subr.return_t_spec = Some(Box::new(none));
}
}
let body = DefBody::new(EQUAL, block, DefId(0));
let def = Def::new(sig, body);
self.pop();
@ -2398,12 +2751,13 @@ impl ASTConverter {
.into_iter()
.map(|deco| self.convert_expr(deco))
.collect::<Vec<_>>();
let inherit = class_def.bases.first().cloned();
let is_inherit = inherit.is_some();
let mut bases = class_def
.bases
.into_iter()
.map(|base| self.convert_expr(base))
.collect::<Vec<_>>();
let inherit = !bases.is_empty();
self.register_name_info(&name, NameKind::Class);
let class_name_loc = PyLocation {
row: loc.row,
@ -2413,7 +2767,7 @@ impl ASTConverter {
let sig = Signature::Var(VarSignature::new(VarPattern::Ident(ident.clone()), None));
self.grow(ident.inspect().to_string(), BlockKind::Class);
let (base_type, methods) = self.extract_method_list(ident, class_def.body, inherit);
let classdef = if inherit {
let classdef = if is_inherit {
// TODO: multiple inheritance
let pos_args = vec![PosArg::new(bases.remove(0))];
let mut args = Args::pos_only(pos_args, None);
@ -2923,6 +3277,7 @@ impl ASTConverter {
}
}
py_ast::Stmt::Return(return_) => {
self.cur_context_mut().return_kind = ReturnKind::Return;
let loc = return_.location();
let value = return_
.value

View File

@ -24,11 +24,11 @@ pub struct DeclFileGenerator {
}
impl DeclFileGenerator {
pub fn new(path: &NormalizedPathBuf, status: CheckStatus) -> Self {
pub fn new(path: &NormalizedPathBuf, status: CheckStatus) -> std::io::Result<Self> {
let (timestamp, hash) = {
let metadata = std::fs::metadata(path).unwrap();
let metadata = std::fs::metadata(path)?;
let dummy_hash = metadata.len();
(metadata.modified().unwrap(), dummy_hash)
(metadata.modified()?, dummy_hash)
};
let status = PylyzerStatus {
status,
@ -37,16 +37,16 @@ impl DeclFileGenerator {
hash,
};
let code = format!("{status}\n");
Self {
Ok(Self {
filename: path
.file_name()
.unwrap()
.unwrap_or_default()
.to_string_lossy()
.replace(".py", ".d.er"),
namespace: "".to_string(),
imported: Set::new(),
code,
}
})
}
pub fn gen_decl_er(mut self, hir: &HIR) -> DeclFile {
@ -102,7 +102,7 @@ impl DeclFileGenerator {
let typ = self.escape_type(ref_t.replace_failure().to_string_unabbreviated());
// Erg can automatically import nested modules
// `import http.client` => `http = pyimport "http"`
let decl = if ref_t.is_py_module() {
let decl = if ref_t.is_py_module() && ref_t.typarams()[0].is_str_value() {
name = name.split('.').next().unwrap().to_string();
let full_path_str = ref_t.typarams()[0].to_string_unabbreviated();
let mod_name = mod_name(Path::new(full_path_str.trim_matches('"')));
@ -182,17 +182,32 @@ impl DeclFileGenerator {
self.gen_chunk_decl(chunk);
}
}
Expr::Compound(compound) => {
for chunk in compound.iter() {
self.gen_chunk_decl(chunk);
}
}
Expr::Call(call) if call.control_kind().is_some() => {
for arg in call.args.iter() {
self.gen_chunk_decl(arg);
}
}
Expr::Lambda(lambda) => {
for arg in lambda.body.iter() {
self.gen_chunk_decl(arg);
}
}
_ => {}
}
self.code.push('\n');
}
}
fn dump_decl_er(path: &NormalizedPathBuf, hir: &HIR, status: CheckStatus) {
let decl_gen = DeclFileGenerator::new(path, status);
fn dump_decl_er(path: &NormalizedPathBuf, hir: &HIR, status: CheckStatus) -> std::io::Result<()> {
let decl_gen = DeclFileGenerator::new(path, status)?;
let file = decl_gen.gen_decl_er(hir);
let Some(dir) = path.parent().and_then(|p| p.canonicalize().ok()) else {
return;
return Ok(());
};
let cache_dir = dir.join("__pycache__");
if !cache_dir.exists() {
@ -200,19 +215,17 @@ fn dump_decl_er(path: &NormalizedPathBuf, hir: &HIR, status: CheckStatus) {
}
let path = cache_dir.join(file.filename);
if !path.exists() {
let _f = File::create(&path);
File::create(&path)?;
}
let Ok(f) = File::options().write(true).open(path) else {
return;
};
let f = File::options().write(true).open(path)?;
let mut f = BufWriter::new(f);
let _ = f.write_all(file.code.as_bytes());
f.write_all(file.code.as_bytes())
}
pub fn dump_decl_package(modules: &SharedModuleCache) {
for (path, module) in modules.raw_iter() {
if let Some(hir) = module.hir.as_ref() {
dump_decl_er(path, hir, module.status);
let _ = dump_decl_er(path, hir, module.status);
}
}
}

View File

@ -20,7 +20,7 @@ erg_common = { workspace = true }
erg_compiler = { workspace = true }
rustpython-parser = { workspace = true }
rustpython-ast = { workspace = true }
py2erg = { version = "0.0.74", path = "../py2erg" }
py2erg = { version = "0.0.82", path = "../py2erg" }
[lib]
path = "lib.rs"

View File

@ -295,7 +295,7 @@ impl PythonAnalyzer {
res
}
pub fn run(&mut self) {
pub fn run(&mut self) -> i32 {
/*if self.cfg.dist_dir.is_some() {
reserve_decl_er(self.cfg.input.clone());
}*/
@ -317,7 +317,7 @@ impl PythonAnalyzer {
dump_decl_package(&self.checker.shared().mod_cache);
println!("A declaration file has been generated to __pycache__ directory.");
}
std::process::exit(0);
0
}
Err(artifact) => {
if !artifact.warns.is_empty() {
@ -345,7 +345,7 @@ impl PythonAnalyzer {
dump_decl_package(&self.checker.shared().mod_cache);
println!("A declaration file has been generated to __pycache__ directory.");
}
std::process::exit(code);
code
}
}
}

View File

@ -37,10 +37,11 @@ fn handle_name_error(error: CompileError) -> Option<CompileError> {
|| {
main.contains(" is not defined") && {
let name = StyledStr::destyle(main.trim_end_matches(" is not defined"));
error
.core
.get_hint()
.is_some_and(|hint| hint.contains(name))
name == "Any"
|| error
.core
.get_hint()
.is_some_and(|hint| hint.contains(name))
}
}
{

View File

@ -68,3 +68,8 @@ Enable `--no-infer-fn-type` and `--fast-error-report`.
## --do-not-show-ext-errors
Do not show errors from external libraries.
## --do-not-respect-pyi
If specified, the actual `.py` types will be respected over the `.pyi` types.
Applying this option may slow down the analysis.

View File

@ -36,4 +36,12 @@ cargo install pylyzer
| - | - | - |
| pylyzer.diagnostics | Enable diagnostics | true |
| pylyzer.inlayHints | Enable inlay hints (this feature is unstable) | false |
| pylyzer.semanticTokens | Enable semantic tokens | false |
| pylyzer.hover | Enable hover | true |
| pylyzer.completion | Enable completion | true |
| pylyzer.smartCompletion | Enable smart completion (see [ELS features](https://github.com/erg-lang/erg/blob/main/crates/els/doc/features.md))| true |
| pylyzer.deepCompletion | Enable deep completion | true |
| pylyzer.signatureHelp | Enable signature help | true |
| pylyzer.documentLink | Enable document link | true |
| pylyzer.codeAction | Enable code action | true |
| pylyzer.codeLens | Enable code lens | true |

View File

@ -1,12 +1,12 @@
{
"name": "pylyzer",
"version": "0.1.10",
"version": "0.1.11",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "pylyzer",
"version": "0.1.10",
"version": "0.1.11",
"dependencies": {
"vscode-languageclient": "^8.0.2"
},
@ -29,9 +29,9 @@
}
},
"node_modules/@biomejs/biome": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.9.3.tgz",
"integrity": "sha512-POjAPz0APAmX33WOQFGQrwLvlu7WLV4CFJMlB12b6ZSg+2q6fYu9kZwLCOA+x83zXfcPd1RpuWOKJW0GbBwLIQ==",
"version": "1.9.4",
"resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.9.4.tgz",
"integrity": "sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog==",
"dev": true,
"hasInstallScript": true,
"license": "MIT OR Apache-2.0",
@ -46,20 +46,20 @@
"url": "https://opencollective.com/biome"
},
"optionalDependencies": {
"@biomejs/cli-darwin-arm64": "1.9.3",
"@biomejs/cli-darwin-x64": "1.9.3",
"@biomejs/cli-linux-arm64": "1.9.3",
"@biomejs/cli-linux-arm64-musl": "1.9.3",
"@biomejs/cli-linux-x64": "1.9.3",
"@biomejs/cli-linux-x64-musl": "1.9.3",
"@biomejs/cli-win32-arm64": "1.9.3",
"@biomejs/cli-win32-x64": "1.9.3"
"@biomejs/cli-darwin-arm64": "1.9.4",
"@biomejs/cli-darwin-x64": "1.9.4",
"@biomejs/cli-linux-arm64": "1.9.4",
"@biomejs/cli-linux-arm64-musl": "1.9.4",
"@biomejs/cli-linux-x64": "1.9.4",
"@biomejs/cli-linux-x64-musl": "1.9.4",
"@biomejs/cli-win32-arm64": "1.9.4",
"@biomejs/cli-win32-x64": "1.9.4"
}
},
"node_modules/@biomejs/cli-darwin-arm64": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.9.3.tgz",
"integrity": "sha512-QZzD2XrjJDUyIZK+aR2i5DDxCJfdwiYbUKu9GzkCUJpL78uSelAHAPy7m0GuPMVtF/Uo+OKv97W3P9nuWZangQ==",
"version": "1.9.4",
"resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.9.4.tgz",
"integrity": "sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw==",
"cpu": [
"arm64"
],
@ -74,9 +74,9 @@
}
},
"node_modules/@biomejs/cli-darwin-x64": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.9.3.tgz",
"integrity": "sha512-vSCoIBJE0BN3SWDFuAY/tRavpUtNoqiceJ5PrU3xDfsLcm/U6N93JSM0M9OAiC/X7mPPfejtr6Yc9vSgWlEgVw==",
"version": "1.9.4",
"resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.9.4.tgz",
"integrity": "sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg==",
"cpu": [
"x64"
],
@ -91,9 +91,9 @@
}
},
"node_modules/@biomejs/cli-linux-arm64": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.9.3.tgz",
"integrity": "sha512-vJkAimD2+sVviNTbaWOGqEBy31cW0ZB52KtpVIbkuma7PlfII3tsLhFa+cwbRAcRBkobBBhqZ06hXoZAN8NODQ==",
"version": "1.9.4",
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.9.4.tgz",
"integrity": "sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g==",
"cpu": [
"arm64"
],
@ -108,9 +108,9 @@
}
},
"node_modules/@biomejs/cli-linux-arm64-musl": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.9.3.tgz",
"integrity": "sha512-VBzyhaqqqwP3bAkkBrhVq50i3Uj9+RWuj+pYmXrMDgjS5+SKYGE56BwNw4l8hR3SmYbLSbEo15GcV043CDSk+Q==",
"version": "1.9.4",
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.9.4.tgz",
"integrity": "sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA==",
"cpu": [
"arm64"
],
@ -125,9 +125,9 @@
}
},
"node_modules/@biomejs/cli-linux-x64": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.9.3.tgz",
"integrity": "sha512-x220V4c+romd26Mu1ptU+EudMXVS4xmzKxPVb9mgnfYlN4Yx9vD5NZraSx/onJnd3Gh/y8iPUdU5CDZJKg9COA==",
"version": "1.9.4",
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.9.4.tgz",
"integrity": "sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg==",
"cpu": [
"x64"
],
@ -142,9 +142,9 @@
}
},
"node_modules/@biomejs/cli-linux-x64-musl": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.9.3.tgz",
"integrity": "sha512-TJmnOG2+NOGM72mlczEsNki9UT+XAsMFAOo8J0me/N47EJ/vkLXxf481evfHLlxMejTY6IN8SdRSiPVLv6AHlA==",
"version": "1.9.4",
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.9.4.tgz",
"integrity": "sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg==",
"cpu": [
"x64"
],
@ -159,9 +159,9 @@
}
},
"node_modules/@biomejs/cli-win32-arm64": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.9.3.tgz",
"integrity": "sha512-lg/yZis2HdQGsycUvHWSzo9kOvnGgvtrYRgoCEwPBwwAL8/6crOp3+f47tPwI/LI1dZrhSji7PNsGKGHbwyAhw==",
"version": "1.9.4",
"resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.9.4.tgz",
"integrity": "sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg==",
"cpu": [
"arm64"
],
@ -176,9 +176,9 @@
}
},
"node_modules/@biomejs/cli-win32-x64": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.9.3.tgz",
"integrity": "sha512-cQMy2zanBkVLpmmxXdK6YePzmZx0s5Z7KEnwmrW54rcXK3myCNbQa09SwGZ8i/8sLw0H9F3X7K4rxVNGU8/D4Q==",
"version": "1.9.4",
"resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.9.4.tgz",
"integrity": "sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA==",
"cpu": [
"x64"
],
@ -203,9 +203,9 @@
}
},
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
"integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
"version": "0.3.8",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
"integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -266,6 +266,28 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@types/eslint": {
"version": "9.6.1",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz",
"integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/estree": "*",
"@types/json-schema": "*"
}
},
"node_modules/@types/eslint-scope": {
"version": "3.7.7",
"resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz",
"integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/eslint": "*",
"@types/estree": "*"
}
},
"node_modules/@types/estree": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
@ -299,16 +321,16 @@
"license": "MIT"
},
"node_modules/@types/mocha": {
"version": "10.0.9",
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.9.tgz",
"integrity": "sha512-sicdRoWtYevwxjOHNMPTl3vSfJM6oyW8o1wXeI7uww6b6xHg8eBznQDNSGBCDJmsE8UMxP05JgZRtsKbTqt//Q==",
"version": "10.0.10",
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.10.tgz",
"integrity": "sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/node": {
"version": "18.19.55",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.55.tgz",
"integrity": "sha512-zzw5Vw52205Zr/nmErSEkN5FLqXPuKX/k5d1D7RKHATGqU7y6YfX9QxZraUzUrFGqH6XzOzG196BC35ltJC4Cw==",
"version": "18.19.75",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.75.tgz",
"integrity": "sha512-UIksWtThob6ZVSyxcOqCLOUNg/dyO1Qvx4McgeuhrEtHTLFTf7BBhEazaE4K806FGTPtzd/2sE90qn4fVr7cyw==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -316,9 +338,9 @@
}
},
"node_modules/@types/vscode": {
"version": "1.94.0",
"resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.94.0.tgz",
"integrity": "sha512-UyQOIUT0pb14XSqJskYnRwD2aG0QrPVefIfrW1djR+/J4KeFQ0i1+hjZoaAmeNf3Z2jleK+R2hv+EboG/m8ruw==",
"version": "1.97.0",
"resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.97.0.tgz",
"integrity": "sha512-ueE73loeOTe7olaVyqP9mrRI54kVPJifUPjblZo9fYcv1CuVLPOEKEkqW0GkqPC454+nCEoigLWnC2Pp7prZ9w==",
"dev": true,
"license": "MIT"
},
@ -340,73 +362,73 @@
}
},
"node_modules/@webassemblyjs/ast": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz",
"integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==",
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz",
"integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@webassemblyjs/helper-numbers": "1.11.6",
"@webassemblyjs/helper-wasm-bytecode": "1.11.6"
"@webassemblyjs/helper-numbers": "1.13.2",
"@webassemblyjs/helper-wasm-bytecode": "1.13.2"
}
},
"node_modules/@webassemblyjs/floating-point-hex-parser": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz",
"integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==",
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz",
"integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==",
"dev": true,
"license": "MIT"
},
"node_modules/@webassemblyjs/helper-api-error": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz",
"integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==",
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz",
"integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@webassemblyjs/helper-buffer": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz",
"integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==",
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz",
"integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==",
"dev": true,
"license": "MIT"
},
"node_modules/@webassemblyjs/helper-numbers": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz",
"integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==",
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz",
"integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@webassemblyjs/floating-point-hex-parser": "1.11.6",
"@webassemblyjs/helper-api-error": "1.11.6",
"@webassemblyjs/floating-point-hex-parser": "1.13.2",
"@webassemblyjs/helper-api-error": "1.13.2",
"@xtuc/long": "4.2.2"
}
},
"node_modules/@webassemblyjs/helper-wasm-bytecode": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz",
"integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==",
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz",
"integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==",
"dev": true,
"license": "MIT"
},
"node_modules/@webassemblyjs/helper-wasm-section": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz",
"integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==",
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz",
"integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@webassemblyjs/ast": "1.12.1",
"@webassemblyjs/helper-buffer": "1.12.1",
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
"@webassemblyjs/wasm-gen": "1.12.1"
"@webassemblyjs/ast": "1.14.1",
"@webassemblyjs/helper-buffer": "1.14.1",
"@webassemblyjs/helper-wasm-bytecode": "1.13.2",
"@webassemblyjs/wasm-gen": "1.14.1"
}
},
"node_modules/@webassemblyjs/ieee754": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz",
"integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==",
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz",
"integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -414,9 +436,9 @@
}
},
"node_modules/@webassemblyjs/leb128": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz",
"integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==",
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz",
"integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
@ -424,79 +446,79 @@
}
},
"node_modules/@webassemblyjs/utf8": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz",
"integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==",
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz",
"integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@webassemblyjs/wasm-edit": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz",
"integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==",
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz",
"integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@webassemblyjs/ast": "1.12.1",
"@webassemblyjs/helper-buffer": "1.12.1",
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
"@webassemblyjs/helper-wasm-section": "1.12.1",
"@webassemblyjs/wasm-gen": "1.12.1",
"@webassemblyjs/wasm-opt": "1.12.1",
"@webassemblyjs/wasm-parser": "1.12.1",
"@webassemblyjs/wast-printer": "1.12.1"
"@webassemblyjs/ast": "1.14.1",
"@webassemblyjs/helper-buffer": "1.14.1",
"@webassemblyjs/helper-wasm-bytecode": "1.13.2",
"@webassemblyjs/helper-wasm-section": "1.14.1",
"@webassemblyjs/wasm-gen": "1.14.1",
"@webassemblyjs/wasm-opt": "1.14.1",
"@webassemblyjs/wasm-parser": "1.14.1",
"@webassemblyjs/wast-printer": "1.14.1"
}
},
"node_modules/@webassemblyjs/wasm-gen": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz",
"integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==",
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz",
"integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@webassemblyjs/ast": "1.12.1",
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
"@webassemblyjs/ieee754": "1.11.6",
"@webassemblyjs/leb128": "1.11.6",
"@webassemblyjs/utf8": "1.11.6"
"@webassemblyjs/ast": "1.14.1",
"@webassemblyjs/helper-wasm-bytecode": "1.13.2",
"@webassemblyjs/ieee754": "1.13.2",
"@webassemblyjs/leb128": "1.13.2",
"@webassemblyjs/utf8": "1.13.2"
}
},
"node_modules/@webassemblyjs/wasm-opt": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz",
"integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==",
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz",
"integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@webassemblyjs/ast": "1.12.1",
"@webassemblyjs/helper-buffer": "1.12.1",
"@webassemblyjs/wasm-gen": "1.12.1",
"@webassemblyjs/wasm-parser": "1.12.1"
"@webassemblyjs/ast": "1.14.1",
"@webassemblyjs/helper-buffer": "1.14.1",
"@webassemblyjs/wasm-gen": "1.14.1",
"@webassemblyjs/wasm-parser": "1.14.1"
}
},
"node_modules/@webassemblyjs/wasm-parser": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz",
"integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==",
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz",
"integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@webassemblyjs/ast": "1.12.1",
"@webassemblyjs/helper-api-error": "1.11.6",
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
"@webassemblyjs/ieee754": "1.11.6",
"@webassemblyjs/leb128": "1.11.6",
"@webassemblyjs/utf8": "1.11.6"
"@webassemblyjs/ast": "1.14.1",
"@webassemblyjs/helper-api-error": "1.13.2",
"@webassemblyjs/helper-wasm-bytecode": "1.13.2",
"@webassemblyjs/ieee754": "1.13.2",
"@webassemblyjs/leb128": "1.13.2",
"@webassemblyjs/utf8": "1.13.2"
}
},
"node_modules/@webassemblyjs/wast-printer": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz",
"integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==",
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz",
"integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@webassemblyjs/ast": "1.12.1",
"@webassemblyjs/ast": "1.14.1",
"@xtuc/long": "4.2.2"
}
},
@ -562,9 +584,9 @@
"license": "Apache-2.0"
},
"node_modules/acorn": {
"version": "8.12.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz",
"integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
"version": "8.14.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
"integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
"dev": true,
"license": "MIT",
"bin": {
@ -574,25 +596,12 @@
"node": ">=0.4.0"
}
},
"node_modules/acorn-import-attributes": {
"version": "1.9.5",
"resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz",
"integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==",
"dev": true,
"license": "MIT",
"peerDependencies": {
"acorn": "^8"
}
},
"node_modules/agent-base": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
"integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==",
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz",
"integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==",
"dev": true,
"license": "MIT",
"dependencies": {
"debug": "^4.3.4"
},
"engines": {
"node": ">= 14"
}
@ -614,6 +623,48 @@
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/ajv-formats": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
"integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
"dev": true,
"license": "MIT",
"dependencies": {
"ajv": "^8.0.0"
},
"peerDependencies": {
"ajv": "^8.0.0"
},
"peerDependenciesMeta": {
"ajv": {
"optional": true
}
}
},
"node_modules/ajv-formats/node_modules/ajv": {
"version": "8.17.1",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
"dev": true,
"license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.3",
"fast-uri": "^3.0.1",
"json-schema-traverse": "^1.0.0",
"require-from-string": "^2.0.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/ajv-formats/node_modules/json-schema-traverse": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
"dev": true,
"license": "MIT"
},
"node_modules/ajv-keywords": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
@ -781,9 +832,9 @@
"license": "ISC"
},
"node_modules/browserslist": {
"version": "4.24.0",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz",
"integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==",
"version": "4.24.4",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz",
"integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==",
"dev": true,
"funding": [
{
@ -801,10 +852,10 @@
],
"license": "MIT",
"dependencies": {
"caniuse-lite": "^1.0.30001663",
"electron-to-chromium": "^1.5.28",
"node-releases": "^2.0.18",
"update-browserslist-db": "^1.1.0"
"caniuse-lite": "^1.0.30001688",
"electron-to-chromium": "^1.5.73",
"node-releases": "^2.0.19",
"update-browserslist-db": "^1.1.1"
},
"bin": {
"browserslist": "cli.js"
@ -859,9 +910,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001669",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001669.tgz",
"integrity": "sha512-DlWzFDJqstqtIVx1zeSpIMLjunf5SmwOw0N2Ck/QSQdS8PLS4+9HrLaYei4w8BIAL7IB/UEDu889d8vhCTPA0w==",
"version": "1.0.30001699",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001699.tgz",
"integrity": "sha512-b+uH5BakXZ9Do9iK+CkDmctUSEqZl+SP056vc5usa0PL+ev5OHw003rZXcnjNDv3L8P5j6rwT6C0BPKSikW08w==",
"dev": true,
"funding": [
{
@ -1087,9 +1138,9 @@
"license": "MIT"
},
"node_modules/cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -1102,9 +1153,9 @@
}
},
"node_modules/debug": {
"version": "4.3.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
"integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -1150,9 +1201,9 @@
"license": "MIT"
},
"node_modules/electron-to-chromium": {
"version": "1.5.39",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.39.tgz",
"integrity": "sha512-4xkpSR6CjuiaNyvwiWDI85N9AxsvbPawB8xc7yzLPonYTuP19BVgYweKyUMFtHEZgIcHWMt1ks5Cqx2m+6/Grg==",
"version": "1.5.96",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.96.tgz",
"integrity": "sha512-8AJUW6dh75Fm/ny8+kZKJzI1pgoE8bKLZlzDU2W1ENd+DXKJrx7I7l9hb8UWR4ojlnb5OlixMt00QWiYJoVw1w==",
"dev": true,
"license": "ISC"
},
@ -1164,9 +1215,9 @@
"license": "MIT"
},
"node_modules/enhanced-resolve": {
"version": "5.17.1",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz",
"integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==",
"version": "5.18.1",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz",
"integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -1191,9 +1242,9 @@
}
},
"node_modules/es-module-lexer": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz",
"integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==",
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz",
"integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==",
"dev": true,
"license": "MIT"
},
@ -1291,6 +1342,23 @@
"dev": true,
"license": "MIT"
},
"node_modules/fast-uri": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz",
"integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fastify"
},
{
"type": "opencollective",
"url": "https://opencollective.com/fastify"
}
],
"license": "BSD-3-Clause"
},
"node_modules/fastest-levenshtein": {
"version": "1.0.16",
"resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz",
@ -1479,13 +1547,13 @@
}
},
"node_modules/https-proxy-agent": {
"version": "7.0.5",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz",
"integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==",
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
"integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
"dev": true,
"license": "MIT",
"dependencies": {
"agent-base": "^7.0.2",
"agent-base": "^7.1.2",
"debug": "4"
},
"engines": {
@ -1583,9 +1651,9 @@
}
},
"node_modules/is-core-module": {
"version": "2.15.1",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz",
"integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==",
"version": "2.16.1",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
"integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -1899,9 +1967,9 @@
}
},
"node_modules/mocha": {
"version": "10.7.3",
"resolved": "https://registry.npmjs.org/mocha/-/mocha-10.7.3.tgz",
"integrity": "sha512-uQWxAu44wwiACGqjbPYmjo7Lg8sFrS3dQe7PP2FQI+woptP4vZXSMcfMyFL/e1yFEeEpV4RtyTpZROOKmxis+A==",
"version": "10.8.2",
"resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz",
"integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -1949,9 +2017,9 @@
"license": "MIT"
},
"node_modules/node-releases": {
"version": "2.0.18",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz",
"integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==",
"version": "2.0.19",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
"integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
"dev": true,
"license": "MIT"
},
@ -2016,9 +2084,9 @@
}
},
"node_modules/ora/node_modules/chalk": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
"integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz",
"integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==",
"dev": true,
"license": "MIT",
"engines": {
@ -2135,9 +2203,9 @@
"license": "MIT"
},
"node_modules/picocolors": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz",
"integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==",
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
"dev": true,
"license": "ISC"
},
@ -2302,20 +2370,33 @@
"node": ">=0.10.0"
}
},
"node_modules/require-from-string": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/resolve": {
"version": "1.22.8",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
"integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
"version": "1.22.10",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
"integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==",
"dev": true,
"license": "MIT",
"dependencies": {
"is-core-module": "^2.13.0",
"is-core-module": "^2.16.0",
"path-parse": "^1.0.7",
"supports-preserve-symlinks-flag": "^1.0.0"
},
"bin": {
"resolve": "bin/resolve"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@ -2387,9 +2468,9 @@
}
},
"node_modules/semver": {
"version": "7.6.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
"integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
"version": "7.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
"integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
@ -2602,9 +2683,9 @@
}
},
"node_modules/terser": {
"version": "5.34.1",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.34.1.tgz",
"integrity": "sha512-FsJZ7iZLd/BXkz+4xrRTGJ26o/6VTjQytUk8b8OxkwcD2I+79VPJlz7qss1+zE7h8GNIScFqXcDyJ/KqBYZFVA==",
"version": "5.38.1",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.38.1.tgz",
"integrity": "sha512-GWANVlPM/ZfYzuPHjq0nxT+EbOEDDN3Jwhwdg1D8TU8oSkktp8w64Uq4auuGLxFSoNTRDncTq2hQHX1Ld9KHkA==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
@ -2621,17 +2702,17 @@
}
},
"node_modules/terser-webpack-plugin": {
"version": "5.3.10",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz",
"integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==",
"version": "5.3.11",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.11.tgz",
"integrity": "sha512-RVCsMfuD0+cTt3EwX8hSl2Ks56EbFHWmhluwcqoPKtBnfjiT6olaq7PRIRfhyU8nnC2MrnDrBLfrD/RGE+cVXQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/trace-mapping": "^0.3.20",
"@jridgewell/trace-mapping": "^0.3.25",
"jest-worker": "^27.4.5",
"schema-utils": "^3.1.1",
"serialize-javascript": "^6.0.1",
"terser": "^5.26.0"
"schema-utils": "^4.3.0",
"serialize-javascript": "^6.0.2",
"terser": "^5.31.1"
},
"engines": {
"node": ">= 10.13.0"
@ -2655,6 +2736,63 @@
}
}
},
"node_modules/terser-webpack-plugin/node_modules/ajv": {
"version": "8.17.1",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
"dev": true,
"license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.3",
"fast-uri": "^3.0.1",
"json-schema-traverse": "^1.0.0",
"require-from-string": "^2.0.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/terser-webpack-plugin/node_modules/ajv-keywords": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
"integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
"dev": true,
"license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.3"
},
"peerDependencies": {
"ajv": "^8.8.2"
}
},
"node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
"dev": true,
"license": "MIT"
},
"node_modules/terser-webpack-plugin/node_modules/schema-utils": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz",
"integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/json-schema": "^7.0.9",
"ajv": "^8.9.0",
"ajv-formats": "^2.1.1",
"ajv-keywords": "^5.1.0"
},
"engines": {
"node": ">= 10.13.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
}
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@ -2669,9 +2807,9 @@
}
},
"node_modules/ts-loader": {
"version": "9.5.1",
"resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz",
"integrity": "sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==",
"version": "9.5.2",
"resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.2.tgz",
"integrity": "sha512-Qo4piXvOTWcMGIgRiuFa6nHNm+54HbYaZCKqc9eeZCLRy3XqafQgwX2F7mofrbJG3g7EEb+lkiR+z2Lic2s3Zw==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -2711,9 +2849,9 @@
"license": "MIT"
},
"node_modules/update-browserslist-db": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz",
"integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==",
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz",
"integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==",
"dev": true,
"funding": [
{
@ -2732,7 +2870,7 @@
"license": "MIT",
"dependencies": {
"escalade": "^3.2.0",
"picocolors": "^1.1.0"
"picocolors": "^1.1.1"
},
"bin": {
"update-browserslist-db": "cli.js"
@ -2812,19 +2950,19 @@
}
},
"node_modules/webpack": {
"version": "5.95.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.95.0.tgz",
"integrity": "sha512-2t3XstrKULz41MNMBF+cJ97TyHdyQ8HCt//pqErqDvNjU9YQBnZxIHa11VXsi7F3mb5/aO2tuDxdeTPdU7xu9Q==",
"version": "5.97.1",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.97.1.tgz",
"integrity": "sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/estree": "^1.0.5",
"@webassemblyjs/ast": "^1.12.1",
"@webassemblyjs/wasm-edit": "^1.12.1",
"@webassemblyjs/wasm-parser": "^1.12.1",
"acorn": "^8.7.1",
"acorn-import-attributes": "^1.9.5",
"browserslist": "^4.21.10",
"@types/eslint-scope": "^3.7.7",
"@types/estree": "^1.0.6",
"@webassemblyjs/ast": "^1.14.1",
"@webassemblyjs/wasm-edit": "^1.14.1",
"@webassemblyjs/wasm-parser": "^1.14.1",
"acorn": "^8.14.0",
"browserslist": "^4.24.0",
"chrome-trace-event": "^1.0.2",
"enhanced-resolve": "^5.17.1",
"es-module-lexer": "^1.2.1",

View File

@ -3,7 +3,7 @@
"displayName": "pylyzer",
"description": "A fast Python static code analyzer & language server for VSCode",
"publisher": "pylyzer",
"version": "0.1.10",
"version": "0.1.11",
"engines": {
"vscode": "^1.70.0"
},
@ -68,6 +68,11 @@
"default": true,
"markdownDescription": "Enable smart completion (see [ELS features](https://github.com/erg-lang/erg/blob/main/crates/els/doc/features.md))"
},
"pylyzer.deepCompletion": {
"type": "boolean",
"default": true,
"markdownDescription": "Enable deep completion (see [ELS features](https://github.com/erg-lang/erg/blob/main/crates/els/doc/features.md))"
},
"pylyzer.signatureHelp": {
"type": "boolean",
"default": true,

View File

@ -22,6 +22,7 @@ async function startLanguageClient(context: ExtensionContext) {
const enableHover = workspace.getConfiguration("pylyzer").get<boolean>("hover", true);
const enableCompletion = workspace.getConfiguration("pylyzer").get<boolean>("completion", true);
const smartCompletion = workspace.getConfiguration("pylyzer").get<boolean>("smartCompletion", true);
const deepCompletion = workspace.getConfiguration("pylyzer").get<boolean>("deepCompletion", true);
const enableSignatureHelp = workspace.getConfiguration("pylyzer").get<boolean>("signatureHelp", true);
const enableDocumentLink = workspace.getConfiguration("pylyzer").get<boolean>("documentLink", true);
const enableCodeAction = workspace.getConfiguration("pylyzer").get<boolean>("codeAction", true);
@ -54,6 +55,10 @@ async function startLanguageClient(context: ExtensionContext) {
args.push("--disable");
args.push("smartCompletion");
}
if (!deepCompletion) {
args.push("--disable");
args.push("deepCompletion");
}
if (!enableSignatureHelp) {
args.push("--disable");
args.push("signatureHelp");

View File

@ -6,6 +6,7 @@ use erg_common::config::{ErgConfig, ErgMode};
use erg_common::io::Input;
use erg_common::pathutil::project_entry_file_of;
use erg_common::switch_lang;
use indexmap::IndexSet;
use crate::copy::clear_cache;
@ -18,7 +19,7 @@ fn entry_file() -> Option<PathBuf> {
let path = ent.path();
if path.file_name().is_some_and(|name| name == "__init__.py") {
return Some(path);
} else if path.extension().map_or(false, |ext| ext == "py") {
} else if path.extension().is_some_and(|ext| ext == "py") {
if opt_path.is_some() {
return None;
} else {
@ -49,7 +50,7 @@ OPTIONS
--clear-cache
--code/-c cmd
--dump-decl
--disable ",
--disable feat ",
"simplified_chinese" =>
"\
@ -67,7 +68,7 @@ OPTIONS
--clear-cache
--code/-c cmd
--dump-decl
--disable ",
--disable feat ",
"traditional_chinese" =>
"\
@ -85,7 +86,7 @@ OPTIONS
--clear-cache
--code/-c cmd
--dump-decl
--disable ",
--disable feat ",
"english" =>
"\
@ -103,7 +104,7 @@ OPTIONS
--clear-cache clear cache
--code/-c cmd program passed in as string
--dump-decl output type declaration file
--disable disable specified features",
--disable feat disable specified features",
)
}
@ -114,6 +115,7 @@ pub(crate) fn parse_args() -> ErgConfig {
let mut cfg = ErgConfig {
effect_check: false,
ownership_check: false,
respect_pyi: true,
..ErgConfig::default()
};
let mut runtime_args: Vec<&'static str> = Vec::new();
@ -171,6 +173,9 @@ pub(crate) fn parse_args() -> ErgConfig {
"--do-not-show-ext-errors" => {
cfg.do_not_show_ext_errors = true;
}
"--do-not-respect-pyi" => {
cfg.respect_pyi = false;
}
other if other.starts_with('-') => {
println!(
"\
@ -208,3 +213,57 @@ For more information try `pylyzer --help`"
cfg.runtime_args = runtime_args.into();
cfg
}
pub(crate) fn files_to_be_checked() -> IndexSet<Result<PathBuf, String>> {
let mut file_or_patterns = vec![];
let mut args = env::args().skip(1);
while let Some(arg) = &args.next() {
match arg.as_str() {
"--" => {
// Discard runtime args
break;
}
"--code" | "-c" | "--disable" | "--verbose" => {
// Skip options
let _ = &args.next();
continue;
}
file_or_pattern if file_or_pattern.starts_with("-") => {
// Skip flags
continue;
}
file_or_pattern => file_or_patterns.push(file_or_pattern.to_owned()),
}
}
let mut files = IndexSet::new();
for file_or_pattern in file_or_patterns {
if PathBuf::from(&file_or_pattern).is_file() {
files.insert(Ok(PathBuf::from(&file_or_pattern)));
} else {
let entries = glob::glob(&file_or_pattern);
match entries {
Err(_) => {
files.insert(Err(file_or_pattern));
continue;
}
Ok(entries) => {
let mut entries = entries.into_iter().peekable();
if entries.peek().is_none() {
files.insert(Err(file_or_pattern));
}
for entry in entries {
match entry {
Err(e) => eprintln!("err: {e}"),
Ok(path) if path.is_file() => {
files.insert(Ok(path));
}
_ => {}
}
}
}
}
}
}
files
}

View File

@ -63,7 +63,10 @@ fn rec_clear_cache(pkg: DirEntry) {
pkg.path().join("__pycache__")
};
if cache.exists() {
for cache_file in cache.read_dir().expect("Failed to read cache") {
let Ok(dir) = cache.read_dir() else {
return;
};
for cache_file in dir {
let Ok(cache_file) = cache_file else {
continue;
};
@ -73,7 +76,10 @@ fn rec_clear_cache(pkg: DirEntry) {
}
}
}
for entry in pkg.path().read_dir().expect("Failed to read dir") {
let Ok(dir) = pkg.path().read_dir() else {
return;
};
for entry in dir {
let Ok(entry) = entry else {
continue;
};

View File

@ -4,8 +4,11 @@ mod copy;
use els::Server;
use erg_common::config::ErgMode;
use erg_common::spawn::exec_new_thread;
use erg_common::style::colors::RED;
use erg_common::style::RESET;
use pylyzer_core::{PythonAnalyzer, SimplePythonParser};
use crate::config::files_to_be_checked;
use crate::copy::copy_dot_erg;
fn run() {
@ -15,8 +18,32 @@ fn run() {
let lang_server = Server::<PythonAnalyzer, SimplePythonParser>::new(cfg, None);
lang_server.run();
} else {
let mut analyzer = PythonAnalyzer::new(cfg);
analyzer.run();
let mut code = 0;
let files = files_to_be_checked();
if files.is_empty() {
let mut analyzer = PythonAnalyzer::new(cfg);
code = analyzer.run();
} else {
for path in files {
match path {
Err(invalid_file_or_pattern) => {
if code == 0 {
code = 1;
}
println!("{RED}Invalid file or pattern{RESET}: {invalid_file_or_pattern}");
}
Ok(path) => {
let cfg = cfg.inherit(path);
let mut analyzer = PythonAnalyzer::new(cfg);
let c = analyzer.run();
if c != 0 {
code = 1;
}
}
}
}
}
std::process::exit(code);
}
}

19
tests/abc.py Normal file
View File

@ -0,0 +1,19 @@
from collections.abc import Sequence
class Vec(Sequence):
x: list[int]
def __init__(self):
self.x = []
def __getitem__(self, i: int) -> int:
return self.x[i]
def __iter__(self):
return iter(self.x)
def __len__(self) -> int:
return len(self.x)
def __contains__(self, i: int) -> bool:
return i in self.x

View File

@ -1,4 +1,4 @@
from typing import Self
from typing import Self, List
class Empty: pass
emp = Empty()
@ -98,3 +98,42 @@ class MyList(list):
return MyList(lis)
else:
return None
class Implicit:
def __init__(self):
self.foo = False
def set_foo(self):
self.foo = True
class Cs:
cs: list[C]
cs2: List[C]
cs_list: list[list[C]]
def __init__(self, cs: list[C]):
self.cs = cs
self.cs2 = cs
self.cs_list = []
def add(self, c: C):
self.cs.append(c)
self.cs2.append(c)
self.cs_list.append([c])
class I:
def __init__(self):
self.ix: int = 1
if True:
self.init_y()
def init_y(self):
self.iy: int = 2
def foo(self):
self.iz: int = 1 # ERR
i = I()
_ = i.ix
_ = i.iy # OK
_ = i.iz # ERR

View File

@ -23,6 +23,10 @@ _ = t[0] == 1 # OK
_ = t[1] == 1 # ERR
_ = t[0:1]
s: set[int] = {1, 2}
s.add(1)
s.add("a") # ERR
def f(s: Str): return None
for i in getattr(1, "aaa", ()):
f(i)
@ -32,3 +36,16 @@ assert 1 in {1, 2}
assert 1 in {1: "a"}
assert 1 in (1, 2)
assert 1 in map(lambda x: x + 1, [0, 1, 2])
def func(d: dict, t: tuple, s: set):
_ = d.get("a")
s.add(1)
for i in t:
print(i)
list_comp = [i + 1 for i in range(10)]
assert list_comp[0] == 1
set_comp = {i + 1 for i in range(10)}
assert 1 in set_comp
dict_comp = {i: i + 1 for i in range(10)}
assert dict_comp[0] == 1

18
tests/err/class.py Normal file
View File

@ -0,0 +1,18 @@
class Foo:
def invalid_append(self):
paths: list[str] = []
paths.append(self) # ERR
class Bar:
foos: list[Foo]
def __init__(self, foos: list[Foo]) -> None:
self.foos = foos
def add_foo(self, foo: Foo):
self.foos.append(foo)
def invalid_add_foo(self):
self.foos.append(1) # ERR
_ = Bar([Bar([])]) # ERR

11
tests/err/property.py Normal file
View File

@ -0,0 +1,11 @@
class Foo:
x: int
def __init__(self, x):
self.x = x
@property
def foo(self):
return self.x
f = Foo(1)
print(f.foo + "a") # ERR

8
tests/err/type_spec.py Normal file
View File

@ -0,0 +1,8 @@
from typing import Callable, Mapping
_: Mapping[int, str, str] = ... # ERR
_: Mapping[int] = ... # ERR
_: Callable[[int, str]] = ... # ERR
_: Callable[int] = ... # ERR
_: dict[int] = ... # ERR
_: dict[int, int, int] = ... # ERR

View File

@ -1,5 +1,9 @@
l = [1, 2, 3]
_ = l[1:2]
_ = l[:]
_ = l[1:]
_ = l[:1]
_ = l[1:1:1]
print(l[2])
print(l["a"]) # ERR

View File

@ -13,3 +13,8 @@ from typing import Optional
x: Optional[int] = None
if x is not None:
x += 1
def sb(s: str | bytes) -> None:
if not isinstance(s, str):
str(s, "ascii")
return None

View File

@ -1,18 +1,29 @@
def imaginary(x):
x.imag
return x.imag
def imaginary2(x):
return imaginary(x)
assert imaginary(1) == 0
assert imaginary(1.0) <= 0.0
assert imaginary2(1) == 0
assert imaginary2(1.0) <= 0.0
print(imaginary("a")) # ERR
class C:
def method(self, x): return x
def call_method(obj, x):
obj.method(x)
return obj.method(x)
def call_method2(obj, x):
return call_method(obj, x)
def call_foo(x):
return x.foo("foo") # OK
c = C()
assert call_method(c, 1) == 1
assert call_method(c, 1) == "a" # ERR
assert call_method2(c, 1) == 1
print(call_method(1, 1)) # ERR
print(call_method(c)) # ERR

11
tests/property.py Normal file
View File

@ -0,0 +1,11 @@
class Foo:
x: int
def __init__(self, x):
self.x = x
@property
def foo(self):
return self.x
f = Foo(1)
assert f.foo + 1 == 2

View File

@ -44,3 +44,6 @@ assert j == 2
with open("test.py") as f:
for line in f.readlines():
print("line: " + line)
print(x := 1)
print(x)

View File

@ -59,6 +59,11 @@ pub fn expect(file_path: &'static str, warns: usize, errors: usize) -> Result<()
exec_new_thread(move || _expect(file_path, warns, errors), file_path)
}
#[test]
fn exec_abc() -> Result<(), String> {
expect("tests/abc.py", 0, 0)
}
#[test]
fn exec_test() -> Result<(), String> {
expect("tests/test.py", 0, 11)
@ -95,7 +100,12 @@ fn exec_func() -> Result<(), String> {
#[test]
fn exec_class() -> Result<(), String> {
expect("tests/class.py", 0, 6)
expect("tests/class.py", 0, 8)
}
#[test]
fn exec_class_err() -> Result<(), String> {
expect("tests/err/class.py", 0, 3)
}
#[test]
@ -118,6 +128,16 @@ fn exec_projection() -> Result<(), String> {
expect("tests/projection.py", 0, 5)
}
#[test]
fn exec_property() -> Result<(), String> {
expect("tests/property.py", 0, 0)
}
#[test]
fn exec_property_err() -> Result<(), String> {
expect("tests/err/property.py", 0, 1)
}
#[test]
fn exec_pyi() -> Result<(), String> {
expect("tests/pyi.py", 0, 5)
@ -145,7 +165,7 @@ fn exec_casting() -> Result<(), String> {
#[test]
fn exec_collection() -> Result<(), String> {
expect("tests/collection.py", 0, 4)
expect("tests/collection.py", 0, 5)
}
#[test]
@ -168,6 +188,11 @@ fn exec_typevar() -> Result<(), String> {
expect("tests/typevar.py", 0, 3)
}
#[test]
fn exec_type_spec() -> Result<(), String> {
expect("tests/err/type_spec.py", 0, 6)
}
#[test]
fn exec_union() -> Result<(), String> {
expect("tests/union.py", 0, 0)

View File

@ -3,3 +3,8 @@ if True:
b = True
if True:
b = "a" # ERR
counter = 100 # counter: Literal[100]
while counter > 0:
counter -= 1 # counter: Int
counter -= 1.0 # counter: Float