feat(server/lsp_server): include .def file changes and offer quoted def/variable completions
This commit is contained in:
@@ -219,21 +219,29 @@ def did_rename_files(params: lsp.RenameFilesParams) -> None:
|
||||
def did_change_watched_files(params: lsp.DidChangeWatchedFilesParams) -> None:
|
||||
"""Keep indexes for closed Tcl files synchronized with disk changes."""
|
||||
for change in params.changes:
|
||||
if pathlib.Path(uris.to_fs_path(change.uri)).suffix.lower() == ".psc":
|
||||
suffix = pathlib.Path(uris.to_fs_path(change.uri)).suffix.lower()
|
||||
if suffix == ".psc":
|
||||
_refresh_psc_index()
|
||||
continue
|
||||
if suffix == ".def":
|
||||
LSP_SERVER.refresh_def_symbols(_workspace_roots(), report=log_warning)
|
||||
continue
|
||||
if change.type == lsp.FileChangeType.Deleted:
|
||||
LSP_SERVER.remove_file_state(change.uri)
|
||||
else:
|
||||
_index_tcl_file_from_disk(change.uri)
|
||||
|
||||
|
||||
def _refresh_psc_index():
|
||||
def _workspace_roots() -> list[pathlib.Path]:
|
||||
folders = LSP_SERVER.workspace.folders
|
||||
roots = [pathlib.Path(uris.to_fs_path(uri)) for uri in folders]
|
||||
if not roots and LSP_SERVER.workspace.root_path:
|
||||
roots = [pathlib.Path(LSP_SERVER.workspace.root_path)]
|
||||
LSP_SERVER.refresh_psc_scripts(roots, report=log_warning)
|
||||
return roots
|
||||
|
||||
|
||||
def _refresh_psc_index():
|
||||
LSP_SERVER.refresh_psc_scripts(_workspace_roots(), report=log_warning)
|
||||
|
||||
|
||||
@LSP_SERVER.feature(
|
||||
@@ -393,6 +401,30 @@ def on_completion(params: lsp.CompletionParams) -> lsp.CompletionList:
|
||||
items = [*ranked_completion_items(static_candidates, CompletionContext.GENERAL), *items]
|
||||
return lsp.CompletionList(is_incomplete=False, items=items)
|
||||
|
||||
def_symbol_items = {
|
||||
DynamicCompletionKind.BLOCK_TEMPLATE: LSP_SERVER.block_template_items,
|
||||
DynamicCompletionKind.ADDRESS: LSP_SERVER.address_items,
|
||||
DynamicCompletionKind.VALUE: list,
|
||||
}.get(argument_completion.dynamic_kind)
|
||||
if def_symbol_items is not None:
|
||||
# MOM_do_template, MOM_force, ... take a .def name, a fixed value (e.g.
|
||||
# Always|Once|Off) or a variable holding one.
|
||||
def_symbols = [*static_candidates, *((0, item) for item in def_symbol_items())]
|
||||
variable_candidates = list(candidates)
|
||||
variable_candidates.extend((300, item) for item in standard_items.nx_variables)
|
||||
variables = []
|
||||
for item in ranked_completion_items(variable_candidates, CompletionContext.VARIABLE):
|
||||
# Without a typed "$" the variable must be substituted.
|
||||
item.insert_text = f"${item.label}"
|
||||
item.filter_text = item.label
|
||||
item.text_edit = None
|
||||
variables.append(item)
|
||||
quoted = [
|
||||
_quoted_item(item, source_lines, position, argument_completion.active_prefix)
|
||||
for item in ranked_completion_items(def_symbols, CompletionContext.GENERAL)
|
||||
]
|
||||
return lsp.CompletionList(is_incomplete=False, items=[*quoted, *variables])
|
||||
|
||||
if argument_completion.dynamic_kind == DynamicCompletionKind.PROCEDURE:
|
||||
procedure_kinds = {
|
||||
lsp.CompletionItemKind.Constructor,
|
||||
@@ -436,6 +468,35 @@ def on_completion(params: lsp.CompletionParams) -> lsp.CompletionList:
|
||||
return lsp.CompletionList(is_incomplete=False, items=items)
|
||||
|
||||
|
||||
def _quoted_item(
|
||||
item: lsp.CompletionItem,
|
||||
source_lines,
|
||||
position: lsp.Position,
|
||||
active_prefix: str,
|
||||
) -> lsp.CompletionItem:
|
||||
"""Insert ``item`` as a quoted word, replacing quotes the user already typed."""
|
||||
line = source_lines[position.line] if position.line < len(source_lines) else ""
|
||||
utf16 = line.encode("utf-16-le")
|
||||
start = position.character - len(active_prefix.encode("utf-16-le")) // 2
|
||||
end = position.character
|
||||
opened = start > 0 and utf16[(start - 1) * 2 : start * 2].decode("utf-16-le") == '"'
|
||||
if opened:
|
||||
start -= 1
|
||||
# Also replace a closing quote the editor inserted automatically.
|
||||
if utf16[end * 2 : (end + 1) * 2].decode("utf-16-le") == '"':
|
||||
end += 1
|
||||
item.text_edit = lsp.TextEdit(
|
||||
range=lsp.Range(
|
||||
start=lsp.Position(line=position.line, character=start),
|
||||
end=lsp.Position(line=position.line, character=end),
|
||||
),
|
||||
new_text=f'"{item.label}"',
|
||||
)
|
||||
item.insert_text = None
|
||||
item.filter_text = f'"{item.label}' if opened else item.label
|
||||
return item
|
||||
|
||||
|
||||
@LSP_SERVER.feature(
|
||||
lsp.TEXT_DOCUMENT_SIGNATURE_HELP,
|
||||
lsp.SignatureHelpOptions(
|
||||
|
||||
Reference in New Issue
Block a user