ruff icon indicating copy to clipboard operation
ruff copied to clipboard

TCH auto-quoting is invalid for strings containing quotation marks

Open dscorbett opened this issue 1 year ago • 5 comments

The automated fixes for TCH001, TCH002, and TCH003 do not correctly handle string literals containing quotation marks. In the following example, running Ruff introduces an invalid type annotation, which mypy reports.

$ ruff --version
ruff 0.7.1

$ cat tch.py
from collections.abc import Sequence
from typing import Literal
def f(x: Sequence[Literal["'"]]) -> None:
    pass

$ mypy tch.py
Success: no issues found in 1 source file

$ ruff check --isolated --config 'lint.flake8-type-checking.quote-annotations = true' --select TCH tch.py --unsafe-fixes --fix
Found 1 error (1 fixed, 0 remaining).

$ cat tch.py
from typing import Literal, TYPE_CHECKING

if TYPE_CHECKING:
    from collections.abc import Sequence
def f(x: "Sequence[Literal[''']]") -> None:
    pass

$ mypy tch.py
tch.py:5: error: Invalid type comment or annotation  [valid-type]
Found 1 error in 1 file (checked 1 source file)

dscorbett avatar Oct 25 '24 22:10 dscorbett

As with other string related fixes, we could consider disabling the fix if the string contains nested quotes. Ideally we would be somewhat clever about it to only disable it when running the fix creates invalid syntax because the use of Literal["Test"] is common

MichaReiser avatar Oct 26 '24 08:10 MichaReiser

Ideally we would be somewhat clever about it to only disable it when running the fix creates invalid syntax because the use of Literal["Test"] is common

I'm not sure what do you mean here because we do fix this correctly by flipping the quotes but we don't consider nested quotes inside another existing string literal (https://play.ruff.rs/fc94efc6-2ccf-4b20-b053-f810a7d06c2f). I think we should avoid generating the fix for this case.

cc @Glyphack if you're interested

dhruvmanila avatar Oct 28 '24 07:10 dhruvmanila

I'm not sure what do you mean here because we do fix this correctly by flipping the quotes but we don't consider nested quotes inside another existing string literal (play.ruff.rs/fc94efc6-2ccf-4b20-b053-f810a7d06c2f).

That's what I mean. We can't just naively test if the annotation contains any quotes. Instead, we have to search for nested quotes.

MichaReiser avatar Oct 28 '24 07:10 MichaReiser

Thanks I like to spend some time on this. I think the simplest fix would be to check if the StringLiteral contains any quotes inside and don't apply the fix or check if the inner quotes will be a problem and then don't apply the fix.

Glyphack avatar Oct 28 '24 08:10 Glyphack

Other characters to beware of are backslashes and newlines.

dscorbett avatar Oct 28 '24 16:10 dscorbett