Skip to content

Commit

Permalink
fix(language_server): error when getting compilation data from unknow…
Browse files Browse the repository at this point in the history
…n function, plugin execution errors caused server to fail to start
  • Loading branch information
TheNuclearNexus committed Jan 31, 2025
1 parent bec834e commit 184ac8f
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 24 deletions.
33 changes: 23 additions & 10 deletions language_server/server/features/completion.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
import inspect
import logging
import types
from typing import Any
from typing import Any, cast

from beet import File, NamespaceFile
from bolt import AstAttribute, AstIdentifier, Runtime, UndefinedIdentifier, Variable
from lsprotocol import types as lsp
from mecha import (
Expand Down Expand Up @@ -107,7 +108,9 @@ def get_completions(
text_doc: TextDocument,
) -> list[lsp.CompletionItem]:
mecha = ctx.inject(Mecha)
compiled_doc = get_compilation_data(ls, ctx, text_doc)

if not (compiled_doc := get_compilation_data(ls, ctx, text_doc)):
return []

ast = compiled_doc.ast
diagnostics = compiled_doc.diagnostics
Expand All @@ -118,14 +121,24 @@ def get_completions(
elif ast is not None:
current_node = get_node_at_position(ast, pos)

if isinstance(current_node, AstResourceLocation):
represents = current_node.__dict__.get("represents")
# logging.debug(GAME_REGISTRIES)
if represents is not None:
add_registry_items(items, represents)
add_registry_items(
items, "tag/" + represents, "#", lsp.CompletionItemKind.Constant
)
# if isinstance(current_node, AstResourceLocation):
# resolved_path = current_node.__dict__.get("resolved_path")
# represents = current_node.__dict__.get("represents")
# # logging.debug(GAME_REGISTRIES)
# if represents and issubclass(represents, File):
# file_type = cast(type[NamespaceFile], represents)
# for pack in ctx.packs:
# if file_type not in pack:
# continue
# logging.debug(ctx.data[file_type])
# for path in pack[file_type]:
# items.append(lsp.CompletionItem(label=path))

# elif isinstance(represents, str):
# add_registry_items(items, represents)
# add_registry_items(
# items, "tag/" + represents, "#", lsp.CompletionItemKind.Constant
# )

if isinstance(current_node, AstItemSlot):
items.extend(
Expand Down
11 changes: 6 additions & 5 deletions language_server/server/features/semantics.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,8 @@ def command(self, node: AstCommand):
else:
return

logging.debug(f"semantic token for {node}")
temp_node = AstNode(location=node.location, end_location=end_location)
logging.debug(f"{temp_node.location} {temp_node.end_location}")

self.nodes.append(
(
temp_node,
Expand Down Expand Up @@ -358,9 +357,11 @@ def semantic_tokens(ls: MechaLanguageServer, params: lsp.SemanticTokensParams):
if ctx is None:
data = []
else:
compiled_doc = get_compilation_data(ls, ctx, text_doc)
ast = compiled_doc.ast
if compiled_doc := get_compilation_data(ls, ctx, text_doc):
ast = compiled_doc.ast

data = SemanticTokenCollector(ctx=ctx).walk(ast) if ast else []
data = SemanticTokenCollector(ctx=ctx).walk(ast) if ast else []
else:
data = []

return lsp.SemanticTokens(data=data)
16 changes: 12 additions & 4 deletions language_server/server/features/validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,20 @@ def tokenstream_error_to_lsp_diag(
def get_compilation_data(
ls: MechaLanguageServer, ctx: LanguageServerContext, text_doc: TextDocument
):
location = ctx.path_to_resource[text_doc.path][0]
if location in COMPILATION_RESULTS:
return COMPILATION_RESULTS[location]
resource = ctx.path_to_resource.get(text_doc.path)

if resource and resource[0] in COMPILATION_RESULTS:
return COMPILATION_RESULTS[resource[0]]

validate_function(ls, ctx, text_doc)

resource = resource or ctx.path_to_resource.get(text_doc.path)

if resource is None:
return None

# logging.debug(COMPILATION_RESULTS)
return COMPILATION_RESULTS[location]
return COMPILATION_RESULTS[resource[0]]


def validate_function(
Expand Down Expand Up @@ -204,6 +211,7 @@ def parse_function(

dependents = set()


compiled_module = None
runtime = ctx.inject(Runtime)
if location in COMPILATION_RESULTS:
Expand Down
16 changes: 11 additions & 5 deletions language_server/server/shadows.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,16 @@ def require(self, *args: GenericPlugin[Context] | str):

self.plugins.add(plugin)

# Advance the plugin only once, ignore remaining work
# Most setup happens in the first half of the plugin
# where side effects happen in the latter
Task(plugin).advance(self.ctx)
try:
# Advance the plugin only once, ignore remaining work
# Most setup happens in the first half of the plugin
# where side effects happen in the latter
Task(plugin).advance(self.ctx)
except Exception as exc:
ls = cast(LanguageServerContext, self.ctx).ls
message = f"An issue occured while running first step of plugin: {plugin}\n{exc}"
ls.show_message(message.split("\n")[0], lsp.MessageType.Warning)
ls.show_message_log(message, lsp.MessageType.Warning)


# We use this shadow of context in order to route calls to `ctx`
Expand Down Expand Up @@ -122,7 +128,7 @@ def bootstrap(self, ctx: Context):
for plugin in plugins:
if plugin in excluded_plugins:
continue

ctx.require(plugin)

# This stripped down version of build only handles loading the plugins from config
Expand Down

0 comments on commit 184ac8f

Please sign in to comment.