java-functional-lsp 0.9.4__tar.gz → 0.9.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/PKG-INFO +1 -1
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/pyproject.toml +1 -1
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/src/java_functional_lsp/__init__.py +1 -1
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/src/java_functional_lsp/server.py +238 -8
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/tests/test_server.py +576 -10
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/uv.lock +1 -1
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/.claude-plugin/plugin.json +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/.githooks/pre-commit +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/.githooks/pre-push +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/.github/CODEOWNERS +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/.github/ISSUE_TEMPLATE/bug-report.md +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/.github/ISSUE_TEMPLATE/feature-request.md +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/.github/SECURITY.md +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/.github/dependabot.yml +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/.github/release-drafter.yml +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/.github/workflows/publish.yml +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/.github/workflows/release-drafter.yml +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/.github/workflows/stale.yml +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/.github/workflows/test.yml +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/.github/workflows/update-homebrew.yml +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/.github/workflows/vscode-ext.yml +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/.gitignore +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/CONTRIBUTING.md +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/LICENSE +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/README.md +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/SKILL.md +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/commands/lint-java.md +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/editors/intellij/README.md +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/editors/intellij/lsp4ij-template.json +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/editors/vscode/.vscodeignore +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/editors/vscode/README.md +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/editors/vscode/package-lock.json +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/editors/vscode/package.json +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/editors/vscode/src/extension.ts +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/editors/vscode/tsconfig.json +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/hooks/hooks.json +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/hooks/java_linter_reminder.py +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/scripts/ensure-lsp.sh +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/scripts/generate-formula.py +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/src/java_functional_lsp/__main__.py +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/src/java_functional_lsp/analyzers/__init__.py +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/src/java_functional_lsp/analyzers/base.py +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/src/java_functional_lsp/analyzers/exception_checker.py +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/src/java_functional_lsp/analyzers/functional_checker.py +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/src/java_functional_lsp/analyzers/mutation_checker.py +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/src/java_functional_lsp/analyzers/null_checker.py +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/src/java_functional_lsp/analyzers/spring_checker.py +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/src/java_functional_lsp/cli.py +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/src/java_functional_lsp/fixes.py +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/src/java_functional_lsp/merkle.py +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/src/java_functional_lsp/proxy.py +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/tests/__init__.py +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/tests/conftest.py +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/tests/test_base.py +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/tests/test_cli.py +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/tests/test_config.py +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/tests/test_e2e.py +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/tests/test_e2e_jdtls.py +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/tests/test_exception_checker.py +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/tests/test_fixes.py +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/tests/test_functional_checker.py +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/tests/test_merkle.py +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/tests/test_merkle_proxy.py +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/tests/test_mutation_checker.py +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/tests/test_null_checker.py +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/tests/test_proxy.py +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/tests/test_spring_checker.py +0 -0
- {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/tests/test_suppress.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: java-functional-lsp
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.6
|
|
4
4
|
Summary: Java LSP server enforcing functional programming best practices — null safety, immutability, no exceptions
|
|
5
5
|
Project-URL: Homepage, https://github.com/aviadshiber/java-functional-lsp
|
|
6
6
|
Project-URL: Repository, https://github.com/aviadshiber/java-functional-lsp
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "java-functional-lsp"
|
|
7
|
-
version = "0.9.
|
|
7
|
+
version = "0.9.6"
|
|
8
8
|
description = "Java LSP server enforcing functional programming best practices — null safety, immutability, no exceptions"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
@@ -446,6 +446,20 @@ _JDTLS_CAPABILITIES: list[tuple[str, str, type[Any], dict[str, Any]]] = [
|
|
|
446
446
|
("definition", lsp.TEXT_DOCUMENT_DEFINITION, lsp.DefinitionRegistrationOptions, {}),
|
|
447
447
|
("references", lsp.TEXT_DOCUMENT_REFERENCES, lsp.ReferenceRegistrationOptions, {}),
|
|
448
448
|
("document-symbol", lsp.TEXT_DOCUMENT_DOCUMENT_SYMBOL, lsp.DocumentSymbolRegistrationOptions, {}),
|
|
449
|
+
("call-hierarchy", lsp.TEXT_DOCUMENT_PREPARE_CALL_HIERARCHY, lsp.CallHierarchyRegistrationOptions, {}),
|
|
450
|
+
(
|
|
451
|
+
"signature-help",
|
|
452
|
+
lsp.TEXT_DOCUMENT_SIGNATURE_HELP,
|
|
453
|
+
lsp.SignatureHelpRegistrationOptions,
|
|
454
|
+
{"trigger_characters": ["(", ","], "retrigger_characters": [")"]},
|
|
455
|
+
),
|
|
456
|
+
("implementation", lsp.TEXT_DOCUMENT_IMPLEMENTATION, lsp.ImplementationRegistrationOptions, {}),
|
|
457
|
+
("type-definition", lsp.TEXT_DOCUMENT_TYPE_DEFINITION, lsp.TypeDefinitionRegistrationOptions, {}),
|
|
458
|
+
("declaration", lsp.TEXT_DOCUMENT_DECLARATION, lsp.DeclarationRegistrationOptions, {}),
|
|
459
|
+
("document-highlight", lsp.TEXT_DOCUMENT_DOCUMENT_HIGHLIGHT, lsp.DocumentHighlightRegistrationOptions, {}),
|
|
460
|
+
("rename", lsp.TEXT_DOCUMENT_RENAME, lsp.RenameRegistrationOptions, {"prepare_provider": True}),
|
|
461
|
+
("type-hierarchy", lsp.TEXT_DOCUMENT_PREPARE_TYPE_HIERARCHY, lsp.TypeHierarchyRegistrationOptions, {}),
|
|
462
|
+
("workspace-symbol", lsp.WORKSPACE_SYMBOL, lsp.WorkspaceSymbolRegistrationOptions, {}),
|
|
449
463
|
]
|
|
450
464
|
|
|
451
465
|
# Maps LSP method → handler function for dynamic registration.
|
|
@@ -457,14 +471,20 @@ _jdtls_capabilities_registered = False
|
|
|
457
471
|
|
|
458
472
|
def _build_jdtls_registrations() -> list[lsp.Registration]:
|
|
459
473
|
"""Build LSP Registration objects for jdtls-dependent capabilities."""
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
474
|
+
result = []
|
|
475
|
+
for suffix, method, opts_cls, extra in _JDTLS_CAPABILITIES:
|
|
476
|
+
field_names = {f.name for f in getattr(opts_cls, "__attrs_attrs__", [])}
|
|
477
|
+
kwargs: dict[str, Any] = {**extra}
|
|
478
|
+
if "document_selector" in field_names:
|
|
479
|
+
kwargs["document_selector"] = _JAVA_SELECTOR
|
|
480
|
+
result.append(
|
|
481
|
+
lsp.Registration(
|
|
482
|
+
id=f"{_JDTLS_REG_PREFIX}{suffix}",
|
|
483
|
+
method=method,
|
|
484
|
+
register_options=_converter.unstructure(opts_cls(**kwargs)),
|
|
485
|
+
)
|
|
465
486
|
)
|
|
466
|
-
|
|
467
|
-
]
|
|
487
|
+
return result
|
|
468
488
|
|
|
469
489
|
|
|
470
490
|
async def _register_jdtls_capabilities() -> None:
|
|
@@ -499,7 +519,11 @@ async def _register_jdtls_capabilities() -> None:
|
|
|
499
519
|
return
|
|
500
520
|
|
|
501
521
|
_jdtls_capabilities_registered = True
|
|
502
|
-
logger.info(
|
|
522
|
+
logger.info(
|
|
523
|
+
"jdtls capabilities registered: completion, hover, definition, references, symbol, "
|
|
524
|
+
"call-hierarchy, signature-help, implementation, type-definition, declaration, "
|
|
525
|
+
"document-highlight, rename, type-hierarchy, workspace-symbol"
|
|
526
|
+
)
|
|
503
527
|
except Exception:
|
|
504
528
|
logger.warning("Failed to dynamically register jdtls capabilities", exc_info=True)
|
|
505
529
|
|
|
@@ -739,6 +763,198 @@ async def _on_document_symbol(params: lsp.DocumentSymbolParams) -> list[lsp.Docu
|
|
|
739
763
|
return None
|
|
740
764
|
|
|
741
765
|
|
|
766
|
+
async def _on_prepare_call_hierarchy(params: lsp.CallHierarchyPrepareParams) -> list[lsp.CallHierarchyItem] | None:
|
|
767
|
+
"""Forward prepareCallHierarchy request to jdtls."""
|
|
768
|
+
result = await _ensure_module_and_forward("textDocument/prepareCallHierarchy", params, params.text_document.uri)
|
|
769
|
+
if result is None:
|
|
770
|
+
return None
|
|
771
|
+
try:
|
|
772
|
+
return [_converter.structure(item, lsp.CallHierarchyItem) for item in result]
|
|
773
|
+
except Exception:
|
|
774
|
+
return None
|
|
775
|
+
|
|
776
|
+
|
|
777
|
+
async def _on_incoming_calls(
|
|
778
|
+
params: lsp.CallHierarchyIncomingCallsParams,
|
|
779
|
+
) -> list[lsp.CallHierarchyIncomingCall] | None:
|
|
780
|
+
"""Forward callHierarchy/incomingCalls request to jdtls."""
|
|
781
|
+
result = await _ensure_module_and_forward("callHierarchy/incomingCalls", params, params.item.uri)
|
|
782
|
+
if result is None:
|
|
783
|
+
return None
|
|
784
|
+
try:
|
|
785
|
+
return [_converter.structure(c, lsp.CallHierarchyIncomingCall) for c in result]
|
|
786
|
+
except Exception:
|
|
787
|
+
return None
|
|
788
|
+
|
|
789
|
+
|
|
790
|
+
async def _on_outgoing_calls(
|
|
791
|
+
params: lsp.CallHierarchyOutgoingCallsParams,
|
|
792
|
+
) -> list[lsp.CallHierarchyOutgoingCall] | None:
|
|
793
|
+
"""Forward callHierarchy/outgoingCalls request to jdtls."""
|
|
794
|
+
result = await _ensure_module_and_forward("callHierarchy/outgoingCalls", params, params.item.uri)
|
|
795
|
+
if result is None:
|
|
796
|
+
return None
|
|
797
|
+
try:
|
|
798
|
+
return [_converter.structure(c, lsp.CallHierarchyOutgoingCall) for c in result]
|
|
799
|
+
except Exception:
|
|
800
|
+
return None
|
|
801
|
+
|
|
802
|
+
|
|
803
|
+
async def _on_signature_help(params: lsp.SignatureHelpParams) -> lsp.SignatureHelp | None:
|
|
804
|
+
"""Forward signatureHelp request to jdtls."""
|
|
805
|
+
result = await _ensure_module_and_forward("textDocument/signatureHelp", params, params.text_document.uri)
|
|
806
|
+
if result is None:
|
|
807
|
+
return None
|
|
808
|
+
try:
|
|
809
|
+
return _converter.structure(result, lsp.SignatureHelp)
|
|
810
|
+
except Exception:
|
|
811
|
+
logger.debug("Failed to structure signatureHelp result", exc_info=True)
|
|
812
|
+
return None
|
|
813
|
+
|
|
814
|
+
|
|
815
|
+
async def _on_implementation(params: lsp.ImplementationParams) -> list[lsp.Location] | None:
|
|
816
|
+
"""Forward go-to-implementation request to jdtls."""
|
|
817
|
+
result = await _ensure_module_and_forward("textDocument/implementation", params, params.text_document.uri)
|
|
818
|
+
if result is None:
|
|
819
|
+
return None
|
|
820
|
+
try:
|
|
821
|
+
if isinstance(result, list):
|
|
822
|
+
return [_converter.structure(loc, lsp.Location) for loc in result]
|
|
823
|
+
return [_converter.structure(result, lsp.Location)]
|
|
824
|
+
except Exception:
|
|
825
|
+
logger.debug("Failed to structure implementation result", exc_info=True)
|
|
826
|
+
return None
|
|
827
|
+
|
|
828
|
+
|
|
829
|
+
async def _on_type_definition(params: lsp.TypeDefinitionParams) -> list[lsp.Location] | None:
|
|
830
|
+
"""Forward go-to-type-definition request to jdtls."""
|
|
831
|
+
result = await _ensure_module_and_forward("textDocument/typeDefinition", params, params.text_document.uri)
|
|
832
|
+
if result is None:
|
|
833
|
+
return None
|
|
834
|
+
try:
|
|
835
|
+
if isinstance(result, list):
|
|
836
|
+
return [_converter.structure(loc, lsp.Location) for loc in result]
|
|
837
|
+
return [_converter.structure(result, lsp.Location)]
|
|
838
|
+
except Exception:
|
|
839
|
+
logger.debug("Failed to structure typeDefinition result", exc_info=True)
|
|
840
|
+
return None
|
|
841
|
+
|
|
842
|
+
|
|
843
|
+
async def _on_declaration(params: lsp.DeclarationParams) -> list[lsp.Location] | None:
|
|
844
|
+
"""Forward go-to-declaration request to jdtls."""
|
|
845
|
+
result = await _ensure_module_and_forward("textDocument/declaration", params, params.text_document.uri)
|
|
846
|
+
if result is None:
|
|
847
|
+
return None
|
|
848
|
+
try:
|
|
849
|
+
if isinstance(result, list):
|
|
850
|
+
return [_converter.structure(loc, lsp.Location) for loc in result]
|
|
851
|
+
return [_converter.structure(result, lsp.Location)]
|
|
852
|
+
except Exception:
|
|
853
|
+
logger.debug("Failed to structure declaration result", exc_info=True)
|
|
854
|
+
return None
|
|
855
|
+
|
|
856
|
+
|
|
857
|
+
async def _on_document_highlight(params: lsp.DocumentHighlightParams) -> list[lsp.DocumentHighlight] | None:
|
|
858
|
+
"""Forward documentHighlight request to jdtls."""
|
|
859
|
+
result = await _ensure_module_and_forward("textDocument/documentHighlight", params, params.text_document.uri)
|
|
860
|
+
if result is None:
|
|
861
|
+
return None
|
|
862
|
+
try:
|
|
863
|
+
return [_converter.structure(h, lsp.DocumentHighlight) for h in result]
|
|
864
|
+
except Exception:
|
|
865
|
+
logger.debug("Failed to structure documentHighlight result", exc_info=True)
|
|
866
|
+
return None
|
|
867
|
+
|
|
868
|
+
|
|
869
|
+
async def _on_rename(params: lsp.RenameParams) -> lsp.WorkspaceEdit | None:
|
|
870
|
+
"""Forward rename request to jdtls."""
|
|
871
|
+
result = await _ensure_module_and_forward("textDocument/rename", params, params.text_document.uri)
|
|
872
|
+
if result is None:
|
|
873
|
+
return None
|
|
874
|
+
try:
|
|
875
|
+
return _converter.structure(result, lsp.WorkspaceEdit)
|
|
876
|
+
except Exception:
|
|
877
|
+
logger.debug("Failed to structure rename result", exc_info=True)
|
|
878
|
+
return None
|
|
879
|
+
|
|
880
|
+
|
|
881
|
+
async def _on_prepare_rename(
|
|
882
|
+
params: lsp.PrepareRenameParams,
|
|
883
|
+
) -> lsp.Range | lsp.PrepareRenamePlaceholder | lsp.PrepareRenameDefaultBehavior | None:
|
|
884
|
+
"""Forward prepareRename request to jdtls.
|
|
885
|
+
|
|
886
|
+
jdtls may return Range, PrepareRenamePlaceholder ({range, placeholder}),
|
|
887
|
+
or PrepareRenameDefaultBehavior ({defaultBehavior}) — try each in order.
|
|
888
|
+
"""
|
|
889
|
+
result = await _ensure_module_and_forward("textDocument/prepareRename", params, params.text_document.uri)
|
|
890
|
+
if result is None:
|
|
891
|
+
return None
|
|
892
|
+
for target_type in (lsp.PrepareRenamePlaceholder, lsp.PrepareRenameDefaultBehavior, lsp.Range):
|
|
893
|
+
try:
|
|
894
|
+
return _converter.structure(result, target_type) # type: ignore[return-value]
|
|
895
|
+
except Exception:
|
|
896
|
+
pass
|
|
897
|
+
logger.debug("Failed to structure prepareRename result as any known type", exc_info=False)
|
|
898
|
+
return None
|
|
899
|
+
|
|
900
|
+
|
|
901
|
+
async def _on_prepare_type_hierarchy(
|
|
902
|
+
params: lsp.TypeHierarchyPrepareParams,
|
|
903
|
+
) -> list[lsp.TypeHierarchyItem] | None:
|
|
904
|
+
"""Forward prepareTypeHierarchy request to jdtls."""
|
|
905
|
+
result = await _ensure_module_and_forward("textDocument/prepareTypeHierarchy", params, params.text_document.uri)
|
|
906
|
+
if result is None:
|
|
907
|
+
return None
|
|
908
|
+
try:
|
|
909
|
+
return [_converter.structure(item, lsp.TypeHierarchyItem) for item in result]
|
|
910
|
+
except Exception:
|
|
911
|
+
logger.debug("Failed to structure prepareTypeHierarchy result", exc_info=True)
|
|
912
|
+
return None
|
|
913
|
+
|
|
914
|
+
|
|
915
|
+
async def _on_type_hierarchy_supertypes(
|
|
916
|
+
params: lsp.TypeHierarchySupertypesParams,
|
|
917
|
+
) -> list[lsp.TypeHierarchyItem] | None:
|
|
918
|
+
"""Forward typeHierarchy/supertypes request to jdtls."""
|
|
919
|
+
result = await _ensure_module_and_forward("typeHierarchy/supertypes", params, params.item.uri)
|
|
920
|
+
if result is None:
|
|
921
|
+
return None
|
|
922
|
+
try:
|
|
923
|
+
return [_converter.structure(item, lsp.TypeHierarchyItem) for item in result]
|
|
924
|
+
except Exception:
|
|
925
|
+
logger.debug("Failed to structure typeHierarchy/supertypes result", exc_info=True)
|
|
926
|
+
return None
|
|
927
|
+
|
|
928
|
+
|
|
929
|
+
async def _on_type_hierarchy_subtypes(
|
|
930
|
+
params: lsp.TypeHierarchySubtypesParams,
|
|
931
|
+
) -> list[lsp.TypeHierarchyItem] | None:
|
|
932
|
+
"""Forward typeHierarchy/subtypes request to jdtls."""
|
|
933
|
+
result = await _ensure_module_and_forward("typeHierarchy/subtypes", params, params.item.uri)
|
|
934
|
+
if result is None:
|
|
935
|
+
return None
|
|
936
|
+
try:
|
|
937
|
+
return [_converter.structure(item, lsp.TypeHierarchyItem) for item in result]
|
|
938
|
+
except Exception:
|
|
939
|
+
logger.debug("Failed to structure typeHierarchy/subtypes result", exc_info=True)
|
|
940
|
+
return None
|
|
941
|
+
|
|
942
|
+
|
|
943
|
+
async def _on_workspace_symbol(params: lsp.WorkspaceSymbolParams) -> list[lsp.WorkspaceSymbol] | None:
|
|
944
|
+
"""Forward workspace/symbol request to jdtls (no text_document — use proxy directly)."""
|
|
945
|
+
proxy = server._proxy
|
|
946
|
+
if not proxy.is_available:
|
|
947
|
+
return None
|
|
948
|
+
result = await proxy.send_request("workspace/symbol", _serialize_params(params))
|
|
949
|
+
if result is None:
|
|
950
|
+
return None
|
|
951
|
+
try:
|
|
952
|
+
return [_converter.structure(s, lsp.WorkspaceSymbol) for s in result]
|
|
953
|
+
except Exception:
|
|
954
|
+
logger.debug("Failed to structure workspace/symbol result", exc_info=True)
|
|
955
|
+
return None
|
|
956
|
+
|
|
957
|
+
|
|
742
958
|
# Populate handler map for dynamic registration.
|
|
743
959
|
_JDTLS_HANDLERS.update(
|
|
744
960
|
{
|
|
@@ -747,6 +963,20 @@ _JDTLS_HANDLERS.update(
|
|
|
747
963
|
lsp.TEXT_DOCUMENT_DEFINITION: _on_definition,
|
|
748
964
|
lsp.TEXT_DOCUMENT_REFERENCES: _on_references,
|
|
749
965
|
lsp.TEXT_DOCUMENT_DOCUMENT_SYMBOL: _on_document_symbol,
|
|
966
|
+
lsp.TEXT_DOCUMENT_PREPARE_CALL_HIERARCHY: _on_prepare_call_hierarchy,
|
|
967
|
+
lsp.CALL_HIERARCHY_INCOMING_CALLS: _on_incoming_calls,
|
|
968
|
+
lsp.CALL_HIERARCHY_OUTGOING_CALLS: _on_outgoing_calls,
|
|
969
|
+
lsp.TEXT_DOCUMENT_SIGNATURE_HELP: _on_signature_help,
|
|
970
|
+
lsp.TEXT_DOCUMENT_IMPLEMENTATION: _on_implementation,
|
|
971
|
+
lsp.TEXT_DOCUMENT_TYPE_DEFINITION: _on_type_definition,
|
|
972
|
+
lsp.TEXT_DOCUMENT_DECLARATION: _on_declaration,
|
|
973
|
+
lsp.TEXT_DOCUMENT_DOCUMENT_HIGHLIGHT: _on_document_highlight,
|
|
974
|
+
lsp.TEXT_DOCUMENT_RENAME: _on_rename,
|
|
975
|
+
lsp.TEXT_DOCUMENT_PREPARE_RENAME: _on_prepare_rename,
|
|
976
|
+
lsp.TEXT_DOCUMENT_PREPARE_TYPE_HIERARCHY: _on_prepare_type_hierarchy,
|
|
977
|
+
lsp.TYPE_HIERARCHY_SUPERTYPES: _on_type_hierarchy_supertypes,
|
|
978
|
+
lsp.TYPE_HIERARCHY_SUBTYPES: _on_type_hierarchy_subtypes,
|
|
979
|
+
lsp.WORKSPACE_SYMBOL: _on_workspace_symbol,
|
|
750
980
|
}
|
|
751
981
|
)
|
|
752
982
|
|
|
@@ -319,25 +319,47 @@ class TestServerInternals:
|
|
|
319
319
|
from java_functional_lsp.server import _JDTLS_REG_PREFIX, _build_jdtls_registrations
|
|
320
320
|
|
|
321
321
|
regs = _build_jdtls_registrations()
|
|
322
|
-
assert len(regs) ==
|
|
322
|
+
assert len(regs) == 14
|
|
323
323
|
methods = {r.method for r in regs}
|
|
324
324
|
assert lsp.TEXT_DOCUMENT_HOVER in methods
|
|
325
325
|
assert lsp.TEXT_DOCUMENT_DEFINITION in methods
|
|
326
326
|
assert lsp.TEXT_DOCUMENT_REFERENCES in methods
|
|
327
327
|
assert lsp.TEXT_DOCUMENT_COMPLETION in methods
|
|
328
328
|
assert lsp.TEXT_DOCUMENT_DOCUMENT_SYMBOL in methods
|
|
329
|
+
assert lsp.TEXT_DOCUMENT_PREPARE_CALL_HIERARCHY in methods
|
|
330
|
+
assert lsp.TEXT_DOCUMENT_SIGNATURE_HELP in methods
|
|
331
|
+
assert lsp.TEXT_DOCUMENT_IMPLEMENTATION in methods
|
|
332
|
+
assert lsp.TEXT_DOCUMENT_TYPE_DEFINITION in methods
|
|
333
|
+
assert lsp.TEXT_DOCUMENT_DECLARATION in methods
|
|
334
|
+
assert lsp.TEXT_DOCUMENT_DOCUMENT_HIGHLIGHT in methods
|
|
335
|
+
assert lsp.TEXT_DOCUMENT_RENAME in methods
|
|
336
|
+
assert lsp.TEXT_DOCUMENT_PREPARE_TYPE_HIERARCHY in methods
|
|
337
|
+
assert lsp.WORKSPACE_SYMBOL in methods
|
|
329
338
|
# All IDs are unique and use the shared prefix
|
|
330
339
|
ids = {r.id for r in regs}
|
|
331
|
-
assert len(ids) ==
|
|
340
|
+
assert len(ids) == 14
|
|
332
341
|
assert all(rid.startswith(_JDTLS_REG_PREFIX) for rid in ids)
|
|
333
|
-
#
|
|
342
|
+
# Document-scoped capabilities have java document selector; workspace-scoped do not
|
|
343
|
+
workspace_scoped = {lsp.WORKSPACE_SYMBOL}
|
|
334
344
|
for r in regs:
|
|
335
345
|
assert r.register_options is not None
|
|
336
|
-
|
|
337
|
-
|
|
346
|
+
if r.method in workspace_scoped:
|
|
347
|
+
assert "documentSelector" not in r.register_options
|
|
348
|
+
else:
|
|
349
|
+
selectors = r.register_options["documentSelector"]
|
|
350
|
+
assert any(s.get("language") == "java" for s in selectors)
|
|
338
351
|
# Completion has triggerCharacters
|
|
339
352
|
comp = next(r for r in regs if r.method == lsp.TEXT_DOCUMENT_COMPLETION)
|
|
353
|
+
assert comp.register_options is not None
|
|
340
354
|
assert comp.register_options.get("triggerCharacters") == ["."]
|
|
355
|
+
# SignatureHelp has triggerCharacters
|
|
356
|
+
sig = next(r for r in regs if r.method == lsp.TEXT_DOCUMENT_SIGNATURE_HELP)
|
|
357
|
+
assert sig.register_options is not None
|
|
358
|
+
assert sig.register_options.get("triggerCharacters") == ["(", ","]
|
|
359
|
+
# Rename advertises prepareProvider so the IDE sends textDocument/prepareRename
|
|
360
|
+
rename = next(r for r in regs if r.method == lsp.TEXT_DOCUMENT_RENAME)
|
|
361
|
+
assert rename.register_options is not None
|
|
362
|
+
assert rename.register_options.get("prepareProvider") is True
|
|
341
363
|
|
|
342
364
|
async def test_register_jdtls_capabilities_logs_on_failure(self, caplog: Any) -> None:
|
|
343
365
|
"""_register_jdtls_capabilities logs a warning when the client rejects."""
|
|
@@ -386,16 +408,30 @@ class TestServerInternals:
|
|
|
386
408
|
await srv_mod._register_jdtls_capabilities()
|
|
387
409
|
finally:
|
|
388
410
|
srv_mod._jdtls_capabilities_registered = old_flag
|
|
389
|
-
# Handlers were registered for all
|
|
411
|
+
# Handlers were registered for all methods (including call hierarchy)
|
|
390
412
|
assert lsp.TEXT_DOCUMENT_HOVER in registered_methods
|
|
391
413
|
assert lsp.TEXT_DOCUMENT_COMPLETION in registered_methods
|
|
392
414
|
assert lsp.TEXT_DOCUMENT_DEFINITION in registered_methods
|
|
393
415
|
assert lsp.TEXT_DOCUMENT_REFERENCES in registered_methods
|
|
394
416
|
assert lsp.TEXT_DOCUMENT_DOCUMENT_SYMBOL in registered_methods
|
|
417
|
+
assert lsp.TEXT_DOCUMENT_PREPARE_CALL_HIERARCHY in registered_methods
|
|
418
|
+
assert lsp.CALL_HIERARCHY_INCOMING_CALLS in registered_methods
|
|
419
|
+
assert lsp.CALL_HIERARCHY_OUTGOING_CALLS in registered_methods
|
|
420
|
+
assert lsp.TEXT_DOCUMENT_SIGNATURE_HELP in registered_methods
|
|
421
|
+
assert lsp.TEXT_DOCUMENT_IMPLEMENTATION in registered_methods
|
|
422
|
+
assert lsp.TEXT_DOCUMENT_TYPE_DEFINITION in registered_methods
|
|
423
|
+
assert lsp.TEXT_DOCUMENT_DECLARATION in registered_methods
|
|
424
|
+
assert lsp.TEXT_DOCUMENT_DOCUMENT_HIGHLIGHT in registered_methods
|
|
425
|
+
assert lsp.TEXT_DOCUMENT_RENAME in registered_methods
|
|
426
|
+
assert lsp.TEXT_DOCUMENT_PREPARE_RENAME in registered_methods
|
|
427
|
+
assert lsp.TEXT_DOCUMENT_PREPARE_TYPE_HIERARCHY in registered_methods
|
|
428
|
+
assert lsp.TYPE_HIERARCHY_SUPERTYPES in registered_methods
|
|
429
|
+
assert lsp.TYPE_HIERARCHY_SUBTYPES in registered_methods
|
|
430
|
+
assert lsp.WORKSPACE_SYMBOL in registered_methods
|
|
395
431
|
# client_register_capability_async was called
|
|
396
432
|
mock_reg.assert_called_once()
|
|
397
433
|
# Success log emitted
|
|
398
|
-
assert any("
|
|
434
|
+
assert any("jdtls capabilities registered" in r.getMessage() for r in caplog.records)
|
|
399
435
|
|
|
400
436
|
async def test_register_jdtls_capabilities_idempotent(self) -> None:
|
|
401
437
|
"""Second call is a no-op (idempotency guard)."""
|
|
@@ -505,7 +541,7 @@ class TestServerInternals:
|
|
|
505
541
|
mock_add = AsyncMock(return_value="file:///mod")
|
|
506
542
|
mock_send = AsyncMock(side_effect=[None, {"result": "ok"}])
|
|
507
543
|
|
|
508
|
-
async def mock_wait(uri: str, timeout: float = 30.0) -> bool:
|
|
544
|
+
async def mock_wait(uri: str, timeout: float = 30.0) -> bool: # pyright: ignore[reportUnusedParameter]
|
|
509
545
|
srv._proxy.modules.mark_ready(uri)
|
|
510
546
|
return True
|
|
511
547
|
|
|
@@ -545,6 +581,530 @@ class TestServerInternals:
|
|
|
545
581
|
finally:
|
|
546
582
|
srv._proxy.modules.clear()
|
|
547
583
|
|
|
584
|
+
async def test_on_prepare_call_hierarchy_forwards_to_jdtls(self) -> None:
|
|
585
|
+
"""_on_prepare_call_hierarchy forwards request and structures result."""
|
|
586
|
+
from unittest.mock import AsyncMock, patch
|
|
587
|
+
|
|
588
|
+
from java_functional_lsp.server import _on_prepare_call_hierarchy
|
|
589
|
+
|
|
590
|
+
item = {
|
|
591
|
+
"name": "parsePrimaryEnrichmentResponse",
|
|
592
|
+
"kind": 6,
|
|
593
|
+
"uri": "file:///mod/Foo.java",
|
|
594
|
+
"range": {"start": {"line": 0, "character": 0}, "end": {"line": 0, "character": 10}},
|
|
595
|
+
"selectionRange": {"start": {"line": 0, "character": 0}, "end": {"line": 0, "character": 10}},
|
|
596
|
+
}
|
|
597
|
+
params = lsp.CallHierarchyPrepareParams(
|
|
598
|
+
text_document=lsp.TextDocumentIdentifier(uri="file:///mod/Foo.java"),
|
|
599
|
+
position=lsp.Position(line=0, character=0),
|
|
600
|
+
)
|
|
601
|
+
mock_forward = AsyncMock(return_value=[item])
|
|
602
|
+
with patch("java_functional_lsp.server._ensure_module_and_forward", mock_forward):
|
|
603
|
+
result = await _on_prepare_call_hierarchy(params)
|
|
604
|
+
assert result is not None
|
|
605
|
+
assert len(result) == 1
|
|
606
|
+
assert result[0].name == "parsePrimaryEnrichmentResponse"
|
|
607
|
+
mock_forward.assert_called_once_with("textDocument/prepareCallHierarchy", params, "file:///mod/Foo.java")
|
|
608
|
+
|
|
609
|
+
async def test_on_prepare_call_hierarchy_returns_none_on_null(self) -> None:
|
|
610
|
+
from unittest.mock import AsyncMock, patch
|
|
611
|
+
|
|
612
|
+
from java_functional_lsp.server import _on_prepare_call_hierarchy
|
|
613
|
+
|
|
614
|
+
params = lsp.CallHierarchyPrepareParams(
|
|
615
|
+
text_document=lsp.TextDocumentIdentifier(uri="file:///mod/Foo.java"),
|
|
616
|
+
position=lsp.Position(line=0, character=0),
|
|
617
|
+
)
|
|
618
|
+
with patch("java_functional_lsp.server._ensure_module_and_forward", AsyncMock(return_value=None)):
|
|
619
|
+
result = await _on_prepare_call_hierarchy(params)
|
|
620
|
+
assert result is None
|
|
621
|
+
|
|
622
|
+
async def test_on_incoming_calls_forwards_using_item_uri(self) -> None:
|
|
623
|
+
"""_on_incoming_calls uses params.item.uri as the file_uri for module resolution."""
|
|
624
|
+
from unittest.mock import AsyncMock, patch
|
|
625
|
+
|
|
626
|
+
from java_functional_lsp.server import _on_incoming_calls
|
|
627
|
+
|
|
628
|
+
item = lsp.CallHierarchyItem(
|
|
629
|
+
name="caller",
|
|
630
|
+
kind=lsp.SymbolKind.Method,
|
|
631
|
+
uri="file:///mod/Foo.java",
|
|
632
|
+
range=lsp.Range(start=lsp.Position(line=0, character=0), end=lsp.Position(line=0, character=5)),
|
|
633
|
+
selection_range=lsp.Range(start=lsp.Position(line=0, character=0), end=lsp.Position(line=0, character=5)),
|
|
634
|
+
)
|
|
635
|
+
params = lsp.CallHierarchyIncomingCallsParams(item=item)
|
|
636
|
+
incoming = {
|
|
637
|
+
"from": {
|
|
638
|
+
"name": "caller",
|
|
639
|
+
"kind": 6,
|
|
640
|
+
"uri": "file:///mod/Foo.java",
|
|
641
|
+
"range": {"start": {"line": 1, "character": 0}, "end": {"line": 1, "character": 6}},
|
|
642
|
+
"selectionRange": {"start": {"line": 1, "character": 0}, "end": {"line": 1, "character": 6}},
|
|
643
|
+
},
|
|
644
|
+
"fromRanges": [{"start": {"line": 1, "character": 0}, "end": {"line": 1, "character": 6}}],
|
|
645
|
+
}
|
|
646
|
+
mock_forward = AsyncMock(return_value=[incoming])
|
|
647
|
+
with patch("java_functional_lsp.server._ensure_module_and_forward", mock_forward):
|
|
648
|
+
result = await _on_incoming_calls(params)
|
|
649
|
+
assert result is not None
|
|
650
|
+
assert len(result) == 1
|
|
651
|
+
mock_forward.assert_called_once_with("callHierarchy/incomingCalls", params, "file:///mod/Foo.java")
|
|
652
|
+
|
|
653
|
+
async def test_on_incoming_calls_returns_none_on_null(self) -> None:
|
|
654
|
+
from unittest.mock import AsyncMock, patch
|
|
655
|
+
|
|
656
|
+
from java_functional_lsp.server import _on_incoming_calls
|
|
657
|
+
|
|
658
|
+
item = lsp.CallHierarchyItem(
|
|
659
|
+
name="x",
|
|
660
|
+
kind=lsp.SymbolKind.Method,
|
|
661
|
+
uri="file:///mod/Foo.java",
|
|
662
|
+
range=lsp.Range(start=lsp.Position(line=0, character=0), end=lsp.Position(line=0, character=1)),
|
|
663
|
+
selection_range=lsp.Range(start=lsp.Position(line=0, character=0), end=lsp.Position(line=0, character=1)),
|
|
664
|
+
)
|
|
665
|
+
params = lsp.CallHierarchyIncomingCallsParams(item=item)
|
|
666
|
+
with patch("java_functional_lsp.server._ensure_module_and_forward", AsyncMock(return_value=None)):
|
|
667
|
+
result = await _on_incoming_calls(params)
|
|
668
|
+
assert result is None
|
|
669
|
+
|
|
670
|
+
async def test_on_outgoing_calls_forwards_using_item_uri(self) -> None:
|
|
671
|
+
"""_on_outgoing_calls uses params.item.uri as the file_uri for module resolution."""
|
|
672
|
+
from unittest.mock import AsyncMock, patch
|
|
673
|
+
|
|
674
|
+
from java_functional_lsp.server import _on_outgoing_calls
|
|
675
|
+
|
|
676
|
+
item = lsp.CallHierarchyItem(
|
|
677
|
+
name="callee",
|
|
678
|
+
kind=lsp.SymbolKind.Method,
|
|
679
|
+
uri="file:///mod/Bar.java",
|
|
680
|
+
range=lsp.Range(start=lsp.Position(line=5, character=0), end=lsp.Position(line=5, character=6)),
|
|
681
|
+
selection_range=lsp.Range(start=lsp.Position(line=5, character=0), end=lsp.Position(line=5, character=6)),
|
|
682
|
+
)
|
|
683
|
+
params = lsp.CallHierarchyOutgoingCallsParams(item=item)
|
|
684
|
+
outgoing = {
|
|
685
|
+
"to": {
|
|
686
|
+
"name": "callee",
|
|
687
|
+
"kind": 6,
|
|
688
|
+
"uri": "file:///mod/Bar.java",
|
|
689
|
+
"range": {"start": {"line": 5, "character": 0}, "end": {"line": 5, "character": 6}},
|
|
690
|
+
"selectionRange": {"start": {"line": 5, "character": 0}, "end": {"line": 5, "character": 6}},
|
|
691
|
+
},
|
|
692
|
+
"fromRanges": [{"start": {"line": 5, "character": 0}, "end": {"line": 5, "character": 6}}],
|
|
693
|
+
}
|
|
694
|
+
mock_forward = AsyncMock(return_value=[outgoing])
|
|
695
|
+
with patch("java_functional_lsp.server._ensure_module_and_forward", mock_forward):
|
|
696
|
+
result = await _on_outgoing_calls(params)
|
|
697
|
+
assert result is not None
|
|
698
|
+
assert len(result) == 1
|
|
699
|
+
mock_forward.assert_called_once_with("callHierarchy/outgoingCalls", params, "file:///mod/Bar.java")
|
|
700
|
+
|
|
701
|
+
async def test_on_signature_help_forwards_to_jdtls(self) -> None:
|
|
702
|
+
"""_on_signature_help forwards and structures a SignatureHelp result."""
|
|
703
|
+
from unittest.mock import AsyncMock, patch
|
|
704
|
+
|
|
705
|
+
from java_functional_lsp.server import _on_signature_help
|
|
706
|
+
|
|
707
|
+
params = lsp.SignatureHelpParams(
|
|
708
|
+
text_document=lsp.TextDocumentIdentifier(uri="file:///mod/Foo.java"),
|
|
709
|
+
position=lsp.Position(line=5, character=10),
|
|
710
|
+
)
|
|
711
|
+
raw = {"signatures": [{"label": "foo(int x)"}], "activeSignature": 0}
|
|
712
|
+
mock_forward = AsyncMock(return_value=raw)
|
|
713
|
+
with patch("java_functional_lsp.server._ensure_module_and_forward", mock_forward):
|
|
714
|
+
result = await _on_signature_help(params)
|
|
715
|
+
assert result is not None
|
|
716
|
+
mock_forward.assert_called_once_with("textDocument/signatureHelp", params, "file:///mod/Foo.java")
|
|
717
|
+
|
|
718
|
+
async def test_on_signature_help_returns_none_on_null(self) -> None:
|
|
719
|
+
from unittest.mock import AsyncMock, patch
|
|
720
|
+
|
|
721
|
+
from java_functional_lsp.server import _on_signature_help
|
|
722
|
+
|
|
723
|
+
params = lsp.SignatureHelpParams(
|
|
724
|
+
text_document=lsp.TextDocumentIdentifier(uri="file:///mod/Foo.java"),
|
|
725
|
+
position=lsp.Position(line=0, character=0),
|
|
726
|
+
)
|
|
727
|
+
with patch("java_functional_lsp.server._ensure_module_and_forward", AsyncMock(return_value=None)):
|
|
728
|
+
assert await _on_signature_help(params) is None
|
|
729
|
+
|
|
730
|
+
async def test_on_implementation_forwards_using_text_document_uri(self) -> None:
|
|
731
|
+
"""_on_implementation uses params.text_document.uri and handles list result."""
|
|
732
|
+
from unittest.mock import AsyncMock, patch
|
|
733
|
+
|
|
734
|
+
from java_functional_lsp.server import _on_implementation
|
|
735
|
+
|
|
736
|
+
params = lsp.ImplementationParams(
|
|
737
|
+
text_document=lsp.TextDocumentIdentifier(uri="file:///mod/Foo.java"),
|
|
738
|
+
position=lsp.Position(line=0, character=0),
|
|
739
|
+
)
|
|
740
|
+
loc = {
|
|
741
|
+
"uri": "file:///mod/Impl.java",
|
|
742
|
+
"range": {"start": {"line": 0, "character": 0}, "end": {"line": 0, "character": 5}},
|
|
743
|
+
}
|
|
744
|
+
mock_forward = AsyncMock(return_value=[loc])
|
|
745
|
+
with patch("java_functional_lsp.server._ensure_module_and_forward", mock_forward):
|
|
746
|
+
result = await _on_implementation(params)
|
|
747
|
+
assert result is not None
|
|
748
|
+
assert len(result) == 1
|
|
749
|
+
mock_forward.assert_called_once_with("textDocument/implementation", params, "file:///mod/Foo.java")
|
|
750
|
+
|
|
751
|
+
async def test_on_implementation_returns_none_on_null(self) -> None:
|
|
752
|
+
from unittest.mock import AsyncMock, patch
|
|
753
|
+
|
|
754
|
+
from java_functional_lsp.server import _on_implementation
|
|
755
|
+
|
|
756
|
+
params = lsp.ImplementationParams(
|
|
757
|
+
text_document=lsp.TextDocumentIdentifier(uri="file:///mod/Foo.java"),
|
|
758
|
+
position=lsp.Position(line=0, character=0),
|
|
759
|
+
)
|
|
760
|
+
with patch("java_functional_lsp.server._ensure_module_and_forward", AsyncMock(return_value=None)):
|
|
761
|
+
assert await _on_implementation(params) is None
|
|
762
|
+
|
|
763
|
+
async def test_on_document_highlight_forwards_to_jdtls(self) -> None:
|
|
764
|
+
"""_on_document_highlight forwards and structures list result."""
|
|
765
|
+
from unittest.mock import AsyncMock, patch
|
|
766
|
+
|
|
767
|
+
from java_functional_lsp.server import _on_document_highlight
|
|
768
|
+
|
|
769
|
+
params = lsp.DocumentHighlightParams(
|
|
770
|
+
text_document=lsp.TextDocumentIdentifier(uri="file:///mod/Foo.java"),
|
|
771
|
+
position=lsp.Position(line=0, character=0),
|
|
772
|
+
)
|
|
773
|
+
raw = [{"range": {"start": {"line": 0, "character": 0}, "end": {"line": 0, "character": 3}}}]
|
|
774
|
+
mock_forward = AsyncMock(return_value=raw)
|
|
775
|
+
with patch("java_functional_lsp.server._ensure_module_and_forward", mock_forward):
|
|
776
|
+
result = await _on_document_highlight(params)
|
|
777
|
+
assert result is not None
|
|
778
|
+
assert len(result) == 1
|
|
779
|
+
mock_forward.assert_called_once_with("textDocument/documentHighlight", params, "file:///mod/Foo.java")
|
|
780
|
+
|
|
781
|
+
async def test_on_rename_forwards_and_returns_workspace_edit(self) -> None:
|
|
782
|
+
"""_on_rename forwards and structures a WorkspaceEdit."""
|
|
783
|
+
from unittest.mock import AsyncMock, patch
|
|
784
|
+
|
|
785
|
+
from java_functional_lsp.server import _on_rename
|
|
786
|
+
|
|
787
|
+
params = lsp.RenameParams(
|
|
788
|
+
text_document=lsp.TextDocumentIdentifier(uri="file:///mod/Foo.java"),
|
|
789
|
+
position=lsp.Position(line=0, character=0),
|
|
790
|
+
new_name="Bar",
|
|
791
|
+
)
|
|
792
|
+
raw: dict[str, object] = {"changes": {}}
|
|
793
|
+
mock_forward = AsyncMock(return_value=raw)
|
|
794
|
+
with patch("java_functional_lsp.server._ensure_module_and_forward", mock_forward):
|
|
795
|
+
result = await _on_rename(params)
|
|
796
|
+
assert result is not None
|
|
797
|
+
mock_forward.assert_called_once_with("textDocument/rename", params, "file:///mod/Foo.java")
|
|
798
|
+
|
|
799
|
+
async def test_on_rename_returns_none_on_null(self) -> None:
|
|
800
|
+
from unittest.mock import AsyncMock, patch
|
|
801
|
+
|
|
802
|
+
from java_functional_lsp.server import _on_rename
|
|
803
|
+
|
|
804
|
+
params = lsp.RenameParams(
|
|
805
|
+
text_document=lsp.TextDocumentIdentifier(uri="file:///mod/Foo.java"),
|
|
806
|
+
position=lsp.Position(line=0, character=0),
|
|
807
|
+
new_name="Bar",
|
|
808
|
+
)
|
|
809
|
+
with patch("java_functional_lsp.server._ensure_module_and_forward", AsyncMock(return_value=None)):
|
|
810
|
+
assert await _on_rename(params) is None
|
|
811
|
+
|
|
812
|
+
async def test_on_prepare_type_hierarchy_forwards_to_jdtls(self) -> None:
|
|
813
|
+
"""_on_prepare_type_hierarchy forwards and structures TypeHierarchyItem list."""
|
|
814
|
+
from unittest.mock import AsyncMock, patch
|
|
815
|
+
|
|
816
|
+
from java_functional_lsp.server import _on_prepare_type_hierarchy
|
|
817
|
+
|
|
818
|
+
params = lsp.TypeHierarchyPrepareParams(
|
|
819
|
+
text_document=lsp.TextDocumentIdentifier(uri="file:///mod/Foo.java"),
|
|
820
|
+
position=lsp.Position(line=0, character=0),
|
|
821
|
+
)
|
|
822
|
+
item = {
|
|
823
|
+
"name": "Foo",
|
|
824
|
+
"kind": 5,
|
|
825
|
+
"uri": "file:///mod/Foo.java",
|
|
826
|
+
"range": {"start": {"line": 0, "character": 0}, "end": {"line": 0, "character": 3}},
|
|
827
|
+
"selectionRange": {"start": {"line": 0, "character": 0}, "end": {"line": 0, "character": 3}},
|
|
828
|
+
}
|
|
829
|
+
mock_forward = AsyncMock(return_value=[item])
|
|
830
|
+
with patch("java_functional_lsp.server._ensure_module_and_forward", mock_forward):
|
|
831
|
+
result = await _on_prepare_type_hierarchy(params)
|
|
832
|
+
assert result is not None
|
|
833
|
+
assert len(result) == 1
|
|
834
|
+
assert result[0].name == "Foo"
|
|
835
|
+
mock_forward.assert_called_once_with("textDocument/prepareTypeHierarchy", params, "file:///mod/Foo.java")
|
|
836
|
+
|
|
837
|
+
async def test_on_type_hierarchy_supertypes_uses_item_uri(self) -> None:
|
|
838
|
+
"""_on_type_hierarchy_supertypes uses params.item.uri for module resolution."""
|
|
839
|
+
from unittest.mock import AsyncMock, patch
|
|
840
|
+
|
|
841
|
+
from java_functional_lsp.server import _on_type_hierarchy_supertypes
|
|
842
|
+
|
|
843
|
+
item = lsp.TypeHierarchyItem(
|
|
844
|
+
name="Foo",
|
|
845
|
+
kind=lsp.SymbolKind.Class,
|
|
846
|
+
uri="file:///mod/Foo.java",
|
|
847
|
+
range=lsp.Range(start=lsp.Position(line=0, character=0), end=lsp.Position(line=0, character=3)),
|
|
848
|
+
selection_range=lsp.Range(start=lsp.Position(line=0, character=0), end=lsp.Position(line=0, character=3)),
|
|
849
|
+
)
|
|
850
|
+
params = lsp.TypeHierarchySupertypesParams(item=item)
|
|
851
|
+
parent = {
|
|
852
|
+
"name": "Base",
|
|
853
|
+
"kind": 5,
|
|
854
|
+
"uri": "file:///mod/Base.java",
|
|
855
|
+
"range": {"start": {"line": 0, "character": 0}, "end": {"line": 0, "character": 4}},
|
|
856
|
+
"selectionRange": {"start": {"line": 0, "character": 0}, "end": {"line": 0, "character": 4}},
|
|
857
|
+
}
|
|
858
|
+
mock_forward = AsyncMock(return_value=[parent])
|
|
859
|
+
with patch("java_functional_lsp.server._ensure_module_and_forward", mock_forward):
|
|
860
|
+
result = await _on_type_hierarchy_supertypes(params)
|
|
861
|
+
assert result is not None
|
|
862
|
+
assert len(result) == 1
|
|
863
|
+
assert result[0].name == "Base"
|
|
864
|
+
mock_forward.assert_called_once_with("typeHierarchy/supertypes", params, "file:///mod/Foo.java")
|
|
865
|
+
|
|
866
|
+
async def test_on_type_hierarchy_subtypes_uses_item_uri(self) -> None:
|
|
867
|
+
"""_on_type_hierarchy_subtypes uses params.item.uri for module resolution."""
|
|
868
|
+
from unittest.mock import AsyncMock, patch
|
|
869
|
+
|
|
870
|
+
from java_functional_lsp.server import _on_type_hierarchy_subtypes
|
|
871
|
+
|
|
872
|
+
item = lsp.TypeHierarchyItem(
|
|
873
|
+
name="Base",
|
|
874
|
+
kind=lsp.SymbolKind.Class,
|
|
875
|
+
uri="file:///mod/Base.java",
|
|
876
|
+
range=lsp.Range(start=lsp.Position(line=0, character=0), end=lsp.Position(line=0, character=4)),
|
|
877
|
+
selection_range=lsp.Range(start=lsp.Position(line=0, character=0), end=lsp.Position(line=0, character=4)),
|
|
878
|
+
)
|
|
879
|
+
params = lsp.TypeHierarchySubtypesParams(item=item)
|
|
880
|
+
child = {
|
|
881
|
+
"name": "Impl",
|
|
882
|
+
"kind": 5,
|
|
883
|
+
"uri": "file:///mod/Impl.java",
|
|
884
|
+
"range": {"start": {"line": 0, "character": 0}, "end": {"line": 0, "character": 4}},
|
|
885
|
+
"selectionRange": {"start": {"line": 0, "character": 0}, "end": {"line": 0, "character": 4}},
|
|
886
|
+
}
|
|
887
|
+
mock_forward = AsyncMock(return_value=[child])
|
|
888
|
+
with patch("java_functional_lsp.server._ensure_module_and_forward", mock_forward):
|
|
889
|
+
result = await _on_type_hierarchy_subtypes(params)
|
|
890
|
+
assert result is not None
|
|
891
|
+
assert len(result) == 1
|
|
892
|
+
assert result[0].name == "Impl"
|
|
893
|
+
mock_forward.assert_called_once_with("typeHierarchy/subtypes", params, "file:///mod/Base.java")
|
|
894
|
+
|
|
895
|
+
async def test_on_type_definition_forwards_to_jdtls(self) -> None:
|
|
896
|
+
"""_on_type_definition uses params.text_document.uri and handles list result."""
|
|
897
|
+
from unittest.mock import AsyncMock, patch
|
|
898
|
+
|
|
899
|
+
from java_functional_lsp.server import _on_type_definition
|
|
900
|
+
|
|
901
|
+
params = lsp.TypeDefinitionParams(
|
|
902
|
+
text_document=lsp.TextDocumentIdentifier(uri="file:///mod/Foo.java"),
|
|
903
|
+
position=lsp.Position(line=0, character=0),
|
|
904
|
+
)
|
|
905
|
+
loc = {
|
|
906
|
+
"uri": "file:///mod/FooType.java",
|
|
907
|
+
"range": {"start": {"line": 0, "character": 0}, "end": {"line": 0, "character": 7}},
|
|
908
|
+
}
|
|
909
|
+
mock_forward = AsyncMock(return_value=[loc])
|
|
910
|
+
with patch("java_functional_lsp.server._ensure_module_and_forward", mock_forward):
|
|
911
|
+
result = await _on_type_definition(params)
|
|
912
|
+
assert result is not None
|
|
913
|
+
assert len(result) == 1
|
|
914
|
+
mock_forward.assert_called_once_with("textDocument/typeDefinition", params, "file:///mod/Foo.java")
|
|
915
|
+
|
|
916
|
+
async def test_on_declaration_forwards_to_jdtls(self) -> None:
|
|
917
|
+
"""_on_declaration uses params.text_document.uri and handles list result."""
|
|
918
|
+
from unittest.mock import AsyncMock, patch
|
|
919
|
+
|
|
920
|
+
from java_functional_lsp.server import _on_declaration
|
|
921
|
+
|
|
922
|
+
params = lsp.DeclarationParams(
|
|
923
|
+
text_document=lsp.TextDocumentIdentifier(uri="file:///mod/Foo.java"),
|
|
924
|
+
position=lsp.Position(line=0, character=0),
|
|
925
|
+
)
|
|
926
|
+
loc = {
|
|
927
|
+
"uri": "file:///mod/IFoo.java",
|
|
928
|
+
"range": {"start": {"line": 0, "character": 0}, "end": {"line": 0, "character": 4}},
|
|
929
|
+
}
|
|
930
|
+
mock_forward = AsyncMock(return_value=[loc])
|
|
931
|
+
with patch("java_functional_lsp.server._ensure_module_and_forward", mock_forward):
|
|
932
|
+
result = await _on_declaration(params)
|
|
933
|
+
assert result is not None
|
|
934
|
+
assert len(result) == 1
|
|
935
|
+
mock_forward.assert_called_once_with("textDocument/declaration", params, "file:///mod/Foo.java")
|
|
936
|
+
|
|
937
|
+
async def test_on_prepare_rename_forwards_to_jdtls(self) -> None:
|
|
938
|
+
"""_on_prepare_rename forwards and structures a Range result."""
|
|
939
|
+
from unittest.mock import AsyncMock, patch
|
|
940
|
+
|
|
941
|
+
from java_functional_lsp.server import _on_prepare_rename
|
|
942
|
+
|
|
943
|
+
params = lsp.PrepareRenameParams(
|
|
944
|
+
text_document=lsp.TextDocumentIdentifier(uri="file:///mod/Foo.java"),
|
|
945
|
+
position=lsp.Position(line=3, character=5),
|
|
946
|
+
)
|
|
947
|
+
raw = {"start": {"line": 3, "character": 4}, "end": {"line": 3, "character": 7}}
|
|
948
|
+
mock_forward = AsyncMock(return_value=raw)
|
|
949
|
+
with patch("java_functional_lsp.server._ensure_module_and_forward", mock_forward):
|
|
950
|
+
result = await _on_prepare_rename(params)
|
|
951
|
+
assert result is not None
|
|
952
|
+
mock_forward.assert_called_once_with("textDocument/prepareRename", params, "file:///mod/Foo.java")
|
|
953
|
+
|
|
954
|
+
async def test_on_workspace_symbol_uses_proxy_directly(self) -> None:
|
|
955
|
+
"""_on_workspace_symbol bypasses _ensure_module_and_forward and calls proxy.send_request."""
|
|
956
|
+
from unittest.mock import AsyncMock, patch
|
|
957
|
+
|
|
958
|
+
from java_functional_lsp.server import _on_workspace_symbol
|
|
959
|
+
from java_functional_lsp.server import server as srv
|
|
960
|
+
|
|
961
|
+
params = lsp.WorkspaceSymbolParams(query="Foo")
|
|
962
|
+
raw = [
|
|
963
|
+
{
|
|
964
|
+
"name": "FooService",
|
|
965
|
+
"kind": 5,
|
|
966
|
+
"location": {
|
|
967
|
+
"uri": "file:///mod/FooService.java",
|
|
968
|
+
"range": {"start": {"line": 0, "character": 0}, "end": {"line": 0, "character": 10}},
|
|
969
|
+
},
|
|
970
|
+
}
|
|
971
|
+
]
|
|
972
|
+
mock_send = AsyncMock(return_value=raw)
|
|
973
|
+
with (
|
|
974
|
+
patch.object(srv._proxy, "_available", True),
|
|
975
|
+
patch.object(srv._proxy, "send_request", mock_send),
|
|
976
|
+
):
|
|
977
|
+
result = await _on_workspace_symbol(params)
|
|
978
|
+
assert result is not None
|
|
979
|
+
assert len(result) == 1
|
|
980
|
+
assert result[0].name == "FooService"
|
|
981
|
+
mock_send.assert_called_once()
|
|
982
|
+
assert mock_send.call_args[0][0] == "workspace/symbol"
|
|
983
|
+
|
|
984
|
+
async def test_on_workspace_symbol_returns_none_when_unavailable(self) -> None:
|
|
985
|
+
"""_on_workspace_symbol returns None when jdtls is not available."""
|
|
986
|
+
from unittest.mock import patch
|
|
987
|
+
|
|
988
|
+
from java_functional_lsp.server import _on_workspace_symbol
|
|
989
|
+
from java_functional_lsp.server import server as srv
|
|
990
|
+
|
|
991
|
+
params = lsp.WorkspaceSymbolParams(query="anything")
|
|
992
|
+
with patch.object(srv._proxy, "_available", False):
|
|
993
|
+
result = await _on_workspace_symbol(params)
|
|
994
|
+
assert result is None
|
|
995
|
+
|
|
996
|
+
async def test_on_document_highlight_returns_none_on_null(self) -> None:
|
|
997
|
+
from unittest.mock import AsyncMock, patch
|
|
998
|
+
|
|
999
|
+
from java_functional_lsp.server import _on_document_highlight
|
|
1000
|
+
|
|
1001
|
+
params = lsp.DocumentHighlightParams(
|
|
1002
|
+
text_document=lsp.TextDocumentIdentifier(uri="file:///mod/Foo.java"),
|
|
1003
|
+
position=lsp.Position(line=0, character=0),
|
|
1004
|
+
)
|
|
1005
|
+
with patch("java_functional_lsp.server._ensure_module_and_forward", AsyncMock(return_value=None)):
|
|
1006
|
+
assert await _on_document_highlight(params) is None
|
|
1007
|
+
|
|
1008
|
+
async def test_on_type_definition_returns_none_on_null(self) -> None:
|
|
1009
|
+
from unittest.mock import AsyncMock, patch
|
|
1010
|
+
|
|
1011
|
+
from java_functional_lsp.server import _on_type_definition
|
|
1012
|
+
|
|
1013
|
+
params = lsp.TypeDefinitionParams(
|
|
1014
|
+
text_document=lsp.TextDocumentIdentifier(uri="file:///mod/Foo.java"),
|
|
1015
|
+
position=lsp.Position(line=0, character=0),
|
|
1016
|
+
)
|
|
1017
|
+
with patch("java_functional_lsp.server._ensure_module_and_forward", AsyncMock(return_value=None)):
|
|
1018
|
+
assert await _on_type_definition(params) is None
|
|
1019
|
+
|
|
1020
|
+
async def test_on_declaration_returns_none_on_null(self) -> None:
|
|
1021
|
+
from unittest.mock import AsyncMock, patch
|
|
1022
|
+
|
|
1023
|
+
from java_functional_lsp.server import _on_declaration
|
|
1024
|
+
|
|
1025
|
+
params = lsp.DeclarationParams(
|
|
1026
|
+
text_document=lsp.TextDocumentIdentifier(uri="file:///mod/Foo.java"),
|
|
1027
|
+
position=lsp.Position(line=0, character=0),
|
|
1028
|
+
)
|
|
1029
|
+
with patch("java_functional_lsp.server._ensure_module_and_forward", AsyncMock(return_value=None)):
|
|
1030
|
+
assert await _on_declaration(params) is None
|
|
1031
|
+
|
|
1032
|
+
async def test_on_prepare_rename_returns_none_on_null(self) -> None:
|
|
1033
|
+
from unittest.mock import AsyncMock, patch
|
|
1034
|
+
|
|
1035
|
+
from java_functional_lsp.server import _on_prepare_rename
|
|
1036
|
+
|
|
1037
|
+
params = lsp.PrepareRenameParams(
|
|
1038
|
+
text_document=lsp.TextDocumentIdentifier(uri="file:///mod/Foo.java"),
|
|
1039
|
+
position=lsp.Position(line=0, character=0),
|
|
1040
|
+
)
|
|
1041
|
+
with patch("java_functional_lsp.server._ensure_module_and_forward", AsyncMock(return_value=None)):
|
|
1042
|
+
assert await _on_prepare_rename(params) is None
|
|
1043
|
+
|
|
1044
|
+
async def test_on_prepare_rename_returns_placeholder_when_jdtls_sends_placeholder(self) -> None:
|
|
1045
|
+
"""_on_prepare_rename handles PrepareRenamePlaceholder (the typical jdtls response)."""
|
|
1046
|
+
from unittest.mock import AsyncMock, patch
|
|
1047
|
+
|
|
1048
|
+
from java_functional_lsp.server import _on_prepare_rename
|
|
1049
|
+
|
|
1050
|
+
params = lsp.PrepareRenameParams(
|
|
1051
|
+
text_document=lsp.TextDocumentIdentifier(uri="file:///mod/Foo.java"),
|
|
1052
|
+
position=lsp.Position(line=3, character=5),
|
|
1053
|
+
)
|
|
1054
|
+
raw = {
|
|
1055
|
+
"range": {"start": {"line": 3, "character": 4}, "end": {"line": 3, "character": 7}},
|
|
1056
|
+
"placeholder": "foo",
|
|
1057
|
+
}
|
|
1058
|
+
mock_forward = AsyncMock(return_value=raw)
|
|
1059
|
+
with patch("java_functional_lsp.server._ensure_module_and_forward", mock_forward):
|
|
1060
|
+
result = await _on_prepare_rename(params)
|
|
1061
|
+
assert isinstance(result, lsp.PrepareRenamePlaceholder)
|
|
1062
|
+
assert result.placeholder == "foo"
|
|
1063
|
+
|
|
1064
|
+
async def test_on_prepare_type_hierarchy_returns_none_on_null(self) -> None:
|
|
1065
|
+
from unittest.mock import AsyncMock, patch
|
|
1066
|
+
|
|
1067
|
+
from java_functional_lsp.server import _on_prepare_type_hierarchy
|
|
1068
|
+
|
|
1069
|
+
params = lsp.TypeHierarchyPrepareParams(
|
|
1070
|
+
text_document=lsp.TextDocumentIdentifier(uri="file:///mod/Foo.java"),
|
|
1071
|
+
position=lsp.Position(line=0, character=0),
|
|
1072
|
+
)
|
|
1073
|
+
with patch("java_functional_lsp.server._ensure_module_and_forward", AsyncMock(return_value=None)):
|
|
1074
|
+
assert await _on_prepare_type_hierarchy(params) is None
|
|
1075
|
+
|
|
1076
|
+
async def test_on_type_hierarchy_supertypes_returns_none_on_null(self) -> None:
|
|
1077
|
+
from unittest.mock import AsyncMock, patch
|
|
1078
|
+
|
|
1079
|
+
from java_functional_lsp.server import _on_type_hierarchy_supertypes
|
|
1080
|
+
|
|
1081
|
+
item = lsp.TypeHierarchyItem(
|
|
1082
|
+
name="Foo",
|
|
1083
|
+
kind=lsp.SymbolKind.Class,
|
|
1084
|
+
uri="file:///mod/Foo.java",
|
|
1085
|
+
range=lsp.Range(start=lsp.Position(line=0, character=0), end=lsp.Position(line=0, character=3)),
|
|
1086
|
+
selection_range=lsp.Range(start=lsp.Position(line=0, character=0), end=lsp.Position(line=0, character=3)),
|
|
1087
|
+
)
|
|
1088
|
+
params = lsp.TypeHierarchySupertypesParams(item=item)
|
|
1089
|
+
with patch("java_functional_lsp.server._ensure_module_and_forward", AsyncMock(return_value=None)):
|
|
1090
|
+
assert await _on_type_hierarchy_supertypes(params) is None
|
|
1091
|
+
|
|
1092
|
+
async def test_on_type_hierarchy_subtypes_returns_none_on_null(self) -> None:
|
|
1093
|
+
from unittest.mock import AsyncMock, patch
|
|
1094
|
+
|
|
1095
|
+
from java_functional_lsp.server import _on_type_hierarchy_subtypes
|
|
1096
|
+
|
|
1097
|
+
item = lsp.TypeHierarchyItem(
|
|
1098
|
+
name="Base",
|
|
1099
|
+
kind=lsp.SymbolKind.Class,
|
|
1100
|
+
uri="file:///mod/Base.java",
|
|
1101
|
+
range=lsp.Range(start=lsp.Position(line=0, character=0), end=lsp.Position(line=0, character=4)),
|
|
1102
|
+
selection_range=lsp.Range(start=lsp.Position(line=0, character=0), end=lsp.Position(line=0, character=4)),
|
|
1103
|
+
)
|
|
1104
|
+
params = lsp.TypeHierarchySubtypesParams(item=item)
|
|
1105
|
+
with patch("java_functional_lsp.server._ensure_module_and_forward", AsyncMock(return_value=None)):
|
|
1106
|
+
assert await _on_type_hierarchy_subtypes(params) is None
|
|
1107
|
+
|
|
548
1108
|
def test_serialize_params_camelcase(self) -> None:
|
|
549
1109
|
from java_functional_lsp.server import _serialize_params
|
|
550
1110
|
|
|
@@ -611,7 +1171,11 @@ class TestServerInternals:
|
|
|
611
1171
|
finally:
|
|
612
1172
|
server.workspace.remove_text_document(uri)
|
|
613
1173
|
assert result is not None
|
|
614
|
-
|
|
1174
|
+
ca = result[0]
|
|
1175
|
+
assert isinstance(ca, lsp.CodeAction)
|
|
1176
|
+
assert ca.edit is not None
|
|
1177
|
+
assert ca.edit.changes is not None
|
|
1178
|
+
assert any("Try.of" in e.new_text for e in ca.edit.changes[uri])
|
|
615
1179
|
|
|
616
1180
|
def test_code_action_filters_foreign(self) -> None:
|
|
617
1181
|
from java_functional_lsp.server import on_code_action, server
|
|
@@ -897,7 +1461,7 @@ class TestFindLombokJar:
|
|
|
897
1461
|
result = _find_lombok_jar()
|
|
898
1462
|
assert result is None
|
|
899
1463
|
|
|
900
|
-
def test_warns_on_missing_config_path(self,
|
|
1464
|
+
def test_warns_on_missing_config_path(self, caplog: Any) -> None:
|
|
901
1465
|
import logging
|
|
902
1466
|
|
|
903
1467
|
from java_functional_lsp.proxy import _find_lombok_jar
|
|
@@ -1027,6 +1591,7 @@ class TestLspLifecycle:
|
|
|
1027
1591
|
assert actions is not None
|
|
1028
1592
|
assert len(actions) >= 1
|
|
1029
1593
|
action = actions[0]
|
|
1594
|
+
assert isinstance(action, lsp.CodeAction)
|
|
1030
1595
|
assert action.title == "Replace with Option.none()"
|
|
1031
1596
|
assert action.kind == lsp.CodeActionKind.QuickFix
|
|
1032
1597
|
assert action.edit is not None
|
|
@@ -1053,6 +1618,7 @@ class TestLspLifecycle:
|
|
|
1053
1618
|
assert actions is not None
|
|
1054
1619
|
assert len(actions) >= 1
|
|
1055
1620
|
action = actions[0]
|
|
1621
|
+
assert isinstance(action, lsp.CodeAction)
|
|
1056
1622
|
assert action.title == "Convert try/catch to Try monadic flow"
|
|
1057
1623
|
assert action.edit is not None
|
|
1058
1624
|
assert action.edit.changes is not None
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/.github/ISSUE_TEMPLATE/bug-report.md
RENAMED
|
File without changes
|
{java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/.github/ISSUE_TEMPLATE/feature-request.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/.github/workflows/release-drafter.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/.github/workflows/update-homebrew.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/editors/intellij/lsp4ij-template.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{java_functional_lsp-0.9.4 → java_functional_lsp-0.9.6}/src/java_functional_lsp/analyzers/base.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|