syntax-map-mcp 1.1.0 → 1.2.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.
- package/CHANGELOG.md +5 -0
- package/README.md +1 -0
- package/dist/analysis/diagnostics.js +73 -0
- package/dist/tools.js +14 -0
- package/docs/tools.md +31 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 1.2.0 - 2026-05-07
|
|
6
|
+
|
|
7
|
+
- `lsp_diagnostics` 도구를 추가해 tree-sitter parse error 기반의 가벼운 문법 진단을 LSP Diagnostic 형태로 반환하도록 했습니다.
|
|
8
|
+
- diagnostics 분석 계층에 provider 인터페이스를 추가해 이후 언어별 LSP 서버 진단 결과를 결합할 수 있게 했습니다.
|
|
9
|
+
|
|
5
10
|
## 1.1.0 - 2026-05-07
|
|
6
11
|
|
|
7
12
|
- Rust `.rs` 파일 파싱을 지원하고, `get_ast_tree`와 LSP document symbols, definition, references, hover, workspace symbols, completion, signature help에서 Rust 심볼을 처리하도록 했습니다.
|
package/README.md
CHANGED
|
@@ -37,6 +37,7 @@ npx -y syntax-map-mcp --workspace-root /path/to/workspace
|
|
|
37
37
|
- `run_query`: 파일 하나에 tree-sitter query 실행
|
|
38
38
|
- `get_ast_tree`: 파일 하나의 tree-sitter AST를 depth 제한 JSON 트리로 반환
|
|
39
39
|
- `lsp_document_symbols`: 파일 하나의 심볼을 LSP DocumentSymbol 형태로 반환
|
|
40
|
+
- `lsp_diagnostics`: 파일 하나의 tree-sitter parse error를 LSP Diagnostic 형태로 반환
|
|
40
41
|
- `lsp_definition`: 파일의 LSP 위치에 있는 식별자의 정의 위치를 반환
|
|
41
42
|
- `lsp_references`: 파일의 LSP 위치에 있는 식별자의 참조 위치를 반환
|
|
42
43
|
- `lsp_hover`: 파일의 LSP 위치에 있는 식별자의 hover markdown을 반환
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { parseSourceFile } from '../parser.js';
|
|
2
|
+
export const treeSitterDiagnosticProvider = {
|
|
3
|
+
name: 'tree-sitter',
|
|
4
|
+
getDiagnostics(context) {
|
|
5
|
+
return collectTreeSitterDiagnostics(context.tree.rootNode);
|
|
6
|
+
}
|
|
7
|
+
};
|
|
8
|
+
const defaultDiagnosticProviders = [treeSitterDiagnosticProvider];
|
|
9
|
+
export async function getDiagnostics(workspace, input, providers = defaultDiagnosticProviders) {
|
|
10
|
+
const file = await workspace.readSourceFile(input.path);
|
|
11
|
+
if (!file.ok)
|
|
12
|
+
return file;
|
|
13
|
+
const parsed = parseSourceFile(file);
|
|
14
|
+
/* v8 ignore next -- parser failures are covered by parser tests. */
|
|
15
|
+
if (!parsed.ok)
|
|
16
|
+
return parsed;
|
|
17
|
+
const context = diagnosticContext(parsed);
|
|
18
|
+
const diagnostics = (await Promise.all(providers.map(provider => Promise.resolve(provider.getDiagnostics(context))))).flat();
|
|
19
|
+
return {
|
|
20
|
+
ok: true,
|
|
21
|
+
path: file.relativePath,
|
|
22
|
+
language: parsed.language,
|
|
23
|
+
diagnostics
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function diagnosticContext(parsed) {
|
|
27
|
+
return {
|
|
28
|
+
path: parsed.file.relativePath,
|
|
29
|
+
language: parsed.language,
|
|
30
|
+
text: parsed.file.text,
|
|
31
|
+
tree: parsed.tree
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function collectTreeSitterDiagnostics(root) {
|
|
35
|
+
if (!root.hasError)
|
|
36
|
+
return [];
|
|
37
|
+
const diagnostics = [];
|
|
38
|
+
collectErrorNodes(root, diagnostics);
|
|
39
|
+
return diagnostics;
|
|
40
|
+
}
|
|
41
|
+
function collectErrorNodes(node, diagnostics) {
|
|
42
|
+
if (node.isError || node.isMissing) {
|
|
43
|
+
diagnostics.push({
|
|
44
|
+
range: lspRange(rangeForNode(node)),
|
|
45
|
+
severity: 1,
|
|
46
|
+
source: 'tree-sitter',
|
|
47
|
+
message: node.isMissing ? `Syntax error: missing ${node.type}` : 'Syntax error'
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
if (!node.hasError)
|
|
51
|
+
return;
|
|
52
|
+
for (const child of node.children) {
|
|
53
|
+
collectErrorNodes(child, diagnostics);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function lspRange(range) {
|
|
57
|
+
return {
|
|
58
|
+
start: {
|
|
59
|
+
line: range.start.row,
|
|
60
|
+
character: range.start.column
|
|
61
|
+
},
|
|
62
|
+
end: {
|
|
63
|
+
line: range.end.row,
|
|
64
|
+
character: range.end.column
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function rangeForNode(node) {
|
|
69
|
+
return {
|
|
70
|
+
start: node.startPosition,
|
|
71
|
+
end: node.endPosition
|
|
72
|
+
};
|
|
73
|
+
}
|
package/dist/tools.js
CHANGED
|
@@ -2,6 +2,7 @@ import { z } from 'zod';
|
|
|
2
2
|
import { getAstTree as getAstTreeAnalysis } from './analysis/ast-tree.js';
|
|
3
3
|
import { buildContext as buildContextAnalysis } from './analysis/context.js';
|
|
4
4
|
import { findDefinitions } from './analysis/definitions.js';
|
|
5
|
+
import { getDiagnostics as getLspDiagnostics } from './analysis/diagnostics.js';
|
|
5
6
|
import { clearIndex as clearWorkspaceIndex, findIndexedDefinitions, findIndexedReferences, getIndexStatus as getWorkspaceIndexStatus, indexWorkspace as indexWorkspaceAnalysis, searchSymbols as searchIndexedSymbols } from './analysis/index.js';
|
|
6
7
|
import { runTreeSitterQuery } from './analysis/query.js';
|
|
7
8
|
import { findReferences as findReferencesAnalysis } from './analysis/references.js';
|
|
@@ -75,6 +76,12 @@ export function createToolHandlers(workspace) {
|
|
|
75
76
|
return toolFailure(result.error.code, result.error.message);
|
|
76
77
|
return jsonResult(result);
|
|
77
78
|
},
|
|
79
|
+
async lspDiagnostics(input) {
|
|
80
|
+
const result = await getLspDiagnostics(workspace, input);
|
|
81
|
+
if (!result.ok)
|
|
82
|
+
return toolFailure(result.error.code, result.error.message);
|
|
83
|
+
return jsonResult(result);
|
|
84
|
+
},
|
|
78
85
|
async lspDefinition(input) {
|
|
79
86
|
const result = await getLspDefinition(workspace, input);
|
|
80
87
|
if (!result.ok)
|
|
@@ -214,6 +221,13 @@ export function registerTools(server, workspace) {
|
|
|
214
221
|
path: z.string()
|
|
215
222
|
}
|
|
216
223
|
}, handlers.lspDocumentSymbols);
|
|
224
|
+
server.registerTool('lsp_diagnostics', {
|
|
225
|
+
title: 'LSP diagnostics',
|
|
226
|
+
description: 'Return lightweight syntax diagnostics from tree-sitter parse errors.',
|
|
227
|
+
inputSchema: {
|
|
228
|
+
path: z.string()
|
|
229
|
+
}
|
|
230
|
+
}, handlers.lspDiagnostics);
|
|
217
231
|
server.registerTool('lsp_definition', {
|
|
218
232
|
title: 'LSP definition',
|
|
219
233
|
description: 'Return definition locations for the identifier at a zero-based LSP position.',
|
package/docs/tools.md
CHANGED
|
@@ -215,6 +215,37 @@ syntax-map-mcp의 주요 MCP 도구 입력과 응답 예시입니다. 응답 예
|
|
|
215
215
|
}
|
|
216
216
|
```
|
|
217
217
|
|
|
218
|
+
## lsp_diagnostics
|
|
219
|
+
|
|
220
|
+
입력:
|
|
221
|
+
|
|
222
|
+
```json
|
|
223
|
+
{
|
|
224
|
+
"path": "src/users.ts"
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
응답 일부:
|
|
229
|
+
|
|
230
|
+
```json
|
|
231
|
+
{
|
|
232
|
+
"ok": true,
|
|
233
|
+
"path": "src/users.ts",
|
|
234
|
+
"language": "typescript",
|
|
235
|
+
"diagnostics": [
|
|
236
|
+
{
|
|
237
|
+
"range": {
|
|
238
|
+
"start": { "line": 10, "character": 4 },
|
|
239
|
+
"end": { "line": 10, "character": 12 }
|
|
240
|
+
},
|
|
241
|
+
"severity": 1,
|
|
242
|
+
"source": "tree-sitter",
|
|
243
|
+
"message": "Syntax error"
|
|
244
|
+
}
|
|
245
|
+
]
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
218
249
|
## lsp_definition
|
|
219
250
|
|
|
220
251
|
입력:
|