Skip to content

Commit

Permalink
WIP: Use noqa_row
Browse files Browse the repository at this point in the history
  • Loading branch information
bluetech committed Feb 25, 2023
1 parent 0ffdf42 commit dad628a
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 55 deletions.
2 changes: 1 addition & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ install:
pip install --no-deps -r requirements-dev.txt

fmt:
ruff --fix ./ruff_lsp ./tests
black ./ruff_lsp ./tests
ruff --fix ./ruff_lsp ./tests

check:
ruff ./ruff_lsp ./tests
Expand Down
106 changes: 60 additions & 46 deletions ruff_lsp/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,11 +132,14 @@ def _parse_output_using_regex(content: str) -> list[Diagnostic]:
# {
# "code": "F841",
# "message": "Local variable `x` is assigned to but never used",
# "fixed": false,
# "location": {
# "row": 2,
# "column": 5
# },
# "end_location": {
# "row": 2,
# "column": 6
# },
# "fix": {
# "content: "",
# "location": {
Expand All @@ -148,7 +151,8 @@ def _parse_output_using_regex(content: str) -> list[Diagnostic]:
# "column: 0
# }
# },
# "filename": "/path/to/test.py"
# "filename": "/path/to/test.py",
# "noqa_row": 2
# },
# ...
# ]
Expand All @@ -167,7 +171,11 @@ def _parse_output_using_regex(content: str) -> list[Diagnostic]:
severity=_get_severity(check["code"]),
code=check["code"],
source=TOOL_DISPLAY,
data=check.get("fix"),
data=DiagnosticData(
fix=check.get("fix"),
# Available since Ruff v0.0.TBD.
noqa_row=check.get("noqa_row"),
),
tags=_get_tags(check["code"]),
)
diagnostics.append(diagnostic)
Expand Down Expand Up @@ -254,6 +262,11 @@ class Fix(TypedDict):
end_location: Location


class DiagnosticData(TypedDict):
fix: Fix | None
noqa_row: int | None


@LSP_SERVER.feature(
TEXT_DOCUMENT_CODE_ACTION,
CodeActionOptions(
Expand Down Expand Up @@ -327,7 +340,8 @@ def code_action(params: CodeActionParams) -> list[CodeAction] | None:
diagnostic
for diagnostic in params.context.diagnostics
if diagnostic.source == "Ruff"
and diagnostic.data is not None
and cast(DiagnosticData, diagnostic.data)["fix"]
is not None
],
),
]
Expand Down Expand Up @@ -392,7 +406,8 @@ def code_action(params: CodeActionParams) -> list[CodeAction] | None:
diagnostic
for diagnostic in params.context.diagnostics
if diagnostic.source == "Ruff"
and diagnostic.data is not None
and cast(DiagnosticData, diagnostic.data)["fix"]
is not None
],
),
)
Expand All @@ -401,9 +416,8 @@ def code_action(params: CodeActionParams) -> list[CodeAction] | None:
if not params.context.only or CodeActionKind.QuickFix in params.context.only:
for diagnostic in params.context.diagnostics:
if diagnostic.source == "Ruff":
if diagnostic.data is not None:
fix = cast(Fix, diagnostic.data)

fix = cast(DiagnosticData, diagnostic.data)["fix"]
if fix is not None:
title: str
if fix.get("message"):
title = f"Ruff ({diagnostic.code}): {fix['message']}"
Expand All @@ -417,9 +431,7 @@ def code_action(params: CodeActionParams) -> list[CodeAction] | None:
title=title,
kind=CodeActionKind.QuickFix,
data=params.text_document.uri,
edit=_create_workspace_edit(
document, cast(Fix, diagnostic.data)
),
edit=_create_workspace_edit(document, fix),
diagnostics=[diagnostic],
),
)
Expand All @@ -428,42 +440,44 @@ def code_action(params: CodeActionParams) -> list[CodeAction] | None:
if not params.context.only or CodeActionKind.QuickFix in params.context.only:
for diagnostic in params.context.diagnostics:
if diagnostic.source == "Ruff":
line = document.lines[diagnostic.range.start.line].rstrip("\r\n")
match = NOQA_REGEX.search(line)
# `foo # noqa: OLD` -> `foo # noqa: OLD,NEW`
if match and match.group("codes") is not None:
codes = match.group("codes") + f",{diagnostic.code}"
start, end = match.start("codes"), match.end("codes")
new_line = line[:start] + codes + line[end:]
# `foo # noqa` -> `foo # noqa: NEW`
elif match:
end = match.end("noqa")
new_line = line[:end] + f": {diagnostic.code}" + line[end:]
# `foo` -> `foo # noqa: NEW`
else:
new_line = f"{line} # noqa: {diagnostic.code}"
fix = Fix(
content=new_line,
message=None,
location=Location(
row=diagnostic.range.start.line + 1,
column=0,
),
end_location=Location(
row=diagnostic.range.start.line + 1,
column=len(line),
),
)
noqa_row = cast(DiagnosticData, diagnostic.data)["noqa_row"]
if noqa_row is not None:
line = document.lines[noqa_row - 1].rstrip("\r\n")
match = NOQA_REGEX.search(line)
# `foo # noqa: OLD` -> `foo # noqa: OLD,NEW`
if match and match.group("codes") is not None:
codes = match.group("codes") + f",{diagnostic.code}"
start, end = match.start("codes"), match.end("codes")
new_line = line[:start] + codes + line[end:]
# `foo # noqa` -> `foo # noqa: NEW`
elif match:
end = match.end("noqa")
new_line = line[:end] + f": {diagnostic.code}" + line[end:]
# `foo` -> `foo # noqa: NEW`
else:
new_line = f"{line} # noqa: {diagnostic.code}"
fix = Fix(
content=new_line,
message=None,
location=Location(
row=noqa_row,
column=0,
),
end_location=Location(
row=noqa_row,
column=len(line),
),
)

actions.append(
CodeAction(
title=f"Ruff: Disable {diagnostic.code} for this line",
kind=CodeActionKind.QuickFix,
data=params.text_document.uri,
edit=_create_workspace_edit(document, fix),
diagnostics=[diagnostic],
),
)
actions.append(
CodeAction(
title=f"Ruff: Disable {diagnostic.code} for this line",
kind=CodeActionKind.QuickFix,
data=params.text_document.uri,
edit=_create_workspace_edit(document, fix),
diagnostics=[diagnostic],
),
)

return actions if actions else None

Expand Down
26 changes: 18 additions & 8 deletions tests/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@


class TestServer(unittest.TestCase):
maxDiff = None

def test_linting_example(self):
logging.info(TEST_FILE_PATH)
contents = TEST_FILE_PATH.read_text()
Expand Down Expand Up @@ -54,10 +56,13 @@ def _handler(params):
"end": {"line": 0, "character": 10},
},
"data": {
"content": "",
"message": "Remove unused import: `sys`",
"location": {"row": 1, "column": 0},
"end_location": {"row": 2, "column": 0},
"fix": {
"content": "",
"message": "Remove unused import: `sys`",
"location": {"row": 1, "column": 0},
"end_location": {"row": 2, "column": 0},
},
"noqa_row": None,
},
"message": "`sys` imported but unused",
"severity": 2,
Expand All @@ -70,6 +75,7 @@ def _handler(params):
"start": {"line": 2, "character": 6},
"end": {"line": 2, "character": 7},
},
"data": {"fix": None, "noqa_row": None},
"message": "Undefined name `x`",
"severity": 2,
"code": "F821",
Expand Down Expand Up @@ -122,10 +128,13 @@ def _handler(params):
"end": {"line": 0, "character": 10},
},
"data": {
"content": "",
"message": "Remove unused import: `sys`",
"location": {"row": 1, "column": 0},
"end_location": {"row": 2, "column": 0},
"fix": {
"content": "",
"message": "Remove unused import: `sys`",
"location": {"row": 1, "column": 0},
"end_location": {"row": 2, "column": 0},
},
"noqa_row": None,
},
"message": "`sys` imported but unused",
"severity": 2,
Expand All @@ -138,6 +147,7 @@ def _handler(params):
"start": {"line": 2, "character": 6},
"end": {"line": 2, "character": 7},
},
"data": {"fix": None, "noqa_row": None},
"message": "Undefined name `x`",
"severity": 2,
"code": "F821",
Expand Down

0 comments on commit dad628a

Please sign in to comment.