Skip to content

Commit 6747e39

Browse files
committed
Migrate to ifileeditor from ifilemanager, which adds support of unsaved(e.g. opened in IDE) files. Split lint action into lint and lint_files, which handles lint by language. Do the same with format. Move jsonrpc client in a new package finecode_jsonrpc.
1 parent 2fdeb11 commit 6747e39

109 files changed

Lines changed: 3522 additions & 1347 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

extensions/fine_python_ast/fine_python_ast/ast_provider.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,23 @@
33

44
from fine_python_ast import iast_provider
55

6-
from finecode_extension_api.interfaces import icache, ifilemanager, ilogger
6+
from finecode_extension_api.interfaces import icache, ifileeditor, ilogger
77

88

99
class PythonSingleAstProvider(iast_provider.IPythonSingleAstProvider):
1010
CACHE_KEY = "PythonSingleAstProvider"
11+
FILE_OPERATION_AUTHOR = ifileeditor.FileOperationAuthor(
12+
id="PythonSingleAstProvider"
13+
)
1114

1215
def __init__(
1316
self,
14-
file_manager: ifilemanager.IFileManager,
17+
file_editor: ifileeditor.IFileEditor,
1518
cache: icache.ICache,
1619
logger: ilogger.ILogger,
1720
):
1821
self.cache = cache
19-
self.file_manager = file_manager
22+
self.file_editor = file_editor
2023
self.logger = logger
2124

2225
async def get_file_ast(self, file_path: Path) -> ast.Module:
@@ -30,8 +33,12 @@ async def get_file_ast(self, file_path: Path) -> ast.Module:
3033
except icache.CacheMissException:
3134
...
3235

33-
file_content: str = await self.file_manager.get_content(file_path)
34-
file_version: str = await self.file_manager.get_file_version(file_path)
36+
async with self.file_editor.session(
37+
author=self.FILE_OPERATION_AUTHOR
38+
) as session:
39+
async with session.read_file(file_path=file_path) as file_info:
40+
file_content: str = file_info.content
41+
file_version: str = file_info.version
3542

3643
try:
3744
ast_instance = ast.parse(file_content)

extensions/fine_python_ast/pyproject.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,7 @@ finecode_dev_common_preset = { path = "../../finecode_dev_common_preset", editab
1818
finecode = { path = "../../", editable = true }
1919
finecode_extension_runner = { path = "../../finecode_extension_runner", editable = true }
2020
finecode_extension_api = { path = "../../finecode_extension_api", editable = true }
21+
finecode_jsonrpc = { path = "../../finecode_jsonrpc", editable = true }
22+
finecode_builtin_handlers = { path = "../../finecode_builtin_handlers", editable = true }
23+
fine_python_lint = { path = "../../presets/fine_python_lint", editable = true }
24+
fine_python_format = { path = "../../presets/fine_python_format", editable = true }

extensions/fine_python_black/pyproject.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,7 @@ finecode_dev_common_preset = { path = "../../finecode_dev_common_preset", editab
1818
finecode = { path = "../../", editable = true }
1919
finecode_extension_runner = { path = "../../finecode_extension_runner", editable = true }
2020
finecode_extension_api = { path = "../../finecode_extension_api", editable = true }
21+
finecode_jsonrpc = { path = "../../finecode_jsonrpc", editable = true }
22+
finecode_builtin_handlers = { path = "../../finecode_builtin_handlers", editable = true }
23+
fine_python_lint = { path = "../../presets/fine_python_lint", editable = true }
24+
fine_python_format = { path = "../../presets/fine_python_format", editable = true }
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
from .action import Flake8LintHandler, Flake8LintHandlerConfig
1+
from .action import Flake8LintFilesHandler, Flake8LintFilesHandlerConfig
22

33
__all__ = [
4-
"Flake8LintHandler",
5-
"Flake8LintHandlerConfig",
4+
"Flake8LintFilesHandler",
5+
"Flake8LintFilesHandlerConfig",
66
]

extensions/fine_python_flake8/fine_python_flake8/action.py

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,21 @@
1212
from flake8.plugins import finder
1313

1414
from finecode_extension_api import code_action
15-
from finecode_extension_api.actions import lint as lint_action
15+
from finecode_extension_api.actions import lint_files as lint_files_action
1616
from finecode_extension_api.interfaces import (
1717
icache,
18-
ifilemanager,
18+
ifileeditor,
1919
ilogger,
2020
iprocessexecutor,
2121
)
2222

2323

24-
def map_flake8_check_result_to_lint_message(result: tuple) -> lint_action.LintMessage:
24+
def map_flake8_check_result_to_lint_message(result: tuple) -> lint_files_action.LintMessage:
2525
error_code, line_number, column, text, physical_line = result
26-
return lint_action.LintMessage(
27-
range=lint_action.Range(
28-
start=lint_action.Position(line=line_number, character=column),
29-
end=lint_action.Position(
26+
return lint_files_action.LintMessage(
27+
range=lint_files_action.Range(
28+
start=lint_files_action.Position(line=line_number, character=column),
29+
end=lint_files_action.Position(
3030
line=line_number,
3131
character=len(physical_line) if physical_line is not None else column,
3232
),
@@ -35,9 +35,9 @@ def map_flake8_check_result_to_lint_message(result: tuple) -> lint_action.LintMe
3535
code=error_code,
3636
source="flake8",
3737
severity=(
38-
lint_action.LintMessageSeverity.WARNING
38+
lint_files_action.LintMessageSeverity.WARNING
3939
if error_code.startswith("W")
40-
else lint_action.LintMessageSeverity.ERROR
40+
else lint_files_action.LintMessageSeverity.ERROR
4141
),
4242
)
4343

@@ -46,9 +46,9 @@ def run_flake8_on_single_file(
4646
file_path: Path,
4747
file_content: str,
4848
file_ast: ast.Module,
49-
config: Flake8LintHandlerConfig,
50-
) -> list[lint_action.LintMessage]:
51-
lint_messages: list[lint_action.LintMessage] = []
49+
config: Flake8LintFilesHandlerConfig,
50+
) -> list[lint_files_action.LintMessage]:
51+
lint_messages: list[lint_files_action.LintMessage] = []
5252
# flake8 expects lines with newline at the end
5353
file_lines = [line + "\n" for line in file_content.split("\n")]
5454
# TODO: investigate whether guide and decider can be reused. They cannot be
@@ -109,31 +109,34 @@ def run_flake8_on_single_file(
109109

110110

111111
@dataclasses.dataclass
112-
class Flake8LintHandlerConfig(code_action.ActionHandlerConfig):
112+
class Flake8LintFilesHandlerConfig(code_action.ActionHandlerConfig):
113113
max_line_length: int = 79
114114
select: list[str] | None = None
115115
extend_select: list[str] | None = None
116116
extend_ignore: list[str] | None = None
117117

118118

119-
class Flake8LintHandler(
120-
code_action.ActionHandler[lint_action.LintAction, Flake8LintHandlerConfig]
119+
class Flake8LintFilesHandler(
120+
code_action.ActionHandler[lint_files_action.LintFilesAction, Flake8LintFilesHandlerConfig]
121121
):
122122
CACHE_KEY = "flake8"
123+
FILE_OPERATION_AUTHOR = ifileeditor.FileOperationAuthor(
124+
id="Flake8LintFilesHandler"
125+
)
123126

124127
def __init__(
125128
self,
126-
config: Flake8LintHandlerConfig,
129+
config: Flake8LintFilesHandlerConfig,
127130
cache: icache.ICache,
128131
logger: ilogger.ILogger,
129-
file_manager: ifilemanager.IFileManager,
132+
file_editor: ifileeditor.IFileEditor,
130133
ast_provider: iast_provider.IPythonSingleAstProvider,
131134
process_executor: iprocessexecutor.IProcessExecutor,
132135
) -> None:
133136
self.config = config
134137
self.cache = cache
135138
self.logger = logger
136-
self.file_manager = file_manager
139+
self.file_editor = file_editor
137140
self.ast_provider = ast_provider
138141
self.process_executor = process_executor
139142

@@ -145,19 +148,24 @@ def __init__(
145148

146149
async def run_on_single_file(
147150
self, file_path: Path
148-
) -> lint_action.LintRunResult | None:
151+
) -> lint_files_action.LintFilesRunResult | None:
149152
messages = {}
150153
try:
151154
cached_lint_messages = await self.cache.get_file_cache(
152155
file_path, self.CACHE_KEY
153156
)
154157
messages[str(file_path)] = cached_lint_messages
155-
return lint_action.LintRunResult(messages=messages)
158+
return lint_files_action.LintFilesRunResult(messages=messages)
156159
except icache.CacheMissException:
157160
pass
158161

159-
file_content = await self.file_manager.get_content(file_path)
160-
file_version = await self.file_manager.get_file_version(file_path)
162+
async with self.file_editor.session(
163+
author=self.FILE_OPERATION_AUTHOR
164+
) as session:
165+
async with session.read_file(file_path=file_path) as file_info:
166+
file_content: str = file_info.content
167+
file_version: str = file_info.version
168+
161169
try:
162170
file_ast = await self.ast_provider.get_file_ast(file_path=file_path)
163171
except SyntaxError:
@@ -175,11 +183,11 @@ async def run_on_single_file(
175183
file_path, file_version, self.CACHE_KEY, lint_messages
176184
)
177185

178-
return lint_action.LintRunResult(messages=messages)
186+
return lint_files_action.LintFilesRunResult(messages=messages)
179187

180188
async def run(
181189
self,
182-
payload: lint_action.LintRunPayload,
190+
payload: lint_files_action.LintFilesRunPayload,
183191
run_context: code_action.RunActionWithPartialResultsContext,
184192
) -> None:
185193
if self.config.select is not None and len(self.config.select) == 0:

extensions/fine_python_import_linter/pyproject.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,7 @@ finecode_dev_common_preset = { path = "../../finecode_dev_common_preset", editab
2323
finecode = { path = "../../", editable = true }
2424
finecode_extension_runner = { path = "../../finecode_extension_runner", editable = true }
2525
finecode_extension_api = { path = "../../finecode_extension_api", editable = true }
26+
finecode_jsonrpc = { path = "../../finecode_jsonrpc", editable = true }
27+
finecode_builtin_handlers = { path = "../../finecode_builtin_handlers", editable = true }
28+
fine_python_lint = { path = "../../presets/fine_python_lint", editable = true }
29+
fine_python_format = { path = "../../presets/fine_python_format", editable = true }

extensions/fine_python_isort/pyproject.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,7 @@ finecode_dev_common_preset = { path = "../../finecode_dev_common_preset", editab
1818
finecode = { path = "../../", editable = true }
1919
finecode_extension_runner = { path = "../../finecode_extension_runner", editable = true }
2020
finecode_extension_api = { path = "../../finecode_extension_api", editable = true }
21+
finecode_jsonrpc = { path = "../../finecode_jsonrpc", editable = true }
22+
finecode_builtin_handlers = { path = "../../finecode_builtin_handlers", editable = true }
23+
fine_python_lint = { path = "../../presets/fine_python_lint", editable = true }
24+
fine_python_format = { path = "../../presets/fine_python_format", editable = true }

extensions/fine_python_module_exports/pyproject.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,7 @@ finecode_dev_common_preset = { path = "../../finecode_dev_common_preset", editab
1818
finecode = { path = "../../", editable = true }
1919
finecode_extension_runner = { path = "../../finecode_extension_runner", editable = true }
2020
finecode_extension_api = { path = "../../finecode_extension_api", editable = true }
21+
finecode_jsonrpc = { path = "../../finecode_jsonrpc", editable = true }
22+
finecode_builtin_handlers = { path = "../../finecode_builtin_handlers", editable = true }
23+
fine_python_lint = { path = "../../presets/fine_python_lint", editable = true }
24+
fine_python_format = { path = "../../presets/fine_python_format", editable = true }

extensions/fine_python_mypy/fine_python_mypy/action.py

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from finecode_extension_api.interfaces import (
1414
icache,
1515
icommandrunner,
16-
ifilemanager,
16+
ifileeditor,
1717
ilogger,
1818
iextensionrunnerinfoprovider,
1919
iprojectinfoprovider,
@@ -31,6 +31,7 @@ class MypyLintHandler(
3131
code_action.ActionHandler[lint_action.LintAction, MypyManyCodeActionConfig]
3232
):
3333
CACHE_KEY = "mypy"
34+
FILE_OPERATION_AUTHOR = ifileeditor.FileOperationAuthor(erovid)
3435

3536
DMYPY_ARGS = [
3637
"--no-color-output",
@@ -50,15 +51,15 @@ def __init__(
5051
project_info_provider: iprojectinfoprovider.IProjectInfoProvider,
5152
cache: icache.ICache,
5253
logger: ilogger.ILogger,
53-
file_manager: ifilemanager.IFileManager,
54+
file_editor: ifileeditor.IFileEditor,
5455
lifecycle: code_action.ActionHandlerLifecycle,
5556
command_runner: icommandrunner.ICommandRunner,
5657
) -> None:
5758
self.extension_runner_info_provider = extension_runner_info_provider
5859
self.project_info_provider = project_info_provider
5960
self.cache = cache
6061
self.logger = logger
61-
self.file_manager = file_manager
62+
self.file_editor = file_editor
6263
self.command_runner = command_runner
6364

6465
lifecycle.on_shutdown(self.shutdown)
@@ -116,9 +117,12 @@ async def run_on_single_file(
116117
files_versions: dict[Path, str] = {}
117118
# can we exclude cached files here? Using the right cache(one that handles
118119
# dependencies as well) should be possible
119-
for file_path in all_project_files:
120-
file_version = await self.file_manager.get_file_version(file_path)
121-
files_versions[file_path] = file_version
120+
async with self.file_editor.session(
121+
author=self.FILE_OPERATION_AUTHOR
122+
) as session:
123+
for file_path in all_project_files:
124+
file_version = await session.read_file_version(file_path)
125+
files_versions[file_path] = file_version
122126

123127
try:
124128
all_processed_files_with_messages = await self._run_dmypy_on_project(
@@ -132,22 +136,25 @@ async def run_on_single_file(
132136
) in all_processed_files_with_messages.items()
133137
}
134138

135-
for (
136-
file_path,
137-
lint_messages,
138-
) in all_processed_files_with_messages.items():
139-
try:
140-
file_version = files_versions[file_path]
141-
except KeyError:
142-
# mypy can resolve dependencies which are not in `files_to_lint`
143-
# and as result also not in `files_versions`
144-
file_version = await self.file_manager.get_file_version(
145-
file_path
139+
async with self.file_editor.session(
140+
author=self.FILE_OPERATION_AUTHOR
141+
) as session:
142+
for (
143+
file_path,
144+
lint_messages,
145+
) in all_processed_files_with_messages.items():
146+
try:
147+
file_version = files_versions[file_path]
148+
except KeyError:
149+
# mypy can resolve dependencies which are not in `files_to_lint`
150+
# and as result also not in `files_versions`
151+
file_version = await session.read_file_version(
152+
file_path
153+
)
154+
155+
await self.cache.save_file_cache(
156+
file_path, file_version, self.CACHE_KEY, lint_messages
146157
)
147-
148-
await self.cache.save_file_cache(
149-
file_path, file_version, self.CACHE_KEY, lint_messages
150-
)
151158
finally:
152159
project_checked_event.set()
153160
del self._projects_being_checked_done_events[project_path]

extensions/fine_python_mypy/fine_python_mypy/ast_provider.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,23 @@
77
import mypy.options as mypy_options
88
from fine_python_mypy import iast_provider
99

10-
from finecode_extension_api.interfaces import icache, ifilemanager, ilogger
10+
from finecode_extension_api.interfaces import icache, ifileeditor, ilogger
1111

1212

1313
class MypySingleAstProvider(iast_provider.IMypySingleAstProvider):
1414
CACHE_KEY = "MypySingleAstProvider"
15+
FILE_OPERATION_AUTHOR = ifileeditor.FileOperationAuthor(
16+
id="MypySingleAstProvider"
17+
)
1518

1619
def __init__(
1720
self,
18-
file_manager: ifilemanager.IFileManager,
21+
file_editor: ifileeditor.IFileEditor,
1922
cache: icache.ICache,
2023
logger: ilogger.ILogger,
2124
):
2225
self.cache = cache
23-
self.file_manager = file_manager
26+
self.file_editor = file_editor
2427
self.logger = logger
2528

2629
async def get_file_ast(self, file_path: Path) -> mypy_nodes.MypyFile:
@@ -34,8 +37,13 @@ async def get_file_ast(self, file_path: Path) -> mypy_nodes.MypyFile:
3437
except icache.CacheMissException:
3538
...
3639

37-
file_text: str = await self.file_manager.get_content(file_path)
38-
file_version: str = await self.file_manager.get_file_version(file_path)
40+
async with self.file_editor.session(
41+
author=self.FILE_OPERATION_AUTHOR
42+
) as session:
43+
async with session.read_file(file_path=file_path) as file_info:
44+
file_text: str = file_info.content
45+
file_version: str = file_info.version
46+
3947
base_dir = self.get_file_package_parent_dir_path(file_path)
4048
module_program_path = self.get_file_program_path(
4149
file_path=file_path, root_package_parent_dir_path=base_dir

0 commit comments

Comments
 (0)