add new features and fix bugs
This commit is contained in:
+70
-19
@@ -42,6 +42,7 @@ import lsp_jsonrpc as jsonrpc
|
||||
import lsprotocol.types as lsp
|
||||
from pygls import uris, workspace
|
||||
from common.load_data import standard_items
|
||||
from tools.folding_ranges import build_folding_ranges
|
||||
from tools.semantic_tokens import _Highlighter, TOKEN_TYPES, TokenModifier
|
||||
from tools.completion_items import completion, remove_existing_items, remove_shared_keys
|
||||
from tools.inlay_hint import InlayHintGenerator
|
||||
@@ -54,7 +55,9 @@ GLOBAL_SETTINGS = {}
|
||||
|
||||
|
||||
MAX_WORKERS = 5
|
||||
LSP_SERVER = TclLanguageServer(name="NX Postprocessor Support", version="0.0.1", max_workers=MAX_WORKERS)
|
||||
LSP_SERVER = TclLanguageServer(
|
||||
name="NX Postprocessor Support", version="0.0.1", max_workers=MAX_WORKERS
|
||||
)
|
||||
|
||||
# **********************************************************
|
||||
# Tool specific code goes below this.
|
||||
@@ -132,16 +135,24 @@ def on_completion(params: lsp.CompletionParams) -> lsp.CompletionList:
|
||||
|
||||
# Base items
|
||||
poco = [item for items in LSP_SERVER.poco_completion.values() for item in items]
|
||||
base_items = standard_items.tcl_keyword_list + standard_items.nx_procs + standard_items.nx_variables + poco
|
||||
base_items = (
|
||||
standard_items.tcl_keyword_list
|
||||
+ standard_items.nx_procs
|
||||
+ standard_items.nx_variables
|
||||
+ poco
|
||||
)
|
||||
|
||||
# Build variable index from current document
|
||||
globals_set, procs_locals, proc_ranges = build_variable_index(doc.source)
|
||||
tree = LSP_SERVER.get_tree(doc)
|
||||
globals_set, procs_locals, proc_ranges = build_variable_index(doc.source, tree)
|
||||
|
||||
# Always include globals (excluding built-ins)
|
||||
dynamic_items = []
|
||||
for name in sorted(globals_set):
|
||||
if name not in BUILTIN_VAR_LABELS:
|
||||
dynamic_items.append(lsp.CompletionItem(label=name, kind=lsp.CompletionItemKind.Variable))
|
||||
dynamic_items.append(
|
||||
lsp.CompletionItem(label=name, kind=lsp.CompletionItemKind.Variable)
|
||||
)
|
||||
|
||||
# Include proc-local variables when cursor is inside that proc
|
||||
pos = params.position
|
||||
@@ -151,7 +162,11 @@ def on_completion(params: lsp.CompletionParams) -> lsp.CompletionList:
|
||||
for name in sorted(procs_locals.get(pr.name, set())):
|
||||
# Exclude built-ins and globals to avoid duplication
|
||||
if name not in BUILTIN_VAR_LABELS and name not in globals_set:
|
||||
dynamic_items.append(lsp.CompletionItem(label=name, kind=lsp.CompletionItemKind.Variable))
|
||||
dynamic_items.append(
|
||||
lsp.CompletionItem(
|
||||
label=name, kind=lsp.CompletionItemKind.Variable
|
||||
)
|
||||
)
|
||||
break
|
||||
|
||||
# Merge with de-duplication for variables only
|
||||
@@ -235,6 +250,13 @@ def semantic_tokens(params: lsp.SemanticTokensParams):
|
||||
return lsp.SemanticTokens(data=data)
|
||||
|
||||
|
||||
@LSP_SERVER.feature(lsp.TEXT_DOCUMENT_FOLDING_RANGE)
|
||||
def folding_ranges(params: lsp.FoldingRangeParams):
|
||||
document = LSP_SERVER.workspace.get_text_document(params.text_document.uri)
|
||||
tree = LSP_SERVER.get_tree(document)
|
||||
return build_folding_ranges(tree)
|
||||
|
||||
|
||||
@LSP_SERVER.feature(lsp.TEXT_DOCUMENT_HOVER)
|
||||
def hover(params: lsp.HoverParams) -> lsp.Hover:
|
||||
pos = params.position
|
||||
@@ -270,7 +292,9 @@ def hover(params: lsp.HoverParams) -> lsp.Hover:
|
||||
if match and match.get("kind") == "function":
|
||||
label = match.get("label", "")
|
||||
parameters = match.get("parameters", [])
|
||||
param_lines = "\n".join(f"- `{p['name']}`: {p['desc']}" for p in parameters) or "_None_"
|
||||
param_lines = (
|
||||
"\n".join(f"- `{p['name']}`: {p['desc']}" for p in parameters) or "_None_"
|
||||
)
|
||||
example_data = match.get("example", [])
|
||||
example_md = "\n".join(f"{line}" for line in example_data)
|
||||
returns_data = match.get("returns", ["None"])
|
||||
@@ -302,7 +326,9 @@ def hover(params: lsp.HoverParams) -> lsp.Hover:
|
||||
proc_docs.update(file_docs)
|
||||
|
||||
if token in proc_docs:
|
||||
return lsp.Hover(lsp.MarkupContent(kind=lsp.MarkupKind.Markdown, value=proc_docs[token]))
|
||||
return lsp.Hover(
|
||||
lsp.MarkupContent(kind=lsp.MarkupKind.Markdown, value=proc_docs[token])
|
||||
)
|
||||
|
||||
return None
|
||||
|
||||
@@ -432,8 +458,12 @@ def initialize(params: lsp.InitializeParams) -> lsp.InitializeResult:
|
||||
|
||||
settings = params.initialization_options["settings"]
|
||||
_update_workspace_settings(settings)
|
||||
log_to_output(f"Settings used to run Server:\r\n{json.dumps(settings, indent=4, ensure_ascii=False)}\r\n")
|
||||
log_to_output(f"Global settings:\r\n{json.dumps(GLOBAL_SETTINGS, indent=4, ensure_ascii=False)}\r\n")
|
||||
log_to_output(
|
||||
f"Settings used to run Server:\r\n{json.dumps(settings, indent=4, ensure_ascii=False)}\r\n"
|
||||
)
|
||||
log_to_output(
|
||||
f"Global settings:\r\n{json.dumps(GLOBAL_SETTINGS, indent=4, ensure_ascii=False)}\r\n"
|
||||
)
|
||||
semantic_tokens_legend = lsp.SemanticTokensLegend(
|
||||
token_types=TOKEN_TYPES,
|
||||
token_modifiers=[m.name for m in TokenModifier],
|
||||
@@ -441,7 +471,10 @@ def initialize(params: lsp.InitializeParams) -> lsp.InitializeResult:
|
||||
return lsp.InitializeResult(
|
||||
capabilities=lsp.ServerCapabilities(
|
||||
document_formatting_provider=GLOBAL_SETTINGS.get("formatter", True),
|
||||
semantic_tokens_provider=lsp.SemanticTokensOptions(legend=semantic_tokens_legend, full=True, range=False),
|
||||
folding_range_provider=True,
|
||||
semantic_tokens_provider=lsp.SemanticTokensOptions(
|
||||
legend=semantic_tokens_legend, full=True, range=False
|
||||
),
|
||||
definition_provider=True,
|
||||
)
|
||||
)
|
||||
@@ -461,22 +494,38 @@ def initialized(_params: lsp.InitializedParams):
|
||||
for sourced_layer in poco_files:
|
||||
completion.reset()
|
||||
try:
|
||||
file_root = pathlib.Path(root).joinpath(sourced_layer.subfolder if sourced_layer.subfolder else "")
|
||||
file_root = pathlib.Path(root).joinpath(
|
||||
sourced_layer.subfolder if sourced_layer.subfolder else ""
|
||||
)
|
||||
for tcl_file in sourced_layer.files:
|
||||
filepath = pathlib.Path(file_root).joinpath(f"{tcl_file}.tcl")
|
||||
filepath = pathlib.Path(file_root).joinpath(
|
||||
f"{tcl_file}.tcl"
|
||||
)
|
||||
if not filepath.exists():
|
||||
continue
|
||||
completion.reset()
|
||||
document = LSP_SERVER.workspace.get_text_document(filepath.as_uri())
|
||||
document = LSP_SERVER.workspace.get_text_document(
|
||||
filepath.as_uri()
|
||||
)
|
||||
tree = LSP_SERVER.parser.parse(document.source)
|
||||
tree.accept(completion, recurse=True)
|
||||
remove_existing_items(completion.custom_functions, LSP_SERVER.poco_completion)
|
||||
LSP_SERVER.poco_completion[str(filepath)] = completion.custom_functions
|
||||
remove_shared_keys(LSP_SERVER.proc_signatures, completion.proc_signatures)
|
||||
LSP_SERVER.proc_signatures[str(filepath)] = completion.proc_signatures
|
||||
remove_existing_items(
|
||||
completion.custom_functions, LSP_SERVER.poco_completion
|
||||
)
|
||||
LSP_SERVER.poco_completion[str(filepath)] = (
|
||||
completion.custom_functions
|
||||
)
|
||||
remove_shared_keys(
|
||||
LSP_SERVER.proc_signatures, completion.proc_signatures
|
||||
)
|
||||
LSP_SERVER.proc_signatures[str(filepath)] = (
|
||||
completion.proc_signatures
|
||||
)
|
||||
from tools.proc_docs import build_proc_docs
|
||||
|
||||
LSP_SERVER.proc_docs[str(filepath)] = build_proc_docs(tree, document.source)
|
||||
LSP_SERVER.proc_docs[str(filepath)] = build_proc_docs(
|
||||
tree, document.source
|
||||
)
|
||||
except Exception as e:
|
||||
log_to_output(f"Fehler beim Parsen von {filepath}: {e}")
|
||||
log_to_output("Background indexing completed.")
|
||||
@@ -578,7 +627,9 @@ def _get_settings_by_document(document: workspace.Document | None):
|
||||
# *****************************************************
|
||||
# Logging and notification.
|
||||
# *****************************************************
|
||||
def log_to_output(message: str, msg_type: lsp.MessageType = lsp.MessageType.Log) -> None:
|
||||
def log_to_output(
|
||||
message: str, msg_type: lsp.MessageType = lsp.MessageType.Log
|
||||
) -> None:
|
||||
LSP_SERVER.show_message_log(message, msg_type)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user