From b680c019890bde4c3a81011a0f0c67ac2ef60c62 Mon Sep 17 00:00:00 2001 From: Christoph Brandau Date: Tue, 5 Aug 2025 18:18:17 +0200 Subject: [PATCH] update file sourcing --- server/src/lsp_server.py | 33 ++++++++++------------ server/src/tools/file_sourcing.py | 25 ++++++++++++++--- server/src/tools/symbols.py | 46 +++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 23 deletions(-) diff --git a/server/src/lsp_server.py b/server/src/lsp_server.py index b05406e..4946446 100644 --- a/server/src/lsp_server.py +++ b/server/src/lsp_server.py @@ -191,16 +191,16 @@ def did_open(params: lsp.DidOpenTextDocumentParams) -> None: document = LSP_SERVER.workspace.get_text_document(params.text_document.uri) LSP_SERVER.compute_diagnostics(document) completion.reset() - all_tcl_files = get_all_tcl_files(LSP_SERVER.workspace.root_path) + # all_tcl_files = get_all_tcl_files(LSP_SERVER.workspace.root_path) - for filepath in all_tcl_files: - try: - with open(filepath, "r", encoding="utf-8") as f: - source = f.read() - tree = LSP_SERVER.parser.parse(source) - tree.accept(completion, recurse=True) - except Exception as e: - log_to_output(f"Fehler beim Parsen von {filepath}: {e}") + # for filepath in all_tcl_files: + # try: + # with open(filepath, "r", encoding="utf-8") as f: + # source = f.read() + # tree = LSP_SERVER.parser.parse(source) + # tree.accept(completion, recurse=True) + # except Exception as e: + # log_to_output(f"Fehler beim Parsen von {filepath}: {e}") @LSP_SERVER.feature(lsp.TEXT_DOCUMENT_DID_SAVE) @@ -214,16 +214,6 @@ def did_close(params: lsp.DidCloseTextDocumentParams) -> None: """LSP handler for textDocument/didClose request.""" -def get_all_tcl_files(root_path: str) -> list[str]: - """Sammelt alle .tcl-Dateien rekursiv im gegebenen Verzeichnis""" - tcl_files = [] - for dirpath, _, filenames in os.walk(root_path): - for filename in filenames: - if filename.endswith(".tcl"): - tcl_files.append(os.path.join(dirpath, filename)) - return tcl_files - - @LSP_SERVER.feature(lsp.TEXT_DOCUMENT_DID_CHANGE) def did_change(params: lsp.DidChangeTextDocumentParams) -> None: """LSP handler for textDocument/didChange request""" @@ -464,6 +454,11 @@ def initialize(params: lsp.InitializeParams) -> lsp.InitializeResult: ) +@LSP_SERVER.feature(lsp.INITIALIZED) +def initialized(params: lsp.InitializedParams) -> lsp.InitializeResult: + pass + + @LSP_SERVER.feature(lsp.EXIT) def on_exit(_params: Optional[Any] = None) -> None: """Handle clean up on exit.""" diff --git a/server/src/tools/file_sourcing.py b/server/src/tools/file_sourcing.py index 5ed2bbe..1cdeab4 100644 --- a/server/src/tools/file_sourcing.py +++ b/server/src/tools/file_sourcing.py @@ -1,22 +1,23 @@ import xml.etree.ElementTree as ET from dataclasses import dataclass from typing import List, Optional +from pathlib import Path @dataclass -class SourcedFiles: +class SourcedFile: layer_name: str subfolder: Optional[str] files: List[str] -def read_psc_file(psc_file: str) -> List[SourcedFiles]: +def read_psc_file(psc_file: Path) -> List[SourcedFile]: tree = ET.parse(psc_file) root = tree.getroot() layers = root.findall(".//Layer") - layer_info_list: List[SourcedFiles] = [] + layer_info_list: List[SourcedFile] = [] for layer in layers: layer_name = layer.attrib.get("Name") subfolder = layer.attrib.get("SubFolder") @@ -30,6 +31,22 @@ def read_psc_file(psc_file: str) -> List[SourcedFiles]: script_names.append(name) layer_info_list.append( - SourcedFiles(layer_name=layer_name, subfolder=subfolder, files=script_names) + SourcedFile(layer_name=layer_name, subfolder=subfolder, files=script_names) ) return layer_info_list + + +def get_all_psc_files(root_path: Path) -> list[Path]: + """Sammelt alle .tcl-Dateien rekursiv im gegebenen Verzeichnis""" + return [path for path in root_path.rglob("*.psc")] + + +if __name__ == "__main__": + test = get_all_psc_files( + Path( + r"H:\janus-engineering-customers\KSB_Frankenthal\custom\library\machine\installed_machines\ksb_pe_grob_g550_sone\postprocessor" + ) + ) + print(test) + for pp in test: + read_psc_file(pp) diff --git a/server/src/tools/symbols.py b/server/src/tools/symbols.py index e69de29..b34f914 100644 --- a/server/src/tools/symbols.py +++ b/server/src/tools/symbols.py @@ -0,0 +1,46 @@ +import logging +from collections import defaultdict +from typing import List, DefaultDict, Union + +from tclint.syntax_tree import Visitor, Command, CommandSub, Node, Script + + +class SymbolTable: + """Holds a symbol table (links symbols to nodes).""" + + def __init__(self): + self.proc_def: DefaultDict[str, list[Node]] = defaultdict(list) + + def add_proc_definition(self, command: Command) -> None: + """Add definition of procedure""" + # command holds the "proc" keyword, so the proc name is 1st argument + proc_name_node = command.args[0] + proc_name = proc_name_node.contents + if not proc_name: + return + logging.debug( + f"Definition of proc '{proc_name}' at {proc_name_node._pos_str()}" + ) + self.proc_def[proc_name].append(proc_name_node) + + def lookup_proc_definitions(self, symbol_text: str) -> List[Node]: + """Lookup definitions of the procedure pointed at by node""" + if symbol_text is None or symbol_text not in self.proc_def: + return [] + return self.proc_def[symbol_text] + + +class SymbolTableBuilder(Visitor): + """Builds a symbol table.""" + + def __init__(self): + self.table = SymbolTable() + + def build(self, tree: Union[CommandSub, Script]) -> SymbolTable: + """Run the builder visitor through the syntax tree, building a table.""" + tree.accept(self, recurse=True) + return self.table + + def visit_command(self, command: Command) -> None: + if command.routine.contents == "proc": + self.table.add_proc_definition(command)