@razdolbai/merls 1.2.2 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/AGENTS.md +64 -64
  2. package/dist/src/lsp/completion.js +14 -11
  3. package/dist/test/completion.test.js +1 -1
  4. package/dist/test/definition-references.test.js +1 -1
  5. package/dist/test/diagnostics.test.js +2 -2
  6. package/dist/test/document-symbol.test.js +1 -1
  7. package/dist/test/fixture-corpus.test.js +4 -4
  8. package/dist/test/hover.test.js +1 -1
  9. package/dist/test/lexer.test.js +4 -4
  10. package/dist/test/local-labels.test.js +1 -1
  11. package/dist/test/publish-diagnostics.test.js +1 -1
  12. package/dist/test/semantic-tokens.test.js +1 -1
  13. package/dist/test/symbols.test.js +1 -1
  14. package/dist/test/workspace-symbol.test.js +2 -2
  15. package/dist/test/workspace.test.js +2 -2
  16. package/package.json +1 -1
  17. package/src/lsp/completion.ts +15 -11
  18. package/test/completion.test.ts +151 -151
  19. package/test/definition-references.test.ts +152 -152
  20. package/test/diagnostics.test.ts +129 -129
  21. package/test/document-symbol.test.ts +131 -131
  22. package/test/fixture-corpus.test.ts +33 -33
  23. package/test/fixtures/valid/{merlin32-linkscript.asm → merlin32-linkscript.S} +16 -16
  24. package/test/hover.test.ts +175 -175
  25. package/test/lexer.test.ts +87 -87
  26. package/test/local-labels.test.ts +47 -47
  27. package/test/publish-diagnostics.test.ts +206 -206
  28. package/test/semantic-tokens.test.ts +128 -128
  29. package/test/smoke/run-smoke.ps1 +177 -177
  30. package/test/symbols.test.ts +41 -41
  31. package/test/workspace-symbol.test.ts +139 -139
  32. package/test/workspace.test.ts +29 -29
  33. /package/test/fixtures/invalid/{65816-bank-ops.asm → 65816-bank-ops.S} +0 -0
  34. /package/test/fixtures/invalid/{65816-long-addressing.asm → 65816-long-addressing.S} +0 -0
  35. /package/test/fixtures/valid/{merlin32-main-6502.asm → merlin32-main-6502.S} +0 -0
  36. /package/test/fixtures/valid/{smoke-test.asm → smoke-test.S} +0 -0
package/AGENTS.md CHANGED
@@ -1,64 +1,64 @@
1
- # Repository Guidelines
2
-
3
- ## Project Structure & Module Organization
4
-
5
- This repository has an established baseline. The main document is `README.md` for scope. The runtime is Node.js with TypeScript and `vscode-languageserver`.
6
-
7
- When the workspace is scaffolded, keep code under `src/`, tests under `test/`, and editor integration examples under `examples/` such as `examples/coc-settings.json`. Store parser fixtures in a dedicated test-fixture area and separate valid 6502 cases from invalid 65816 cases.
8
-
9
- The current bootstrap server entrypoint is `src/server.ts`, and the packaged CLI entrypoint is `src/cli.ts`, which compiles to `dist/src/cli.js`.
10
- The repository now includes `examples/coc-settings.json` as the baseline coc.nvim launch example, targeting `dist/src/cli.js --stdio` with `.git` and `package.json` root markers.
11
- The initial positive fixture corpus now lives under `test/fixtures/valid/` and is transcribed from upstream Merlin32 sources.
12
- The initial negative fixture corpus now lives under `test/fixtures/invalid/` and captures unsupported 65816-only syntax.
13
- Shared 6502 opcode and Merlin directive metadata now lives under `src/asm/metadata.ts`.
14
- Shared token-kind and line-shape metadata now lives under `src/asm/syntax.ts`.
15
- The current lexer implementation now lives under `src/asm/lexer.ts` and is covered by fixture-driven unit tests.
16
- The current expression parser now lives under `src/asm/expression.ts` and is covered by unit tests for numeric forms, modifiers, arithmetic, and indexed operands.
17
- The current line parser now lives under `src/asm/parser.ts` and classifies equates, instructions, directives, data lines, and malformed input.
18
- The current document model now lives under `src/asm/document.ts` and preserves line-by-line structure while collecting malformed-line errors.
19
- The current symbol collector now lives under `src/asm/symbols.ts` and indexes labels, equates, and named storage/data definitions.
20
- The current local-label resolver now lives under `src/asm/local-labels.ts` and resolves Merlin `]local` and `:local` labels within the nearest global-label scope.
21
- The current workspace indexer now lives under `src/asm/workspace.ts` and follows `asm`/`put`/`use` directives across the local fixture corpus.
22
- The current diagnostics pass now lives under `src/asm/diagnostics.ts` and reports duplicate symbols, unresolved references, malformed lines, and unsupported 65816-only syntax.
23
- The current `textDocument/documentSymbol` provider is wired through `src/server.ts` and `src/lsp/document-symbols.ts`.
24
- The current `workspace/symbol` provider is wired through `src/server.ts` and `src/lsp/workspace-symbols.ts` over the open-document symbol set.
25
- The current `textDocument/definition` and `textDocument/references` handlers are wired through `src/server.ts` and `src/lsp/symbol-navigation.ts`.
26
- The current `textDocument/hover` handler is wired through `src/server.ts` and `src/lsp/hover.ts`.
27
- The current `textDocument/completion` handler is wired through `src/server.ts` and `src/lsp/completion.ts`.
28
- The current `textDocument/semanticTokens` handler is wired through `src/server.ts` and `src/lsp/semantic-tokens.ts`.
29
- The current `textDocument/publishDiagnostics` path is wired through `src/server.ts` and `src/lsp/diagnostics.ts`, with full-document sync on open/change so editor clients receive live parser and resolver diagnostics.
30
- The current packaged CLI entrypoint lives under `src/cli.ts` and is covered by a compiled stdio launch-contract integration test.
31
- The coc.nvim smoke test now lives under `test/smoke/` with a headless Vim runner (`run-smoke.ps1`) and a minimal vimrc that isolates the test from the user's real Vim configuration.
32
-
33
- ## Build, Test, and Development Commands
34
-
35
- The repository now includes the initial Node/TypeScript workspace scaffold:
36
-
37
- - `npm install`: install project dependencies.
38
- - `npm run build`: compile TypeScript sources to `dist/`.
39
- - `npm test`: build the project and run the current test suite.
40
- - `npm run dev`: run the TypeScript compiler in watch mode during bootstrap work.
41
-
42
- The supported stdio launch contract is now `merls --stdio`, with `node dist/src/cli.js --stdio` as the equivalent local-development invocation.
43
-
44
- ## Coding Style & Naming Conventions
45
-
46
- Use TypeScript throughout the implementation. Prefer small modules with explicit types and single-purpose exports. Use `camelCase` for variables and functions, `PascalCase` for types and classes, and kebab-case for example/config file names.
47
-
48
- Keep parser, symbol, and LSP layers separate. Name tests and fixtures after the behavior they cover, for example `parser.labels.test.ts` or `fixtures/invalid/65816-long-a.asm`.
49
-
50
- ## Testing Guidelines
51
-
52
- TDD is mandatory in this repository: add or extend a failing test or fixture before implementation. Positive fixtures must cover supported Merlin-style 6502 syntax. Negative fixtures must explicitly cover unsupported 65816 syntax and expected diagnostics.
53
-
54
- Prefer focused unit tests for lexer/parser behavior and integration tests for LSP requests such as `initialize`, hover, and definition.
55
-
56
- The current bootstrap test suite already includes compiled-stdio integration checks for the packaged CLI contract, `initialize`, and diagnostics publication.
57
-
58
- ## Commit & Pull Request Guidelines
59
-
60
- This workspace does not currently include accessible git history, so no local commit convention can be inferred from prior commits. Use short, imperative commit subjects such as `Add lexer token fixtures`.
61
-
62
- Task completion includes documentation maintenance. When a change affects repository behavior, structure, workflow, or contributor expectations, update both `README.md` and `AGENTS.md` in the same task.
63
-
64
- PRs should describe the user-visible behavior change, list the tests added or updated, and include sample diagnostics or editor screenshots when LSP behavior changes. Keep PRs scoped to one phase task or one coherent feature.
1
+ # Repository Guidelines
2
+
3
+ ## Project Structure & Module Organization
4
+
5
+ This repository has an established baseline. The main document is `README.md` for scope. The runtime is Node.js with TypeScript and `vscode-languageserver`.
6
+
7
+ When the workspace is scaffolded, keep code under `src/`, tests under `test/`, and editor integration examples under `examples/` such as `examples/coc-settings.json`. Store parser fixtures in a dedicated test-fixture area and separate valid 6502 cases from invalid 65816 cases.
8
+
9
+ The current bootstrap server entrypoint is `src/server.ts`, and the packaged CLI entrypoint is `src/cli.ts`, which compiles to `dist/src/cli.js`.
10
+ The repository now includes `examples/coc-settings.json` as the baseline coc.nvim launch example, targeting `dist/src/cli.js --stdio` with `.git` and `package.json` root markers.
11
+ The initial positive fixture corpus now lives under `test/fixtures/valid/` and is transcribed from upstream Merlin32 sources.
12
+ The initial negative fixture corpus now lives under `test/fixtures/invalid/` and captures unsupported 65816-only syntax.
13
+ Shared 6502 opcode and Merlin directive metadata now lives under `src/asm/metadata.ts`.
14
+ Shared token-kind and line-shape metadata now lives under `src/asm/syntax.ts`.
15
+ The current lexer implementation now lives under `src/asm/lexer.ts` and is covered by fixture-driven unit tests.
16
+ The current expression parser now lives under `src/asm/expression.ts` and is covered by unit tests for numeric forms, modifiers, arithmetic, and indexed operands.
17
+ The current line parser now lives under `src/asm/parser.ts` and classifies equates, instructions, directives, data lines, and malformed input.
18
+ The current document model now lives under `src/asm/document.ts` and preserves line-by-line structure while collecting malformed-line errors.
19
+ The current symbol collector now lives under `src/asm/symbols.ts` and indexes labels, equates, and named storage/data definitions.
20
+ The current local-label resolver now lives under `src/asm/local-labels.ts` and resolves Merlin `]local` and `:local` labels within the nearest global-label scope.
21
+ The current workspace indexer now lives under `src/asm/workspace.ts` and follows `asm`/`put`/`use` directives across the local fixture corpus.
22
+ The current diagnostics pass now lives under `src/asm/diagnostics.ts` and reports duplicate symbols, unresolved references, malformed lines, and unsupported 65816-only syntax.
23
+ The current `textDocument/documentSymbol` provider is wired through `src/server.ts` and `src/lsp/document-symbols.ts`.
24
+ The current `workspace/symbol` provider is wired through `src/server.ts` and `src/lsp/workspace-symbols.ts` over the open-document symbol set.
25
+ The current `textDocument/definition` and `textDocument/references` handlers are wired through `src/server.ts` and `src/lsp/symbol-navigation.ts`.
26
+ The current `textDocument/hover` handler is wired through `src/server.ts` and `src/lsp/hover.ts`.
27
+ The current `textDocument/completion` handler is wired through `src/server.ts` and `src/lsp/completion.ts`.
28
+ The current `textDocument/semanticTokens` handler is wired through `src/server.ts` and `src/lsp/semantic-tokens.ts`.
29
+ The current `textDocument/publishDiagnostics` path is wired through `src/server.ts` and `src/lsp/diagnostics.ts`, with full-document sync on open/change so editor clients receive live parser and resolver diagnostics.
30
+ The current packaged CLI entrypoint lives under `src/cli.ts` and is covered by a compiled stdio launch-contract integration test.
31
+ The coc.nvim smoke test now lives under `test/smoke/` with a headless Vim runner (`run-smoke.ps1`) and a minimal vimrc that isolates the test from the user's real Vim configuration.
32
+
33
+ ## Build, Test, and Development Commands
34
+
35
+ The repository now includes the initial Node/TypeScript workspace scaffold:
36
+
37
+ - `npm install`: install project dependencies.
38
+ - `npm run build`: compile TypeScript sources to `dist/`.
39
+ - `npm test`: build the project and run the current test suite.
40
+ - `npm run dev`: run the TypeScript compiler in watch mode during bootstrap work.
41
+
42
+ The supported stdio launch contract is now `merls --stdio`, with `node dist/src/cli.js --stdio` as the equivalent local-development invocation.
43
+
44
+ ## Coding Style & Naming Conventions
45
+
46
+ Use TypeScript throughout the implementation. Prefer small modules with explicit types and single-purpose exports. Use `camelCase` for variables and functions, `PascalCase` for types and classes, and kebab-case for example/config file names.
47
+
48
+ Keep parser, symbol, and LSP layers separate. Name tests and fixtures after the behavior they cover, for example `parser.labels.test.ts` or `fixtures/invalid/65816-long-a.S`.
49
+
50
+ ## Testing Guidelines
51
+
52
+ TDD is mandatory in this repository: add or extend a failing test or fixture before implementation. Positive fixtures must cover supported Merlin-style 6502 syntax. Negative fixtures must explicitly cover unsupported 65816 syntax and expected diagnostics.
53
+
54
+ Prefer focused unit tests for lexer/parser behavior and integration tests for LSP requests such as `initialize`, hover, and definition.
55
+
56
+ The current bootstrap test suite already includes compiled-stdio integration checks for the packaged CLI contract, `initialize`, and diagnostics publication.
57
+
58
+ ## Commit & Pull Request Guidelines
59
+
60
+ This workspace does not currently include accessible git history, so no local commit convention can be inferred from prior commits. Use short, imperative commit subjects such as `Add lexer token fixtures`.
61
+
62
+ Task completion includes documentation maintenance. When a change affects repository behavior, structure, workflow, or contributor expectations, update both `README.md` and `AGENTS.md` in the same task.
63
+
64
+ PRs should describe the user-visible behavior change, list the tests added or updated, and include sample diagnostics or editor screenshots when LSP behavior changes. Keep PRs scoped to one phase task or one coherent feature.
@@ -11,22 +11,25 @@ function buildCompletionItems(openDocuments, uri, line) {
11
11
  return [];
12
12
  }
13
13
  const document = (0, document_1.parseDocument)(source);
14
- const text = document.lines[line]?.node.text.trimStart().toLowerCase() ?? "";
15
- if (text === "ld" || text === "ld\n" || text.startsWith("ld")) {
16
- return metadata_1.opcodeDefinitions.map((opcode) => ({
14
+ const completions = [];
15
+ for (const opcode of metadata_1.opcodeDefinitions) {
16
+ completions.push({
17
17
  label: opcode.mnemonic,
18
18
  kind: node_1.CompletionItemKind.Keyword
19
- }));
19
+ });
20
20
  }
21
- if (text === "du" || text.startsWith("du")) {
22
- return metadata_1.directiveDefinitions.map((directive) => ({
21
+ for (const directive of metadata_1.directiveDefinitions) {
22
+ completions.push({
23
23
  label: directive.name,
24
24
  kind: node_1.CompletionItemKind.Function
25
- }));
25
+ });
26
26
  }
27
27
  const symbols = (0, symbols_1.collectSymbols)(document);
28
- return [...symbols.values()].map((symbol) => ({
29
- label: symbol.name,
30
- kind: node_1.CompletionItemKind.Variable
31
- }));
28
+ for (const symbol of symbols.values()) {
29
+ completions.push({
30
+ label: symbol.name,
31
+ kind: node_1.CompletionItemKind.Variable
32
+ });
33
+ }
34
+ return completions;
32
35
  }
@@ -46,7 +46,7 @@ function positionOf(text, needle) {
46
46
  }
47
47
  async function runCompletionTest() {
48
48
  const serverPath = node_path_1.default.resolve(__dirname, "../src/server.js");
49
- const mainPath = node_path_1.default.resolve(process.cwd(), "test/fixtures/valid/merlin32-main-6502.asm");
49
+ const mainPath = node_path_1.default.resolve(process.cwd(), "test/fixtures/valid/merlin32-main-6502.S");
50
50
  const mainUri = `file://${mainPath.replace(/\\/g, "/")}`;
51
51
  const text = `${node_fs_1.default.readFileSync(mainPath, "utf8")}\n ld\n du\n bpl G`;
52
52
  const child = (0, node_child_process_1.spawn)(process.execPath, [serverPath], {
@@ -46,7 +46,7 @@ function positionOf(text, needle) {
46
46
  }
47
47
  async function runDefinitionReferencesTest() {
48
48
  const serverPath = node_path_1.default.resolve(__dirname, "../src/server.js");
49
- const mainPath = node_path_1.default.resolve(process.cwd(), "test/fixtures/valid/merlin32-main-6502.asm");
49
+ const mainPath = node_path_1.default.resolve(process.cwd(), "test/fixtures/valid/merlin32-main-6502.S");
50
50
  const mainUri = `file://${mainPath.replace(/\\/g, "/")}`;
51
51
  const text = node_fs_1.default.readFileSync(mainPath, "utf8");
52
52
  const child = (0, node_child_process_1.spawn)(process.execPath, [serverPath], {
@@ -20,8 +20,8 @@ function runDiagnosticsTest() {
20
20
  " typ BLAH",
21
21
  " end BLAH"
22
22
  ].join("\n");
23
- const bankOpsPath = node_path_1.default.resolve(process.cwd(), "test/fixtures/invalid/65816-bank-ops.asm");
24
- const longPath = node_path_1.default.resolve(process.cwd(), "test/fixtures/invalid/65816-long-addressing.asm");
23
+ const bankOpsPath = node_path_1.default.resolve(process.cwd(), "test/fixtures/invalid/65816-bank-ops.S");
24
+ const longPath = node_path_1.default.resolve(process.cwd(), "test/fixtures/invalid/65816-long-addressing.S");
25
25
  const diagnostics = (0, diagnostics_1.collectWorkspaceDiagnostics)([
26
26
  {
27
27
  filePath: "<memory>",
@@ -36,7 +36,7 @@ function decodeMessages(streamBuffer) {
36
36
  }
37
37
  async function runDocumentSymbolTest() {
38
38
  const serverPath = node_path_1.default.resolve(__dirname, "../src/server.js");
39
- const fixturePath = node_path_1.default.resolve(process.cwd(), "test/fixtures/valid/merlin32-main-6502.asm");
39
+ const fixturePath = node_path_1.default.resolve(process.cwd(), "test/fixtures/valid/merlin32-main-6502.S");
40
40
  const uri = `file://${fixturePath.replace(/\\/g, "/")}`;
41
41
  const text = node_fs_1.default.readFileSync(fixturePath, "utf8");
42
42
  const child = (0, node_child_process_1.spawn)(process.execPath, [serverPath], {
@@ -8,12 +8,12 @@ const strict_1 = __importDefault(require("node:assert/strict"));
8
8
  const node_fs_1 = __importDefault(require("node:fs"));
9
9
  const node_path_1 = __importDefault(require("node:path"));
10
10
  const validFixturePaths = [
11
- "test/fixtures/valid/merlin32-linkscript.asm",
12
- "test/fixtures/valid/merlin32-main-6502.asm"
11
+ "test/fixtures/valid/merlin32-linkscript.S",
12
+ "test/fixtures/valid/merlin32-main-6502.S"
13
13
  ];
14
14
  const invalidFixturePaths = [
15
- "test/fixtures/invalid/65816-bank-ops.asm",
16
- "test/fixtures/invalid/65816-long-addressing.asm"
15
+ "test/fixtures/invalid/65816-bank-ops.S",
16
+ "test/fixtures/invalid/65816-long-addressing.S"
17
17
  ];
18
18
  function runFixtureCorpusTest() {
19
19
  for (const fixturePath of validFixturePaths) {
@@ -53,7 +53,7 @@ function positionOfInMatch(text, needle, offset) {
53
53
  }
54
54
  async function runHoverTest() {
55
55
  const serverPath = node_path_1.default.resolve(__dirname, "../src/server.js");
56
- const mainPath = node_path_1.default.resolve(process.cwd(), "test/fixtures/valid/merlin32-main-6502.asm");
56
+ const mainPath = node_path_1.default.resolve(process.cwd(), "test/fixtures/valid/merlin32-main-6502.S");
57
57
  const mainUri = `file://${mainPath.replace(/\\/g, "/")}`;
58
58
  const text = node_fs_1.default.readFileSync(mainPath, "utf8");
59
59
  const child = (0, node_child_process_1.spawn)(process.execPath, [serverPath], {
@@ -17,8 +17,8 @@ function findLine(lines, source) {
17
17
  return line;
18
18
  }
19
19
  function runLexerTest() {
20
- const mainFixturePath = node_path_1.default.resolve(process.cwd(), "test/fixtures/valid/merlin32-main-6502.asm");
21
- const linkFixturePath = node_path_1.default.resolve(process.cwd(), "test/fixtures/valid/merlin32-linkscript.asm");
20
+ const mainFixturePath = node_path_1.default.resolve(process.cwd(), "test/fixtures/valid/merlin32-main-6502.S");
21
+ const linkFixturePath = node_path_1.default.resolve(process.cwd(), "test/fixtures/valid/merlin32-linkscript.S");
22
22
  const mainFixture = node_fs_1.default.readFileSync(mainFixturePath, "utf8");
23
23
  const linkFixture = node_fs_1.default.readFileSync(linkFixturePath, "utf8");
24
24
  const mainLines = (0, lexer_1.lexSource)(mainFixture).lines;
@@ -46,8 +46,8 @@ function runLexerTest() {
46
46
  ["mnemonic", "ldx"],
47
47
  ["numericLiteral", "$C000"]
48
48
  ]);
49
- strict_1.default.deepEqual(summarizeTokens(findLine(linkLines, " asm \"merlin32-main-6502.asm\"").tokens), [
49
+ strict_1.default.deepEqual(summarizeTokens(findLine(linkLines, " asm \"merlin32-main-6502.S\"").tokens), [
50
50
  ["directive", "asm"],
51
- ["string", "\"merlin32-main-6502.asm\""]
51
+ ["string", "\"merlin32-main-6502.S\""]
52
52
  ]);
53
53
  }
@@ -10,7 +10,7 @@ const node_path_1 = __importDefault(require("node:path"));
10
10
  const document_1 = require("../src/asm/document");
11
11
  const local_labels_1 = require("../src/asm/local-labels");
12
12
  function runLocalLabelScopeTest() {
13
- const fixturePath = node_path_1.default.resolve(process.cwd(), "test/fixtures/valid/merlin32-main-6502.asm");
13
+ const fixturePath = node_path_1.default.resolve(process.cwd(), "test/fixtures/valid/merlin32-main-6502.S");
14
14
  const source = node_fs_1.default.readFileSync(fixturePath, "utf8");
15
15
  const document = (0, document_1.parseDocument)(source);
16
16
  const scope = (0, local_labels_1.resolveLocalLabels)(document);
@@ -35,7 +35,7 @@ function decodeMessages(streamBuffer) {
35
35
  }
36
36
  async function runPublishDiagnosticsTest() {
37
37
  const serverPath = node_path_1.default.resolve(__dirname, "../src/server.js");
38
- const documentPath = node_path_1.default.resolve(process.cwd(), "test/fixtures/invalid/publish-diagnostics.asm");
38
+ const documentPath = node_path_1.default.resolve(process.cwd(), "test/fixtures/invalid/publish-diagnostics.S");
39
39
  const documentUri = `file://${documentPath.replace(/\\/g, "/")}`;
40
40
  const brokenText = ["dup equ 1", " lda missing", "dup equ 2", " adc ("].join("\n");
41
41
  const fixedText = ["dup equ 1", " lda dup", " adc #1"].join("\n");
@@ -36,7 +36,7 @@ function decodeMessages(streamBuffer) {
36
36
  }
37
37
  async function runSemanticTokensTest() {
38
38
  const serverPath = node_path_1.default.resolve(__dirname, "../src/server.js");
39
- const mainPath = node_path_1.default.resolve(process.cwd(), "test/fixtures/valid/merlin32-main-6502.asm");
39
+ const mainPath = node_path_1.default.resolve(process.cwd(), "test/fixtures/valid/merlin32-main-6502.S");
40
40
  const mainUri = `file://${mainPath.replace(/\\/g, "/")}`;
41
41
  const text = node_fs_1.default.readFileSync(mainPath, "utf8");
42
42
  const child = (0, node_child_process_1.spawn)(process.execPath, [serverPath], {
@@ -10,7 +10,7 @@ const node_path_1 = __importDefault(require("node:path"));
10
10
  const document_1 = require("../src/asm/document");
11
11
  const symbols_1 = require("../src/asm/symbols");
12
12
  function runSymbolsTest() {
13
- const fixturePath = node_path_1.default.resolve(process.cwd(), "test/fixtures/valid/merlin32-main-6502.asm");
13
+ const fixturePath = node_path_1.default.resolve(process.cwd(), "test/fixtures/valid/merlin32-main-6502.S");
14
14
  const source = node_fs_1.default.readFileSync(fixturePath, "utf8");
15
15
  const document = (0, document_1.parseDocument)(source);
16
16
  const symbols = (0, symbols_1.collectSymbols)(document);
@@ -36,8 +36,8 @@ function decodeMessages(streamBuffer) {
36
36
  }
37
37
  async function runWorkspaceSymbolTest() {
38
38
  const serverPath = node_path_1.default.resolve(__dirname, "../src/server.js");
39
- const linkPath = node_path_1.default.resolve(process.cwd(), "test/fixtures/valid/merlin32-linkscript.asm");
40
- const mainPath = node_path_1.default.resolve(process.cwd(), "test/fixtures/valid/merlin32-main-6502.asm");
39
+ const linkPath = node_path_1.default.resolve(process.cwd(), "test/fixtures/valid/merlin32-linkscript.S");
40
+ const mainPath = node_path_1.default.resolve(process.cwd(), "test/fixtures/valid/merlin32-main-6502.S");
41
41
  const linkUri = `file://${linkPath.replace(/\\/g, "/")}`;
42
42
  const mainUri = `file://${mainPath.replace(/\\/g, "/")}`;
43
43
  const child = (0, node_child_process_1.spawn)(process.execPath, [serverPath], {
@@ -8,8 +8,8 @@ const strict_1 = __importDefault(require("node:assert/strict"));
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
9
  const workspace_1 = require("../src/asm/workspace");
10
10
  function runWorkspaceGraphTest() {
11
- const entryPath = node_path_1.default.resolve(process.cwd(), "test/fixtures/valid/merlin32-linkscript.asm");
12
- const mainPath = node_path_1.default.resolve(process.cwd(), "test/fixtures/valid/merlin32-main-6502.asm");
11
+ const entryPath = node_path_1.default.resolve(process.cwd(), "test/fixtures/valid/merlin32-linkscript.S");
12
+ const mainPath = node_path_1.default.resolve(process.cwd(), "test/fixtures/valid/merlin32-main-6502.S");
13
13
  const workspace = (0, workspace_1.indexWorkspace)(entryPath);
14
14
  strict_1.default.deepEqual(workspace.loadOrder, [entryPath, mainPath]);
15
15
  strict_1.default.deepEqual(workspace.dependencies.get(entryPath), [mainPath]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@razdolbai/merls",
3
- "version": "1.2.2",
3
+ "version": "1.3.0",
4
4
  "description": "Language server for Merlin-style 6502 assembly.",
5
5
  "license": "MIT",
6
6
  "type": "commonjs",
@@ -18,25 +18,29 @@ export function buildCompletionItems(
18
18
  }
19
19
 
20
20
  const document = parseDocument(source);
21
- const text = document.lines[line]?.node.text.trimStart().toLowerCase() ?? "";
21
+ const completions: CompletionItem[] = [];
22
22
 
23
- if (text === "ld" || text === "ld\n" || text.startsWith("ld")) {
24
- return opcodeDefinitions.map((opcode) => ({
23
+ for (const opcode of opcodeDefinitions) {
24
+ completions.push({
25
25
  label: opcode.mnemonic,
26
26
  kind: CompletionItemKind.Keyword
27
- }));
27
+ });
28
28
  }
29
29
 
30
- if (text === "du" || text.startsWith("du")) {
31
- return directiveDefinitions.map((directive) => ({
30
+ for (const directive of directiveDefinitions) {
31
+ completions.push({
32
32
  label: directive.name,
33
33
  kind: CompletionItemKind.Function
34
- }));
34
+ });
35
35
  }
36
36
 
37
37
  const symbols = collectSymbols(document);
38
- return [...symbols.values()].map((symbol) => ({
39
- label: symbol.name,
40
- kind: CompletionItemKind.Variable
41
- }));
38
+ for (const symbol of symbols.values()) {
39
+ completions.push({
40
+ label: symbol.name,
41
+ kind: CompletionItemKind.Variable
42
+ });
43
+ }
44
+
45
+ return completions;
42
46
  }