Skip to content

Conversation

@ntBre
Copy link
Contributor

@ntBre ntBre commented Jul 17, 2025

Summary

This PR moves most of the work of rendering concise diagnostics in Ruff into ruff_db, where the code is shared with ty. To accomplish this without breaking backwards compatibility in Ruff, there are two main changes on the ruff_db/ty side:

  • Added the logic from Ruff for remapping notebook line numbers to cells
  • Reordered the fields in the diagnostic to match Ruff and rustc
    # old
    error[invalid-assignment] try.py:3:1: Object of type `Literal[1]` is not assignable to `str`
    # new
    try.py:3:1: error[invalid-assignment]: Object of type `Literal[1]` is not assignable to `str`
    

I don't think the notebook change failed any tests on its own, and only a handful of snaphots changed in ty after reordering the fields, but this will obviously affect any other uses of the concise format, outside of tests, too.

The other big change should only affect Ruff:

  • Added three new DisplayDiagnosticConfig options
    Micha and I hoped that we could get by with one option (hide_severity), but Ruff also toggles show_fix_status itself, independently (there are cases where we want neither severity nor the fix status), and during the implementation I realized we also needed access to an Applicability. The main goal here is to suppress the severity (error above) because ruff only uses the error severity and to use the secondary/noqa code instead of the line name (invalid-assignment above).
    # ty - same as "new" above
    try.py:3:1: error[invalid-assignment]: Object of type `Literal[1]` is not assignable to `str`
    # ruff
    try.py:3:1: RUF123 [*] Object of type `Literal[1]` is not assignable to `str`
    

This part of the concise diagnostic is actually shared with the full output format in Ruff, but with the settings above, there are no snapshot changes to either format.

Test Plan

Existing tests with the handful of updates mentioned above, as well as some new tests in the concise module.

Also this PR. Swapping the fields might have broken mypy_primer, unless it occasionally times out on its own.

I also ran this script in the root of my Ruff checkout, which also has CPython in it:

flags=(--isolated --no-cache --no-respect-gitignore --output-format concise .)
diff <(target/release/ruff check ${flags[@]} 2> /dev/null) \
     <(ruff check ${flags[@]} 2> /dev/null)

This yielded an expected diff due to some t-string error changes on main since 0.12.4:

33622c33622
< crates/ruff_python_parser/resources/inline/err/f_string_lambda_without_parentheses.py:1:15: SyntaxError: Expected an element of or the end of the f-string
---
> crates/ruff_python_parser/resources/inline/err/f_string_lambda_without_parentheses.py:1:15: SyntaxError: Expected an f-string or t-string element or the end of the f-string or t-string
33742c33742
< crates/ruff_python_parser/resources/inline/err/implicitly_concatenated_unterminated_string_multiline.py:4:1: SyntaxError: Expected an element of or the end of the f-string
---
> crates/ruff_python_parser/resources/inline/err/implicitly_concatenated_unterminated_string_multiline.py:4:1: SyntaxError: Expected an f-string or t-string element or the end of the f-string or t-string
34131c34131
< crates/ruff_python_parser/resources/inline/err/t_string_lambda_without_parentheses.py:2:15: SyntaxError: Expected an element of or the end of the t-string
---
> crates/ruff_python_parser/resources/inline/err/t_string_lambda_without_parentheses.py:2:15: SyntaxError: Expected an f-string or t-string element or the end of the f-string or t-string

So modulo color, the results are identical on 38,186 errors in our test suite and CPython 3.10.

@ntBre ntBre added internal An internal refactor or improvement diagnostics Related to reporting of diagnostics. labels Jul 17, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Jul 17, 2025

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

✅ ecosystem check detected no linter changes.

@ntBre
Copy link
Contributor Author

ntBre commented Jul 21, 2025

I think this is ready for a first review. The preview changes in the ecosystem are expected, but maybe undesirable. A couple of them look useful, but I'm definitely open to suppressing this for now if we want to try to make some of the fix suggestions less redundant with the main message before exposing them to users in this format.

@ntBre ntBre marked this pull request as ready for review July 21, 2025 16:56
@ntBre ntBre changed the title [prototype] Move concise diagnostic rendering to ruff_db Move concise diagnostic rendering to ruff_db Jul 21, 2025
@ntBre ntBre requested review from BurntSushi and removed request for AlexWaygood, carljm, dcreager and sharkdp July 21, 2025 16:56
@MichaReiser
Copy link
Member

MichaReiser commented Jul 21, 2025

I'll take a closer look tomorrow and try to come up with a suggestion. I don't think we can keep the rendering as is. The messages contain too much redundant information now

@MichaReiser
Copy link
Member

Isn't your other PR addressing the difference in rendering (by moving the help text?)

@ntBre
Copy link
Contributor Author

ntBre commented Jul 21, 2025

Isn't your other PR addressing the difference in rendering (by moving the help text?)

Oh yeah, I think you're right. I was only thinking about the full diagnostic, but that should resolve this as well. We should just be able to use concise_message here again.

@MichaReiser
Copy link
Member

I'll review this after rebasing ontop of your ohter PR. That will make it easier for me to understand the scope of the changes.

@ntBre
Copy link
Contributor Author

ntBre commented Jul 22, 2025

As discussed on Discord, we should now match Ruff's concise styling exactly. I was hoping to get a clean diff from this command:

diff <(CLICOLOR_FORCE=1 ruff check . --output-format concise --no-cache) \
     <(CLICOLOR_FORCE=1 ~/astral/ruff/target/debug/ruff check . --output-format concise --no-cache)

but I think colored and anstyle output slightly different escape codes. This is the remaining diff, but I think both of these should render the same way:

image image

I did have to add some new Styles to the Stylesheet since Ruff was using non-bold cyan and bold red instead of bold bright red.

@github-actions
Copy link
Contributor

ecosystem-analyzer results

Lint rule Added Removed Changed
unresolved-import 134 134 0
invalid-argument-type 5 5 0
invalid-assignment 4 4 0
possibly-unresolved-reference 4 4 0
possibly-unbound-attribute 1 1 0
unresolved-reference 1 1 0
Total 149 149 0

Full report with detailed diff

@ntBre ntBre merged commit 4daf59e into main Jul 23, 2025
37 of 38 checks passed
@ntBre ntBre deleted the brent/concise branch July 23, 2025 15:43
dcreager added a commit that referenced this pull request Jul 23, 2025
* main:
  [ty] Fix narrowing and reachability of class patterns with arguments (#19512)
  [ty] Implemented partial support for "find references" language server feature. (#19475)
  [`flake8-use-pathlib`] Add autofix for `PTH101`, `PTH104`, `PTH105`, `PTH121` (#19404)
  [`perflint`] Parenthesize generator expressions (`PERF401`) (#19325)
  [`pep8-naming`] Fix `N802` false positives for `CGIHTTPRequestHandler` and `SimpleHTTPRequestHandler` (#19432)
  [`pylint`] Handle empty comments after line continuation (`PLR2044`) (#19405)
  Move concise diagnostic rendering to `ruff_db` (#19398)
  [ty] highlight the argument in `static_assert` error messages (#19426)
  [ty] Infer single-valuedness for enums based on `int`/`str` (#19510)
  [ty] Restructure submodule query around `File` dependency
  [ty] Make `Module` a Salsa ingredient
  [ty] Reachability analysis for `isinstance(…)` branches (#19503)
  [ty] Normalize single-member enums to their instance type (#19502)
  [ty] Invert `ty_ide` and `ty_project` dependency (#19501)
  [ty] Implement mock language server for testing (#19391)
  [ty] Detect enums if metaclass is a subtype of EnumType/EnumMeta (#19481)
  [ty] perform type narrowing for places marked `global` too (#19381)
AlexWaygood pushed a commit that referenced this pull request Jul 25, 2025
## Summary

This PR moves most of the work of rendering concise diagnostics in Ruff
into `ruff_db`, where the code is shared with ty. To accomplish this
without breaking backwards compatibility in Ruff, there are two main
changes on the `ruff_db`/ty side:
- Added the logic from Ruff for remapping notebook line numbers to cells
- Reordered the fields in the diagnostic to match Ruff and rustc
  ```text
  # old
error[invalid-assignment] try.py:3:1: Object of type `Literal[1]` is not
assignable to `str`
  # new
try.py:3:1: error[invalid-assignment]: Object of type `Literal[1]` is
not assignable to `str`
  ```

I don't think the notebook change failed any tests on its own, and only
a handful of snaphots changed in ty after reordering the fields, but
this will obviously affect any other uses of the concise format, outside
of tests, too.

The other big change should only affect Ruff:

- Added three new `DisplayDiagnosticConfig` options
Micha and I hoped that we could get by with one option
(`hide_severity`), but Ruff also toggles `show_fix_status` itself,
independently (there are cases where we want neither severity nor the
fix status), and during the implementation I realized we also needed
access to an `Applicability`. The main goal here is to suppress the
severity (`error` above) because ruff only uses the `error` severity and
to use the secondary/noqa code instead of the line name
(`invalid-assignment` above).
  ```text
  # ty - same as "new" above
try.py:3:1: error[invalid-assignment]: Object of type `Literal[1]` is
not assignable to `str`
  # ruff
try.py:3:1: RUF123 [*] Object of type `Literal[1]` is not assignable to
`str`
  ```

This part of the concise diagnostic is actually shared with the `full`
output format in Ruff, but with the settings above, there are no
snapshot changes to either format.

## Test Plan

Existing tests with the handful of updates mentioned above, as well as
some new tests in the `concise` module.

Also this PR. Swapping the fields might have broken mypy_primer, unless
it occasionally times out on its own.

I also ran this script in the root of my Ruff checkout, which also has
CPython in it:

```shell
flags=(--isolated --no-cache --no-respect-gitignore --output-format concise .)
diff <(target/release/ruff check ${flags[@]} 2> /dev/null) \
     <(ruff check ${flags[@]} 2> /dev/null)
```

This yielded an expected diff due to some t-string error changes on main
since 0.12.4:
```diff
33622c33622
< crates/ruff_python_parser/resources/inline/err/f_string_lambda_without_parentheses.py:1:15: SyntaxError: Expected an element of or the end of the f-string
---
> crates/ruff_python_parser/resources/inline/err/f_string_lambda_without_parentheses.py:1:15: SyntaxError: Expected an f-string or t-string element or the end of the f-string or t-string
33742c33742
< crates/ruff_python_parser/resources/inline/err/implicitly_concatenated_unterminated_string_multiline.py:4:1: SyntaxError: Expected an element of or the end of the f-string
---
> crates/ruff_python_parser/resources/inline/err/implicitly_concatenated_unterminated_string_multiline.py:4:1: SyntaxError: Expected an f-string or t-string element or the end of the f-string or t-string
34131c34131
< crates/ruff_python_parser/resources/inline/err/t_string_lambda_without_parentheses.py:2:15: SyntaxError: Expected an element of or the end of the t-string
---
> crates/ruff_python_parser/resources/inline/err/t_string_lambda_without_parentheses.py:2:15: SyntaxError: Expected an f-string or t-string element or the end of the f-string or t-string
```

So modulo color, the results are identical on 38,186 errors in our test
suite and CPython 3.10.

---------

Co-authored-by: David Peter <mail@david-peter.de>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

diagnostics Related to reporting of diagnostics. ecosystem-analyzer internal An internal refactor or improvement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants