feat(tcloo): add document-local TclOO completions, signature help and hints
Add conservative, document-local TclOO type inference and tooling so the server can offer method completions, signature help, and inlay parameter hints for statically resolvable TclOO receivers (including `new`/`create`, `my`, and simple return-chains). Also surface class names as completion items and emit semantic tokens for class declarations/references. Notable changes: - New tcloo_* tools: completion, symbols, and argument parsing; integrated into on_completion, signature_help, inlay hint generation and semantic token highlighting. Completions are returned early when an OO receiver context is detected. - Use a completion-friendly parser fallback when the main AST fails (TclSyntaxError) so editing-in-progress code still yields useful completions. - Add CompletionItemKind.Class to command kinds, exclude class items from the poco completion name cache, and include new unit tests for the TclOO helpers.
This commit is contained in:
@@ -9,6 +9,8 @@ from typing import Any
|
||||
import lsprotocol.types as lsp
|
||||
from tclint.syntax_tree import Command, VarSub, Visitor
|
||||
from tools.navigation import FileSymbolIndex
|
||||
from tools.tcloo_arguments import method_parameters
|
||||
from tools.tcloo_completion import resolved_method_calls
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@@ -160,6 +162,7 @@ class InlayHintGenerator(Visitor):
|
||||
self.source_lines = (
|
||||
source_lines if source_lines is not None else source.splitlines()
|
||||
)
|
||||
self.source = source
|
||||
self.proc_signatures = proc_signatures
|
||||
self.requested_range = requested_range
|
||||
self.parameter_names = parameter_names
|
||||
@@ -194,6 +197,17 @@ class InlayHintGenerator(Visitor):
|
||||
walk(child)
|
||||
|
||||
walk(tree)
|
||||
if self.parameter_names != "none":
|
||||
for call in resolved_method_calls(self.source):
|
||||
if not self._node_intersects_requested_range(call.command):
|
||||
continue
|
||||
parameters = method_parameters(call.parameters)
|
||||
signature = InlayHintSignature(
|
||||
parameters=tuple(InlayHintParameter(p.name, variadic=p.variadic) for p in parameters),
|
||||
display_label=" ".join([call.label, *(p.label for p in parameters)]),
|
||||
)
|
||||
self._argument_hints(signature, call.command.args[call.argument_offset:])
|
||||
self.hints.sort(key=lambda hint: (hint.position.line, hint.position.character))
|
||||
return self.hints
|
||||
|
||||
def _position(self, line: int, column: int) -> lsp.Position:
|
||||
@@ -238,7 +252,10 @@ class InlayHintGenerator(Visitor):
|
||||
if signature is None or self.parameter_names == "none":
|
||||
return
|
||||
|
||||
for argument_index, argument in enumerate(command.args):
|
||||
self._argument_hints(signature, command.args)
|
||||
|
||||
def _argument_hints(self, signature, arguments):
|
||||
for argument_index, argument in enumerate(arguments):
|
||||
parameter = self._parameter_for_argument(signature, argument_index)
|
||||
if parameter is None:
|
||||
break
|
||||
|
||||
Reference in New Issue
Block a user