Merge pull request 'update' (#25) from tcl_language_support into main
/ build_and_publish (release) Successful in 33s
/ build_and_publish (release) Successful in 33s
Reviewed-on: #25
This commit was merged in pull request #25.
This commit is contained in:
@@ -79,7 +79,8 @@ export async function getWorkspaceSettings(
|
||||
interpreter: resolveVariables(interpreter, workspace),
|
||||
importStrategy: config.get<string>(`importStrategy`) ?? "useBundled",
|
||||
showNotifications: config.get<string>(`showNotifications`) ?? "off",
|
||||
formatter: config.get<boolean>(`formatter`) ?? true
|
||||
formatter: config.get<boolean>(`formatter`) ?? true,
|
||||
inlayHint: config.get<boolean>(`inlayHint`) ?? true
|
||||
}
|
||||
return workspaceSetting
|
||||
}
|
||||
@@ -111,7 +112,8 @@ export async function getGlobalSettings(
|
||||
interpreter: interpreter,
|
||||
importStrategy: getGlobalValue<string>(config, "importStrategy", "useBundled"),
|
||||
showNotifications: getGlobalValue<string>(config, "showNotifications", "off"),
|
||||
formatter: config.get<boolean>(`formatter`) ?? true
|
||||
formatter: config.get<boolean>(`formatter`) ?? true,
|
||||
inlayHint: config.get<boolean>(`inlayHint`) ?? true
|
||||
}
|
||||
return setting
|
||||
}
|
||||
@@ -126,7 +128,8 @@ export function checkIfConfigurationChanged(
|
||||
`${namespace}.interpreter`,
|
||||
`${namespace}.importStrategy`,
|
||||
`${namespace}.showNotifications`,
|
||||
`${namespace}.formatter`
|
||||
`${namespace}.formatter`,
|
||||
`${namespace}.inlayHint`
|
||||
]
|
||||
const changed = settings.map((s) => e.affectsConfiguration(s))
|
||||
return changed.includes(true)
|
||||
|
||||
+6
-1
@@ -85,6 +85,11 @@
|
||||
"default": false,
|
||||
"description": "Use the TCL formatter from `NX Postprocessor Support`"
|
||||
},
|
||||
"nx-post-support.inlayHint": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Use the Inlay Hints in from `NX Postprocessor Support`"
|
||||
},
|
||||
"nx-post-support.importStrategy": {
|
||||
"default": "useBundled",
|
||||
"description": "Defines where `NX Postprocessor Support` is imported from.",
|
||||
@@ -124,4 +129,4 @@
|
||||
"prettier": "^3.4.2",
|
||||
"typescript": "^5.7.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -71,6 +71,10 @@
|
||||
{
|
||||
"label": "expr",
|
||||
"kind": "keyword"
|
||||
},
|
||||
{
|
||||
"label": "return",
|
||||
"kind": "keyword"
|
||||
}
|
||||
],
|
||||
"MOM_procs": [
|
||||
|
||||
+7
-112
@@ -38,123 +38,13 @@ update_sys_path(
|
||||
# pylint: disable=wrong-import-position,import-error
|
||||
import lsp_jsonrpc as jsonrpc
|
||||
import lsprotocol.types as lsp
|
||||
from pygls import server, uris, workspace
|
||||
from pygls.workspace.text_document import TextDocument
|
||||
from pygls import uris, workspace
|
||||
from common.load_data import standard_items
|
||||
from tclint.lexer import TclSyntaxError
|
||||
from tclint.format import Formatter, FormatterOpts
|
||||
from tclint.violations import Violation
|
||||
from plugins.poco_plugin import commands
|
||||
from tools import checks, parser
|
||||
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
|
||||
from tools.file_sourcing import get_all_psc_files, read_psc_file
|
||||
|
||||
DIAGNOSTIC_SOURCE = "nx-post-support"
|
||||
|
||||
|
||||
class TclLanguageServer(server.LanguageServer):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.parser = parser.CustomParser()
|
||||
for command in commands:
|
||||
self.parser._commands.update(command)
|
||||
self.diagnostics = {}
|
||||
self.poco_completion: dict = {}
|
||||
self.proc_signatures: dict = {}
|
||||
|
||||
def format(
|
||||
self,
|
||||
document: TextDocument,
|
||||
options: lsp.FormattingOptions,
|
||||
range: Optional[Tuple[int, int]] = None,
|
||||
):
|
||||
# parser = Parser(command_plugins=["nx_plugins.poco_plugin.py"])
|
||||
# parser._commands.update(commands)
|
||||
|
||||
indent = "\t" if not options.insert_spaces else " " * options.tab_size
|
||||
formatter = Formatter(
|
||||
FormatterOpts(
|
||||
indent=indent,
|
||||
spaces_in_braces=False,
|
||||
max_blank_lines=500,
|
||||
indent_namespace_eval=True,
|
||||
),
|
||||
)
|
||||
|
||||
if range is not None:
|
||||
start, end = range
|
||||
return formatter.format_partial(document.source[start:end], self.parser)
|
||||
|
||||
return formatter.format_top(document.source, self.parser)
|
||||
|
||||
def linter(
|
||||
self,
|
||||
document: TextDocument,
|
||||
) -> List[Violation]:
|
||||
violations = []
|
||||
self.parser.violations = []
|
||||
tree = self.parser.parse(document.source)
|
||||
violations += self.parser.violations
|
||||
# log_to_output(tree.pretty(2))
|
||||
for checker in checks.get_checkers():
|
||||
violations += checker.check(document.source, tree)
|
||||
return violations
|
||||
|
||||
def lint(self, document: TextDocument):
|
||||
diagnostics = []
|
||||
|
||||
try:
|
||||
violations = self.linter(document)
|
||||
except TclSyntaxError as e:
|
||||
return [
|
||||
lsp.Diagnostic(
|
||||
message=str(e),
|
||||
severity=lsp.DiagnosticSeverity.Error,
|
||||
range=lsp.Range(
|
||||
start=lsp.Position(e.start[0] - 1, e.start[1] - 1),
|
||||
end=lsp.Position(e.end[0] - 1, e.end[1] - 1),
|
||||
),
|
||||
code="syntax error",
|
||||
source=DIAGNOSTIC_SOURCE,
|
||||
)
|
||||
]
|
||||
|
||||
for violation in violations:
|
||||
message = violation.message
|
||||
severity = lsp.DiagnosticSeverity.Warning
|
||||
start = lsp.Position(line=violation.start[0] - 1, character=violation.start[1] - 1)
|
||||
end = lsp.Position(line=violation.end[0] - 1, character=violation.end[1] - 1)
|
||||
|
||||
diagnostics.append(
|
||||
lsp.Diagnostic(
|
||||
message=message,
|
||||
severity=severity,
|
||||
range=lsp.Range(
|
||||
start=start,
|
||||
end=end,
|
||||
),
|
||||
code=violation.id,
|
||||
source=DIAGNOSTIC_SOURCE,
|
||||
)
|
||||
)
|
||||
|
||||
return diagnostics
|
||||
|
||||
def _compute_diagnostics(self, document: TextDocument) -> List[lsp.Diagnostic]:
|
||||
return self.lint(document)
|
||||
|
||||
def compute_diagnostics(self, document: TextDocument):
|
||||
# `None` sentinel ensures that `diagnostics` gets updated if the URI is not
|
||||
# present.
|
||||
_, previous = self.diagnostics.get(document, (0, None))
|
||||
|
||||
diagnostics = self._compute_diagnostics(document)
|
||||
|
||||
# Only update if the list has changed
|
||||
if previous != diagnostics:
|
||||
self.diagnostics[document.uri] = (document.version, diagnostics)
|
||||
from lsp_tclserver import TclLanguageServer
|
||||
|
||||
|
||||
WORKSPACE_SETTINGS = {}
|
||||
@@ -204,6 +94,7 @@ def did_change(params: lsp.DidChangeTextDocumentParams) -> None:
|
||||
"""LSP handler for textDocument/didChange request"""
|
||||
document = LSP_SERVER.workspace.get_text_document(params.text_document.uri)
|
||||
LSP_SERVER.compute_diagnostics(document)
|
||||
LSP_SERVER.update_poco_completion_for_file(document)
|
||||
|
||||
|
||||
@LSP_SERVER.feature(
|
||||
@@ -253,6 +144,9 @@ def on_completion(params: lsp.CompletionParams) -> list[lsp.CompletionItem]:
|
||||
|
||||
@LSP_SERVER.feature(lsp.TEXT_DOCUMENT_INLAY_HINT)
|
||||
def inlay_hints(params: lsp.InlayHintParams):
|
||||
log_to_output(str(GLOBAL_SETTINGS.get("inlayHint", False)))
|
||||
if not GLOBAL_SETTINGS.get("inlayHint", False):
|
||||
return []
|
||||
document = LSP_SERVER.workspace.get_text_document(params.text_document.uri)
|
||||
tree = LSP_SERVER.parser.parse(document.source)
|
||||
|
||||
@@ -474,6 +368,7 @@ def _get_global_defaults():
|
||||
"importStrategy": GLOBAL_SETTINGS.get("importStrategy", "useBundled"),
|
||||
"showNotifications": GLOBAL_SETTINGS.get("showNotifications", "off"),
|
||||
"formatter": GLOBAL_SETTINGS.get("formatter", True),
|
||||
"inlayHint": GLOBAL_SETTINGS.get("inlayHint", True),
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
import logging
|
||||
import pathlib
|
||||
from typing import List, Optional, Tuple
|
||||
import lsprotocol.types as lsp
|
||||
from pygls.workspace.text_document import TextDocument
|
||||
from tclint.lexer import TclSyntaxError
|
||||
from tclint.format import Formatter, FormatterOpts
|
||||
from tclint.violations import Violation
|
||||
from plugins.poco_plugin import commands
|
||||
from tools import checks, parser
|
||||
from pygls import server, uris
|
||||
from tools.completion_items import completion, remove_existing_items, remove_shared_keys
|
||||
|
||||
|
||||
DIAGNOSTIC_SOURCE = "nx-post-support"
|
||||
|
||||
|
||||
class TclLanguageServer(server.LanguageServer):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.parser = parser.CustomParser()
|
||||
for command in commands:
|
||||
self.parser._commands.update(command)
|
||||
self.diagnostics = {}
|
||||
self.poco_completion: dict = {}
|
||||
self.proc_signatures: dict = {}
|
||||
|
||||
def update_poco_completion_for_file(self, document: TextDocument):
|
||||
"""Update poco_completion for a specific file when it changes"""
|
||||
filepath = str(pathlib.Path(uris.to_fs_path(document.uri)))
|
||||
|
||||
# Remove existing completion items for this file
|
||||
if filepath in self.poco_completion:
|
||||
del self.poco_completion[filepath]
|
||||
if filepath in self.proc_signatures:
|
||||
del self.proc_signatures[filepath]
|
||||
|
||||
# Parse and extract new completion items
|
||||
completion.reset()
|
||||
try:
|
||||
tree = self.parser.parse(document.source)
|
||||
tree.accept(completion, recurse=True)
|
||||
remove_existing_items(completion.custom_functions, self.poco_completion)
|
||||
self.poco_completion[filepath] = completion.custom_functions
|
||||
remove_shared_keys(self.proc_signatures, completion.proc_signatures)
|
||||
self.proc_signatures[filepath] = completion.proc_signatures
|
||||
except Exception as e:
|
||||
logging.debug(f"Error parsing {filepath}: {e}")
|
||||
|
||||
def format(
|
||||
self,
|
||||
document: TextDocument,
|
||||
options: lsp.FormattingOptions,
|
||||
range: Optional[Tuple[int, int]] = None,
|
||||
):
|
||||
# parser = Parser(command_plugins=["nx_plugins.poco_plugin.py"])
|
||||
# parser._commands.update(commands)
|
||||
|
||||
indent = "\t" if not options.insert_spaces else " " * options.tab_size
|
||||
formatter = Formatter(
|
||||
FormatterOpts(
|
||||
indent=indent,
|
||||
spaces_in_braces=False,
|
||||
max_blank_lines=500,
|
||||
indent_namespace_eval=True,
|
||||
),
|
||||
)
|
||||
|
||||
if range is not None:
|
||||
start, end = range
|
||||
return formatter.format_partial(document.source[start:end], self.parser)
|
||||
|
||||
return formatter.format_top(document.source, self.parser)
|
||||
|
||||
def linter(
|
||||
self,
|
||||
document: TextDocument,
|
||||
) -> List[Violation]:
|
||||
violations = []
|
||||
self.parser.violations = []
|
||||
tree = self.parser.parse(document.source)
|
||||
violations += self.parser.violations
|
||||
for checker in checks.get_checkers():
|
||||
violations += checker.check(document.source, tree)
|
||||
return violations
|
||||
|
||||
def lint(self, document: TextDocument):
|
||||
diagnostics = []
|
||||
|
||||
try:
|
||||
violations = self.linter(document)
|
||||
except TclSyntaxError as e:
|
||||
return [
|
||||
lsp.Diagnostic(
|
||||
message=str(e),
|
||||
severity=lsp.DiagnosticSeverity.Error,
|
||||
range=lsp.Range(
|
||||
start=lsp.Position(e.start[0] - 1, e.start[1] - 1),
|
||||
end=lsp.Position(e.end[0] - 1, e.end[1] - 1),
|
||||
),
|
||||
code="syntax error",
|
||||
source=DIAGNOSTIC_SOURCE,
|
||||
)
|
||||
]
|
||||
|
||||
for violation in violations:
|
||||
message = violation.message
|
||||
severity = lsp.DiagnosticSeverity.Warning
|
||||
start = lsp.Position(line=violation.start[0] - 1, character=violation.start[1] - 1)
|
||||
end = lsp.Position(line=violation.end[0] - 1, character=violation.end[1] - 1)
|
||||
|
||||
diagnostics.append(
|
||||
lsp.Diagnostic(
|
||||
message=message,
|
||||
severity=severity,
|
||||
range=lsp.Range(
|
||||
start=start,
|
||||
end=end,
|
||||
),
|
||||
code=violation.id,
|
||||
source=DIAGNOSTIC_SOURCE,
|
||||
)
|
||||
)
|
||||
|
||||
return diagnostics
|
||||
|
||||
def _compute_diagnostics(self, document: TextDocument) -> List[lsp.Diagnostic]:
|
||||
return self.lint(document)
|
||||
|
||||
def compute_diagnostics(self, document: TextDocument):
|
||||
# `None` sentinel ensures that `diagnostics` gets updated if the URI is not
|
||||
# present.
|
||||
_, previous = self.diagnostics.get(document, (0, None))
|
||||
|
||||
diagnostics = self._compute_diagnostics(document)
|
||||
|
||||
# Only update if the list has changed
|
||||
if previous != diagnostics:
|
||||
self.diagnostics[document.uri] = (document.version, diagnostics)
|
||||
Reference in New Issue
Block a user