Skip to content

Commit

Permalink
fix: adding new files properly adds them to context
Browse files Browse the repository at this point in the history
  • Loading branch information
TheNuclearNexus committed Nov 20, 2024
1 parent d0d14ea commit 96e8676
Show file tree
Hide file tree
Showing 10 changed files with 2,338 additions and 102 deletions.
2,289 changes: 2,223 additions & 66 deletions extension/package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
"@typescript-eslint/parser": "^5.3.0",
"esbuild": "^0.24.0",
"eslint": "^8.2.0",
"npm-run-all": "^4.1.5",
"typescript": "^5.1.0",
"vsce": "^2.15.0"
},
Expand Down
25 changes: 13 additions & 12 deletions extension/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ function registerCommand(
commandIdentifier: string,
callback: () => any
) {
logger.info(commandIdentifier)
logger.info(commandIdentifier);
context.subscriptions.push(
vscode.commands.registerCommand(commandIdentifier, callback)
);
Expand Down Expand Up @@ -83,38 +83,39 @@ export async function activate(context: vscode.ExtensionContext) {
"Failed to download extension\n" + resp.statusText
);


const buffer = await resp.arrayBuffer()
const zip = await JSZip.loadAsync(buffer)
const buffer = await resp.arrayBuffer();
const zip = await JSZip.loadAsync(buffer);

let extension = undefined;
for (const file in zip.files) {
if (file.endsWith(".vsix")) {
extension = file
break
extension = file;
break;
}
}

if (extension === undefined) {
return vscode.window.showErrorMessage("Failed to find .vsix in zip")
}
return vscode.window.showErrorMessage(
"Failed to find .vsix in zip"
);
}

const filePath = path.join(context.extensionPath, "..", "update.vsix")
const filePath = path.join(context.extensionPath, "..", "update.vsix");

fs.writeFileSync(
filePath,
await zip.file(extension).async('nodebuffer')
await zip.file(extension).async("nodebuffer")
);

if (context.extensionMode == vscode.ExtensionMode.Production) {
await vscode.commands.executeCommand(
"workbench.extensions.uninstallExtension",
"thenuclearnexus.mecha-language-server"
)
);
vscode.commands.executeCommand(
"workbench.extensions.installExtension",
vscode.Uri.file(filePath)
);
);
}
});

Expand Down
18 changes: 10 additions & 8 deletions language_server/server/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
from beet import (
Context,
NamespaceFile,
PluginImportError,
Project,
ProjectConfig,
load_config,
PluginError,
locate_config,
)
from beet.library.base import LATEST_MINECRAFT_VERSION

Expand Down Expand Up @@ -85,7 +87,7 @@ def load_registry(self, minecraft_version: str):
os.remove(file_path)


def create_context(self, config: ProjectConfig, config_path: Path) -> Context:
def create_context(self, config: ProjectConfig, config_path: Path) -> LanguageServerContext:
"""Attempt to configure the project's context and run necessary plugins"""
project = Project(config, None, config_path)

Expand All @@ -95,7 +97,7 @@ def create_context(self, config: ProjectConfig, config_path: Path) -> Context:

def create_instance(
self, config_path: Path
) -> Context | None:
) -> LanguageServerContext | None:
config = load_config(config_path)
logging.debug(config)
# Ensure that we aren't loading in all project files
Expand All @@ -115,7 +117,8 @@ def create_instance(

try:
instance = self.create_context(config, config_path)

except PluginImportError as plugin_error:
logging.error(f"Plugin Import Error: {plugin_error}\n{plugin_error.__cause__}")
except PluginError as plugin_error:
logging.error(plugin_error.__cause__)
raise plugin_error.__cause__
Expand All @@ -141,14 +144,13 @@ def setup_workspaces(self):
for w in self.workspace.folders.values():
ws_path = self.uri_to_path(w.uri)

for config_type in CONFIG_TYPES:
for config_path in ws_path.glob("**/" + config_type):
config_paths.append(config_path)
logging.debug(config_path)
if config_path := locate_config(ws_path):
config_paths.append(config_path)

for config_path in config_paths:
try:
self.instances[config_path.parent] = self.create_instance(config_path)
if config := self.create_instance(config_path):
self.instances[config_path.parent] = config
except Exception as exc:
logging.error(f"Failed to load config at {config_path} due to the following\n{exc}")

Expand Down
93 changes: 79 additions & 14 deletions language_server/server/features/validate.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from dataclasses import dataclass
import logging
import os
from pathlib import Path, PurePath
import traceback
from typing import Any
from beet import Context, Function, TextFileBase
from beet import Context, DataPack, Function, PackLoadUrl, PackageablePath, TextFileBase
from beet.contrib.load import load
from bolt import CompiledModule, Module, Runtime
from lsprotocol import types as lsp
from mecha import AstChildren, AstNode, AstRoot, CompilationUnit, Mecha
Expand All @@ -12,12 +14,17 @@
from pygls.workspace import TextDocument

from language_server.server.indexing import MetaDataAttacher, index_function_ast
from language_server.server.shadows import LanguageServerContext, CompiledDocument, COMPILATION_RESULTS

from .. import (
MechaLanguageServer
from language_server.server.shadows import (
LanguageServerContext,
CompiledDocument,
COMPILATION_RESULTS,
)

from .. import MechaLanguageServer


SUPPORTED_EXTENSIONS = [Function.extension, Module.extension]


def validate(
ls: MechaLanguageServer,
Expand Down Expand Up @@ -63,7 +70,9 @@ def tokenstream_error_to_lsp_diag(
)


def get_compilation_data(ls: MechaLanguageServer, ctx: LanguageServerContext, text_doc: TextDocument):
def get_compilation_data(
ls: MechaLanguageServer, ctx: LanguageServerContext, text_doc: TextDocument
):
if text_doc.uri in COMPILATION_RESULTS:
return COMPILATION_RESULTS[text_doc.uri]

Expand All @@ -79,10 +88,12 @@ def validate_function(
path = os.path.normcase(os.path.normpath(text_doc.path))

if path not in ctx.path_to_resource:
COMPILATION_RESULTS[text_doc.uri] = CompiledDocument(
ctx, "", None, [], None, None
)
return []
if not try_to_mount_file(ctx, path):
COMPILATION_RESULTS[text_doc.uri] = CompiledDocument(
ctx, "", None, [], None, None
)
return []


location, file = ctx.path_to_resource[path]

Expand All @@ -91,20 +102,75 @@ def validate_function(
ctx, location, None, [], None, None
)
return []

# file.text = text_doc.source

# file.set_content(text_doc.source)

compiled_doc = parse_function(ctx, location, type(file)(text_doc.source, text_doc.path))
compiled_doc = parse_function(
ctx, location, type(file)(text_doc.source, text_doc.path)
)

COMPILATION_RESULTS[text_doc.uri] = compiled_doc

return compiled_doc.diagnostics


def try_to_mount_file(ctx: LanguageServerContext, file_path: str):
"""Try to mount a given file path to the context. True if the file was successfully mounted"""

_, file_extension = os.path.splitext(file_path)
logging.debug(f"\n\nTry to mount {file_path}, {file_extension}\n\n")
if not file_extension in SUPPORTED_EXTENSIONS:
return False

load_options = ctx.project_config.data_pack.load
prefix = None
for entry in load_options.entries():
# File can't be relative to a url
if isinstance(entry, PackLoadUrl):
continue

if isinstance(entry, dict):
for key, paths in entry.items():
for path in paths.entries():
logging.debug(f"\n\n{path}")
# File can't be relative to a url
if isinstance(path, PackLoadUrl):
continue

if PurePath(file_path).is_relative_to(path):
logging.debug('was relative too')
relative = PurePath(file_path).relative_to(path)
prefix = str(key / relative)
break
elif PurePath(file_path).is_relative_to(entry):
prefix = str(entry)

if prefix == None:
return False

try:
temp = DataPack()
temp.mount(prefix, file_path)
for [location, file] in temp.all():
if not (isinstance(file, Function) or isinstance(file, Module)):
continue

path = os.path.normpath(file.ensure_source_path())
path = os.path.normcase(path)
ctx.path_to_resource[path] = (location, file)
ctx.data[type(file)][location] = file

return True
except Exception as exc:
logging.error(f"Failed to mount {path}, reloading datapack,\n{exc}")

return False


def parse_function(
ctx: Context, location: str, function: Function | Module
ctx: LanguageServerContext, location: str, function: Function | Module
) -> CompiledDocument:
mecha = ctx.inject(Mecha)

Expand Down Expand Up @@ -133,7 +199,6 @@ def parse_function(
except Exception as exec:
logging.error(f"{type(exec)}: {exec}")


ast = index_function_ast(ast, location)
for node in ast.walk():
if isinstance(node, AstError):
Expand Down
4 changes: 4 additions & 0 deletions language_server/server/shadows.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
NamespaceFile,
PluginSpec,
ProjectBuilder,
ProjectConfig,
Task,
PluginError,
Pipeline,
Expand Down Expand Up @@ -68,9 +69,11 @@ def require(self, *args: GenericPlugin[Context] | str):
@dataclass(frozen=True)
class LanguageServerContext(Context):
show_message: Callable[[Any, lsp.MessageType], None] = required_field()
project_config: ProjectConfig = required_field()

path_to_resource: dict[str, tuple[str, NamespaceFile]] = extra_field(default_factory=dict)


def require(self, *args: PluginSpec):
"""Execute the specified plugin."""
for arg in args:
Expand Down Expand Up @@ -123,6 +126,7 @@ def initialize(self, show_message: Callable[[Any, lsp.MessageType], None]) -> La

ctx = LanguageServerContext(
show_message=show_message,
project_config=self.config,
project_id=self.config.id or normalize_string(name),
project_name=name,
project_description=self.config.description,
Expand Down
4 changes: 3 additions & 1 deletion tests/beet.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ require:
- bolt_expressions

data_pack:
load: .
load:
- .
- data/test/functions: foo

meta:
bolt:
Expand Down
3 changes: 2 additions & 1 deletion tests/data/test/modules/macros.bolt
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ function ./foo/baz:
pass

function ~/baz2:
pass
pass

1 change: 1 addition & 0 deletions tests/foo/bar.mcfunction
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

2 changes: 2 additions & 0 deletions tests/foo/baz3.mcfunction
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
say baa
say ssa

0 comments on commit 96e8676

Please sign in to comment.