kiri-mcp-server 0.16.1 → 0.18.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/README.md +65 -22
- package/dist/package.json +4 -2
- package/dist/src/client/proxy.js +0 -0
- package/dist/src/daemon/daemon.js +0 -0
- package/dist/src/indexer/codeintel/dart/adapter.d.ts +36 -0
- package/dist/src/indexer/codeintel/dart/adapter.d.ts.map +1 -0
- package/dist/src/indexer/codeintel/dart/adapter.js +60 -0
- package/dist/src/indexer/codeintel/dart/adapter.js.map +1 -0
- package/dist/src/indexer/codeintel/dart/index.d.ts +7 -0
- package/dist/src/indexer/codeintel/dart/index.d.ts.map +1 -0
- package/dist/src/indexer/codeintel/dart/index.js +7 -0
- package/dist/src/indexer/codeintel/dart/index.js.map +1 -0
- package/dist/src/indexer/codeintel/index.d.ts +30 -0
- package/dist/src/indexer/codeintel/index.d.ts.map +1 -0
- package/dist/src/indexer/codeintel/index.js +32 -0
- package/dist/src/indexer/codeintel/index.js.map +1 -0
- package/dist/src/indexer/codeintel/java/analyzer.d.ts +22 -0
- package/dist/src/indexer/codeintel/java/analyzer.d.ts.map +1 -0
- package/dist/src/indexer/codeintel/java/analyzer.js +281 -0
- package/dist/src/indexer/codeintel/java/analyzer.js.map +1 -0
- package/dist/src/indexer/codeintel/java/index.d.ts +7 -0
- package/dist/src/indexer/codeintel/java/index.d.ts.map +1 -0
- package/dist/src/indexer/codeintel/java/index.js +7 -0
- package/dist/src/indexer/codeintel/java/index.js.map +1 -0
- package/dist/src/indexer/codeintel/php/analyzer.d.ts +23 -0
- package/dist/src/indexer/codeintel/php/analyzer.d.ts.map +1 -0
- package/dist/src/indexer/codeintel/php/analyzer.js +342 -0
- package/dist/src/indexer/codeintel/php/analyzer.js.map +1 -0
- package/dist/src/indexer/codeintel/php/index.d.ts +7 -0
- package/dist/src/indexer/codeintel/php/index.d.ts.map +1 -0
- package/dist/src/indexer/codeintel/php/index.js +7 -0
- package/dist/src/indexer/codeintel/php/index.js.map +1 -0
- package/dist/src/indexer/codeintel/registry.d.ts +76 -0
- package/dist/src/indexer/codeintel/registry.d.ts.map +1 -0
- package/dist/src/indexer/codeintel/registry.js +127 -0
- package/dist/src/indexer/codeintel/registry.js.map +1 -0
- package/dist/src/indexer/codeintel/rust/analyzer.d.ts +14 -0
- package/dist/src/indexer/codeintel/rust/analyzer.d.ts.map +1 -0
- package/dist/src/indexer/codeintel/rust/analyzer.js +388 -0
- package/dist/src/indexer/codeintel/rust/analyzer.js.map +1 -0
- package/dist/src/indexer/codeintel/rust/index.d.ts +5 -0
- package/dist/src/indexer/codeintel/rust/index.d.ts.map +1 -0
- package/dist/src/indexer/codeintel/rust/index.js +5 -0
- package/dist/src/indexer/codeintel/rust/index.js.map +1 -0
- package/dist/src/indexer/codeintel/swift/analyzer.d.ts +22 -0
- package/dist/src/indexer/codeintel/swift/analyzer.d.ts.map +1 -0
- package/dist/src/indexer/codeintel/swift/analyzer.js +271 -0
- package/dist/src/indexer/codeintel/swift/analyzer.js.map +1 -0
- package/dist/src/indexer/codeintel/swift/index.d.ts +7 -0
- package/dist/src/indexer/codeintel/swift/index.d.ts.map +1 -0
- package/dist/src/indexer/codeintel/swift/index.js +7 -0
- package/dist/src/indexer/codeintel/swift/index.js.map +1 -0
- package/dist/src/indexer/codeintel/types.d.ts +114 -0
- package/dist/src/indexer/codeintel/types.d.ts.map +1 -0
- package/dist/src/indexer/codeintel/types.js +13 -0
- package/dist/src/indexer/codeintel/types.js.map +1 -0
- package/dist/src/indexer/codeintel/typescript/analyzer.d.ts +22 -0
- package/dist/src/indexer/codeintel/typescript/analyzer.d.ts.map +1 -0
- package/dist/{indexer/codeintel.js → src/indexer/codeintel/typescript/analyzer.js} +62 -34
- package/dist/src/indexer/codeintel/typescript/analyzer.js.map +1 -0
- package/dist/src/indexer/codeintel/typescript/index.d.ts +7 -0
- package/dist/src/indexer/codeintel/typescript/index.d.ts.map +1 -0
- package/dist/src/indexer/codeintel/typescript/index.js +7 -0
- package/dist/src/indexer/codeintel/typescript/index.js.map +1 -0
- package/dist/src/indexer/codeintel/utils.d.ts +91 -0
- package/dist/src/indexer/codeintel/utils.d.ts.map +1 -0
- package/dist/src/indexer/codeintel/utils.js +145 -0
- package/dist/src/indexer/codeintel/utils.js.map +1 -0
- package/dist/src/indexer/codeintel.d.ts +33 -26
- package/dist/src/indexer/codeintel.d.ts.map +1 -1
- package/dist/src/indexer/codeintel.js +56 -1078
- package/dist/src/indexer/codeintel.js.map +1 -1
- package/dist/src/indexer/graph-metrics.d.ts.map +1 -1
- package/dist/src/indexer/graph-metrics.js +16 -4
- package/dist/src/indexer/graph-metrics.js.map +1 -1
- package/dist/src/server/boost-profiles.d.ts +1 -1
- package/dist/src/server/boost-profiles.d.ts.map +1 -1
- package/dist/src/server/boost-profiles.js +22 -0
- package/dist/src/server/boost-profiles.js.map +1 -1
- package/dist/src/server/main.js +0 -0
- package/dist/src/server/rpc.js +4 -4
- package/dist/src/server/rpc.js.map +1 -1
- package/package.json +10 -2
- package/dist/client/cli.js +0 -68
- package/dist/client/cli.js.map +0 -1
- package/dist/client/index.js +0 -5
- package/dist/client/index.js.map +0 -1
- package/dist/eval/metrics.js +0 -47
- package/dist/eval/metrics.js.map +0 -1
- package/dist/indexer/cli.js +0 -362
- package/dist/indexer/cli.js.map +0 -1
- package/dist/indexer/codeintel.js.map +0 -1
- package/dist/indexer/git.js +0 -30
- package/dist/indexer/git.js.map +0 -1
- package/dist/indexer/language.js +0 -34
- package/dist/indexer/language.js.map +0 -1
- package/dist/indexer/pipeline/filters/denylist.js +0 -71
- package/dist/indexer/pipeline/filters/denylist.js.map +0 -1
- package/dist/indexer/schema.js +0 -101
- package/dist/indexer/schema.js.map +0 -1
- package/dist/server/bootstrap.js +0 -19
- package/dist/server/bootstrap.js.map +0 -1
- package/dist/server/context.js +0 -1
- package/dist/server/context.js.map +0 -1
- package/dist/server/fallbacks/degradeController.js +0 -69
- package/dist/server/fallbacks/degradeController.js.map +0 -1
- package/dist/server/handlers.js +0 -1268
- package/dist/server/handlers.js.map +0 -1
- package/dist/server/main.js +0 -151
- package/dist/server/main.js.map +0 -1
- package/dist/server/observability/metrics.js +0 -56
- package/dist/server/observability/metrics.js.map +0 -1
- package/dist/server/observability/tracing.js +0 -58
- package/dist/server/observability/tracing.js.map +0 -1
- package/dist/server/rpc.js +0 -477
- package/dist/server/rpc.js.map +0 -1
- package/dist/server/runtime.js +0 -47
- package/dist/server/runtime.js.map +0 -1
- package/dist/server/scoring.js +0 -116
- package/dist/server/scoring.js.map +0 -1
- package/dist/server/stdio.js +0 -76
- package/dist/server/stdio.js.map +0 -1
- package/dist/shared/duckdb.js +0 -119
- package/dist/shared/duckdb.js.map +0 -1
- package/dist/shared/embedding.js +0 -98
- package/dist/shared/embedding.js.map +0 -1
- package/dist/shared/index.js +0 -9
- package/dist/shared/index.js.map +0 -1
- package/dist/shared/security/config.js +0 -64
- package/dist/shared/security/config.js.map +0 -1
- package/dist/shared/security/masker.js +0 -56
- package/dist/shared/security/masker.js.map +0 -1
- package/dist/shared/tokenizer.js +0 -4
- package/dist/shared/tokenizer.js.map +0 -1
- package/dist/shared/utils/simpleYaml.js +0 -89
- package/dist/shared/utils/simpleYaml.js.map +0 -1
- package/dist/src/server/rrf.d.ts +0 -86
- package/dist/src/server/rrf.d.ts.map +0 -1
- package/dist/src/server/rrf.js +0 -108
- package/dist/src/server/rrf.js.map +0 -1
- package/dist/src/shared/embedding/engine.d.ts +0 -38
- package/dist/src/shared/embedding/engine.d.ts.map +0 -1
- package/dist/src/shared/embedding/engine.js +0 -6
- package/dist/src/shared/embedding/engine.js.map +0 -1
- package/dist/src/shared/embedding/lsh-engine.d.ts +0 -11
- package/dist/src/shared/embedding/lsh-engine.d.ts.map +0 -1
- package/dist/src/shared/embedding/lsh-engine.js +0 -14
- package/dist/src/shared/embedding/lsh-engine.js.map +0 -1
- package/dist/src/shared/embedding/registry.d.ts +0 -25
- package/dist/src/shared/embedding/registry.d.ts.map +0 -1
- package/dist/src/shared/embedding/registry.js +0 -50
- package/dist/src/shared/embedding/registry.js.map +0 -1
- package/dist/src/shared/embedding/semantic-engine.d.ts +0 -14
- package/dist/src/shared/embedding/semantic-engine.d.ts.map +0 -1
- package/dist/src/shared/embedding/semantic-engine.js +0 -50
- package/dist/src/shared/embedding/semantic-engine.js.map +0 -1
- package/dist/src/shared/models/model-manager.d.ts +0 -38
- package/dist/src/shared/models/model-manager.d.ts.map +0 -1
- package/dist/src/shared/models/model-manager.js +0 -116
- package/dist/src/shared/models/model-manager.js.map +0 -1
- package/dist/src/shared/models/model-manifest.d.ts +0 -22
- package/dist/src/shared/models/model-manifest.d.ts.map +0 -1
- package/dist/src/shared/models/model-manifest.js +0 -24
- package/dist/src/shared/models/model-manifest.js.map +0 -1
|
@@ -1,1088 +1,66 @@
|
|
|
1
|
-
import { createRequire } from "node:module";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import Parser from "tree-sitter";
|
|
4
|
-
import Java from "tree-sitter-java";
|
|
5
|
-
import Swift from "tree-sitter-swift";
|
|
6
|
-
import ts from "typescript";
|
|
7
|
-
// tree-sitter-php is a CommonJS module, so import it using require.
|
|
8
|
-
// tree-sitter-php: Using version 0.22.8 for compatibility with tree-sitter 0.22.4.
|
|
9
|
-
// Version 0.24.2 had a nodeTypeInfo bug that caused runtime errors.
|
|
10
|
-
// php_only: for pure PHP files (<?php at start)
|
|
11
|
-
// php: for HTML-mixed PHP files (HTML with <?php ... ?> tags)
|
|
12
|
-
const require = createRequire(import.meta.url);
|
|
13
|
-
const PHPModule = require("tree-sitter-php");
|
|
14
|
-
const PHP_ONLY = PHPModule.php_only;
|
|
15
|
-
const PHP_MIXED = PHPModule.php;
|
|
16
|
-
// Dart Analysis Server integration
|
|
17
|
-
// eslint-disable-next-line import/order
|
|
18
|
-
import { analyzeDartSource } from "./dart/analyze.js";
|
|
19
|
-
const SUPPORTED_LANGUAGES = new Set(["TypeScript", "Swift", "PHP", "Java", "Dart"]);
|
|
20
|
-
function sanitizeSignature(source, node) {
|
|
21
|
-
const start = node.getStart(source);
|
|
22
|
-
const endCandidate = node.forEachChild((child) => {
|
|
23
|
-
if (ts.isBlock(child) || ts.isModuleBlock(child)) {
|
|
24
|
-
return child.getFullStart();
|
|
25
|
-
}
|
|
26
|
-
return undefined;
|
|
27
|
-
});
|
|
28
|
-
const end = typeof endCandidate === "number" ? endCandidate : node.getEnd();
|
|
29
|
-
const snippet = source.text.slice(start, Math.min(end, start + 200));
|
|
30
|
-
return snippet.split(/\r?\n/)[0]?.trim().replace(/\s+/g, " ") ?? "";
|
|
31
|
-
}
|
|
32
|
-
function getDocComment(node) {
|
|
33
|
-
const tags = ts.getJSDocCommentsAndTags(node);
|
|
34
|
-
const parts = [];
|
|
35
|
-
for (const tag of tags) {
|
|
36
|
-
if (ts.isJSDoc(tag)) {
|
|
37
|
-
if (typeof tag.comment === "string") {
|
|
38
|
-
parts.push(tag.comment);
|
|
39
|
-
}
|
|
40
|
-
else if (Array.isArray(tag.comment)) {
|
|
41
|
-
parts.push(tag.comment.map((part) => (typeof part === "string" ? part : part.text)).join(""));
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
if (parts.length === 0) {
|
|
46
|
-
return null;
|
|
47
|
-
}
|
|
48
|
-
return parts.join("\n").trim() || null;
|
|
49
|
-
}
|
|
50
|
-
function toLineNumber(source, position) {
|
|
51
|
-
return source.getLineAndCharacterOfPosition(position).line + 1;
|
|
52
|
-
}
|
|
53
1
|
/**
|
|
54
|
-
*
|
|
55
|
-
*/
|
|
56
|
-
function sanitizeSwiftSignature(node, content) {
|
|
57
|
-
const nodeText = content.substring(node.startIndex, node.endIndex);
|
|
58
|
-
// 関数本体({...})を除外
|
|
59
|
-
const bodyIndex = nodeText.indexOf("{");
|
|
60
|
-
const signatureText = bodyIndex >= 0 ? nodeText.substring(0, bodyIndex) : nodeText;
|
|
61
|
-
// 最初の200文字に制限し、1行に圧縮
|
|
62
|
-
const truncated = signatureText.substring(0, 200);
|
|
63
|
-
return truncated.split(/\r?\n/)[0]?.trim().replace(/\s+/g, " ") ?? "";
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Swiftのドキュメントコメント(/// または /** */)を抽出
|
|
67
|
-
*/
|
|
68
|
-
function getSwiftDocComment(node, content) {
|
|
69
|
-
const parent = node.parent;
|
|
70
|
-
if (!parent)
|
|
71
|
-
return null;
|
|
72
|
-
// 親ノードのすべての子から、このノードの直前にあるコメントを探す
|
|
73
|
-
const precedingComments = [];
|
|
74
|
-
const siblings = parent.children; // namedChildrenではなくchildrenを使用
|
|
75
|
-
const nodeIndex = siblings.indexOf(node);
|
|
76
|
-
// このノードより前の兄弟を逆順で調べる
|
|
77
|
-
for (let i = nodeIndex - 1; i >= 0; i--) {
|
|
78
|
-
const sibling = siblings[i];
|
|
79
|
-
if (!sibling)
|
|
80
|
-
continue;
|
|
81
|
-
// commentまたはmultiline_commentをチェック
|
|
82
|
-
if (sibling.type === "comment" || sibling.type === "multiline_comment") {
|
|
83
|
-
const commentText = content.substring(sibling.startIndex, sibling.endIndex);
|
|
84
|
-
// /// または /** */ 形式のドキュメントコメントのみ抽出
|
|
85
|
-
if (commentText.startsWith("///") || commentText.startsWith("/**")) {
|
|
86
|
-
const cleanedComment = commentText
|
|
87
|
-
.replace(/^\/\/\/\s?/gm, "")
|
|
88
|
-
.replace(/^\/\*\*\s?|\s?\*\/$/g, "")
|
|
89
|
-
.replace(/^\s*\*\s?/gm, "")
|
|
90
|
-
.trim();
|
|
91
|
-
precedingComments.unshift(cleanedComment);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
else if (sibling.type !== "{" &&
|
|
95
|
-
sibling.type !== "}" &&
|
|
96
|
-
!sibling.text.trim().match(/^\s*$/)) {
|
|
97
|
-
// コメント以外の実質的なノードに到達したら終了
|
|
98
|
-
break;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
if (precedingComments.length === 0) {
|
|
102
|
-
return null;
|
|
103
|
-
}
|
|
104
|
-
return precedingComments.join("\n");
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* tree-sitterの位置情報から行番号を取得(1-based)
|
|
108
|
-
*/
|
|
109
|
-
function toSwiftLineNumber(position) {
|
|
110
|
-
return position.row + 1;
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* Detect whether PHP file is pure PHP or HTML-mixed.
|
|
114
|
-
* Pure PHP: starts with <?php tag (possibly after whitespace, shebang, or BOM)
|
|
115
|
-
* HTML-mixed: contains HTML content before <?php tag
|
|
2
|
+
* Code Intelligence API
|
|
116
3
|
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
*
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
return null;
|
|
155
|
-
// 親ノードのすべての子から、このノードの直前にあるコメントを探す
|
|
156
|
-
const precedingComments = [];
|
|
157
|
-
const siblings = parent.children;
|
|
158
|
-
const nodeIndex = siblings.indexOf(node);
|
|
159
|
-
// このノードより前の兄弟を逆順で調べる
|
|
160
|
-
for (let i = nodeIndex - 1; i >= 0; i--) {
|
|
161
|
-
const sibling = siblings[i];
|
|
162
|
-
if (!sibling)
|
|
163
|
-
continue;
|
|
164
|
-
// commentをチェック
|
|
165
|
-
if (sibling.type === "comment") {
|
|
166
|
-
const commentText = content.substring(sibling.startIndex, sibling.endIndex);
|
|
167
|
-
// /** */ 形式のPHPDocコメントのみ抽出
|
|
168
|
-
if (commentText.startsWith("/**") && commentText.endsWith("*/")) {
|
|
169
|
-
const cleanedComment = commentText
|
|
170
|
-
.replace(/^\/\*\*\s?|\s?\*\/$/g, "")
|
|
171
|
-
.replace(/^\s*\*\s?/gm, "")
|
|
172
|
-
.trim();
|
|
173
|
-
precedingComments.unshift(cleanedComment);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
else if (sibling.type !== "text" && !sibling.text.trim().match(/^\s*$/)) {
|
|
177
|
-
// コメント以外の実質的なノードに到達したら終了
|
|
178
|
-
break;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
if (precedingComments.length === 0) {
|
|
182
|
-
return null;
|
|
183
|
-
}
|
|
184
|
-
return precedingComments.join("\n");
|
|
185
|
-
}
|
|
186
|
-
/**
|
|
187
|
-
* tree-sitterの位置情報から行番号を取得(1-based)
|
|
188
|
-
*/
|
|
189
|
-
function toPHPLineNumber(position) {
|
|
190
|
-
return position.row + 1;
|
|
191
|
-
}
|
|
192
|
-
/**
|
|
193
|
-
* PHPのシンボルレコードを作成
|
|
194
|
-
*/
|
|
195
|
-
function createPHPSymbolRecords(tree, content) {
|
|
196
|
-
const results = [];
|
|
197
|
-
/**
|
|
198
|
-
* 子ノードから名前を抽出
|
|
199
|
-
*/
|
|
200
|
-
function extractName(node) {
|
|
201
|
-
function findName(n) {
|
|
202
|
-
if (n.type === "name") {
|
|
203
|
-
return n;
|
|
204
|
-
}
|
|
205
|
-
for (const child of n.namedChildren) {
|
|
206
|
-
const found = findName(child);
|
|
207
|
-
if (found)
|
|
208
|
-
return found;
|
|
209
|
-
}
|
|
210
|
-
return null;
|
|
211
|
-
}
|
|
212
|
-
const nameNode = findName(node);
|
|
213
|
-
return nameNode ? content.substring(nameNode.startIndex, nameNode.endIndex) : null;
|
|
214
|
-
}
|
|
215
|
-
/**
|
|
216
|
-
* ツリーを再帰的にトラバースしてシンボルを抽出
|
|
217
|
-
*/
|
|
218
|
-
function visit(node) {
|
|
219
|
-
// class_declaration: クラス宣言
|
|
220
|
-
if (node.type === "class_declaration") {
|
|
221
|
-
const name = extractName(node);
|
|
222
|
-
if (name) {
|
|
223
|
-
results.push({
|
|
224
|
-
name,
|
|
225
|
-
kind: "class",
|
|
226
|
-
rangeStartLine: toPHPLineNumber(node.startPosition),
|
|
227
|
-
rangeEndLine: toPHPLineNumber(node.endPosition),
|
|
228
|
-
signature: sanitizePHPSignature(node, content),
|
|
229
|
-
doc: getPHPDocComment(node, content),
|
|
230
|
-
});
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
// interface_declaration: インターフェース宣言
|
|
234
|
-
else if (node.type === "interface_declaration") {
|
|
235
|
-
const name = extractName(node);
|
|
236
|
-
if (name) {
|
|
237
|
-
results.push({
|
|
238
|
-
name,
|
|
239
|
-
kind: "interface",
|
|
240
|
-
rangeStartLine: toPHPLineNumber(node.startPosition),
|
|
241
|
-
rangeEndLine: toPHPLineNumber(node.endPosition),
|
|
242
|
-
signature: sanitizePHPSignature(node, content),
|
|
243
|
-
doc: getPHPDocComment(node, content),
|
|
244
|
-
});
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
// trait_declaration: トレイト宣言
|
|
248
|
-
else if (node.type === "trait_declaration") {
|
|
249
|
-
const name = extractName(node);
|
|
250
|
-
if (name) {
|
|
251
|
-
results.push({
|
|
252
|
-
name,
|
|
253
|
-
kind: "trait",
|
|
254
|
-
rangeStartLine: toPHPLineNumber(node.startPosition),
|
|
255
|
-
rangeEndLine: toPHPLineNumber(node.endPosition),
|
|
256
|
-
signature: sanitizePHPSignature(node, content),
|
|
257
|
-
doc: getPHPDocComment(node, content),
|
|
258
|
-
});
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
// function_definition: トップレベル関数またはメソッド
|
|
262
|
-
else if (node.type === "function_definition" || node.type === "method_declaration") {
|
|
263
|
-
const name = extractName(node);
|
|
264
|
-
if (name) {
|
|
265
|
-
// 親がclass_declaration/trait_declaration/interface_declarationの子孫の場合はmethod、それ以外はfunction
|
|
266
|
-
let isMethod = false;
|
|
267
|
-
let parentNode = node.parent;
|
|
268
|
-
while (parentNode) {
|
|
269
|
-
if (parentNode.type === "class_declaration" ||
|
|
270
|
-
parentNode.type === "trait_declaration" ||
|
|
271
|
-
parentNode.type === "interface_declaration") {
|
|
272
|
-
isMethod = true;
|
|
273
|
-
break;
|
|
274
|
-
}
|
|
275
|
-
parentNode = parentNode.parent;
|
|
276
|
-
}
|
|
277
|
-
const kind = isMethod ? "method" : "function";
|
|
278
|
-
results.push({
|
|
279
|
-
name,
|
|
280
|
-
kind,
|
|
281
|
-
rangeStartLine: toPHPLineNumber(node.startPosition),
|
|
282
|
-
rangeEndLine: toPHPLineNumber(node.endPosition),
|
|
283
|
-
signature: sanitizePHPSignature(node, content),
|
|
284
|
-
doc: getPHPDocComment(node, content),
|
|
285
|
-
});
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
// property_declaration: プロパティ
|
|
289
|
-
else if (node.type === "property_declaration") {
|
|
290
|
-
// property_element から変数名を抽出
|
|
291
|
-
const propertyElement = node.namedChildren.find((child) => child.type === "property_element");
|
|
292
|
-
if (propertyElement) {
|
|
293
|
-
const variableNameNode = propertyElement.namedChildren.find((child) => child.type === "variable_name");
|
|
294
|
-
if (variableNameNode) {
|
|
295
|
-
const name = content
|
|
296
|
-
.substring(variableNameNode.startIndex, variableNameNode.endIndex)
|
|
297
|
-
.replace(/^\$/, ""); // $を除去
|
|
298
|
-
results.push({
|
|
299
|
-
name,
|
|
300
|
-
kind: "property",
|
|
301
|
-
rangeStartLine: toPHPLineNumber(node.startPosition),
|
|
302
|
-
rangeEndLine: toPHPLineNumber(node.endPosition),
|
|
303
|
-
signature: sanitizePHPSignature(node, content),
|
|
304
|
-
doc: getPHPDocComment(node, content),
|
|
305
|
-
});
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
// const_declaration: 定数(クラス定数)
|
|
310
|
-
else if (node.type === "const_declaration") {
|
|
311
|
-
const constElement = node.namedChildren.find((child) => child.type === "const_element");
|
|
312
|
-
if (constElement) {
|
|
313
|
-
const name = extractName(constElement);
|
|
314
|
-
if (name) {
|
|
315
|
-
results.push({
|
|
316
|
-
name,
|
|
317
|
-
kind: "constant",
|
|
318
|
-
rangeStartLine: toPHPLineNumber(node.startPosition),
|
|
319
|
-
rangeEndLine: toPHPLineNumber(node.endPosition),
|
|
320
|
-
signature: sanitizePHPSignature(node, content),
|
|
321
|
-
doc: getPHPDocComment(node, content),
|
|
322
|
-
});
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
// namespace_definition: 名前空間
|
|
327
|
-
else if (node.type === "namespace_definition") {
|
|
328
|
-
const namespaceName = node.namedChildren.find((child) => child.type === "namespace_name");
|
|
329
|
-
if (namespaceName) {
|
|
330
|
-
const name = content.substring(namespaceName.startIndex, namespaceName.endIndex);
|
|
331
|
-
results.push({
|
|
332
|
-
name,
|
|
333
|
-
kind: "namespace",
|
|
334
|
-
rangeStartLine: toPHPLineNumber(node.startPosition),
|
|
335
|
-
rangeEndLine: toPHPLineNumber(node.endPosition),
|
|
336
|
-
signature: sanitizePHPSignature(node, content),
|
|
337
|
-
doc: getPHPDocComment(node, content),
|
|
338
|
-
});
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
// 子ノードを再帰的に訪問
|
|
342
|
-
for (const child of node.namedChildren) {
|
|
343
|
-
visit(child);
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
visit(tree.rootNode);
|
|
347
|
-
return results
|
|
348
|
-
.sort((a, b) => a.rangeStartLine - b.rangeStartLine)
|
|
349
|
-
.map((item, index) => ({ symbolId: index + 1, ...item }));
|
|
350
|
-
}
|
|
351
|
-
/**
|
|
352
|
-
* PHPのuse文を解析して依存関係を収集
|
|
353
|
-
*/
|
|
354
|
-
function collectPHPDependencies(sourcePath, tree, content, _fileSet) {
|
|
355
|
-
const dependencies = new Map();
|
|
356
|
-
const record = (kind, dst) => {
|
|
357
|
-
const key = `${kind}:${dst}`;
|
|
358
|
-
if (!dependencies.has(key)) {
|
|
359
|
-
dependencies.set(key, { dstKind: kind, dst, rel: "import" });
|
|
360
|
-
}
|
|
361
|
-
};
|
|
362
|
-
function visit(node) {
|
|
363
|
-
// namespace_use_declaration: use文
|
|
364
|
-
if (node.type === "namespace_use_declaration") {
|
|
365
|
-
// namespace_use_clauseを探す(通常のuse文)
|
|
366
|
-
const useClauses = node.namedChildren.filter((child) => child.type === "namespace_use_clause");
|
|
367
|
-
for (const useClause of useClauses) {
|
|
368
|
-
// qualified_nameまたはnameを抽出
|
|
369
|
-
const qualifiedName = useClause.namedChildren.find((child) => child.type === "qualified_name" || child.type === "name");
|
|
370
|
-
if (qualifiedName) {
|
|
371
|
-
const importName = content.substring(qualifiedName.startIndex, qualifiedName.endIndex);
|
|
372
|
-
// Treat all namespaced imports as packages until composer.json parsing is implemented.
|
|
373
|
-
// PSR-4 maps namespace prefixes to base directories (e.g., App\ -> src/),
|
|
374
|
-
// not relative paths from the current file's directory.
|
|
375
|
-
// TODO: Implement proper PSR-4 resolution by parsing composer.json
|
|
376
|
-
record("package", importName);
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
// namespace_use_groupを探す(グループ化されたuse文: use Foo\{Bar, Baz};)
|
|
380
|
-
const useGroups = node.namedChildren.filter((child) => child.type === "namespace_use_group");
|
|
381
|
-
if (useGroups.length > 0) {
|
|
382
|
-
// プレフィックスを取得(例: App\Services)
|
|
383
|
-
const prefixNode = node.namedChildren.find((child) => child.type === "namespace_name");
|
|
384
|
-
const prefix = prefixNode
|
|
385
|
-
? content.substring(prefixNode.startIndex, prefixNode.endIndex)
|
|
386
|
-
: "";
|
|
387
|
-
for (const useGroup of useGroups) {
|
|
388
|
-
// namespace_use_group_clauseを処理
|
|
389
|
-
const groupClauses = useGroup.namedChildren.filter((child) => child.type === "namespace_use_group_clause");
|
|
390
|
-
for (const groupClause of groupClauses) {
|
|
391
|
-
const namespaceName = groupClause.namedChildren.find((child) => child.type === "namespace_name" || child.type === "name");
|
|
392
|
-
if (namespaceName) {
|
|
393
|
-
const suffix = content.substring(namespaceName.startIndex, namespaceName.endIndex);
|
|
394
|
-
const fullName = prefix ? `${prefix}\\${suffix}` : suffix;
|
|
395
|
-
// Treat all namespaced imports as packages (same reasoning as above)
|
|
396
|
-
record("package", fullName);
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
// 子ノードを再帰的に訪問
|
|
403
|
-
for (const child of node.namedChildren) {
|
|
404
|
-
visit(child);
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
visit(tree.rootNode);
|
|
408
|
-
return Array.from(dependencies.values());
|
|
409
|
-
}
|
|
410
|
-
/**
|
|
411
|
-
* Javaのシグネチャをサニタイズ(本体を除外し、最初の200文字に制限)
|
|
412
|
-
*/
|
|
413
|
-
function sanitizeJavaSignature(node, content) {
|
|
414
|
-
const nodeText = content.substring(node.startIndex, node.endIndex);
|
|
415
|
-
// メソッド本体({...})を除外
|
|
416
|
-
const bodyIndex = nodeText.indexOf("{");
|
|
417
|
-
const signatureText = bodyIndex >= 0 ? nodeText.substring(0, bodyIndex) : nodeText;
|
|
418
|
-
// 改行を空白に置き換えて1行に圧縮してから200文字に制限
|
|
419
|
-
// (先に改行処理することで、複数行シグネチャの情報が失われるのを防ぐ)
|
|
420
|
-
const normalized = signatureText.replace(/\s+/g, " ").trim();
|
|
421
|
-
return normalized.substring(0, 200);
|
|
422
|
-
}
|
|
423
|
-
/**
|
|
424
|
-
* Javadocコメント(/** */)を抽出
|
|
425
|
-
*/
|
|
426
|
-
function getJavaDocComment(node, content) {
|
|
427
|
-
const parent = node.parent;
|
|
428
|
-
if (!parent)
|
|
429
|
-
return null;
|
|
430
|
-
// 親ノードのすべての子から、このノードの直前にあるコメントを探す
|
|
431
|
-
const precedingComments = [];
|
|
432
|
-
const siblings = parent.children;
|
|
433
|
-
const nodeIndex = siblings.indexOf(node);
|
|
434
|
-
// このノードより前の兄弟を逆順で調べる
|
|
435
|
-
for (let i = nodeIndex - 1; i >= 0; i--) {
|
|
436
|
-
const sibling = siblings[i];
|
|
437
|
-
if (!sibling)
|
|
438
|
-
continue;
|
|
439
|
-
// block_commentをチェック
|
|
440
|
-
if (sibling.type === "block_comment") {
|
|
441
|
-
const commentText = content.substring(sibling.startIndex, sibling.endIndex);
|
|
442
|
-
// /** */ 形式のJavadocコメントのみ抽出
|
|
443
|
-
if (commentText.startsWith("/**") && commentText.endsWith("*/")) {
|
|
444
|
-
const cleanedComment = commentText
|
|
445
|
-
.replace(/^\/\*\*\s?|\s?\*\/$/g, "")
|
|
446
|
-
.replace(/^\s*\*\s?/gm, "")
|
|
447
|
-
.trim();
|
|
448
|
-
precedingComments.unshift(cleanedComment);
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
else if (!sibling.text.trim().match(/^\s*$/)) {
|
|
452
|
-
// コメント以外の実質的なノードに到達したら終了
|
|
453
|
-
break;
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
if (precedingComments.length === 0) {
|
|
457
|
-
return null;
|
|
458
|
-
}
|
|
459
|
-
return precedingComments.join("\n");
|
|
460
|
-
}
|
|
461
|
-
/**
|
|
462
|
-
* tree-sitterの位置情報から行番号を取得(1-based)
|
|
463
|
-
*/
|
|
464
|
-
function toJavaLineNumber(position) {
|
|
465
|
-
return position.row + 1;
|
|
466
|
-
}
|
|
467
|
-
/**
|
|
468
|
-
* Javaのシンボルレコードを作成
|
|
469
|
-
*/
|
|
470
|
-
function createJavaSymbolRecords(tree, content) {
|
|
471
|
-
const results = [];
|
|
472
|
-
/**
|
|
473
|
-
* 子ノードから識別子名を抽出
|
|
474
|
-
*/
|
|
475
|
-
function extractName(node) {
|
|
476
|
-
const identifierNode = node.namedChildren.find((child) => child.type === "identifier");
|
|
477
|
-
return identifierNode
|
|
478
|
-
? content.substring(identifierNode.startIndex, identifierNode.endIndex)
|
|
479
|
-
: null;
|
|
480
|
-
}
|
|
481
|
-
/**
|
|
482
|
-
* ツリーを再帰的にトラバースしてシンボルを抽出
|
|
483
|
-
*/
|
|
484
|
-
function visit(node) {
|
|
485
|
-
// class_declaration: クラス宣言
|
|
486
|
-
if (node.type === "class_declaration") {
|
|
487
|
-
const name = extractName(node);
|
|
488
|
-
if (name) {
|
|
489
|
-
results.push({
|
|
490
|
-
name,
|
|
491
|
-
kind: "class",
|
|
492
|
-
rangeStartLine: toJavaLineNumber(node.startPosition),
|
|
493
|
-
rangeEndLine: toJavaLineNumber(node.endPosition),
|
|
494
|
-
signature: sanitizeJavaSignature(node, content),
|
|
495
|
-
doc: getJavaDocComment(node, content),
|
|
496
|
-
});
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
// interface_declaration: インターフェース宣言
|
|
500
|
-
if (node.type === "interface_declaration") {
|
|
501
|
-
const name = extractName(node);
|
|
502
|
-
if (name) {
|
|
503
|
-
results.push({
|
|
504
|
-
name,
|
|
505
|
-
kind: "interface",
|
|
506
|
-
rangeStartLine: toJavaLineNumber(node.startPosition),
|
|
507
|
-
rangeEndLine: toJavaLineNumber(node.endPosition),
|
|
508
|
-
signature: sanitizeJavaSignature(node, content),
|
|
509
|
-
doc: getJavaDocComment(node, content),
|
|
510
|
-
});
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
// enum_declaration: 列挙型宣言
|
|
514
|
-
if (node.type === "enum_declaration") {
|
|
515
|
-
const name = extractName(node);
|
|
516
|
-
if (name) {
|
|
517
|
-
results.push({
|
|
518
|
-
name,
|
|
519
|
-
kind: "enum",
|
|
520
|
-
rangeStartLine: toJavaLineNumber(node.startPosition),
|
|
521
|
-
rangeEndLine: toJavaLineNumber(node.endPosition),
|
|
522
|
-
signature: sanitizeJavaSignature(node, content),
|
|
523
|
-
doc: getJavaDocComment(node, content),
|
|
524
|
-
});
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
// annotation_type_declaration: アノテーション型宣言
|
|
528
|
-
if (node.type === "annotation_type_declaration") {
|
|
529
|
-
const name = extractName(node);
|
|
530
|
-
if (name) {
|
|
531
|
-
results.push({
|
|
532
|
-
name,
|
|
533
|
-
kind: "annotation",
|
|
534
|
-
rangeStartLine: toJavaLineNumber(node.startPosition),
|
|
535
|
-
rangeEndLine: toJavaLineNumber(node.endPosition),
|
|
536
|
-
signature: sanitizeJavaSignature(node, content),
|
|
537
|
-
doc: getJavaDocComment(node, content),
|
|
538
|
-
});
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
// field_declaration: フィールド宣言
|
|
542
|
-
if (node.type === "field_declaration") {
|
|
543
|
-
// variable_declaratorから変数名を抽出
|
|
544
|
-
const declarators = node.namedChildren.filter((child) => child.type === "variable_declarator");
|
|
545
|
-
for (const declarator of declarators) {
|
|
546
|
-
const name = extractName(declarator);
|
|
547
|
-
if (name) {
|
|
548
|
-
results.push({
|
|
549
|
-
name,
|
|
550
|
-
kind: "field",
|
|
551
|
-
rangeStartLine: toJavaLineNumber(node.startPosition),
|
|
552
|
-
rangeEndLine: toJavaLineNumber(node.endPosition),
|
|
553
|
-
signature: sanitizeJavaSignature(node, content),
|
|
554
|
-
doc: getJavaDocComment(node, content),
|
|
555
|
-
});
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
// constructor_declaration: コンストラクタ宣言
|
|
560
|
-
if (node.type === "constructor_declaration") {
|
|
561
|
-
const name = extractName(node);
|
|
562
|
-
if (name) {
|
|
563
|
-
results.push({
|
|
564
|
-
name,
|
|
565
|
-
kind: "constructor",
|
|
566
|
-
rangeStartLine: toJavaLineNumber(node.startPosition),
|
|
567
|
-
rangeEndLine: toJavaLineNumber(node.endPosition),
|
|
568
|
-
signature: sanitizeJavaSignature(node, content),
|
|
569
|
-
doc: getJavaDocComment(node, content),
|
|
570
|
-
});
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
// method_declaration: メソッド宣言
|
|
574
|
-
if (node.type === "method_declaration") {
|
|
575
|
-
const name = extractName(node);
|
|
576
|
-
if (name) {
|
|
577
|
-
results.push({
|
|
578
|
-
name,
|
|
579
|
-
kind: "method",
|
|
580
|
-
rangeStartLine: toJavaLineNumber(node.startPosition),
|
|
581
|
-
rangeEndLine: toJavaLineNumber(node.endPosition),
|
|
582
|
-
signature: sanitizeJavaSignature(node, content),
|
|
583
|
-
doc: getJavaDocComment(node, content),
|
|
584
|
-
});
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
// annotation_type_element_declaration: アノテーション内のメソッド宣言
|
|
588
|
-
if (node.type === "annotation_type_element_declaration") {
|
|
589
|
-
const name = extractName(node);
|
|
590
|
-
if (name) {
|
|
591
|
-
results.push({
|
|
592
|
-
name,
|
|
593
|
-
kind: "method",
|
|
594
|
-
rangeStartLine: toJavaLineNumber(node.startPosition),
|
|
595
|
-
rangeEndLine: toJavaLineNumber(node.endPosition),
|
|
596
|
-
signature: sanitizeJavaSignature(node, content),
|
|
597
|
-
doc: getJavaDocComment(node, content),
|
|
598
|
-
});
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
// 子ノードを再帰的に訪問
|
|
602
|
-
for (const child of node.namedChildren) {
|
|
603
|
-
visit(child);
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
|
-
visit(tree.rootNode);
|
|
607
|
-
// symbolIdを割り当て
|
|
608
|
-
return results
|
|
609
|
-
.sort((a, b) => a.rangeStartLine - b.rangeStartLine)
|
|
610
|
-
.map((item, index) => ({ symbolId: index + 1, ...item }));
|
|
611
|
-
}
|
|
612
|
-
/**
|
|
613
|
-
* Javaのimport文を解析して依存関係を収集
|
|
614
|
-
*/
|
|
615
|
-
function collectJavaDependencies(_sourcePath, tree, content, fileSet) {
|
|
616
|
-
const dependencies = new Map();
|
|
617
|
-
const record = (kind, dst) => {
|
|
618
|
-
const key = `${kind}:${dst}`;
|
|
619
|
-
if (!dependencies.has(key)) {
|
|
620
|
-
dependencies.set(key, { dstKind: kind, dst, rel: "import" });
|
|
621
|
-
}
|
|
622
|
-
};
|
|
623
|
-
function visit(node) {
|
|
624
|
-
// import_declaration: import文
|
|
625
|
-
if (node.type === "import_declaration") {
|
|
626
|
-
// scoped_identifier または identifier を探す
|
|
627
|
-
const identifierNode = node.namedChildren.find((child) => child.type === "scoped_identifier" || child.type === "identifier");
|
|
628
|
-
if (identifierNode) {
|
|
629
|
-
let importName = content.substring(identifierNode.startIndex, identifierNode.endIndex);
|
|
630
|
-
// ワイルドカードインポートのチェック (import java.util.*)
|
|
631
|
-
// asteriskノードを探す
|
|
632
|
-
const hasAsterisk = node.namedChildren.some((child) => child.type === "asterisk");
|
|
633
|
-
if (hasAsterisk) {
|
|
634
|
-
importName += ".*";
|
|
635
|
-
}
|
|
636
|
-
// ローカルファイル判定: com.example.MyClass -> com/example/MyClass.java
|
|
637
|
-
// ワイルドカードの場合はパッケージとして扱う
|
|
638
|
-
let kind = "package";
|
|
639
|
-
if (!hasAsterisk) {
|
|
640
|
-
const filePath = importName.replace(/\./g, "/") + ".java";
|
|
641
|
-
// Maven/Gradle標準構造のプレフィックスを除去して完全一致でチェック
|
|
642
|
-
// これにより、同名ファイルが異なるパッケージに存在する場合も正確に解決できる
|
|
643
|
-
const matchingFile = Array.from(fileSet).find((f) => {
|
|
644
|
-
// 標準的なソースディレクトリプレフィックスを除去
|
|
645
|
-
const normalizedPath = f
|
|
646
|
-
.replace(/^src\/main\/java\//, "")
|
|
647
|
-
.replace(/^src\/test\/java\//, "")
|
|
648
|
-
.replace(/^src\//, "");
|
|
649
|
-
return normalizedPath === filePath;
|
|
650
|
-
});
|
|
651
|
-
kind = matchingFile ? "path" : "package";
|
|
652
|
-
}
|
|
653
|
-
record(kind, importName);
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
// 子ノードを再帰的に訪問
|
|
657
|
-
for (const child of node.namedChildren) {
|
|
658
|
-
visit(child);
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
visit(tree.rootNode);
|
|
662
|
-
return Array.from(dependencies.values());
|
|
663
|
-
}
|
|
664
|
-
function createSymbolRecords(source) {
|
|
665
|
-
const results = [];
|
|
666
|
-
const visit = (node) => {
|
|
667
|
-
if (ts.isFunctionDeclaration(node) && node.name) {
|
|
668
|
-
results.push({
|
|
669
|
-
name: node.name.getText(source),
|
|
670
|
-
kind: "function",
|
|
671
|
-
rangeStartLine: toLineNumber(source, node.getStart(source)),
|
|
672
|
-
rangeEndLine: toLineNumber(source, node.getEnd()),
|
|
673
|
-
signature: sanitizeSignature(source, node),
|
|
674
|
-
doc: getDocComment(node),
|
|
675
|
-
});
|
|
676
|
-
}
|
|
677
|
-
else if (ts.isClassDeclaration(node) && node.name) {
|
|
678
|
-
results.push({
|
|
679
|
-
name: node.name.getText(source),
|
|
680
|
-
kind: "class",
|
|
681
|
-
rangeStartLine: toLineNumber(source, node.getStart(source)),
|
|
682
|
-
rangeEndLine: toLineNumber(source, node.getEnd()),
|
|
683
|
-
signature: sanitizeSignature(source, node),
|
|
684
|
-
doc: getDocComment(node),
|
|
685
|
-
});
|
|
686
|
-
}
|
|
687
|
-
else if (ts.isInterfaceDeclaration(node) && node.name) {
|
|
688
|
-
results.push({
|
|
689
|
-
name: node.name.getText(source),
|
|
690
|
-
kind: "interface",
|
|
691
|
-
rangeStartLine: toLineNumber(source, node.getStart(source)),
|
|
692
|
-
rangeEndLine: toLineNumber(source, node.getEnd()),
|
|
693
|
-
signature: sanitizeSignature(source, node),
|
|
694
|
-
doc: getDocComment(node),
|
|
695
|
-
});
|
|
696
|
-
}
|
|
697
|
-
else if (ts.isEnumDeclaration(node) && node.name) {
|
|
698
|
-
results.push({
|
|
699
|
-
name: node.name.getText(source),
|
|
700
|
-
kind: "enum",
|
|
701
|
-
rangeStartLine: toLineNumber(source, node.getStart(source)),
|
|
702
|
-
rangeEndLine: toLineNumber(source, node.getEnd()),
|
|
703
|
-
signature: sanitizeSignature(source, node),
|
|
704
|
-
doc: getDocComment(node),
|
|
705
|
-
});
|
|
706
|
-
}
|
|
707
|
-
else if (ts.isMethodDeclaration(node) && node.name) {
|
|
708
|
-
const name = node.name.getText(source);
|
|
709
|
-
results.push({
|
|
710
|
-
name,
|
|
711
|
-
kind: "method",
|
|
712
|
-
rangeStartLine: toLineNumber(source, node.getStart(source)),
|
|
713
|
-
rangeEndLine: toLineNumber(source, node.getEnd()),
|
|
714
|
-
signature: sanitizeSignature(source, node),
|
|
715
|
-
doc: getDocComment(node),
|
|
716
|
-
});
|
|
717
|
-
}
|
|
718
|
-
ts.forEachChild(node, visit);
|
|
719
|
-
};
|
|
720
|
-
ts.forEachChild(source, visit);
|
|
721
|
-
return results
|
|
722
|
-
.sort((a, b) => a.rangeStartLine - b.rangeStartLine)
|
|
723
|
-
.map((item, index) => ({ symbolId: index + 1, ...item }));
|
|
724
|
-
}
|
|
725
|
-
/**
|
|
726
|
-
* Swiftのシンボルレコードを作成
|
|
727
|
-
*/
|
|
728
|
-
function createSwiftSymbolRecords(tree, content) {
|
|
729
|
-
const results = [];
|
|
730
|
-
/**
|
|
731
|
-
* 子ノードから識別子名を抽出(再帰的に探索)
|
|
732
|
-
*/
|
|
733
|
-
function extractName(node) {
|
|
734
|
-
function findIdentifier(n) {
|
|
735
|
-
if (n.type === "type_identifier" || n.type === "simple_identifier") {
|
|
736
|
-
return n;
|
|
737
|
-
}
|
|
738
|
-
for (const child of n.namedChildren) {
|
|
739
|
-
const found = findIdentifier(child);
|
|
740
|
-
if (found)
|
|
741
|
-
return found;
|
|
742
|
-
}
|
|
743
|
-
return null;
|
|
744
|
-
}
|
|
745
|
-
const identifierNode = findIdentifier(node);
|
|
746
|
-
return identifierNode
|
|
747
|
-
? content.substring(identifierNode.startIndex, identifierNode.endIndex)
|
|
748
|
-
: null;
|
|
749
|
-
}
|
|
750
|
-
/**
|
|
751
|
-
* class_declarationのキーワードから種類を判定
|
|
752
|
-
*/
|
|
753
|
-
function getClassDeclKind(node) {
|
|
754
|
-
for (const child of node.children) {
|
|
755
|
-
if (child.type === "class")
|
|
756
|
-
return "class";
|
|
757
|
-
if (child.type === "struct")
|
|
758
|
-
return "struct";
|
|
759
|
-
if (child.type === "enum")
|
|
760
|
-
return "enum";
|
|
761
|
-
if (child.type === "extension")
|
|
762
|
-
return "extension";
|
|
763
|
-
}
|
|
764
|
-
return null;
|
|
765
|
-
}
|
|
766
|
-
/**
|
|
767
|
-
* ツリーを再帰的にトラバースしてシンボルを抽出
|
|
768
|
-
*/
|
|
769
|
-
function visit(node) {
|
|
770
|
-
// class_declaration: class/struct/enum/extension
|
|
771
|
-
if (node.type === "class_declaration") {
|
|
772
|
-
const kind = getClassDeclKind(node);
|
|
773
|
-
const name = extractName(node);
|
|
774
|
-
if (kind && name) {
|
|
775
|
-
results.push({
|
|
776
|
-
name,
|
|
777
|
-
kind,
|
|
778
|
-
rangeStartLine: toSwiftLineNumber(node.startPosition),
|
|
779
|
-
rangeEndLine: toSwiftLineNumber(node.endPosition),
|
|
780
|
-
signature: sanitizeSwiftSignature(node, content),
|
|
781
|
-
doc: getSwiftDocComment(node, content),
|
|
782
|
-
});
|
|
783
|
-
}
|
|
784
|
-
}
|
|
785
|
-
// protocol_declaration
|
|
786
|
-
else if (node.type === "protocol_declaration") {
|
|
787
|
-
const name = extractName(node);
|
|
788
|
-
if (name) {
|
|
789
|
-
results.push({
|
|
790
|
-
name,
|
|
791
|
-
kind: "protocol",
|
|
792
|
-
rangeStartLine: toSwiftLineNumber(node.startPosition),
|
|
793
|
-
rangeEndLine: toSwiftLineNumber(node.endPosition),
|
|
794
|
-
signature: sanitizeSwiftSignature(node, content),
|
|
795
|
-
doc: getSwiftDocComment(node, content),
|
|
796
|
-
});
|
|
797
|
-
}
|
|
798
|
-
}
|
|
799
|
-
// function_declaration: トップレベル関数またはメソッド
|
|
800
|
-
else if (node.type === "function_declaration") {
|
|
801
|
-
const name = extractName(node);
|
|
802
|
-
if (name) {
|
|
803
|
-
// 親がclass_bodyの場合はmethod、それ以外はfunction
|
|
804
|
-
const kind = node.parent?.type === "class_body" ? "method" : "function";
|
|
805
|
-
results.push({
|
|
806
|
-
name,
|
|
807
|
-
kind,
|
|
808
|
-
rangeStartLine: toSwiftLineNumber(node.startPosition),
|
|
809
|
-
rangeEndLine: toSwiftLineNumber(node.endPosition),
|
|
810
|
-
signature: sanitizeSwiftSignature(node, content),
|
|
811
|
-
doc: getSwiftDocComment(node, content),
|
|
812
|
-
});
|
|
813
|
-
}
|
|
814
|
-
}
|
|
815
|
-
// init_declaration: イニシャライザ
|
|
816
|
-
else if (node.type === "init_declaration") {
|
|
817
|
-
results.push({
|
|
818
|
-
name: "init",
|
|
819
|
-
kind: "initializer",
|
|
820
|
-
rangeStartLine: toSwiftLineNumber(node.startPosition),
|
|
821
|
-
rangeEndLine: toSwiftLineNumber(node.endPosition),
|
|
822
|
-
signature: sanitizeSwiftSignature(node, content),
|
|
823
|
-
doc: getSwiftDocComment(node, content),
|
|
824
|
-
});
|
|
825
|
-
}
|
|
826
|
-
// property_declaration: プロパティ(クラス/構造体/プロトコル/エクステンション内のみ)
|
|
827
|
-
else if (node.type === "property_declaration") {
|
|
828
|
-
// 親がclass_body、struct_body、protocol_body、enum_class_body、extension_bodyの場合のみプロパティとして扱う
|
|
829
|
-
const isClassMember = node.parent?.type === "class_body" ||
|
|
830
|
-
node.parent?.type === "struct_body" ||
|
|
831
|
-
node.parent?.type === "protocol_body" ||
|
|
832
|
-
node.parent?.type === "enum_class_body" ||
|
|
833
|
-
node.parent?.type === "extension_body";
|
|
834
|
-
if (isClassMember) {
|
|
835
|
-
const name = extractName(node);
|
|
836
|
-
if (name) {
|
|
837
|
-
results.push({
|
|
838
|
-
name,
|
|
839
|
-
kind: "property",
|
|
840
|
-
rangeStartLine: toSwiftLineNumber(node.startPosition),
|
|
841
|
-
rangeEndLine: toSwiftLineNumber(node.endPosition),
|
|
842
|
-
signature: sanitizeSwiftSignature(node, content),
|
|
843
|
-
doc: getSwiftDocComment(node, content),
|
|
844
|
-
});
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
// protocol_function_declaration: プロトコル内のメソッド宣言
|
|
849
|
-
else if (node.type === "protocol_function_declaration") {
|
|
850
|
-
const name = extractName(node);
|
|
851
|
-
if (name) {
|
|
852
|
-
results.push({
|
|
853
|
-
name,
|
|
854
|
-
kind: "protocol_method",
|
|
855
|
-
rangeStartLine: toSwiftLineNumber(node.startPosition),
|
|
856
|
-
rangeEndLine: toSwiftLineNumber(node.endPosition),
|
|
857
|
-
signature: sanitizeSwiftSignature(node, content),
|
|
858
|
-
doc: getSwiftDocComment(node, content),
|
|
859
|
-
});
|
|
860
|
-
}
|
|
861
|
-
}
|
|
862
|
-
// 子ノードを再帰的に訪問
|
|
863
|
-
for (const child of node.namedChildren) {
|
|
864
|
-
visit(child);
|
|
865
|
-
}
|
|
866
|
-
}
|
|
867
|
-
visit(tree.rootNode);
|
|
868
|
-
return results
|
|
869
|
-
.sort((a, b) => a.rangeStartLine - b.rangeStartLine)
|
|
870
|
-
.map((item, index) => ({ symbolId: index + 1, ...item }));
|
|
871
|
-
}
|
|
872
|
-
function normalizePathSpecifier(sourcePath, specifier, fileSet) {
|
|
873
|
-
if (specifier.startsWith(".") || specifier.startsWith("/")) {
|
|
874
|
-
const baseDir = path.posix.dirname(sourcePath);
|
|
875
|
-
// Strip .js extension if present (ESM imports use .js but source files are .ts)
|
|
876
|
-
const pathWithoutJs = specifier.endsWith(".js") ? specifier.slice(0, -3) : specifier;
|
|
877
|
-
const joined = path.posix.normalize(path.posix.join(baseDir, pathWithoutJs));
|
|
878
|
-
const candidates = [
|
|
879
|
-
joined,
|
|
880
|
-
`${joined}.ts`,
|
|
881
|
-
`${joined}.tsx`,
|
|
882
|
-
`${joined}.js`,
|
|
883
|
-
`${joined}.jsx`,
|
|
884
|
-
`${joined}/index.ts`,
|
|
885
|
-
`${joined}/index.tsx`,
|
|
886
|
-
];
|
|
887
|
-
for (const candidate of candidates) {
|
|
888
|
-
if (fileSet.has(candidate)) {
|
|
889
|
-
return { kind: "path", target: candidate };
|
|
890
|
-
}
|
|
891
|
-
}
|
|
892
|
-
return null;
|
|
893
|
-
}
|
|
894
|
-
return { kind: "package", target: specifier };
|
|
895
|
-
}
|
|
896
|
-
function collectDependencies(sourcePath, source, fileSet) {
|
|
897
|
-
const dependencies = new Map();
|
|
898
|
-
const record = (kind, dst) => {
|
|
899
|
-
const key = `${kind}:${dst}`;
|
|
900
|
-
if (!dependencies.has(key)) {
|
|
901
|
-
dependencies.set(key, { dstKind: kind, dst, rel: "import" });
|
|
902
|
-
}
|
|
903
|
-
};
|
|
904
|
-
const visit = (node) => {
|
|
905
|
-
if (ts.isImportDeclaration(node) &&
|
|
906
|
-
node.moduleSpecifier &&
|
|
907
|
-
ts.isStringLiteral(node.moduleSpecifier)) {
|
|
908
|
-
const target = normalizePathSpecifier(sourcePath, node.moduleSpecifier.text, fileSet);
|
|
909
|
-
if (target) {
|
|
910
|
-
record(target.kind, target.target);
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
else if (ts.isExportDeclaration(node) &&
|
|
914
|
-
node.moduleSpecifier &&
|
|
915
|
-
ts.isStringLiteral(node.moduleSpecifier)) {
|
|
916
|
-
const target = normalizePathSpecifier(sourcePath, node.moduleSpecifier.text, fileSet);
|
|
917
|
-
if (target) {
|
|
918
|
-
record(target.kind, target.target);
|
|
919
|
-
}
|
|
920
|
-
}
|
|
921
|
-
else if (ts.isCallExpression(node)) {
|
|
922
|
-
const firstArg = node.arguments[0];
|
|
923
|
-
if (node.expression.getText(source) === "require" &&
|
|
924
|
-
node.arguments.length === 1 &&
|
|
925
|
-
firstArg &&
|
|
926
|
-
ts.isStringLiteral(firstArg)) {
|
|
927
|
-
const target = normalizePathSpecifier(sourcePath, firstArg.text, fileSet);
|
|
928
|
-
if (target) {
|
|
929
|
-
record(target.kind, target.target);
|
|
930
|
-
}
|
|
931
|
-
}
|
|
932
|
-
}
|
|
933
|
-
ts.forEachChild(node, visit);
|
|
934
|
-
};
|
|
935
|
-
ts.forEachChild(source, visit);
|
|
936
|
-
return Array.from(dependencies.values());
|
|
937
|
-
}
|
|
938
|
-
/**
|
|
939
|
-
* Swiftのimport文を解析して依存関係を収集
|
|
4
|
+
* 言語アナライザーシステムの公開APIを提供するファサード。
|
|
5
|
+
* 実際の解析処理は codeintel/ モジュールの LanguageRegistry に委譲。
|
|
6
|
+
*
|
|
7
|
+
* 使用例:
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { analyzeSource } from './codeintel.js';
|
|
10
|
+
*
|
|
11
|
+
* const result = await analyzeSource('src/index.ts', 'TypeScript', content, fileSet);
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export { buildFallbackSnippet } from "./codeintel/utils.js";
|
|
15
|
+
// Registry と Analyzer をインポート
|
|
16
|
+
import { createDartAnalyzer } from "./codeintel/dart/index.js";
|
|
17
|
+
import { createJavaAnalyzer } from "./codeintel/java/index.js";
|
|
18
|
+
import { createPHPAnalyzer } from "./codeintel/php/index.js";
|
|
19
|
+
import { LanguageRegistry } from "./codeintel/registry.js";
|
|
20
|
+
import { createRustAnalyzer } from "./codeintel/rust/index.js";
|
|
21
|
+
import { createSwiftAnalyzer } from "./codeintel/swift/index.js";
|
|
22
|
+
import { createTypeScriptAnalyzer } from "./codeintel/typescript/index.js";
|
|
23
|
+
// シングルトンレジストリを初期化
|
|
24
|
+
const registry = LanguageRegistry.getInstance();
|
|
25
|
+
// 全言語アナライザーを登録
|
|
26
|
+
registry.register(createTypeScriptAnalyzer());
|
|
27
|
+
registry.register(createSwiftAnalyzer());
|
|
28
|
+
registry.register(createPHPAnalyzer());
|
|
29
|
+
registry.register(createJavaAnalyzer());
|
|
30
|
+
registry.register(createDartAnalyzer());
|
|
31
|
+
registry.register(createRustAnalyzer());
|
|
32
|
+
/**
|
|
33
|
+
* ソースコードを解析してシンボル、スニペット、依存関係を抽出
|
|
34
|
+
*
|
|
35
|
+
* @param pathInRepo - リポジトリ内のファイルパス
|
|
36
|
+
* @param lang - 言語名 (TypeScript, Swift, PHP, Java, Dart など)
|
|
37
|
+
* @param content - ファイルコンテンツ
|
|
38
|
+
* @param fileSet - リポジトリ内の全ファイルパスセット (依存関係解決用)
|
|
39
|
+
* @param workspaceRoot - ワークスペースルート (Dart 解析で必須)
|
|
40
|
+
* @returns シンボル、スニペット、依存関係を含む解析結果
|
|
940
41
|
*/
|
|
941
|
-
function collectSwiftDependencies(sourcePath, tree, content, fileSet) {
|
|
942
|
-
const dependencies = new Map();
|
|
943
|
-
const record = (kind, dst) => {
|
|
944
|
-
const key = `${kind}:${dst}`;
|
|
945
|
-
if (!dependencies.has(key)) {
|
|
946
|
-
dependencies.set(key, { dstKind: kind, dst, rel: "import" });
|
|
947
|
-
}
|
|
948
|
-
};
|
|
949
|
-
function visit(node) {
|
|
950
|
-
if (node.type === "import_declaration") {
|
|
951
|
-
// import_declarationの子からidentifierを抽出
|
|
952
|
-
const identifier = node.namedChildren.find((child) => child.type === "identifier");
|
|
953
|
-
if (identifier) {
|
|
954
|
-
const moduleName = content.substring(identifier.startIndex, identifier.endIndex);
|
|
955
|
-
// Swiftファイルへの相対パスかどうかをチェック
|
|
956
|
-
// 通常はシステムモジュール(Foundation, UIKit等)が多いため"package"として扱う
|
|
957
|
-
const baseDir = path.posix.dirname(sourcePath);
|
|
958
|
-
const swiftPath = path.posix.normalize(path.posix.join(baseDir, `${moduleName}.swift`));
|
|
959
|
-
if (fileSet.has(swiftPath)) {
|
|
960
|
-
record("path", swiftPath);
|
|
961
|
-
}
|
|
962
|
-
else {
|
|
963
|
-
record("package", moduleName);
|
|
964
|
-
}
|
|
965
|
-
}
|
|
966
|
-
}
|
|
967
|
-
// 子ノードを再帰的に訪問
|
|
968
|
-
for (const child of node.namedChildren) {
|
|
969
|
-
visit(child);
|
|
970
|
-
}
|
|
971
|
-
}
|
|
972
|
-
visit(tree.rootNode);
|
|
973
|
-
return Array.from(dependencies.values());
|
|
974
|
-
}
|
|
975
42
|
export async function analyzeSource(pathInRepo, lang, content, fileSet, workspaceRoot) {
|
|
976
43
|
const normalizedLang = lang ?? "";
|
|
977
|
-
|
|
44
|
+
// サポート対象言語かチェック
|
|
45
|
+
if (!registry.isSupported(normalizedLang)) {
|
|
978
46
|
return { symbols: [], snippets: [], dependencies: [] };
|
|
979
47
|
}
|
|
980
|
-
//
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
}
|
|
988
|
-
// PHP language: use tree-sitter
|
|
989
|
-
if (normalizedLang === "PHP") {
|
|
990
|
-
try {
|
|
991
|
-
// Create new parser instance for each file (thread-safety for concurrent processing)
|
|
992
|
-
const parser = new Parser();
|
|
993
|
-
// tree-sitter-php provides two parsers:
|
|
994
|
-
// - php_only: for pure PHP files (<?php at start)
|
|
995
|
-
// - php: for HTML-mixed PHP files (HTML with <?php ... ?> tags)
|
|
996
|
-
const phpType = detectPHPType(content);
|
|
997
|
-
const language = phpType === "html-mixed" ? PHP_MIXED : PHP_ONLY;
|
|
998
|
-
// Validate language object before setting it
|
|
999
|
-
if (!language || typeof language !== "object") {
|
|
1000
|
-
throw new Error(`Tree-sitter language for PHP type "${phpType}" is invalid or undefined`);
|
|
1001
|
-
}
|
|
1002
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1003
|
-
parser.setLanguage(language);
|
|
1004
|
-
const tree = parser.parse(content);
|
|
1005
|
-
const symbols = createPHPSymbolRecords(tree, content);
|
|
1006
|
-
const snippets = symbols.map((symbol) => ({
|
|
1007
|
-
startLine: symbol.rangeStartLine,
|
|
1008
|
-
endLine: symbol.rangeEndLine,
|
|
1009
|
-
symbolId: symbol.symbolId,
|
|
1010
|
-
}));
|
|
1011
|
-
const dependencies = collectPHPDependencies(pathInRepo, tree, content, fileSet);
|
|
1012
|
-
return { symbols, snippets, dependencies };
|
|
1013
|
-
}
|
|
1014
|
-
catch (error) {
|
|
1015
|
-
// パース失敗時は空の結果を返して他のファイルの処理を継続
|
|
1016
|
-
console.error(`Failed to parse PHP file ${pathInRepo}:`, error);
|
|
1017
|
-
return { symbols: [], snippets: [], dependencies: [] };
|
|
1018
|
-
}
|
|
1019
|
-
}
|
|
1020
|
-
// Java言語の場合、tree-sitterを使用
|
|
1021
|
-
if (normalizedLang === "Java") {
|
|
1022
|
-
try {
|
|
1023
|
-
// 各ファイルごとに新しいパーサーインスタンスを作成(並行処理の安全性のため)
|
|
1024
|
-
const parser = new Parser();
|
|
1025
|
-
// Validate language object before setting it
|
|
1026
|
-
if (!Java || typeof Java !== "object") {
|
|
1027
|
-
throw new Error("Tree-sitter language for Java is invalid or undefined");
|
|
1028
|
-
}
|
|
1029
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1030
|
-
parser.setLanguage(Java);
|
|
1031
|
-
const tree = parser.parse(content);
|
|
1032
|
-
const symbols = createJavaSymbolRecords(tree, content);
|
|
1033
|
-
const snippets = symbols.map((symbol) => ({
|
|
1034
|
-
startLine: symbol.rangeStartLine,
|
|
1035
|
-
endLine: symbol.rangeEndLine,
|
|
1036
|
-
symbolId: symbol.symbolId,
|
|
1037
|
-
}));
|
|
1038
|
-
const dependencies = collectJavaDependencies(pathInRepo, tree, content, fileSet);
|
|
1039
|
-
return { symbols, snippets, dependencies };
|
|
1040
|
-
}
|
|
1041
|
-
catch (error) {
|
|
1042
|
-
// パース失敗時は空の結果を返して他のファイルの処理を継続
|
|
1043
|
-
console.error(`Failed to parse Java file ${pathInRepo}:`, error);
|
|
1044
|
-
return { symbols: [], snippets: [], dependencies: [] };
|
|
1045
|
-
}
|
|
1046
|
-
}
|
|
1047
|
-
// Swift言語の場合、tree-sitterを使用
|
|
1048
|
-
if (normalizedLang === "Swift") {
|
|
1049
|
-
try {
|
|
1050
|
-
// 各ファイルごとに新しいパーサーインスタンスを作成(並行処理の安全性のため)
|
|
1051
|
-
const parser = new Parser();
|
|
1052
|
-
// Validate language object before setting it
|
|
1053
|
-
if (!Swift || typeof Swift !== "object") {
|
|
1054
|
-
throw new Error("Tree-sitter language for Swift is invalid or undefined");
|
|
1055
|
-
}
|
|
1056
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1057
|
-
parser.setLanguage(Swift);
|
|
1058
|
-
const tree = parser.parse(content);
|
|
1059
|
-
const symbols = createSwiftSymbolRecords(tree, content);
|
|
1060
|
-
const snippets = symbols.map((symbol) => ({
|
|
1061
|
-
startLine: symbol.rangeStartLine,
|
|
1062
|
-
endLine: symbol.rangeEndLine,
|
|
1063
|
-
symbolId: symbol.symbolId,
|
|
1064
|
-
}));
|
|
1065
|
-
const dependencies = collectSwiftDependencies(pathInRepo, tree, content, fileSet);
|
|
1066
|
-
return { symbols, snippets, dependencies };
|
|
1067
|
-
}
|
|
1068
|
-
catch (error) {
|
|
1069
|
-
// パース失敗時は空の結果を返して他のファイルの処理を継続
|
|
1070
|
-
console.error(`Failed to parse Swift file ${pathInRepo}:`, error);
|
|
1071
|
-
return { symbols: [], snippets: [], dependencies: [] };
|
|
1072
|
-
}
|
|
1073
|
-
}
|
|
1074
|
-
// TypeScript言語の場合、TypeScript Compiler APIを使用
|
|
1075
|
-
const sourceFile = ts.createSourceFile(pathInRepo, content, ts.ScriptTarget.Latest, true);
|
|
1076
|
-
const symbols = createSymbolRecords(sourceFile);
|
|
1077
|
-
const snippets = symbols.map((symbol) => ({
|
|
1078
|
-
startLine: symbol.rangeStartLine,
|
|
1079
|
-
endLine: symbol.rangeEndLine,
|
|
1080
|
-
symbolId: symbol.symbolId,
|
|
1081
|
-
}));
|
|
1082
|
-
const dependencies = collectDependencies(pathInRepo, sourceFile, fileSet);
|
|
1083
|
-
return { symbols, snippets, dependencies };
|
|
48
|
+
// レジストリ経由で解析を実行
|
|
49
|
+
// exactOptionalPropertyTypes対応: workspaceRootはundefinedの場合は省略
|
|
50
|
+
return await registry.analyze(normalizedLang, {
|
|
51
|
+
pathInRepo,
|
|
52
|
+
content,
|
|
53
|
+
fileSet,
|
|
54
|
+
...(workspaceRoot !== undefined && { workspaceRoot }),
|
|
55
|
+
});
|
|
1084
56
|
}
|
|
1085
|
-
|
|
1086
|
-
|
|
57
|
+
/**
|
|
58
|
+
* 全言語アナライザーのリソースをクリーンアップ
|
|
59
|
+
*
|
|
60
|
+
* プロセス終了前に呼び出すことで、
|
|
61
|
+
* Dart Analysis Server などの外部プロセスを適切に終了
|
|
62
|
+
*/
|
|
63
|
+
export async function cleanup() {
|
|
64
|
+
await registry.cleanup();
|
|
1087
65
|
}
|
|
1088
66
|
//# sourceMappingURL=codeintel.js.map
|