Rename Red Knot (#17820)

This commit is contained in:
Micha Reiser 2025-05-03 19:49:15 +02:00 committed by GitHub
parent e6a798b962
commit b51c4f82ea
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
1564 changed files with 1598 additions and 1578 deletions

10
.github/CODEOWNERS vendored
View file

@ -14,11 +14,11 @@
# flake8-pyi # flake8-pyi
/crates/ruff_linter/src/rules/flake8_pyi/ @AlexWaygood /crates/ruff_linter/src/rules/flake8_pyi/ @AlexWaygood
# Script for fuzzing the parser/red-knot etc. # Script for fuzzing the parser/ty etc.
/python/py-fuzzer/ @AlexWaygood /python/py-fuzzer/ @AlexWaygood
# red-knot # ty
/crates/red_knot* @carljm @MichaReiser @AlexWaygood @sharkdp @dcreager /crates/ty* @carljm @MichaReiser @AlexWaygood @sharkdp @dcreager
/crates/ruff_db/ @carljm @MichaReiser @AlexWaygood @sharkdp @dcreager /crates/ruff_db/ @carljm @MichaReiser @AlexWaygood @sharkdp @dcreager
/scripts/knot_benchmark/ @carljm @MichaReiser @AlexWaygood @sharkdp @dcreager /scripts/ty_benchmark/ @carljm @MichaReiser @AlexWaygood @sharkdp @dcreager
/crates/red_knot_python_semantic @carljm @AlexWaygood @sharkdp @dcreager /crates/ty_python_semantic @carljm @AlexWaygood @sharkdp @dcreager

View file

@ -36,8 +36,8 @@ jobs:
code: ${{ steps.check_code.outputs.changed }} code: ${{ steps.check_code.outputs.changed }}
# Flag that is raised when any code that affects the fuzzer is changed # Flag that is raised when any code that affects the fuzzer is changed
fuzz: ${{ steps.check_fuzzer.outputs.changed }} fuzz: ${{ steps.check_fuzzer.outputs.changed }}
# Flag that is set to "true" when code related to red-knot changes. # Flag that is set to "true" when code related to ty changes.
red_knot: ${{ steps.check_red_knot.outputs.changed }} ty: ${{ steps.check_ty.outputs.changed }}
# Flag that is set to "true" when code related to the playground changes. # Flag that is set to "true" when code related to the playground changes.
playground: ${{ steps.check_playground.outputs.changed }} playground: ${{ steps.check_playground.outputs.changed }}
@ -84,7 +84,7 @@ jobs:
if git diff --quiet "${MERGE_BASE}...HEAD" -- ':Cargo.toml' \ if git diff --quiet "${MERGE_BASE}...HEAD" -- ':Cargo.toml' \
':Cargo.lock' \ ':Cargo.lock' \
':crates/**' \ ':crates/**' \
':!crates/red_knot*/**' \ ':!crates/ty*/**' \
':!crates/ruff_python_formatter/**' \ ':!crates/ruff_python_formatter/**' \
':!crates/ruff_formatter/**' \ ':!crates/ruff_formatter/**' \
':!crates/ruff_dev/**' \ ':!crates/ruff_dev/**' \
@ -145,7 +145,7 @@ jobs:
run: | run: |
if git diff --quiet "${MERGE_BASE}...HEAD" -- ':**' \ if git diff --quiet "${MERGE_BASE}...HEAD" -- ':**' \
':!**/*.md' \ ':!**/*.md' \
':crates/red_knot_python_semantic/resources/mdtest/**/*.md' \ ':crates/ty_python_semantic/resources/mdtest/**/*.md' \
':!docs/**' \ ':!docs/**' \
':!assets/**' \ ':!assets/**' \
':.github/workflows/ci.yaml' \ ':.github/workflows/ci.yaml' \
@ -168,15 +168,15 @@ jobs:
echo "changed=true" >> "$GITHUB_OUTPUT" echo "changed=true" >> "$GITHUB_OUTPUT"
fi fi
- name: Check if the red-knot code changed - name: Check if the ty code changed
id: check_red_knot id: check_ty
env: env:
MERGE_BASE: ${{ steps.merge_base.outputs.sha }} MERGE_BASE: ${{ steps.merge_base.outputs.sha }}
run: | run: |
if git diff --quiet "${MERGE_BASE}...HEAD" -- \ if git diff --quiet "${MERGE_BASE}...HEAD" -- \
':Cargo.toml' \ ':Cargo.toml' \
':Cargo.lock' \ ':Cargo.lock' \
':crates/red_knot*/**' \ ':crates/ty*/**' \
':crates/ruff_db/**' \ ':crates/ruff_db/**' \
':crates/ruff_annotate_snippets/**' \ ':crates/ruff_annotate_snippets/**' \
':crates/ruff_python_ast/**' \ ':crates/ruff_python_ast/**' \
@ -221,7 +221,7 @@ jobs:
- name: "Clippy" - name: "Clippy"
run: cargo clippy --workspace --all-targets --all-features --locked -- -D warnings run: cargo clippy --workspace --all-targets --all-features --locked -- -D warnings
- name: "Clippy (wasm)" - name: "Clippy (wasm)"
run: cargo clippy -p ruff_wasm -p red_knot_wasm --target wasm32-unknown-unknown --all-features --locked -- -D warnings run: cargo clippy -p ruff_wasm -p ty_wasm --target wasm32-unknown-unknown --all-features --locked -- -D warnings
cargo-test-linux: cargo-test-linux:
name: "cargo test (linux)" name: "cargo test (linux)"
@ -246,14 +246,14 @@ jobs:
uses: taiki-e/install-action@ab3728c7ba6948b9b429627f4d55a68842b27f18 # v2 uses: taiki-e/install-action@ab3728c7ba6948b9b429627f4d55a68842b27f18 # v2
with: with:
tool: cargo-insta tool: cargo-insta
- name: Red-knot mdtests (GitHub annotations) - name: ty mdtests (GitHub annotations)
if: ${{ needs.determine_changes.outputs.red_knot == 'true' }} if: ${{ needs.determine_changes.outputs.ty == 'true' }}
env: env:
NO_COLOR: 1 NO_COLOR: 1
MDTEST_GITHUB_ANNOTATIONS_FORMAT: 1 MDTEST_GITHUB_ANNOTATIONS_FORMAT: 1
# Ignore errors if this step fails; we want to continue to later steps in the workflow anyway. # Ignore errors if this step fails; we want to continue to later steps in the workflow anyway.
# This step is just to get nice GitHub annotations on the PR diff in the files-changed tab. # This step is just to get nice GitHub annotations on the PR diff in the files-changed tab.
run: cargo test -p red_knot_python_semantic --test mdtest || true run: cargo test -p ty_python_semantic --test mdtest || true
- name: "Run tests" - name: "Run tests"
shell: bash shell: bash
env: env:
@ -268,7 +268,7 @@ jobs:
# sync, not just public items. Eventually we should do this for all # sync, not just public items. Eventually we should do this for all
# crates; for now add crates here as they are warning-clean to prevent # crates; for now add crates here as they are warning-clean to prevent
# regression. # regression.
- run: cargo doc --no-deps -p red_knot_python_semantic -p red_knot -p red_knot_test -p ruff_db --document-private-items - run: cargo doc --no-deps -p ty_python_semantic -p ty -p ty_test -p ruff_db --document-private-items
env: env:
# Setting RUSTDOCFLAGS because `cargo doc --check` isn't yet implemented (https://github.com/rust-lang/cargo/issues/10025). # Setting RUSTDOCFLAGS because `cargo doc --check` isn't yet implemented (https://github.com/rust-lang/cargo/issues/10025).
RUSTDOCFLAGS: "-D warnings" RUSTDOCFLAGS: "-D warnings"
@ -278,8 +278,8 @@ jobs:
path: target/debug/ruff path: target/debug/ruff
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with: with:
name: red_knot name: ty
path: target/debug/red_knot path: target/debug/ty
cargo-test-linux-release: cargo-test-linux-release:
name: "cargo test (linux, release)" name: "cargo test (linux, release)"
@ -362,9 +362,9 @@ jobs:
run: | run: |
cd crates/ruff_wasm cd crates/ruff_wasm
wasm-pack test --node wasm-pack test --node
- name: "Test red_knot_wasm" - name: "Test ty_wasm"
run: | run: |
cd crates/red_knot_wasm cd crates/ty_wasm
wasm-pack test --node wasm-pack test --node
cargo-build-release: cargo-build-release:
@ -636,29 +636,29 @@ jobs:
name: ecosystem-result name: ecosystem-result
path: ecosystem-result path: ecosystem-result
fuzz-redknot: fuzz-ty:
name: "Fuzz for new red-knot panics" name: "Fuzz for new ty panics"
runs-on: depot-ubuntu-22.04-16 runs-on: depot-ubuntu-22.04-16
needs: needs:
- cargo-test-linux - cargo-test-linux
- determine_changes - determine_changes
# Only runs on pull requests, since that is the only we way we can find the base version for comparison. # Only runs on pull requests, since that is the only we way we can find the base version for comparison.
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && github.event_name == 'pull_request' && needs.determine_changes.outputs.red_knot == 'true' }} if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && github.event_name == 'pull_request' && needs.determine_changes.outputs.ty == 'true' }}
timeout-minutes: 20 timeout-minutes: 20
steps: steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with: with:
persist-credentials: false persist-credentials: false
- uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 - uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1
name: Download new red-knot binary name: Download new ty binary
id: redknot-new id: ty-new
with: with:
name: red_knot name: ty
path: target/debug path: target/debug
- uses: dawidd6/action-download-artifact@20319c5641d495c8a52e688b7dc5fada6c3a9fbc # v8 - uses: dawidd6/action-download-artifact@20319c5641d495c8a52e688b7dc5fada6c3a9fbc # v8
name: Download baseline red-knot binary name: Download baseline ty binary
with: with:
name: red_knot name: ty
branch: ${{ github.event.pull_request.base.ref }} branch: ${{ github.event.pull_request.base.ref }}
workflow: "ci.yaml" workflow: "ci.yaml"
check_artifacts: true check_artifacts: true
@ -666,20 +666,20 @@ jobs:
- name: Fuzz - name: Fuzz
env: env:
FORCE_COLOR: 1 FORCE_COLOR: 1
NEW_REDKNOT: ${{ steps.redknot-new.outputs.download-path }} NEW_TY: ${{ steps.ty-new.outputs.download-path }}
run: | run: |
# Make executable, since artifact download doesn't preserve this # Make executable, since artifact download doesn't preserve this
chmod +x "${PWD}/red_knot" "${NEW_REDKNOT}/red_knot" chmod +x "${PWD}/ty" "${NEW_TY}/ty"
( (
uvx \ uvx \
--python="${PYTHON_VERSION}" \ --python="${PYTHON_VERSION}" \
--from=./python/py-fuzzer \ --from=./python/py-fuzzer \
fuzz \ fuzz \
--test-executable="${NEW_REDKNOT}/red_knot" \ --test-executable="${NEW_TY}/ty" \
--baseline-executable="${PWD}/red_knot" \ --baseline-executable="${PWD}/ty" \
--only-new-bugs \ --only-new-bugs \
--bin=red_knot \ --bin=ty \
0-500 0-500
) )

View file

@ -38,17 +38,17 @@ jobs:
- name: "Install mold" - name: "Install mold"
uses: rui314/setup-mold@e16410e7f8d9e167b74ad5697a9089a35126eb50 # v1 uses: rui314/setup-mold@e16410e7f8d9e167b74ad5697a9089a35126eb50 # v1
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8 - uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
- name: Build Red Knot - name: Build ty
# A release build takes longer (2 min vs 1 min), but the property tests run much faster in release # A release build takes longer (2 min vs 1 min), but the property tests run much faster in release
# mode (1.5 min vs 14 min), so the overall time is shorter with a release build. # mode (1.5 min vs 14 min), so the overall time is shorter with a release build.
run: cargo build --locked --release --package red_knot_python_semantic --tests run: cargo build --locked --release --package ty_python_semantic --tests
- name: Run property tests - name: Run property tests
shell: bash shell: bash
run: | run: |
export QUICKCHECK_TESTS=100000 export QUICKCHECK_TESTS=100000
for _ in {1..5}; do for _ in {1..5}; do
cargo test --locked --release --package red_knot_python_semantic -- --ignored list::property_tests cargo test --locked --release --package ty_python_semantic -- --ignored list::property_tests
cargo test --locked --release --package red_knot_python_semantic -- --ignored types::property_tests::stable cargo test --locked --release --package ty_python_semantic -- --ignored types::property_tests::stable
done done
create-issue-on-failure: create-issue-on-failure:
@ -68,5 +68,5 @@ jobs:
repo: "ruff", repo: "ruff",
title: `Daily property test run failed on ${new Date().toDateString()}`, title: `Daily property test run failed on ${new Date().toDateString()}`,
body: "Run listed here: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", body: "Run listed here: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
labels: ["bug", "red-knot", "testing"], labels: ["bug", "ty", "testing"],
}) })

View file

@ -5,7 +5,7 @@ permissions: {}
on: on:
pull_request: pull_request:
paths: paths:
- "crates/red_knot*/**" - "crates/ty*/**"
- "crates/ruff_db" - "crates/ruff_db"
- "crates/ruff_python_ast" - "crates/ruff_python_ast"
- "crates/ruff_python_parser" - "crates/ruff_python_parser"
@ -50,7 +50,7 @@ jobs:
run: | run: |
cd ruff cd ruff
PRIMER_SELECTOR="$(paste -s -d'|' crates/red_knot_python_semantic/resources/primer/good.txt)" PRIMER_SELECTOR="$(paste -s -d'|' crates/ty_python_semantic/resources/primer/good.txt)"
echo "new commit" echo "new commit"
git rev-list --format=%s --max-count=1 "$GITHUB_SHA" git rev-list --format=%s --max-count=1 "$GITHUB_SHA"
@ -65,10 +65,10 @@ jobs:
echo "Project selector: $PRIMER_SELECTOR" echo "Project selector: $PRIMER_SELECTOR"
# Allow the exit code to be 0 or 1, only fail for actual mypy_primer crashes/bugs # Allow the exit code to be 0 or 1, only fail for actual mypy_primer crashes/bugs
uvx \ uvx \
--from="git+https://github.com/hauntsaninja/mypy_primer@b83b9eade0b7ed2f4b9b129b163acac1ecb48f71" \ --from="git+https://github.com/hauntsaninja/mypy_primer@4b15cf3b07db69db67bbfaebfffb2a8a28040933" \
mypy_primer \ mypy_primer \
--repo ruff \ --repo ruff \
--type-checker knot \ --type-checker ty \
--old base_commit \ --old base_commit \
--new "$GITHUB_SHA" \ --new "$GITHUB_SHA" \
--project-selector "/($PRIMER_SELECTOR)\$" \ --project-selector "/($PRIMER_SELECTOR)\$" \

View file

@ -1,5 +1,5 @@
# Publish the Red Knot playground. # Publish the ty playground.
name: "[Knot Playground] Release" name: "[ty Playground] Release"
permissions: {} permissions: {}
@ -7,12 +7,12 @@ on:
push: push:
branches: [main] branches: [main]
paths: paths:
- "crates/red_knot*/**" - "crates/ty*/**"
- "crates/ruff_db/**" - "crates/ruff_db/**"
- "crates/ruff_python_ast/**" - "crates/ruff_python_ast/**"
- "crates/ruff_python_parser/**" - "crates/ruff_python_parser/**"
- "playground/**" - "playground/**"
- ".github/workflows/publish-knot-playground.yml" - ".github/workflows/publish-ty-playground.yml"
concurrency: concurrency:
group: ${{ github.workflow }}-${{ github.ref_name }} group: ${{ github.workflow }}-${{ github.ref_name }}
@ -45,8 +45,8 @@ jobs:
- name: "Run TypeScript checks" - name: "Run TypeScript checks"
run: npm run check run: npm run check
working-directory: playground working-directory: playground
- name: "Build Knot playground" - name: "Build ty playground"
run: npm run build --workspace knot-playground run: npm run build --workspace ty-playground
working-directory: playground working-directory: playground
- name: "Deploy to Cloudflare Pages" - name: "Deploy to Cloudflare Pages"
if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }} if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }}
@ -55,4 +55,4 @@ jobs:
apiToken: ${{ secrets.CF_API_TOKEN }} apiToken: ${{ secrets.CF_API_TOKEN }}
accountId: ${{ secrets.CF_ACCOUNT_ID }} accountId: ${{ secrets.CF_ACCOUNT_ID }}
# `github.head_ref` is only set during pull requests and for manual runs or tags we use `main` to deploy to production # `github.head_ref` is only set during pull requests and for manual runs or tags we use `main` to deploy to production
command: pages deploy playground/knot/dist --project-name=knot-playground --branch ${{ github.head_ref || 'main' }} --commit-hash ${GITHUB_SHA} command: pages deploy playground/ty/dist --project-name=ty-playground --branch ${{ github.head_ref || 'main' }} --commit-hash ${GITHUB_SHA}

View file

@ -39,13 +39,13 @@ jobs:
- name: Sync typeshed - name: Sync typeshed
id: sync id: sync
run: | run: |
rm -rf ruff/crates/red_knot_vendored/vendor/typeshed rm -rf ruff/crates/ty_vendored/vendor/typeshed
mkdir ruff/crates/red_knot_vendored/vendor/typeshed mkdir ruff/crates/ty_vendored/vendor/typeshed
cp typeshed/README.md ruff/crates/red_knot_vendored/vendor/typeshed cp typeshed/README.md ruff/crates/ty_vendored/vendor/typeshed
cp typeshed/LICENSE ruff/crates/red_knot_vendored/vendor/typeshed cp typeshed/LICENSE ruff/crates/ty_vendored/vendor/typeshed
cp -r typeshed/stdlib ruff/crates/red_knot_vendored/vendor/typeshed/stdlib cp -r typeshed/stdlib ruff/crates/ty_vendored/vendor/typeshed/stdlib
rm -rf ruff/crates/red_knot_vendored/vendor/typeshed/stdlib/@tests rm -rf ruff/crates/ty_vendored/vendor/typeshed/stdlib/@tests
git -C typeshed rev-parse HEAD > ruff/crates/red_knot_vendored/vendor/typeshed/source_commit.txt git -C typeshed rev-parse HEAD > ruff/crates/ty_vendored/vendor/typeshed/source_commit.txt
- name: Commit the changes - name: Commit the changes
id: commit id: commit
if: ${{ steps.sync.outcome == 'success' }} if: ${{ steps.sync.outcome == 'success' }}
@ -79,5 +79,5 @@ jobs:
repo: "ruff", repo: "ruff",
title: `Automated typeshed sync failed on ${new Date().toDateString()}`, title: `Automated typeshed sync failed on ${new Date().toDateString()}`,
body: "Run listed here: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", body: "Run listed here: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
labels: ["bug", "red-knot"], labels: ["bug", "ty"],
}) })

View file

@ -3,8 +3,8 @@ fail_fast: false
exclude: | exclude: |
(?x)^( (?x)^(
.github/workflows/release.yml| .github/workflows/release.yml|
crates/red_knot_vendored/vendor/.*| crates/ty_vendored/vendor/.*|
crates/red_knot_project/resources/.*| crates/ty_project/resources/.*|
crates/ruff_benchmark/resources/.*| crates/ruff_benchmark/resources/.*|
crates/ruff_linter/resources/.*| crates/ruff_linter/resources/.*|
crates/ruff_linter/src/rules/.*/snapshots/.*| crates/ruff_linter/src/rules/.*/snapshots/.*|

426
Cargo.lock generated
View file

@ -2472,216 +2472,6 @@ dependencies = [
"crossbeam-utils", "crossbeam-utils",
] ]
[[package]]
name = "red_knot"
version = "0.0.0"
dependencies = [
"anyhow",
"argfile",
"clap",
"colored 3.0.0",
"countme",
"crossbeam",
"ctrlc",
"filetime",
"insta",
"insta-cmd",
"jiff",
"rayon",
"red_knot_project",
"red_knot_python_semantic",
"red_knot_server",
"regex",
"ruff_db",
"ruff_python_ast",
"ruff_python_trivia",
"salsa",
"tempfile",
"toml",
"tracing",
"tracing-flame",
"tracing-subscriber",
"tracing-tree",
"wild",
]
[[package]]
name = "red_knot_ide"
version = "0.0.0"
dependencies = [
"insta",
"red_knot_python_semantic",
"red_knot_vendored",
"ruff_db",
"ruff_python_ast",
"ruff_python_parser",
"ruff_text_size",
"rustc-hash 2.1.1",
"salsa",
"smallvec",
"tracing",
]
[[package]]
name = "red_knot_project"
version = "0.0.0"
dependencies = [
"anyhow",
"crossbeam",
"glob",
"insta",
"notify",
"pep440_rs",
"rayon",
"red_knot_ide",
"red_knot_python_semantic",
"red_knot_vendored",
"ruff_cache",
"ruff_db",
"ruff_macros",
"ruff_python_ast",
"ruff_python_formatter",
"ruff_text_size",
"rustc-hash 2.1.1",
"salsa",
"schemars",
"serde",
"thiserror 2.0.12",
"toml",
"tracing",
]
[[package]]
name = "red_knot_python_semantic"
version = "0.0.0"
dependencies = [
"anyhow",
"bitflags 2.9.0",
"camino",
"compact_str",
"countme",
"dir-test",
"drop_bomb",
"hashbrown 0.15.2",
"indexmap",
"insta",
"itertools 0.14.0",
"memchr",
"ordermap",
"quickcheck",
"quickcheck_macros",
"red_knot_test",
"red_knot_vendored",
"ruff_db",
"ruff_index",
"ruff_macros",
"ruff_python_ast",
"ruff_python_literal",
"ruff_python_parser",
"ruff_python_stdlib",
"ruff_python_trivia",
"ruff_source_file",
"ruff_text_size",
"rustc-hash 2.1.1",
"salsa",
"schemars",
"serde",
"smallvec",
"static_assertions",
"strum",
"strum_macros",
"tempfile",
"test-case",
"thiserror 2.0.12",
"tracing",
]
[[package]]
name = "red_knot_server"
version = "0.0.0"
dependencies = [
"anyhow",
"crossbeam",
"jod-thread",
"libc",
"lsp-server",
"lsp-types",
"red_knot_ide",
"red_knot_project",
"red_knot_python_semantic",
"ruff_db",
"ruff_notebook",
"ruff_source_file",
"ruff_text_size",
"rustc-hash 2.1.1",
"serde",
"serde_json",
"shellexpand",
"tracing",
"tracing-subscriber",
]
[[package]]
name = "red_knot_test"
version = "0.0.0"
dependencies = [
"anyhow",
"camino",
"colored 3.0.0",
"insta",
"memchr",
"red_knot_python_semantic",
"red_knot_vendored",
"regex",
"ruff_db",
"ruff_index",
"ruff_notebook",
"ruff_python_ast",
"ruff_python_trivia",
"ruff_source_file",
"ruff_text_size",
"rustc-hash 2.1.1",
"salsa",
"serde",
"smallvec",
"tempfile",
"thiserror 2.0.12",
"toml",
"tracing",
]
[[package]]
name = "red_knot_vendored"
version = "0.0.0"
dependencies = [
"path-slash",
"ruff_db",
"walkdir",
"zip",
]
[[package]]
name = "red_knot_wasm"
version = "0.0.0"
dependencies = [
"console_error_panic_hook",
"console_log",
"getrandom 0.3.2",
"js-sys",
"log",
"red_knot_ide",
"red_knot_project",
"red_knot_python_semantic",
"ruff_db",
"ruff_notebook",
"ruff_python_formatter",
"ruff_source_file",
"ruff_text_size",
"serde-wasm-bindgen",
"wasm-bindgen",
"wasm-bindgen-test",
]
[[package]] [[package]]
name = "redox_syscall" name = "redox_syscall"
version = "0.5.10" version = "0.5.10"
@ -2838,7 +2628,6 @@ dependencies = [
"criterion", "criterion",
"mimalloc", "mimalloc",
"rayon", "rayon",
"red_knot_project",
"ruff_db", "ruff_db",
"ruff_linter", "ruff_linter",
"ruff_python_ast", "ruff_python_ast",
@ -2847,6 +2636,7 @@ dependencies = [
"ruff_python_trivia", "ruff_python_trivia",
"rustc-hash 2.1.1", "rustc-hash 2.1.1",
"tikv-jemallocator", "tikv-jemallocator",
"ty_project",
] ]
[[package]] [[package]]
@ -2913,7 +2703,6 @@ dependencies = [
"libcst", "libcst",
"pretty_assertions", "pretty_assertions",
"rayon", "rayon",
"red_knot_project",
"regex", "regex",
"ruff", "ruff",
"ruff_diagnostics", "ruff_diagnostics",
@ -2936,6 +2725,7 @@ dependencies = [
"tracing", "tracing",
"tracing-indicatif", "tracing-indicatif",
"tracing-subscriber", "tracing-subscriber",
"ty_project",
] ]
[[package]] [[package]]
@ -2971,7 +2761,6 @@ version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"clap", "clap",
"red_knot_python_semantic",
"ruff_cache", "ruff_cache",
"ruff_db", "ruff_db",
"ruff_linter", "ruff_linter",
@ -2981,6 +2770,7 @@ dependencies = [
"salsa", "salsa",
"schemars", "schemars",
"serde", "serde",
"ty_python_semantic",
"zip", "zip",
] ]
@ -4150,6 +3940,216 @@ dependencies = [
"snapbox", "snapbox",
] ]
[[package]]
name = "ty"
version = "0.0.0"
dependencies = [
"anyhow",
"argfile",
"clap",
"colored 3.0.0",
"countme",
"crossbeam",
"ctrlc",
"filetime",
"insta",
"insta-cmd",
"jiff",
"rayon",
"regex",
"ruff_db",
"ruff_python_ast",
"ruff_python_trivia",
"salsa",
"tempfile",
"toml",
"tracing",
"tracing-flame",
"tracing-subscriber",
"tracing-tree",
"ty_project",
"ty_python_semantic",
"ty_server",
"wild",
]
[[package]]
name = "ty_ide"
version = "0.0.0"
dependencies = [
"insta",
"ruff_db",
"ruff_python_ast",
"ruff_python_parser",
"ruff_text_size",
"rustc-hash 2.1.1",
"salsa",
"smallvec",
"tracing",
"ty_python_semantic",
"ty_vendored",
]
[[package]]
name = "ty_project"
version = "0.0.0"
dependencies = [
"anyhow",
"crossbeam",
"glob",
"insta",
"notify",
"pep440_rs",
"rayon",
"ruff_cache",
"ruff_db",
"ruff_macros",
"ruff_python_ast",
"ruff_python_formatter",
"ruff_text_size",
"rustc-hash 2.1.1",
"salsa",
"schemars",
"serde",
"thiserror 2.0.12",
"toml",
"tracing",
"ty_ide",
"ty_python_semantic",
"ty_vendored",
]
[[package]]
name = "ty_python_semantic"
version = "0.0.0"
dependencies = [
"anyhow",
"bitflags 2.9.0",
"camino",
"compact_str",
"countme",
"dir-test",
"drop_bomb",
"hashbrown 0.15.2",
"indexmap",
"insta",
"itertools 0.14.0",
"memchr",
"ordermap",
"quickcheck",
"quickcheck_macros",
"ruff_db",
"ruff_index",
"ruff_macros",
"ruff_python_ast",
"ruff_python_literal",
"ruff_python_parser",
"ruff_python_stdlib",
"ruff_python_trivia",
"ruff_source_file",
"ruff_text_size",
"rustc-hash 2.1.1",
"salsa",
"schemars",
"serde",
"smallvec",
"static_assertions",
"strum",
"strum_macros",
"tempfile",
"test-case",
"thiserror 2.0.12",
"tracing",
"ty_test",
"ty_vendored",
]
[[package]]
name = "ty_server"
version = "0.0.0"
dependencies = [
"anyhow",
"crossbeam",
"jod-thread",
"libc",
"lsp-server",
"lsp-types",
"ruff_db",
"ruff_notebook",
"ruff_source_file",
"ruff_text_size",
"rustc-hash 2.1.1",
"serde",
"serde_json",
"shellexpand",
"tracing",
"tracing-subscriber",
"ty_ide",
"ty_project",
"ty_python_semantic",
]
[[package]]
name = "ty_test"
version = "0.0.0"
dependencies = [
"anyhow",
"camino",
"colored 3.0.0",
"insta",
"memchr",
"regex",
"ruff_db",
"ruff_index",
"ruff_notebook",
"ruff_python_ast",
"ruff_python_trivia",
"ruff_source_file",
"ruff_text_size",
"rustc-hash 2.1.1",
"salsa",
"serde",
"smallvec",
"tempfile",
"thiserror 2.0.12",
"toml",
"tracing",
"ty_python_semantic",
"ty_vendored",
]
[[package]]
name = "ty_vendored"
version = "0.0.0"
dependencies = [
"path-slash",
"ruff_db",
"walkdir",
"zip",
]
[[package]]
name = "ty_wasm"
version = "0.0.0"
dependencies = [
"console_error_panic_hook",
"console_log",
"getrandom 0.3.2",
"js-sys",
"log",
"ruff_db",
"ruff_notebook",
"ruff_python_formatter",
"ruff_source_file",
"ruff_text_size",
"serde-wasm-bindgen",
"ty_ide",
"ty_project",
"ty_python_semantic",
"wasm-bindgen",
"wasm-bindgen-test",
]
[[package]] [[package]]
name = "typed-arena" name = "typed-arena"
version = "2.0.2" version = "2.0.2"

View file

@ -35,14 +35,14 @@ ruff_python_trivia = { path = "crates/ruff_python_trivia" }
ruff_server = { path = "crates/ruff_server" } ruff_server = { path = "crates/ruff_server" }
ruff_source_file = { path = "crates/ruff_source_file" } ruff_source_file = { path = "crates/ruff_source_file" }
ruff_text_size = { path = "crates/ruff_text_size" } ruff_text_size = { path = "crates/ruff_text_size" }
red_knot_vendored = { path = "crates/red_knot_vendored" }
ruff_workspace = { path = "crates/ruff_workspace" } ruff_workspace = { path = "crates/ruff_workspace" }
red_knot_ide = { path = "crates/red_knot_ide" } ty_ide = { path = "crates/ty_ide" }
red_knot_project = { path = "crates/red_knot_project", default-features = false } ty_project = { path = "crates/ty_project", default-features = false }
red_knot_python_semantic = { path = "crates/red_knot_python_semantic" } ty_python_semantic = { path = "crates/ty_python_semantic" }
red_knot_server = { path = "crates/red_knot_server" } ty_server = { path = "crates/ty_server" }
red_knot_test = { path = "crates/red_knot_test" } ty_test = { path = "crates/ty_test" }
ty_vendored = { path = "crates/ty_vendored" }
aho-corasick = { version = "1.1.3" } aho-corasick = { version = "1.1.3" }
anstream = { version = "0.6.18" } anstream = { version = "0.6.18" }

View file

@ -1,7 +1,7 @@
[files] [files]
# https://github.com/crate-ci/typos/issues/868 # https://github.com/crate-ci/typos/issues/868
extend-exclude = [ extend-exclude = [
"crates/red_knot_vendored/vendor/**/*", "crates/ty_vendored/vendor/**/*",
"**/resources/**/*", "**/resources/**/*",
"**/snapshots/**/*", "**/snapshots/**/*",
] ]

View file

@ -1,25 +0,0 @@
# Red Knot
Red Knot is an extremely fast type checker.
Currently, it is a work-in-progress and not ready for user testing.
Red Knot is designed to prioritize good type inference, even in unannotated code,
and aims to avoid false positives.
While Red Knot will produce similar results to mypy and pyright on many codebases,
100% compatibility with these tools is a non-goal.
On some codebases, Red Knot's design decisions lead to different outcomes
than you would get from running one of these more established tools.
## Contributing
Core type checking tests are written as Markdown code blocks.
They can be found in [`red_knot_python_semantic/resources/mdtest`][resources-mdtest].
See [`red_knot_test/README.md`][mdtest-readme] for more information
on the test framework itself.
The list of open issues can be found [here][open-issues].
[mdtest-readme]: ../red_knot_test/README.md
[open-issues]: https://github.com/astral-sh/ruff/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20label%3Ared-knot
[resources-mdtest]: ../red_knot_python_semantic/resources/mdtest

View file

@ -1,191 +0,0 @@
# Suppressing errors with `knot: ignore`
Type check errors can be suppressed by a `knot: ignore` comment on the same line as the violation.
## Simple `knot: ignore`
```py
a = 4 + test # knot: ignore
```
## Suppressing a specific code
```py
a = 4 + test # knot: ignore[unresolved-reference]
```
## Unused suppression
```py
test = 10
# error: [unused-ignore-comment] "Unused `knot: ignore` directive: 'possibly-unresolved-reference'"
a = test + 3 # knot: ignore[possibly-unresolved-reference]
```
## Unused suppression if the error codes don't match
```py
# error: [unresolved-reference]
# error: [unused-ignore-comment] "Unused `knot: ignore` directive: 'possibly-unresolved-reference'"
a = test + 3 # knot: ignore[possibly-unresolved-reference]
```
## Suppressed unused comment
```py
# error: [unused-ignore-comment]
a = 10 / 2 # knot: ignore[division-by-zero]
a = 10 / 2 # knot: ignore[division-by-zero, unused-ignore-comment]
a = 10 / 2 # knot: ignore[unused-ignore-comment, division-by-zero]
a = 10 / 2 # knot: ignore[unused-ignore-comment] # type: ignore
a = 10 / 2 # type: ignore # knot: ignore[unused-ignore-comment]
```
## Unused ignore comment
```py
# error: [unused-ignore-comment] "Unused `knot: ignore` directive: 'unused-ignore-comment'"
a = 10 / 0 # knot: ignore[division-by-zero, unused-ignore-comment]
```
## Multiple unused comments
Today, Red Knot emits a diagnostic for every unused code. We might want to group the codes by
comment at some point in the future.
```py
# error: [unused-ignore-comment] "Unused `knot: ignore` directive: 'division-by-zero'"
# error: [unused-ignore-comment] "Unused `knot: ignore` directive: 'unresolved-reference'"
a = 10 / 2 # knot: ignore[division-by-zero, unresolved-reference]
# error: [unused-ignore-comment] "Unused `knot: ignore` directive: 'invalid-assignment'"
# error: [unused-ignore-comment] "Unused `knot: ignore` directive: 'unresolved-reference'"
a = 10 / 0 # knot: ignore[invalid-assignment, division-by-zero, unresolved-reference]
```
## Multiple suppressions
```py
# fmt: off
def test(a: f"f-string type annotation", b: b"byte-string-type-annotation"): ... # knot: ignore[fstring-type-annotation, byte-string-type-annotation]
```
## Can't suppress syntax errors
<!-- blacken-docs:off -->
```py
# error: [invalid-syntax]
# error: [unused-ignore-comment]
def test($): # knot: ignore
pass
```
<!-- blacken-docs:on -->
## Can't suppress `revealed-type` diagnostics
```py
a = 10
# revealed: Literal[10]
# error: [unknown-rule] "Unknown rule `revealed-type`"
reveal_type(a) # knot: ignore[revealed-type]
```
## Extra whitespace in type ignore comments is allowed
```py
a = 10 / 0 # knot : ignore
a = 10 / 0 # knot: ignore [ division-by-zero ]
```
## Whitespace is optional
```py
# fmt: off
a = 10 / 0 #knot:ignore[division-by-zero]
```
## Trailing codes comma
Trailing commas in the codes section are allowed:
```py
a = 10 / 0 # knot: ignore[division-by-zero,]
```
## Invalid characters in codes
```py
# error: [division-by-zero]
# error: [invalid-ignore-comment] "Invalid `knot: ignore` comment: expected a alphanumeric character or `-` or `_` as code"
a = 10 / 0 # knot: ignore[*-*]
```
## Trailing whitespace
<!-- blacken-docs:off -->
```py
a = 10 / 0 # knot: ignore[division-by-zero]
# ^^^^^^ trailing whitespace
```
<!-- blacken-docs:on -->
## Missing comma
A missing comma results in an invalid suppression comment. We may want to recover from this in the
future.
```py
# error: [unresolved-reference]
# error: [invalid-ignore-comment] "Invalid `knot: ignore` comment: expected a comma separating the rule codes"
a = x / 0 # knot: ignore[division-by-zero unresolved-reference]
```
## Missing closing bracket
```py
# error: [unresolved-reference] "Name `x` used when not defined"
# error: [invalid-ignore-comment] "Invalid `knot: ignore` comment: expected a comma separating the rule codes"
a = x / 2 # knot: ignore[unresolved-reference
```
## Empty codes
An empty codes array suppresses no-diagnostics and is always useless
```py
# error: [division-by-zero]
# error: [unused-ignore-comment] "Unused `knot: ignore` without a code"
a = 4 / 0 # knot: ignore[]
```
## File-level suppression comments
File level suppression comments are currently intentionally unsupported because we've yet to decide
if they should use a different syntax that also supports enabling rules or changing the rule's
severity: `knot: possibly-undefined-reference=error`
```py
# error: [unused-ignore-comment]
# knot: ignore[division-by-zero]
a = 4 / 0 # error: [division-by-zero]
```
## Unknown rule
```py
# error: [unknown-rule] "Unknown rule `is-equal-14`"
a = 10 + 4 # knot: ignore[is-equal-14]
```
## Code with `lint:` prefix
```py
# error:[unknown-rule] "Unknown rule `lint:division-by-zero`. Did you mean `division-by-zero`?"
# error: [division-by-zero]
a = 10 / 0 # knot: ignore[lint:division-by-zero]
```

View file

@ -1,3 +0,0 @@
The `knot_extensions.pyi` file in this directory will be symlinked into
the `vendor/typeshed/stdlib` directory every time we sync our `typeshed`
stubs (see `.github/workflows/sync_typeshed.yaml`).

View file

@ -552,7 +552,7 @@ fn venv() -> Result<()> {
}); });
// test the error message for a non-existent venv. it's important that the `ruff analyze graph` // test the error message for a non-existent venv. it's important that the `ruff analyze graph`
// flag matches the red-knot flag used to generate the error message (`--python`) // flag matches the ty flag used to generate the error message (`--python`)
insta::with_settings!({ insta::with_settings!({
filters => INSTA_FILTERS.to_vec(), filters => INSTA_FILTERS.to_vec(),
}, { }, {

View file

@ -33,7 +33,7 @@ name = "formatter"
harness = false harness = false
[[bench]] [[bench]]
name = "red_knot" name = "ty"
harness = false harness = false
[dependencies] [dependencies]
@ -49,7 +49,7 @@ ruff_python_ast = { workspace = true }
ruff_python_formatter = { workspace = true } ruff_python_formatter = { workspace = true }
ruff_python_parser = { workspace = true } ruff_python_parser = { workspace = true }
ruff_python_trivia = { workspace = true } ruff_python_trivia = { workspace = true }
red_knot_project = { workspace = true } ty_project = { workspace = true }
[lints] [lints]
workspace = true workspace = true

View file

@ -7,16 +7,16 @@ use criterion::{criterion_group, criterion_main, BatchSize, Criterion};
use rayon::ThreadPoolBuilder; use rayon::ThreadPoolBuilder;
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
use red_knot_project::metadata::options::{EnvironmentOptions, Options};
use red_knot_project::metadata::value::RangedValue;
use red_knot_project::watch::{ChangeEvent, ChangedKind};
use red_knot_project::{Db, ProjectDatabase, ProjectMetadata};
use ruff_benchmark::TestFile; use ruff_benchmark::TestFile;
use ruff_db::diagnostic::{Diagnostic, DiagnosticId, Severity}; use ruff_db::diagnostic::{Diagnostic, DiagnosticId, Severity};
use ruff_db::files::{system_path_to_file, File}; use ruff_db::files::{system_path_to_file, File};
use ruff_db::source::source_text; use ruff_db::source::source_text;
use ruff_db::system::{MemoryFileSystem, SystemPath, SystemPathBuf, TestSystem}; use ruff_db::system::{MemoryFileSystem, SystemPath, SystemPathBuf, TestSystem};
use ruff_python_ast::PythonVersion; use ruff_python_ast::PythonVersion;
use ty_project::metadata::options::{EnvironmentOptions, Options};
use ty_project::metadata::value::RangedValue;
use ty_project::watch::{ChangeEvent, ChangedKind};
use ty_project::{Db, ProjectDatabase, ProjectMetadata};
struct Case { struct Case {
db: ProjectDatabase, db: ProjectDatabase,
@ -122,7 +122,7 @@ static RAYON_INITIALIZED: std::sync::Once = std::sync::Once::new();
fn setup_rayon() { fn setup_rayon() {
// Initialize the rayon thread pool outside the benchmark because it has a significant cost. // Initialize the rayon thread pool outside the benchmark because it has a significant cost.
// We limit the thread pool to only one (the current thread) because we're focused on // We limit the thread pool to only one (the current thread) because we're focused on
// where red knot spends time and less about how well the code runs concurrently. // where ty spends time and less about how well the code runs concurrently.
// We might want to add a benchmark focusing on concurrency to detect congestion in the future. // We might want to add a benchmark focusing on concurrency to detect congestion in the future.
RAYON_INITIALIZED.call_once(|| { RAYON_INITIALIZED.call_once(|| {
ThreadPoolBuilder::new() ThreadPoolBuilder::new()
@ -172,7 +172,7 @@ fn benchmark_incremental(criterion: &mut Criterion) {
setup_rayon(); setup_rayon();
criterion.bench_function("red_knot_check_file[incremental]", |b| { criterion.bench_function("ty_check_file[incremental]", |b| {
b.iter_batched_ref(setup, incremental, BatchSize::SmallInput); b.iter_batched_ref(setup, incremental, BatchSize::SmallInput);
}); });
} }
@ -180,7 +180,7 @@ fn benchmark_incremental(criterion: &mut Criterion) {
fn benchmark_cold(criterion: &mut Criterion) { fn benchmark_cold(criterion: &mut Criterion) {
setup_rayon(); setup_rayon();
criterion.bench_function("red_knot_check_file[cold]", |b| { criterion.bench_function("ty_check_file[cold]", |b| {
b.iter_batched_ref( b.iter_batched_ref(
setup_tomllib_case, setup_tomllib_case,
|case| { |case| {
@ -257,7 +257,7 @@ fn setup_micro_case(code: &str) -> Case {
fn benchmark_many_string_assignments(criterion: &mut Criterion) { fn benchmark_many_string_assignments(criterion: &mut Criterion) {
setup_rayon(); setup_rayon();
criterion.bench_function("red_knot_micro[many_string_assignments]", |b| { criterion.bench_function("ty_micro[many_string_assignments]", |b| {
b.iter_batched_ref( b.iter_batched_ref(
|| { || {
// This is a micro benchmark, but it is effectively identical to a code sample // This is a micro benchmark, but it is effectively identical to a code sample

View file

@ -134,20 +134,20 @@ impl Diagnostic {
/// NOTE: At present, this routine will return the first primary /// NOTE: At present, this routine will return the first primary
/// annotation's message as the primary message when the main diagnostic /// annotation's message as the primary message when the main diagnostic
/// message is empty. This is meant to facilitate an incremental migration /// message is empty. This is meant to facilitate an incremental migration
/// in Red Knot over to the new diagnostic data model. (The old data model /// in ty over to the new diagnostic data model. (The old data model
/// didn't distinguish between messages on the entire diagnostic and /// didn't distinguish between messages on the entire diagnostic and
/// messages attached to a particular span.) /// messages attached to a particular span.)
pub fn primary_message(&self) -> &str { pub fn primary_message(&self) -> &str {
if !self.inner.message.as_str().is_empty() { if !self.inner.message.as_str().is_empty() {
return self.inner.message.as_str(); return self.inner.message.as_str();
} }
// FIXME: As a special case, while we're migrating Red Knot // FIXME: As a special case, while we're migrating ty
// to the new diagnostic data model, we'll look for a primary // to the new diagnostic data model, we'll look for a primary
// message from the primary annotation. This is because most // message from the primary annotation. This is because most
// Red Knot diagnostics are created with an empty diagnostic // ty diagnostics are created with an empty diagnostic
// message and instead attach the message to the annotation. // message and instead attach the message to the annotation.
// Fixing this will require touching basically every diagnostic // Fixing this will require touching basically every diagnostic
// in Red Knot, so we do it this way for now to match the old // in ty, so we do it this way for now to match the old
// semantics. ---AG // semantics. ---AG
self.primary_annotation() self.primary_annotation()
.and_then(|ann| ann.get_message()) .and_then(|ann| ann.get_message())
@ -165,7 +165,7 @@ impl Diagnostic {
/// ///
/// The reason why we don't just always return both the main diagnostic /// The reason why we don't just always return both the main diagnostic
/// message and the primary annotation message is because this was written /// message and the primary annotation message is because this was written
/// in the midst of an incremental migration of Red Knot over to the new /// in the midst of an incremental migration of ty over to the new
/// diagnostic data model. At time of writing, diagnostics were still /// diagnostic data model. At time of writing, diagnostics were still
/// constructed in the old model where the main diagnostic message and the /// constructed in the old model where the main diagnostic message and the
/// primary annotation message were not distinguished from each other. So /// primary annotation message were not distinguished from each other. So

View file

@ -624,7 +624,7 @@ impl<'r> RenderableAnnotation<'r> {
/// For example, at time of writing (2025-03-07), the plan is (roughly) for /// For example, at time of writing (2025-03-07), the plan is (roughly) for
/// Ruff to grow its own interner of file paths so that a `Span` can store an /// Ruff to grow its own interner of file paths so that a `Span` can store an
/// interned ID instead of a (roughly) `Arc<Path>`. This interner is planned /// interned ID instead of a (roughly) `Arc<Path>`. This interner is planned
/// to be entirely separate from the Salsa interner used by Red Knot, and so, /// to be entirely separate from the Salsa interner used by ty, and so,
/// callers will need to pass in a different "resolver" for turning `Span`s /// callers will need to pass in a different "resolver" for turning `Span`s
/// into actual file paths/contents. The infrastructure for this isn't fully in /// into actual file paths/contents. The infrastructure for this isn't fully in
/// place, but this type serves to demarcate the intended abstraction boundary. /// place, but this type serves to demarcate the intended abstraction boundary.

View file

@ -107,7 +107,7 @@ fn query_name<Q>(_query: &Q) -> &'static str {
.unwrap_or(full_qualified_query_name) .unwrap_or(full_qualified_query_name)
} }
/// Sets up logging for the current thread. It captures all `red_knot` and `ruff` events. /// Sets up logging for the current thread. It captures all `ty` and `ruff` events.
/// ///
/// Useful for capturing the tracing output in a failing test. /// Useful for capturing the tracing output in a failing test.
/// ///
@ -128,7 +128,7 @@ pub fn setup_logging() -> LoggingGuard {
/// # Examples /// # Examples
/// ``` /// ```
/// use ruff_db::testing::setup_logging_with_filter; /// use ruff_db::testing::setup_logging_with_filter;
/// let _logging = setup_logging_with_filter("red_knot_module_resolver::resolver"); /// let _logging = setup_logging_with_filter("ty_module_resolver::resolver");
/// ``` /// ```
/// ///
/// # Filter /// # Filter
@ -148,11 +148,7 @@ impl LoggingBuilder {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
filter: EnvFilter::default() filter: EnvFilter::default()
.add_directive( .add_directive("ty=trace".parse().expect("Hardcoded directive to be valid"))
"red_knot=trace"
.parse()
.expect("Hardcoded directive to be valid"),
)
.add_directive( .add_directive(
"ruff=trace" "ruff=trace"
.parse() .parse()

View file

@ -11,7 +11,7 @@ repository = { workspace = true }
license = { workspace = true } license = { workspace = true }
[dependencies] [dependencies]
red_knot_project = { workspace = true, features = ["schemars"] } ty_project = { workspace = true, features = ["schemars"] }
ruff = { workspace = true } ruff = { workspace = true }
ruff_diagnostics = { workspace = true } ruff_diagnostics = { workspace = true }
ruff_formatter = { workspace = true } ruff_formatter = { workspace = true }

View file

@ -2,7 +2,7 @@
use anyhow::Result; use anyhow::Result;
use crate::{generate_cli_help, generate_docs, generate_json_schema, generate_knot_schema}; use crate::{generate_cli_help, generate_docs, generate_json_schema, generate_ty_schema};
pub(crate) const REGENERATE_ALL_COMMAND: &str = "cargo dev generate-all"; pub(crate) const REGENERATE_ALL_COMMAND: &str = "cargo dev generate-all";
@ -33,7 +33,7 @@ impl Mode {
pub(crate) fn main(args: &Args) -> Result<()> { pub(crate) fn main(args: &Args) -> Result<()> {
generate_json_schema::main(&generate_json_schema::Args { mode: args.mode })?; generate_json_schema::main(&generate_json_schema::Args { mode: args.mode })?;
generate_knot_schema::main(&generate_knot_schema::Args { mode: args.mode })?; generate_ty_schema::main(&generate_ty_schema::Args { mode: args.mode })?;
generate_cli_help::main(&generate_cli_help::Args { mode: args.mode })?; generate_cli_help::main(&generate_cli_help::Args { mode: args.mode })?;
generate_docs::main(&generate_docs::Args { generate_docs::main(&generate_docs::Args {
dry_run: args.mode.is_dry_run(), dry_run: args.mode.is_dry_run(),

View file

@ -9,11 +9,11 @@ use schemars::schema_for;
use crate::generate_all::{Mode, REGENERATE_ALL_COMMAND}; use crate::generate_all::{Mode, REGENERATE_ALL_COMMAND};
use crate::ROOT_DIR; use crate::ROOT_DIR;
use red_knot_project::metadata::options::Options; use ty_project::metadata::options::Options;
#[derive(clap::Args)] #[derive(clap::Args)]
pub(crate) struct Args { pub(crate) struct Args {
/// Write the generated table to stdout (rather than to `knot.schema.json`). /// Write the generated table to stdout (rather than to `ty.schema.json`).
#[arg(long, default_value_t, value_enum)] #[arg(long, default_value_t, value_enum)]
pub(crate) mode: Mode, pub(crate) mode: Mode,
} }
@ -21,7 +21,7 @@ pub(crate) struct Args {
pub(crate) fn main(args: &Args) -> Result<()> { pub(crate) fn main(args: &Args) -> Result<()> {
let schema = schema_for!(Options); let schema = schema_for!(Options);
let schema_string = serde_json::to_string_pretty(&schema).unwrap(); let schema_string = serde_json::to_string_pretty(&schema).unwrap();
let filename = "knot.schema.json"; let filename = "ty.schema.json";
let schema_path = PathBuf::from(ROOT_DIR).join(filename); let schema_path = PathBuf::from(ROOT_DIR).join(filename);
match args.mode { match args.mode {
@ -62,7 +62,7 @@ mod tests {
#[test] #[test]
fn test_generate_json_schema() -> Result<()> { fn test_generate_json_schema() -> Result<()> {
let mode = if env::var("KNOT_UPDATE_SCHEMA").as_deref() == Ok("1") { let mode = if env::var("TY_UPDATE_SCHEMA").as_deref() == Ok("1") {
Mode::Write Mode::Write
} else { } else {
Mode::Check Mode::Check

View file

@ -13,9 +13,9 @@ mod generate_all;
mod generate_cli_help; mod generate_cli_help;
mod generate_docs; mod generate_docs;
mod generate_json_schema; mod generate_json_schema;
mod generate_knot_schema;
mod generate_options; mod generate_options;
mod generate_rules_table; mod generate_rules_table;
mod generate_ty_schema;
mod print_ast; mod print_ast;
mod print_cst; mod print_cst;
mod print_tokens; mod print_tokens;
@ -40,8 +40,8 @@ enum Command {
GenerateAll(generate_all::Args), GenerateAll(generate_all::Args),
/// Generate JSON schema for the TOML configuration file. /// Generate JSON schema for the TOML configuration file.
GenerateJSONSchema(generate_json_schema::Args), GenerateJSONSchema(generate_json_schema::Args),
/// Generate JSON schema for the Red Knot TOML configuration file. /// Generate JSON schema for the ty TOML configuration file.
GenerateKnotSchema(generate_knot_schema::Args), GenerateTySchema(generate_ty_schema::Args),
/// Generate a Markdown-compatible table of supported lint rules. /// Generate a Markdown-compatible table of supported lint rules.
GenerateRulesTable, GenerateRulesTable,
/// Generate a Markdown-compatible listing of configuration options. /// Generate a Markdown-compatible listing of configuration options.
@ -86,7 +86,7 @@ fn main() -> Result<ExitCode> {
match command { match command {
Command::GenerateAll(args) => generate_all::main(&args)?, Command::GenerateAll(args) => generate_all::main(&args)?,
Command::GenerateJSONSchema(args) => generate_json_schema::main(&args)?, Command::GenerateJSONSchema(args) => generate_json_schema::main(&args)?,
Command::GenerateKnotSchema(args) => generate_knot_schema::main(&args)?, Command::GenerateTySchema(args) => generate_ty_schema::main(&args)?,
Command::GenerateRulesTable => println!("{}", generate_rules_table::generate()), Command::GenerateRulesTable => println!("{}", generate_rules_table::generate()),
Command::GenerateOptions => println!("{}", generate_options::generate()), Command::GenerateOptions => println!("{}", generate_options::generate()),
Command::GenerateCliHelp(args) => generate_cli_help::main(&args)?, Command::GenerateCliHelp(args) => generate_cli_help::main(&args)?,

View file

@ -10,13 +10,13 @@ authors.workspace = true
license.workspace = true license.workspace = true
[dependencies] [dependencies]
red_knot_python_semantic = { workspace = true }
ruff_cache = { workspace = true } ruff_cache = { workspace = true }
ruff_db = { workspace = true, features = ["os", "serde"] } ruff_db = { workspace = true, features = ["os", "serde"] }
ruff_linter = { workspace = true } ruff_linter = { workspace = true }
ruff_macros = { workspace = true } ruff_macros = { workspace = true }
ruff_python_ast = { workspace = true } ruff_python_ast = { workspace = true }
ruff_python_parser = { workspace = true } ruff_python_parser = { workspace = true }
ty_python_semantic = { workspace = true }
anyhow = { workspace = true } anyhow = { workspace = true }
clap = { workspace = true, optional = true } clap = { workspace = true, optional = true }

View file

@ -1,8 +1,8 @@
use red_knot_python_semantic::ModuleName;
use ruff_python_ast::visitor::source_order::{ use ruff_python_ast::visitor::source_order::{
walk_expr, walk_module, walk_stmt, SourceOrderVisitor, walk_expr, walk_module, walk_stmt, SourceOrderVisitor,
}; };
use ruff_python_ast::{self as ast, Expr, Mod, Stmt}; use ruff_python_ast::{self as ast, Expr, Mod, Stmt};
use ty_python_semantic::ModuleName;
/// Collect all imports for a given Python file. /// Collect all imports for a given Python file.
#[derive(Default, Debug)] #[derive(Default, Debug)]

View file

@ -2,16 +2,16 @@ use anyhow::Result;
use std::sync::Arc; use std::sync::Arc;
use zip::CompressionMethod; use zip::CompressionMethod;
use red_knot_python_semantic::lint::{LintRegistry, RuleSelection};
use red_knot_python_semantic::{
default_lint_registry, Db, Program, ProgramSettings, PythonPath, PythonPlatform,
SearchPathSettings,
};
use ruff_db::files::{File, Files}; use ruff_db::files::{File, Files};
use ruff_db::system::{OsSystem, System, SystemPathBuf}; use ruff_db::system::{OsSystem, System, SystemPathBuf};
use ruff_db::vendored::{VendoredFileSystem, VendoredFileSystemBuilder}; use ruff_db::vendored::{VendoredFileSystem, VendoredFileSystemBuilder};
use ruff_db::{Db as SourceDb, Upcast}; use ruff_db::{Db as SourceDb, Upcast};
use ruff_python_ast::PythonVersion; use ruff_python_ast::PythonVersion;
use ty_python_semantic::lint::{LintRegistry, RuleSelection};
use ty_python_semantic::{
default_lint_registry, Db, Program, ProgramSettings, PythonPath, PythonPlatform,
SearchPathSettings,
};
static EMPTY_VENDORED: std::sync::LazyLock<VendoredFileSystem> = std::sync::LazyLock::new(|| { static EMPTY_VENDORED: std::sync::LazyLock<VendoredFileSystem> = std::sync::LazyLock::new(|| {
let mut builder = VendoredFileSystemBuilder::new(CompressionMethod::Stored); let mut builder = VendoredFileSystemBuilder::new(CompressionMethod::Stored);

View file

@ -1,5 +1,5 @@
use red_knot_python_semantic::resolve_module;
use ruff_db::files::FilePath; use ruff_db::files::FilePath;
use ty_python_semantic::resolve_module;
use crate::collector::CollectedImport; use crate::collector::CollectedImport;
use crate::ModuleDb; use crate::ModuleDb;

View file

@ -12,7 +12,7 @@ flask.Markup("unsafe %s" % content) # S704
Markup(object="safe") Markup(object="safe")
Markup(object="unsafe {}".format(content)) # Not currently detected Markup(object="unsafe {}".format(content)) # Not currently detected
# NOTE: We may be able to get rid of these false positives with red-knot # NOTE: We may be able to get rid of these false positives with ty
# if it includes comprehensive constant expression detection/evaluation. # if it includes comprehensive constant expression detection/evaluation.
Markup("*" * 8) # S704 (false positive) Markup("*" * 8) # S704 (false positive)
flask.Markup("hello {}".format("world")) # S704 (false positive) flask.Markup("hello {}".format("world")) # S704 (false positive)

View file

@ -151,7 +151,7 @@ pub fn set_up_logging(level: LogLevel) -> Result<()> {
}) })
.level(level.level_filter()) .level(level.level_filter())
.level_for("globset", log::LevelFilter::Warn) .level_for("globset", log::LevelFilter::Warn)
.level_for("red_knot_python_semantic", log::LevelFilter::Warn) .level_for("ty_python_semantic", log::LevelFilter::Warn)
.level_for("salsa", log::LevelFilter::Warn) .level_for("salsa", log::LevelFilter::Warn)
.chain(std::io::stderr()) .chain(std::io::stderr())
.apply()?; .apply()?;

View file

@ -42,7 +42,7 @@ S704.py:11:1: S704 Unsafe use of `flask.Markup` detected
S704.py:17:1: S704 Unsafe use of `markupsafe.Markup` detected S704.py:17:1: S704 Unsafe use of `markupsafe.Markup` detected
| |
15 | # NOTE: We may be able to get rid of these false positives with red-knot 15 | # NOTE: We may be able to get rid of these false positives with ty
16 | # if it includes comprehensive constant expression detection/evaluation. 16 | # if it includes comprehensive constant expression detection/evaluation.
17 | Markup("*" * 8) # S704 (false positive) 17 | Markup("*" * 8) # S704 (false positive)
| ^^^^^^^^^^^^^^^ S704 | ^^^^^^^^^^^^^^^ S704

View file

@ -36,8 +36,8 @@ pub fn derive_combine_options(input: TokenStream) -> TokenStream {
.into() .into()
} }
/// Automatically derives a `red_knot_project::project::Combine` implementation for the attributed type /// Automatically derives a `ty_project::project::Combine` implementation for the attributed type
/// that calls `red_knot_project::project::Combine::combine` for each field. /// that calls `ty_project::project::Combine::combine` for each field.
/// ///
/// The derive macro can only be used on structs. Enums aren't yet supported. /// The derive macro can only be used on structs. Enums aren't yet supported.
#[proc_macro_derive(Combine)] #[proc_macro_derive(Combine)]

View file

@ -1,5 +1,5 @@
[package] [package]
name = "red_knot" name = "ty"
version = "0.0.0" version = "0.0.0"
edition.workspace = true edition.workspace = true
rust-version.workspace = true rust-version.workspace = true
@ -12,11 +12,11 @@ license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
red_knot_python_semantic = { workspace = true }
red_knot_project = { workspace = true, features = ["zstd"] }
red_knot_server = { workspace = true }
ruff_db = { workspace = true, features = ["os", "cache"] } ruff_db = { workspace = true, features = ["os", "cache"] }
ruff_python_ast = { workspace = true } ruff_python_ast = { workspace = true }
ty_python_semantic = { workspace = true }
ty_project = { workspace = true, features = ["zstd"] }
ty_server = { workspace = true }
anyhow = { workspace = true } anyhow = { workspace = true }
argfile = { workspace = true } argfile = { workspace = true }

25
crates/ty/README.md Normal file
View file

@ -0,0 +1,25 @@
# ty
ty is an extremely fast type checker.
Currently, it is a work-in-progress and not ready for user testing.
ty is designed to prioritize good type inference, even in unannotated code,
and aims to avoid false positives.
While ty will produce similar results to mypy and pyright on many codebases,
100% compatibility with these tools is a non-goal.
On some codebases, ty's design decisions lead to different outcomes
than you would get from running one of these more established tools.
## Contributing
Core type checking tests are written as Markdown code blocks.
They can be found in [`ty_python_semantic/resources/mdtest`][resources-mdtest].
See [`ty_test/README.md`][mdtest-readme] for more information
on the test framework itself.
The list of open issues can be found [here][open-issues].
[mdtest-readme]: ../ty_test/README.md
[open-issues]: https://github.com/astral-sh/ty/issues
[resources-mdtest]: ../ty_python_semantic/resources/mdtest

View file

@ -59,8 +59,8 @@ fn commit_info(workspace_root: &Path) {
let mut parts = stdout.split_whitespace(); let mut parts = stdout.split_whitespace();
let mut next = || parts.next().unwrap(); let mut next = || parts.next().unwrap();
let _commit_hash = next(); let _commit_hash = next();
println!("cargo::rustc-env=RED_KNOT_COMMIT_SHORT_HASH={}", next()); println!("cargo::rustc-env=TY_COMMIT_SHORT_HASH={}", next());
println!("cargo::rustc-env=RED_KNOT_COMMIT_DATE={}", next()); println!("cargo::rustc-env=TY_COMMIT_DATE={}", next());
// Describe can fail for some commits // Describe can fail for some commits
// https://git-scm.com/docs/pretty-formats#Documentation/pretty-formats.txt-emdescribeoptionsem // https://git-scm.com/docs/pretty-formats#Documentation/pretty-formats.txt-emdescribeoptionsem
@ -70,7 +70,7 @@ fn commit_info(workspace_root: &Path) {
// If this is the tagged commit, this component will be missing // If this is the tagged commit, this component will be missing
println!( println!(
"cargo::rustc-env=RED_KNOT_LAST_TAG_DISTANCE={}", "cargo::rustc-env=TY_LAST_TAG_DISTANCE={}",
describe_parts.next().unwrap_or("0") describe_parts.next().unwrap_or("0")
); );
} }

View file

@ -22,7 +22,7 @@ To show the diagnostics diff between two Git revisions (e.g. your feature branch
```sh ```sh
mypy_primer \ mypy_primer \
--type-checker knot \ --type-checker ty \
--old origin/main \ --old origin/main \
--new my/feature \ --new my/feature \
--debug \ --debug \
@ -31,15 +31,15 @@ mypy_primer \
``` ```
This will show the diagnostics diff for the `black` project between the `main` branch and your `my/feature` branch. To run the This will show the diagnostics diff for the `black` project between the `main` branch and your `my/feature` branch. To run the
diff for all projects we currently enable in CI, use `--project-selector "/($(paste -s -d'|' crates/red_knot_python_semantic/resources/primer/good.txt))\$"`. diff for all projects we currently enable in CI, use `--project-selector "/($(paste -s -d'|' crates/ty_python_semantic/resources/primer/good.txt))\$"`.
You can also take a look at the [full list of ecosystem projects]. Note that some of them might still need a `knot_paths` configuration You can also take a look at the [full list of ecosystem projects]. Note that some of them might still need a `ty_paths` configuration
option to work correctly. option to work correctly.
## Avoiding recompilation ## Avoiding recompilation
If you want to run `mypy_primer` repeatedly, e.g. for different projects, but for the same combination of `--old` and `--new`, you If you want to run `mypy_primer` repeatedly, e.g. for different projects, but for the same combination of `--old` and `--new`, you
can use set the `MYPY_PRIMER_NO_REBUILD` environment variable to avoid recompilation of Red Knot: can use set the `MYPY_PRIMER_NO_REBUILD` environment variable to avoid recompilation of ty:
```sh ```sh
MYPY_PRIMER_NO_REBUILD=1 mypy_primer … MYPY_PRIMER_NO_REBUILD=1 mypy_primer …

View file

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Before After
Before After

View file

@ -11,16 +11,16 @@ The CLI supports different verbosity levels.
- default: Only show errors and warnings. - default: Only show errors and warnings.
- `-v` activates `info!`: Show generally useful information such as paths of configuration files, detected platform, etc., but it's not a lot of messages, it's something you'll activate in CI by default. cargo build e.g. shows you which packages are fresh. - `-v` activates `info!`: Show generally useful information such as paths of configuration files, detected platform, etc., but it's not a lot of messages, it's something you'll activate in CI by default. cargo build e.g. shows you which packages are fresh.
- `-vv` activates `debug!` and timestamps: This should be enough information to get to the bottom of bug reports. When you're processing many packages or files, you'll get pages and pages of output, but each line is link to a specific action or state change. - `-vv` activates `debug!` and timestamps: This should be enough information to get to the bottom of bug reports. When you're processing many packages or files, you'll get pages and pages of output, but each line is link to a specific action or state change.
- `-vvv` activates `trace!` (only in debug builds) and shows tracing-spans: At this level, you're logging everything. Most of this is wasted, it's really slow, we dump e.g. the entire resolution graph. Only useful to developers, and you almost certainly want to use `RED_KNOT_LOG` to filter it down to the area your investigating. - `-vvv` activates `trace!` (only in debug builds) and shows tracing-spans: At this level, you're logging everything. Most of this is wasted, it's really slow, we dump e.g. the entire resolution graph. Only useful to developers, and you almost certainly want to use `TY_LOG` to filter it down to the area your investigating.
## Better logging with `RED_KNOT_LOG` and `RAYON_NUM_THREADS` ## Better logging with `TY_LOG` and `RAYON_NUM_THREADS`
By default, the CLI shows messages from the `ruff` and `red_knot` crates. Tracing messages from other crates are not shown. By default, the CLI shows messages from the `ruff` and `ty` crates. Tracing messages from other crates are not shown.
The `RED_KNOT_LOG` environment variable allows you to customize which messages are shown by specifying one The `TY_LOG` environment variable allows you to customize which messages are shown by specifying one
or more [filter directives](https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html#directives). or more [filter directives](https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html#directives).
The `RAYON_NUM_THREADS` environment variable, meanwhile, can be used to control the level of concurrency red-knot uses. The `RAYON_NUM_THREADS` environment variable, meanwhile, can be used to control the level of concurrency ty uses.
By default, red-knot will attempt to parallelize its work so that multiple files are checked simultaneously, By default, ty will attempt to parallelize its work so that multiple files are checked simultaneously,
but this can result in a confused logging output where messages from different threads are intertwined. but this can result in a confused logging output where messages from different threads are intertwined.
To switch off concurrency entirely and have more readable logs, use `RAYON_NUM_THREADS=1`. To switch off concurrency entirely and have more readable logs, use `RAYON_NUM_THREADS=1`.
@ -31,23 +31,23 @@ To switch off concurrency entirely and have more readable logs, use `RAYON_NUM_T
Shows debug messages from all crates. Shows debug messages from all crates.
```bash ```bash
RED_KNOT_LOG=debug TY_LOG=debug
``` ```
#### Show salsa query execution messages #### Show salsa query execution messages
Show the salsa `execute: my_query` messages in addition to all red knot messages. Show the salsa `execute: my_query` messages in addition to all ty messages.
```bash ```bash
RED_KNOT_LOG=ruff=trace,red_knot=trace,salsa=info TY_LOG=ruff=trace,ty=trace,salsa=info
``` ```
#### Show typing traces #### Show typing traces
Only show traces for the `red_knot_python_semantic::types` module. Only show traces for the `ty_python_semantic::types` module.
```bash ```bash
RED_KNOT_LOG="red_knot_python_semantic::types" TY_LOG="ty_python_semantic::types"
``` ```
Note: Ensure that you use `-vvv` to see tracing spans. Note: Ensure that you use `-vvv` to see tracing spans.
@ -57,7 +57,7 @@ Note: Ensure that you use `-vvv` to see tracing spans.
Shows all messages that are inside of a span for a specific file. Shows all messages that are inside of a span for a specific file.
```bash ```bash
RED_KNOT_LOG=red_knot[{file=/home/micha/astral/test/x.py}]=trace TY_LOG=ty[{file=/home/micha/astral/test/x.py}]=trace
``` ```
**Note**: Tracing still shows all spans because tracing can't know at the time of entering the span **Note**: Tracing still shows all spans because tracing can't know at the time of entering the span
@ -103,10 +103,10 @@ called **once**.
## Profiling ## Profiling
Red Knot generates a folded stack trace to the current directory named `tracing.folded` when setting the environment variable `RED_KNOT_LOG_PROFILE` to `1` or `true`. ty generates a folded stack trace to the current directory named `tracing.folded` when setting the environment variable `TY_LOG_PROFILE` to `1` or `true`.
```bash ```bash
RED_KNOT_LOG_PROFILE=1 red_knot -- --current-directory=../test -vvv TY_LOG_PROFILE=1 ty -- --current-directory=../test -vvv
``` ```
You can convert the textual representation into a visual one using `inferno`. You can convert the textual representation into a visual one using `inferno`.

View file

@ -1,17 +1,13 @@
use crate::logging::Verbosity; use crate::logging::Verbosity;
use crate::python_version::PythonVersion; use crate::python_version::PythonVersion;
use clap::{ArgAction, ArgMatches, Error, Parser}; use clap::{ArgAction, ArgMatches, Error, Parser};
use red_knot_project::metadata::options::{EnvironmentOptions, Options, TerminalOptions};
use red_knot_project::metadata::value::{RangedValue, RelativePathBuf};
use red_knot_python_semantic::lint;
use ruff_db::system::SystemPathBuf; use ruff_db::system::SystemPathBuf;
use ty_project::metadata::options::{EnvironmentOptions, Options, TerminalOptions};
use ty_project::metadata::value::{RangedValue, RelativePathBuf};
use ty_python_semantic::lint;
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
#[command( #[command(author, name = "ty", about = "An extremely fast Python type checker.")]
author,
name = "red-knot",
about = "An extremely fast Python type checker."
)]
#[command(version)] #[command(version)]
pub(crate) struct Args { pub(crate) struct Args {
#[command(subcommand)] #[command(subcommand)]
@ -26,7 +22,7 @@ pub(crate) enum Command {
/// Start the language server /// Start the language server
Server, Server,
/// Display Red Knot's version /// Display ty's version
Version, Version,
} }
@ -48,11 +44,11 @@ pub(crate) struct CheckCommand {
#[arg(long, value_name = "PROJECT")] #[arg(long, value_name = "PROJECT")]
pub(crate) project: Option<SystemPathBuf>, pub(crate) project: Option<SystemPathBuf>,
/// Path to the Python installation from which Red Knot resolves type information and third-party dependencies. /// Path to the Python installation from which ty resolves type information and third-party dependencies.
/// ///
/// If not specified, Red Knot will look at the `VIRTUAL_ENV` environment variable. /// If not specified, ty will look at the `VIRTUAL_ENV` environment variable.
/// ///
/// Red Knot will search in the path's `site-packages` directories for type information and /// ty will search in the path's `site-packages` directories for type information and
/// third-party imports. /// third-party imports.
/// ///
/// This option is commonly used to specify the path to a virtual environment. /// This option is commonly used to specify the path to a virtual environment.

View file

@ -1,4 +1,4 @@
//! Sets up logging for Red Knot //! Sets up logging for ty
use anyhow::Context; use anyhow::Context;
use colored::Colorize; use colored::Colorize;
@ -42,14 +42,14 @@ impl Verbosity {
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
pub(crate) enum VerbosityLevel { pub(crate) enum VerbosityLevel {
/// Default output level. Only shows Ruff and Red Knot events up to the [`WARN`](tracing::Level::WARN). /// Default output level. Only shows Ruff and ty events up to the [`WARN`](tracing::Level::WARN).
Default, Default,
/// Enables verbose output. Emits Ruff and Red Knot events up to the [`INFO`](tracing::Level::INFO). /// Enables verbose output. Emits Ruff and ty events up to the [`INFO`](tracing::Level::INFO).
/// Corresponds to `-v`. /// Corresponds to `-v`.
Verbose, Verbose,
/// Enables a more verbose tracing format and emits Ruff and Red Knot events up to [`DEBUG`](tracing::Level::DEBUG). /// Enables a more verbose tracing format and emits Ruff and ty events up to [`DEBUG`](tracing::Level::DEBUG).
/// Corresponds to `-vv` /// Corresponds to `-vv`
ExtraVerbose, ExtraVerbose,
@ -79,11 +79,11 @@ impl VerbosityLevel {
pub(crate) fn setup_tracing(level: VerbosityLevel) -> anyhow::Result<TracingGuard> { pub(crate) fn setup_tracing(level: VerbosityLevel) -> anyhow::Result<TracingGuard> {
use tracing_subscriber::prelude::*; use tracing_subscriber::prelude::*;
// The `RED_KNOT_LOG` environment variable overrides the default log level. // The `TY_LOG` environment variable overrides the default log level.
let filter = if let Ok(log_env_variable) = std::env::var("RED_KNOT_LOG") { let filter = if let Ok(log_env_variable) = std::env::var("TY_LOG") {
EnvFilter::builder() EnvFilter::builder()
.parse(log_env_variable) .parse(log_env_variable)
.context("Failed to parse directives specified in RED_KNOT_LOG environment variable.")? .context("Failed to parse directives specified in TY_LOG environment variable.")?
} else { } else {
match level { match level {
VerbosityLevel::Default => { VerbosityLevel::Default => {
@ -93,9 +93,9 @@ pub(crate) fn setup_tracing(level: VerbosityLevel) -> anyhow::Result<TracingGuar
level => { level => {
let level_filter = level.level_filter(); let level_filter = level.level_filter();
// Show info|debug|trace events, but allow `RED_KNOT_LOG` to override // Show info|debug|trace events, but allow `TY_LOG` to override
let filter = EnvFilter::default().add_directive( let filter = EnvFilter::default().add_directive(
format!("red_knot={level_filter}") format!("ty={level_filter}")
.parse() .parse()
.expect("Hardcoded directive to be valid"), .expect("Hardcoded directive to be valid"),
); );
@ -131,7 +131,7 @@ pub(crate) fn setup_tracing(level: VerbosityLevel) -> anyhow::Result<TracingGuar
} else { } else {
let subscriber = registry.with( let subscriber = registry.with(
tracing_subscriber::fmt::layer() tracing_subscriber::fmt::layer()
.event_format(RedKnotFormat { .event_format(TyFormat {
display_level: true, display_level: true,
display_timestamp: level.is_extra_verbose(), display_timestamp: level.is_extra_verbose(),
show_spans: false, show_spans: false,
@ -155,7 +155,7 @@ fn setup_profile<S>() -> (
where where
S: Subscriber + for<'span> LookupSpan<'span>, S: Subscriber + for<'span> LookupSpan<'span>,
{ {
if let Ok("1" | "true") = std::env::var("RED_KNOT_LOG_PROFILE").as_deref() { if let Ok("1" | "true") = std::env::var("TY_LOG_PROFILE").as_deref() {
let (layer, guard) = tracing_flame::FlameLayer::with_file("tracing.folded") let (layer, guard) = tracing_flame::FlameLayer::with_file("tracing.folded")
.expect("Flame layer to be created"); .expect("Flame layer to be created");
(Some(layer), Some(guard)) (Some(layer), Some(guard))
@ -168,14 +168,14 @@ pub(crate) struct TracingGuard {
_flame_guard: Option<tracing_flame::FlushGuard<BufWriter<File>>>, _flame_guard: Option<tracing_flame::FlushGuard<BufWriter<File>>>,
} }
struct RedKnotFormat { struct TyFormat {
display_timestamp: bool, display_timestamp: bool,
display_level: bool, display_level: bool,
show_spans: bool, show_spans: bool,
} }
/// See <https://docs.rs/tracing-subscriber/0.3.18/src/tracing_subscriber/fmt/format/mod.rs.html#1026-1156> /// See <https://docs.rs/tracing-subscriber/0.3.18/src/tracing_subscriber/fmt/format/mod.rs.html#1026-1156>
impl<S, N> FormatEvent<S, N> for RedKnotFormat impl<S, N> FormatEvent<S, N> for TyFormat
where where
S: Subscriber + for<'a> LookupSpan<'a>, S: Subscriber + for<'a> LookupSpan<'a>,
N: for<'a> FormatFields<'a> + 'static, N: for<'a> FormatFields<'a> + 'static,

View file

@ -10,14 +10,14 @@ use anyhow::{anyhow, Context};
use clap::Parser; use clap::Parser;
use colored::Colorize; use colored::Colorize;
use crossbeam::channel as crossbeam_channel; use crossbeam::channel as crossbeam_channel;
use red_knot_project::metadata::options::Options;
use red_knot_project::watch::ProjectWatcher;
use red_knot_project::{watch, Db};
use red_knot_project::{ProjectDatabase, ProjectMetadata};
use red_knot_server::run_server;
use ruff_db::diagnostic::{Diagnostic, DisplayDiagnosticConfig, Severity}; use ruff_db::diagnostic::{Diagnostic, DisplayDiagnosticConfig, Severity};
use ruff_db::system::{OsSystem, SystemPath, SystemPathBuf}; use ruff_db::system::{OsSystem, SystemPath, SystemPathBuf};
use salsa::plumbing::ZalsaDatabase; use salsa::plumbing::ZalsaDatabase;
use ty_project::metadata::options::Options;
use ty_project::watch::ProjectWatcher;
use ty_project::{watch, Db};
use ty_project::{ProjectDatabase, ProjectMetadata};
use ty_server::run_server;
mod args; mod args;
mod logging; mod logging;
@ -32,9 +32,9 @@ pub fn main() -> ExitStatus {
// Use `writeln` instead of `eprintln` to avoid panicking when the stderr pipe is broken. // Use `writeln` instead of `eprintln` to avoid panicking when the stderr pipe is broken.
let mut stderr = std::io::stderr().lock(); let mut stderr = std::io::stderr().lock();
// This communicates that this isn't a linter error but Red Knot itself hard-errored for // This communicates that this isn't a linter error but ty itself hard-errored for
// some reason (e.g. failed to resolve the configuration) // some reason (e.g. failed to resolve the configuration)
writeln!(stderr, "{}", "Red Knot failed".red().bold()).ok(); writeln!(stderr, "{}", "ty failed".red().bold()).ok();
// Currently we generally only see one error, but e.g. with io errors when resolving // Currently we generally only see one error, but e.g. with io errors when resolving
// the configuration it is help to chain errors ("resolving configuration failed" -> // the configuration it is help to chain errors ("resolving configuration failed" ->
// "failed to read file: subdir/pyproject.toml") // "failed to read file: subdir/pyproject.toml")
@ -71,7 +71,7 @@ fn run() -> anyhow::Result<ExitStatus> {
pub(crate) fn version() -> Result<()> { pub(crate) fn version() -> Result<()> {
let mut stdout = BufWriter::new(io::stdout().lock()); let mut stdout = BufWriter::new(io::stdout().lock());
let version_info = crate::version::version(); let version_info = crate::version::version();
writeln!(stdout, "red knot {}", &version_info)?; writeln!(stdout, "ty {}", &version_info)?;
Ok(()) Ok(())
} }
@ -90,7 +90,7 @@ fn run_check(args: CheckCommand) -> anyhow::Result<ExitStatus> {
SystemPathBuf::from_path_buf(cwd) SystemPathBuf::from_path_buf(cwd)
.map_err(|path| { .map_err(|path| {
anyhow!( anyhow!(
"The current working directory `{}` contains non-Unicode characters. Red Knot only supports Unicode paths.", "The current working directory `{}` contains non-Unicode characters. ty only supports Unicode paths.",
path.display() path.display()
) )
})? })?
@ -172,7 +172,7 @@ pub enum ExitStatus {
/// Checking failed due to an invocation error (e.g. the current directory no longer exists, incorrect CLI arguments, ...) /// Checking failed due to an invocation error (e.g. the current directory no longer exists, incorrect CLI arguments, ...)
Error = 2, Error = 2,
/// Internal Red Knot error (panic, or any other error that isn't due to the user using the /// Internal ty error (panic, or any other error that isn't due to the user using the
/// program incorrectly or transient environment errors). /// program incorrectly or transient environment errors).
InternalError = 101, InternalError = 101,
} }

View file

@ -1,16 +1,16 @@
//! Code for representing Red Knot's release version number. //! Code for representing ty's release version number.
use std::fmt; use std::fmt;
/// Information about the git repository where Red Knot was built from. /// Information about the git repository where ty was built from.
pub(crate) struct CommitInfo { pub(crate) struct CommitInfo {
short_commit_hash: String, short_commit_hash: String,
commit_date: String, commit_date: String,
commits_since_last_tag: u32, commits_since_last_tag: u32,
} }
/// Red Knot's version. /// ty's version.
pub(crate) struct VersionInfo { pub(crate) struct VersionInfo {
/// Red Knot's version, such as "0.5.1" /// ty's version, such as "0.5.1"
version: String, version: String,
/// Information about the git commit we may have been built from. /// Information about the git commit we may have been built from.
/// ///
@ -34,7 +34,7 @@ impl fmt::Display for VersionInfo {
} }
} }
/// Returns information about Red Knot's version. /// Returns information about ty's version.
pub(crate) fn version() -> VersionInfo { pub(crate) fn version() -> VersionInfo {
// Environment variables are only read at compile-time // Environment variables are only read at compile-time
macro_rules! option_env_str { macro_rules! option_env_str {
@ -47,14 +47,13 @@ pub(crate) fn version() -> VersionInfo {
let version = option_env_str!("CARGO_PKG_VERSION").unwrap(); let version = option_env_str!("CARGO_PKG_VERSION").unwrap();
// Commit info is pulled from git and set by `build.rs` // Commit info is pulled from git and set by `build.rs`
let commit_info = let commit_info = option_env_str!("TY_COMMIT_SHORT_HASH").map(|short_commit_hash| CommitInfo {
option_env_str!("RED_KNOT_COMMIT_SHORT_HASH").map(|short_commit_hash| CommitInfo { short_commit_hash,
short_commit_hash, commit_date: option_env_str!("TY_COMMIT_DATE").unwrap(),
commit_date: option_env_str!("RED_KNOT_COMMIT_DATE").unwrap(), commits_since_last_tag: option_env_str!("TY_LAST_TAG_DISTANCE")
commits_since_last_tag: option_env_str!("RED_KNOT_LAST_TAG_DISTANCE") .as_deref()
.as_deref() .map_or(0, |value| value.parse::<u32>().unwrap_or(0)),
.map_or(0, |value| value.parse::<u32>().unwrap_or(0)), });
});
VersionInfo { VersionInfo {
version, version,

View file

@ -79,7 +79,7 @@ fn test_respect_ignore_files() -> anyhow::Result<()> {
"); ");
// Test that we can set to false via config file // Test that we can set to false via config file
case.write_file("knot.toml", "respect-ignore-files = false")?; case.write_file("ty.toml", "respect-ignore-files = false")?;
assert_cmd_snapshot!(case.command(), @r" assert_cmd_snapshot!(case.command(), @r"
success: false success: false
exit_code: 1 exit_code: 1
@ -97,7 +97,7 @@ fn test_respect_ignore_files() -> anyhow::Result<()> {
"); ");
// Ensure CLI takes precedence // Ensure CLI takes precedence
case.write_file("knot.toml", "respect-ignore-files = true")?; case.write_file("ty.toml", "respect-ignore-files = true")?;
assert_cmd_snapshot!(case.command().arg("--no-respect-ignore-files"), @r" assert_cmd_snapshot!(case.command().arg("--no-respect-ignore-files"), @r"
success: false success: false
exit_code: 1 exit_code: 1
@ -123,7 +123,7 @@ fn config_override_python_version() -> anyhow::Result<()> {
( (
"pyproject.toml", "pyproject.toml",
r#" r#"
[tool.knot.environment] [tool.ty.environment]
python-version = "3.11" python-version = "3.11"
"#, "#,
), ),
@ -174,7 +174,7 @@ fn config_override_python_platform() -> anyhow::Result<()> {
( (
"pyproject.toml", "pyproject.toml",
r#" r#"
[tool.knot.environment] [tool.ty.environment]
python-platform = "linux" python-platform = "linux"
"#, "#,
), ),
@ -249,7 +249,7 @@ fn cli_arguments_are_relative_to_the_current_directory() -> anyhow::Result<()> {
( (
"pyproject.toml", "pyproject.toml",
r#" r#"
[tool.knot.environment] [tool.ty.environment]
python-version = "3.11" python-version = "3.11"
"#, "#,
), ),
@ -320,7 +320,7 @@ fn paths_in_configuration_files_are_relative_to_the_project_root() -> anyhow::Re
( (
"pyproject.toml", "pyproject.toml",
r#" r#"
[tool.knot.environment] [tool.ty.environment]
python-version = "3.11" python-version = "3.11"
extra-paths = ["libs"] extra-paths = ["libs"]
"#, "#,
@ -401,7 +401,7 @@ fn configuration_rule_severity() -> anyhow::Result<()> {
case.write_file( case.write_file(
"pyproject.toml", "pyproject.toml",
r#" r#"
[tool.knot.rules] [tool.ty.rules]
division-by-zero = "warn" # demote to warn division-by-zero = "warn" # demote to warn
possibly-unresolved-reference = "ignore" possibly-unresolved-reference = "ignore"
"#, "#,
@ -604,14 +604,14 @@ fn cli_rule_severity_precedence() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
/// Red Knot warns about unknown rules specified in a configuration file /// ty warns about unknown rules specified in a configuration file
#[test] #[test]
fn configuration_unknown_rules() -> anyhow::Result<()> { fn configuration_unknown_rules() -> anyhow::Result<()> {
let case = TestCase::with_files([ let case = TestCase::with_files([
( (
"pyproject.toml", "pyproject.toml",
r#" r#"
[tool.knot.rules] [tool.ty.rules]
division-by-zer = "warn" # incorrect rule name division-by-zer = "warn" # incorrect rule name
"#, "#,
), ),
@ -625,7 +625,7 @@ fn configuration_unknown_rules() -> anyhow::Result<()> {
warning: unknown-rule warning: unknown-rule
--> pyproject.toml:3:1 --> pyproject.toml:3:1
| |
2 | [tool.knot.rules] 2 | [tool.ty.rules]
3 | division-by-zer = "warn" # incorrect rule name 3 | division-by-zer = "warn" # incorrect rule name
| ^^^^^^^^^^^^^^^ Unknown lint rule `division-by-zer` | ^^^^^^^^^^^^^^^ Unknown lint rule `division-by-zer`
| |
@ -638,7 +638,7 @@ fn configuration_unknown_rules() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
/// Red Knot warns about unknown rules specified in a CLI argument /// ty warns about unknown rules specified in a CLI argument
#[test] #[test]
fn cli_unknown_rules() -> anyhow::Result<()> { fn cli_unknown_rules() -> anyhow::Result<()> {
let case = TestCase::with_file("test.py", "print(10)")?; let case = TestCase::with_file("test.py", "print(10)")?;
@ -768,7 +768,7 @@ fn exit_code_no_errors_but_error_on_warning_is_enabled_in_configuration() -> any
let case = TestCase::with_files([ let case = TestCase::with_files([
("test.py", r"print(x) # [unresolved-reference]"), ("test.py", r"print(x) # [unresolved-reference]"),
( (
"knot.toml", "ty.toml",
r#" r#"
[terminal] [terminal]
error-on-warning = true error-on-warning = true
@ -913,7 +913,7 @@ fn exit_code_exit_zero_is_true() -> anyhow::Result<()> {
fn user_configuration() -> anyhow::Result<()> { fn user_configuration() -> anyhow::Result<()> {
let case = TestCase::with_files([ let case = TestCase::with_files([
( (
"project/knot.toml", "project/ty.toml",
r#" r#"
[rules] [rules]
division-by-zero = "warn" division-by-zero = "warn"
@ -973,7 +973,7 @@ fn user_configuration() -> anyhow::Result<()> {
// Changing the level for `division-by-zero` has no effect, because the project-level configuration // Changing the level for `division-by-zero` has no effect, because the project-level configuration
// has higher precedence. // has higher precedence.
case.write_file( case.write_file(
config_directory.join("knot/knot.toml"), config_directory.join("ty/ty.toml"),
r#" r#"
[rules] [rules]
division-by-zero = "error" division-by-zero = "error"
@ -1267,7 +1267,7 @@ impl TestCase {
} }
fn command(&self) -> Command { fn command(&self) -> Command {
let mut command = Command::new(get_cargo_bin("red_knot")); let mut command = Command::new(get_cargo_bin("ty"));
command.current_dir(&self.project_dir).arg("check"); command.current_dir(&self.project_dir).arg("check");
command command
} }

View file

@ -3,12 +3,6 @@ use std::io::Write;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use anyhow::{anyhow, Context}; use anyhow::{anyhow, Context};
use red_knot_project::metadata::options::{EnvironmentOptions, Options};
use red_knot_project::metadata::pyproject::{PyProject, Tool};
use red_knot_project::metadata::value::{RangedValue, RelativePathBuf};
use red_knot_project::watch::{directory_watcher, ChangeEvent, ProjectWatcher};
use red_knot_project::{Db, ProjectDatabase, ProjectMetadata};
use red_knot_python_semantic::{resolve_module, ModuleName, PythonPlatform};
use ruff_db::files::{system_path_to_file, File, FileError}; use ruff_db::files::{system_path_to_file, File, FileError};
use ruff_db::source::source_text; use ruff_db::source::source_text;
use ruff_db::system::{ use ruff_db::system::{
@ -16,6 +10,12 @@ use ruff_db::system::{
}; };
use ruff_db::{Db as _, Upcast}; use ruff_db::{Db as _, Upcast};
use ruff_python_ast::PythonVersion; use ruff_python_ast::PythonVersion;
use ty_project::metadata::options::{EnvironmentOptions, Options};
use ty_project::metadata::pyproject::{PyProject, Tool};
use ty_project::metadata::value::{RangedValue, RelativePathBuf};
use ty_project::watch::{directory_watcher, ChangeEvent, ProjectWatcher};
use ty_project::{Db, ProjectDatabase, ProjectMetadata};
use ty_python_semantic::{resolve_module, ModuleName, PythonPlatform};
struct TestCase { struct TestCase {
db: ProjectDatabase, db: ProjectDatabase,
@ -173,9 +173,7 @@ impl TestCase {
self.project_path("pyproject.toml").as_std_path(), self.project_path("pyproject.toml").as_std_path(),
toml::to_string(&PyProject { toml::to_string(&PyProject {
project: None, project: None,
tool: Some(Tool { tool: Some(Tool { ty: Some(options) }),
knot: Some(options),
}),
}) })
.context("Failed to serialize options")?, .context("Failed to serialize options")?,
) )
@ -382,9 +380,7 @@ where
project_path.join("pyproject.toml").as_std_path(), project_path.join("pyproject.toml").as_std_path(),
toml::to_string(&PyProject { toml::to_string(&PyProject {
project: None, project: None,
tool: Some(Tool { tool: Some(Tool { ty: Some(options) }),
knot: Some(options),
}),
}) })
.context("Failed to serialize options")?, .context("Failed to serialize options")?,
) )
@ -1546,7 +1542,7 @@ mod unix {
// //
// I further tested how good editor support is for symlinked files and it is not good ;) // I further tested how good editor support is for symlinked files and it is not good ;)
// * VS Code doesn't update the file content if a file gets changed through a symlink // * VS Code doesn't update the file content if a file gets changed through a symlink
// * PyCharm doesn't update diagnostics if a symlinked module is changed (same as red knot). // * PyCharm doesn't update diagnostics if a symlinked module is changed (same as ty).
// //
// That's why I think it's fine to not support this case for now. // That's why I think it's fine to not support this case for now.
@ -1658,7 +1654,7 @@ mod unix {
// It would be nice if this is supported but the underlying file system watchers // It would be nice if this is supported but the underlying file system watchers
// only emit a single event. For reference // only emit a single event. For reference
// * VS Code doesn't update the file content if a file gets changed through a symlink // * VS Code doesn't update the file content if a file gets changed through a symlink
// * PyCharm doesn't update diagnostics if a symlinked module is changed (same as red knot). // * PyCharm doesn't update diagnostics if a symlinked module is changed (same as ty).
// We could add support for it by keeping a reverse map from `real_path` to symlinked path but // We could add support for it by keeping a reverse map from `real_path` to symlinked path but
// it doesn't seem worth doing considering that as prominent tools like PyCharm don't support it. // it doesn't seem worth doing considering that as prominent tools like PyCharm don't support it.
// Pyright does support it, thanks to chokidar. // Pyright does support it, thanks to chokidar.
@ -1682,7 +1678,7 @@ fn nested_projects_delete_root() -> anyhow::Result<()> {
[project] [project]
name = "inner" name = "inner"
[tool.knot] [tool.ty]
"#, "#,
)?; )?;
@ -1692,7 +1688,7 @@ fn nested_projects_delete_root() -> anyhow::Result<()> {
[project] [project]
name = "outer" name = "outer"
[tool.knot] [tool.ty]
"#, "#,
)?; )?;
@ -1732,9 +1728,9 @@ fn changes_to_user_configuration() -> anyhow::Result<()> {
)?; )?;
let config_directory = context.join_root_path("home/.config"); let config_directory = context.join_root_path("home/.config");
std::fs::create_dir_all(config_directory.join("knot").as_std_path())?; std::fs::create_dir_all(config_directory.join("ty").as_std_path())?;
std::fs::write( std::fs::write(
config_directory.join("knot/knot.toml").as_std_path(), config_directory.join("ty/ty.toml").as_std_path(),
r#" r#"
[rules] [rules]
division-by-zero = "ignore" division-by-zero = "ignore"
@ -1765,14 +1761,14 @@ fn changes_to_user_configuration() -> anyhow::Result<()> {
// Enable division-by-zero in the user configuration with warning severity // Enable division-by-zero in the user configuration with warning severity
update_file( update_file(
case.root_path().join("home/.config/knot/knot.toml"), case.root_path().join("home/.config/ty/ty.toml"),
r#" r#"
[rules] [rules]
division-by-zero = "warn" division-by-zero = "warn"
"#, "#,
)?; )?;
let changes = case.stop_watch(event_for_file("knot.toml")); let changes = case.stop_watch(event_for_file("ty.toml"));
case.apply_changes(changes); case.apply_changes(changes);
@ -1793,7 +1789,7 @@ fn changes_to_user_configuration() -> anyhow::Result<()> {
/// ///
/// This test currently fails on case-insensitive systems because `Files` is case-sensitive /// This test currently fails on case-insensitive systems because `Files` is case-sensitive
/// but the `System::metadata` call isn't. This means that /// but the `System::metadata` call isn't. This means that
/// Red Knot considers both `Lib.py` and `lib.py` to exist when only `lib.py` does /// ty considers both `Lib.py` and `lib.py` to exist when only `lib.py` does
/// ///
/// The incoming change events then are no-ops because they don't change either file's /// The incoming change events then are no-ops because they don't change either file's
/// status nor does it update their last modified time (renaming a file doesn't bump it's /// status nor does it update their last modified time (renaming a file doesn't bump it's
@ -1805,7 +1801,7 @@ fn changes_to_user_configuration() -> anyhow::Result<()> {
/// `System` calls should be case sensitive. This would be the most consistent /// `System` calls should be case sensitive. This would be the most consistent
/// but might be hard to pull off. /// but might be hard to pull off.
/// ///
/// What the right solution is also depends on if Red Knot itself should be case /// What the right solution is also depends on if ty itself should be case
/// sensitive or not. E.g. should `include="src"` be case sensitive on all systems /// sensitive or not. E.g. should `include="src"` be case sensitive on all systems
/// or only on case-sensitive systems? /// or only on case-sensitive systems?
/// ///

View file

@ -1,5 +1,5 @@
[package] [package]
name = "red_knot_ide" name = "ty_ide"
version = "0.0.0" version = "0.0.0"
publish = false publish = false
authors = { workspace = true } authors = { workspace = true }
@ -15,7 +15,7 @@ ruff_db = { workspace = true }
ruff_python_ast = { workspace = true } ruff_python_ast = { workspace = true }
ruff_python_parser = { workspace = true } ruff_python_parser = { workspace = true }
ruff_text_size = { workspace = true } ruff_text_size = { workspace = true }
red_knot_python_semantic = { workspace = true } ty_python_semantic = { workspace = true }
rustc-hash = { workspace = true } rustc-hash = { workspace = true }
salsa = { workspace = true } salsa = { workspace = true }
@ -23,7 +23,7 @@ smallvec = { workspace = true }
tracing = { workspace = true } tracing = { workspace = true }
[dev-dependencies] [dev-dependencies]
red_knot_vendored = { workspace = true } ty_vendored = { workspace = true }
insta = { workspace = true, features = ["filters"] } insta = { workspace = true, features = ["filters"] }

View file

@ -1,5 +1,5 @@
use red_knot_python_semantic::Db as SemanticDb;
use ruff_db::{Db as SourceDb, Upcast}; use ruff_db::{Db as SourceDb, Upcast};
use ty_python_semantic::Db as SemanticDb;
#[salsa::db] #[salsa::db]
pub trait Db: SemanticDb + Upcast<dyn SemanticDb> + Upcast<dyn SourceDb> {} pub trait Db: SemanticDb + Upcast<dyn SemanticDb> + Upcast<dyn SourceDb> {}
@ -9,12 +9,12 @@ pub(crate) mod tests {
use std::sync::Arc; use std::sync::Arc;
use super::Db; use super::Db;
use red_knot_python_semantic::lint::{LintRegistry, RuleSelection};
use red_knot_python_semantic::{default_lint_registry, Db as SemanticDb, Program};
use ruff_db::files::{File, Files}; use ruff_db::files::{File, Files};
use ruff_db::system::{DbWithTestSystem, System, TestSystem}; use ruff_db::system::{DbWithTestSystem, System, TestSystem};
use ruff_db::vendored::VendoredFileSystem; use ruff_db::vendored::VendoredFileSystem;
use ruff_db::{Db as SourceDb, Upcast}; use ruff_db::{Db as SourceDb, Upcast};
use ty_python_semantic::lint::{LintRegistry, RuleSelection};
use ty_python_semantic::{default_lint_registry, Db as SemanticDb, Program};
#[salsa::db] #[salsa::db]
#[derive(Clone)] #[derive(Clone)]
@ -33,7 +33,7 @@ pub(crate) mod tests {
Self { Self {
storage: salsa::Storage::default(), storage: salsa::Storage::default(),
system: TestSystem::default(), system: TestSystem::default(),
vendored: red_knot_vendored::file_system().clone(), vendored: ty_vendored::file_system().clone(),
events: Arc::default(), events: Arc::default(),
files: Files::default(), files: Files::default(),
rule_selection: Arc::new(RuleSelection::from_registry(default_lint_registry())), rule_selection: Arc::new(RuleSelection::from_registry(default_lint_registry())),

View file

@ -1,12 +1,12 @@
use crate::find_node::covering_node; use crate::find_node::covering_node;
use crate::{Db, HasNavigationTargets, NavigationTargets, RangedValue}; use crate::{Db, HasNavigationTargets, NavigationTargets, RangedValue};
use red_knot_python_semantic::types::Type;
use red_knot_python_semantic::{HasType, SemanticModel};
use ruff_db::files::{File, FileRange}; use ruff_db::files::{File, FileRange};
use ruff_db::parsed::{parsed_module, ParsedModule}; use ruff_db::parsed::{parsed_module, ParsedModule};
use ruff_python_ast::{self as ast, AnyNodeRef}; use ruff_python_ast::{self as ast, AnyNodeRef};
use ruff_python_parser::TokenKind; use ruff_python_parser::TokenKind;
use ruff_text_size::{Ranged, TextRange, TextSize}; use ruff_text_size::{Ranged, TextRange, TextSize};
use ty_python_semantic::types::Type;
use ty_python_semantic::{HasType, SemanticModel};
pub fn goto_type_definition( pub fn goto_type_definition(
db: &dyn Db, db: &dyn Db,

View file

@ -1,12 +1,12 @@
use crate::goto::{find_goto_target, GotoTarget}; use crate::goto::{find_goto_target, GotoTarget};
use crate::{Db, MarkupKind, RangedValue}; use crate::{Db, MarkupKind, RangedValue};
use red_knot_python_semantic::types::Type;
use red_knot_python_semantic::SemanticModel;
use ruff_db::files::{File, FileRange}; use ruff_db::files::{File, FileRange};
use ruff_db::parsed::parsed_module; use ruff_db::parsed::parsed_module;
use ruff_text_size::{Ranged, TextSize}; use ruff_text_size::{Ranged, TextSize};
use std::fmt; use std::fmt;
use std::fmt::Formatter; use std::fmt::Formatter;
use ty_python_semantic::types::Type;
use ty_python_semantic::SemanticModel;
pub fn hover(db: &dyn Db, file: File, offset: TextSize) -> Option<RangedValue<Hover>> { pub fn hover(db: &dyn Db, file: File, offset: TextSize) -> Option<RangedValue<Hover>> {
let parsed = parsed_module(db.upcast(), file); let parsed = parsed_module(db.upcast(), file);

View file

@ -1,6 +1,4 @@
use crate::Db; use crate::Db;
use red_knot_python_semantic::types::Type;
use red_knot_python_semantic::{HasType, SemanticModel};
use ruff_db::files::File; use ruff_db::files::File;
use ruff_db::parsed::parsed_module; use ruff_db::parsed::parsed_module;
use ruff_python_ast::visitor::source_order::{self, SourceOrderVisitor, TraversalSignal}; use ruff_python_ast::visitor::source_order::{self, SourceOrderVisitor, TraversalSignal};
@ -8,6 +6,8 @@ use ruff_python_ast::{AnyNodeRef, Expr, Stmt};
use ruff_text_size::{Ranged, TextRange, TextSize}; use ruff_text_size::{Ranged, TextRange, TextSize};
use std::fmt; use std::fmt;
use std::fmt::Formatter; use std::fmt::Formatter;
use ty_python_semantic::types::Type;
use ty_python_semantic::{HasType, SemanticModel};
#[derive(Debug, Clone, Eq, PartialEq)] #[derive(Debug, Clone, Eq, PartialEq)]
pub struct InlayHint<'db> { pub struct InlayHint<'db> {
@ -157,11 +157,11 @@ mod tests {
use crate::db::tests::TestDb; use crate::db::tests::TestDb;
use red_knot_python_semantic::{
Program, ProgramSettings, PythonPath, PythonPlatform, SearchPathSettings,
};
use ruff_db::system::{DbWithWritableSystem, SystemPathBuf}; use ruff_db::system::{DbWithWritableSystem, SystemPathBuf};
use ruff_python_ast::PythonVersion; use ruff_python_ast::PythonVersion;
use ty_python_semantic::{
Program, ProgramSettings, PythonPath, PythonPlatform, SearchPathSettings,
};
pub(super) fn inlay_hint_test(source: &str) -> InlayHintTest { pub(super) fn inlay_hint_test(source: &str) -> InlayHintTest {
const START: &str = "<START>"; const START: &str = "<START>";

View file

@ -16,9 +16,9 @@ pub use markup::MarkupKind;
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use red_knot_python_semantic::types::{Type, TypeDefinition};
use ruff_db::files::{File, FileRange}; use ruff_db::files::{File, FileRange};
use ruff_text_size::{Ranged, TextRange}; use ruff_text_size::{Ranged, TextRange};
use ty_python_semantic::types::{Type, TypeDefinition};
/// Information associated with a text range. /// Information associated with a text range.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
@ -201,14 +201,14 @@ impl HasNavigationTargets for TypeDefinition<'_> {
mod tests { mod tests {
use crate::db::tests::TestDb; use crate::db::tests::TestDb;
use insta::internals::SettingsBindDropGuard; use insta::internals::SettingsBindDropGuard;
use red_knot_python_semantic::{
Program, ProgramSettings, PythonPath, PythonPlatform, SearchPathSettings,
};
use ruff_db::diagnostic::{Diagnostic, DiagnosticFormat, DisplayDiagnosticConfig}; use ruff_db::diagnostic::{Diagnostic, DiagnosticFormat, DisplayDiagnosticConfig};
use ruff_db::files::{system_path_to_file, File}; use ruff_db::files::{system_path_to_file, File};
use ruff_db::system::{DbWithWritableSystem, SystemPath, SystemPathBuf}; use ruff_db::system::{DbWithWritableSystem, SystemPath, SystemPathBuf};
use ruff_python_ast::PythonVersion; use ruff_python_ast::PythonVersion;
use ruff_text_size::TextSize; use ruff_text_size::TextSize;
use ty_python_semantic::{
Program, ProgramSettings, PythonPath, PythonPlatform, SearchPathSettings,
};
pub(super) fn cursor_test(source: &str) -> CursorTest { pub(super) fn cursor_test(source: &str) -> CursorTest {
let mut db = TestDb::new(); let mut db = TestDb::new();

View file

@ -1,5 +1,5 @@
[package] [package]
name = "red_knot_project" name = "ty_project"
version = "0.0.0" version = "0.0.0"
edition.workspace = true edition.workspace = true
rust-version.workspace = true rust-version.workspace = true
@ -18,9 +18,9 @@ ruff_macros = { workspace = true }
ruff_python_ast = { workspace = true, features = ["serde"] } ruff_python_ast = { workspace = true, features = ["serde"] }
ruff_python_formatter = { workspace = true, optional = true } ruff_python_formatter = { workspace = true, optional = true }
ruff_text_size = { workspace = true } ruff_text_size = { workspace = true }
red_knot_ide = { workspace = true } ty_ide = { workspace = true }
red_knot_python_semantic = { workspace = true, features = ["serde"] } ty_python_semantic = { workspace = true, features = ["serde"] }
red_knot_vendored = { workspace = true } ty_vendored = { workspace = true }
anyhow = { workspace = true } anyhow = { workspace = true }
crossbeam = { workspace = true } crossbeam = { workspace = true }
@ -43,13 +43,13 @@ insta = { workspace = true, features = ["redactions", "ron"] }
[features] [features]
default = ["zstd"] default = ["zstd"]
deflate = ["red_knot_vendored/deflate"] deflate = ["ty_vendored/deflate"]
schemars = [ schemars = [
"dep:schemars", "dep:schemars",
"ruff_db/schemars", "ruff_db/schemars",
"red_knot_python_semantic/schemars", "ty_python_semantic/schemars",
] ]
zstd = ["red_knot_vendored/zstd"] zstd = ["ty_vendored/zstd"]
format = ["ruff_python_formatter"] format = ["ruff_python_formatter"]
[lints] [lints]

Some files were not shown because too many files have changed in this diff Show more