meaoiu 0.1.3 → 0.1.4

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 (67) hide show
  1. package/LANGUAGE_GUIDE.md +1 -0
  2. package/README.md +385 -336
  3. package/dist/api/serviceState.d.ts +1 -1
  4. package/dist/api/serviceState.d.ts.map +1 -1
  5. package/dist/api/serviceState.js +1 -1
  6. package/dist/api/serviceState.js.map +1 -1
  7. package/dist/api/services/completions.d.ts.map +1 -1
  8. package/dist/api/services/completions.js +4 -3
  9. package/dist/api/services/completions.js.map +1 -1
  10. package/dist/api/services/formatting.d.ts +6 -1
  11. package/dist/api/services/formatting.d.ts.map +1 -1
  12. package/dist/api/services/formatting.js +156 -146
  13. package/dist/api/services/formatting.js.map +1 -1
  14. package/dist/api/services/inlayHints.d.ts +1 -1
  15. package/dist/api/services/inlayHints.d.ts.map +1 -1
  16. package/dist/api/services/inlayHints.js +1 -0
  17. package/dist/api/services/inlayHints.js.map +1 -1
  18. package/dist/api/services/search.d.ts.map +1 -1
  19. package/dist/api/services/search.js +5 -1
  20. package/dist/api/services/search.js.map +1 -1
  21. package/dist/api/utils/astUtils.d.ts.map +1 -1
  22. package/dist/api/utils/astUtils.js +18 -12
  23. package/dist/api/utils/astUtils.js.map +1 -1
  24. package/dist/api/utils/symbolAnalyzer.d.ts +1 -1
  25. package/dist/api/utils/symbolAnalyzer.d.ts.map +1 -1
  26. package/dist/api/utils/symbolAnalyzer.js +60 -63
  27. package/dist/api/utils/symbolAnalyzer.js.map +1 -1
  28. package/dist/cli/main.d.ts +0 -1
  29. package/dist/cli/main.js +3 -9
  30. package/dist/cli/main.js.map +1 -1
  31. package/dist/cli/tools/formatter.d.ts.map +1 -1
  32. package/dist/cli/tools/formatter.js +13 -3
  33. package/dist/cli/tools/formatter.js.map +1 -1
  34. package/dist/cli/tools/searcher.js +1 -1
  35. package/dist/cli/tools/searcher.js.map +1 -1
  36. package/dist/cli/tools/starter.d.ts +1 -2
  37. package/dist/cli/tools/starter.d.ts.map +1 -1
  38. package/dist/cli/tools/starter.js +5 -3
  39. package/dist/cli/tools/starter.js.map +1 -1
  40. package/dist/cli/tools/toolUtils.d.ts.map +1 -1
  41. package/dist/cli/tools/toolUtils.js +9 -13
  42. package/dist/cli/tools/toolUtils.js.map +1 -1
  43. package/dist/core/ast.d.ts +3 -2
  44. package/dist/core/ast.d.ts.map +1 -1
  45. package/dist/core/builtIns.d.ts.map +1 -1
  46. package/dist/core/builtIns.js +3 -1
  47. package/dist/core/builtIns.js.map +1 -1
  48. package/dist/core/error.d.ts +1 -0
  49. package/dist/core/error.d.ts.map +1 -1
  50. package/dist/core/error.js +4 -11
  51. package/dist/core/error.js.map +1 -1
  52. package/dist/core/lexer/tokenizer.d.ts +50 -50
  53. package/dist/core/lexer/tokenizer.d.ts.map +1 -1
  54. package/dist/core/lexer/tokenizer.js +59 -52
  55. package/dist/core/lexer/tokenizer.js.map +1 -1
  56. package/dist/core/parser.d.ts.map +1 -1
  57. package/dist/core/parser.js +176 -192
  58. package/dist/core/parser.js.map +1 -1
  59. package/dist/core/run/environment.js +3 -3
  60. package/dist/core/run/interpreter.d.ts.map +1 -1
  61. package/dist/core/run/interpreter.js +151 -157
  62. package/dist/core/run/interpreter.js.map +1 -1
  63. package/dist/core/run/io.d.ts.map +1 -1
  64. package/dist/core/run/io.js +4 -0
  65. package/dist/core/run/io.js.map +1 -1
  66. package/dist/core/typedef.js +5 -5
  67. package/package.json +3 -3
package/README.md CHANGED
@@ -1,336 +1,385 @@
1
- # 喵谕 Meaoiu
2
- > 知识好喵~
3
- ## 这是什么喵 (简介)
4
- 这是一门用手糊出来的、不确定是否适合正常人的编程语言喵~ 它不仅有一套**不**需要去挂精神科的**普通**语法,还极其自然地自带了代码格式化、静态诊断、自动补全等一整套工具喵~
5
- ### 不简之介
6
- 想懂就来这看看喵 -> **[喵谕语言半解](LANGUAGE_GUIDE.md)**
7
-
8
- ## 怎么领回家喵 (安装)
9
- 别问我为什么,既然是 Node.js 做的破烂,安装当然是用 npm 喵~
10
-
11
- ```bash
12
- npm install -g meaoiu
13
- ```
14
-
15
- (你也可以自己把这团代码抓下来执行 `npm install` 然后 `npm run build`,随你便喵)
16
-
17
- ## 怎么求它施法喵 (命令接口使用)
18
- 别告诉我你连终端模拟器都不认识喵~
19
- 大喊 `meaoiu` 召唤它喵!
20
- 文件名后缀是 `.miu` 喵~ 奇怪的东西不可以喵~
21
-
22
- **咏唱你的小作文喵**:`meaoiu <你的大典.miu>`
23
- - **--diagnose**:静态诊断喵~ 看看你的著作里藏了什么语病喵~
24
- - **--format**:格式整理喵~ 能把你那像狗啃一样乱的缩进和换行变得像猫舔一样乱喵~
25
- - **--definition <行:列>**:定义追溯喵~ 比如 `meaoiu 你的大典.miu --definition 2:3`,去抓这个玩具的本体喵~
26
- - **--references <行:列>**:调查引用喵~ 找出这个玩具的各种名字喵~
27
- - **--hover <行:列>**:悬停提示喵~ 凑数的东西喵~
28
- - **--complete <行:列>**:补全建议喵~ 不想打字就用这个喵~ ~~(可能要打更多字)~~
29
-
30
- ## 搞半天想自己拼喵 (编程接口使用)
31
- >(这里抄:[Meaoiu-LanguageServer](https://github.com/P-TNPC/Meaoiu-LanguageServer))
32
-
33
- 想自己做抓板配件?真上进喵~ 那些 LSP 零件都把肚皮露出来了喵~
34
- 灵魂就在 `StateManager` 和 `ServiceState` 喵~
35
-
36
- ```typescript
37
- import { StateManager, getDiagnostics, getFormattedCode } from 'meaoiu';
38
-
39
- // 1. 拿出状态管理器喵
40
- // true 表示行列号从 1 开始算,适合大多数人类喵
41
- const stateManager = new StateManager(true);
42
-
43
- // 2. 把你的小作文塞进去,伪装成文档状态喵
44
- const docState = StateManager.makeDocState(233, "扒[='闲话'=]喵~");
45
-
46
- // 3. 让管理器咬住文档状态,吐出服务状态喵
47
- const serviceState = stateManager.useState(docState);
48
-
49
- // 4. 开始压榨各种价值喵!
50
-
51
- // 格式化代码喵 (格式化不需要传 ServiceState,直接传源码字符串喵)
52
- const prettyCode = getFormattedCode('【#(偷懒)#]好不好?好喵~');
53
-
54
- // 诊断代码,看语病喵
55
- const { syntaxErrors, semanticErrors } = getDiagnostics(serviceState);
56
-
57
- // 别的魔法喵 (定义引用查找、补全等都要传入 serviceState 和 行列位置)
58
- import { getCompletions, findDefinition, getHoverInfo } from 'meaoiu';
59
-
60
- // 注意你的光标位置喵
61
- const pos = { line: 1, character: 4 }; // 对应 LSP 协议,传入的列号名为 character,输出的以实际为准(常用 col)
62
-
63
- const completions = getCompletions(serviceState, pos);
64
- const definition = findDefinition(serviceState, pos);
65
- const hover = getHoverInfo(serviceState, pos);
66
- ```
67
-
68
- 有没有看懂喵?看不懂就去复读一百遍 `ServiceState` 的源码喵!
69
-
70
- ## 防误食小零件清单喵 (编程接口说明)
71
-
72
- 既然你诚心诚意地想知道每个零件怎么用,我就大发慈悲地告诉你喵~
73
-
74
- ### 灵魂玩具喵 (`StateManager` 与 `ServiceState`)
75
-
76
- 灵魂就是这两个东西喵~ 帮你节省脑细胞(电脑的)喵~
77
-
78
- **`StateManager`** 负责记住你的小作文版本,减少重复解析喵~
79
- - `constructor(useOnebased = true)`:`useOnebased` 为 `true` 时行列号从 1 开始数,适合人类喵;为 `false` 时从 0 开始,适合机器喵~
80
- - `static makeDocState(version: number, sourceCode: string): DocState`:随便捏个文档状态玩具喵~ `version` 随便写个数字,变了就重新解析喵~
81
- - `updateState(doc: DocState): ServiceState`:强行更新状态(不管版本变没变)喵~
82
- - `useState(doc: DocState): ServiceState`:聪明地更新状态(版本变了才重新解析)喵~
83
- - `getParseResult(doc: DocState): ParseResult | undefined` 和 `getAnalyzeResult(doc: DocState): AnalyzeResult | undefined`:直接掏缓存喵~
84
-
85
- **`ServiceState`** 是一次解析的成果,包含抽象语法树和符号表喵~ 我不喜欢你 new 它喵,请让 `StateManager` 喂给你喵~
86
- - `version: number`:文档版本号喵~
87
- - `parseResult: ParseResult`:语法解析结果,里面有 `program`(AST 根节点)和 `errors`(语法错误)喵~
88
- - `analyzeResult: AnalyzeResult`:符号分析结果,里面有 `rootScope`、`symbolMap`、`nodeScopeMap` 和 `errors`(语义错误)喵~
89
-
90
- ### 格式整理喵 (`getFormattedCode`)
91
- ```typescript
92
- function getFormattedCode(sourceCode: string): string
93
- ```
94
-
95
- - **请求参数**:`sourceCode` —— 你乱糟糟的小人乍丶一乂字符串喵~
96
- - **响应格式**:整理好的小作文字符串喵~(缩进、换行、括号都会变漂亮喵)
97
- - **使用示例**:
98
- ```typescript
99
- import { getFormattedCode } from 'meaoiu';
100
- const pretty = getFormattedCode('扒【=零食=] 吃~');
101
- console.log(pretty); // 输出 "扒[= 零食 =]吃~"
102
- ```
103
-
104
- ### 静态诊断喵 (`getDiagnostics`)
105
- ```typescript
106
- function getDiagnostics(serviceState: ServiceState): Diagnostics
107
- ```
108
-
109
- - **请求参数**:`serviceState` —— [上面](#灵魂玩具喵-statemanager-与-servicestate)说过了喵~
110
- - **响应格式**:`{ syntaxErrors: MeaoiuError[], semanticErrors: MeaoiuError[] }` 喵~
111
- - `syntaxErrors`:语法错误,比如括号不配对、关键词写错喵~
112
- - `semanticErrors`:语义错误,比如变量未定义、类型不匹配、重复声明喵~
113
- - **使用示例**:
114
- ```typescript
115
- import { getDiagnostics } from 'meaoiu';
116
- const { syntaxErrors, semanticErrors } = getDiagnostics(serviceState);
117
- syntaxErrors.forEach(err => console.error(`第 ${err.line} 行有语病喵:${err.message}`));
118
- ```
119
-
120
- ### 补全建议喵 (`getCompletions`)
121
- ```typescript
122
- function getCompletions(serviceState: ServiceState, position: { line: number; character: number }): Suggestion[]
123
- ```
124
-
125
- - **请求参数**:
126
- - `serviceState`:上上面说过了喵~
127
- - `position`:光标位置喵~ `line` 和 `character` 的行列号取决于你构造 `StateManager` 时用的 `useOnebased` 喵~
128
- - **响应格式**:`Suggestion[]`,每个建议有 `label`(显示的文本)和 `kind`(类型)喵~ `kind` 是 `SuggestionKind` 枚举值,对应 LSP 的 `CompletionItemKind` 喵~
129
- - **使用示例**:
130
- ```typescript
131
- import { getCompletions } from 'meaoiu';
132
- const suggestions = getCompletions(serviceState, { line: 2, character: 5 });
133
- suggestions.forEach(s => console.log(`可以补全 ${s.label} (种类 ${s.kind})`));
134
- ```
135
-
136
- ### 定义追溯喵 (`findDefinition`)
137
- ```typescript
138
- function findDefinition(serviceState: ServiceState, position: { line: number; character: number }): SymbolInfo | undefined
139
- ```
140
-
141
- - **请求参数**:同上喵,光标位置喵~
142
- - **响应格式**:`SymbolInfo` 或 `undefined`(没找到)喵~ `SymbolInfo` 包含名字、种类、类型、声明位置、引用位置等喵~
143
- - **使用示例**:
144
- ```typescript
145
- import { findDefinition } from 'meaoiu';
146
- const def = findDefinition(serviceState, { line: 3, character: 7 });
147
- if (def) console.log(`定义在 L${def.declarations[0]?.line}:${def.declarations[0]?.col}`));
148
- ```
149
-
150
- ### 引用调查喵 (`findReferences`)
151
- ```typescript
152
- function findReferences(serviceState: ServiceState, position: { line: number; character: number }): Identifier[]
153
- ```
154
-
155
- - **请求参数**:光标位置喵~
156
- - **响应格式**:`Identifier[]`,该符号的所有名字喵~ 每个 `Identifier` 都有 `line`、`col`、`endLine`、`endCol` 喵~
157
- - **使用示例**:
158
- ```typescript
159
- import { findReferences } from 'meaoiu';
160
- const refs = findReferences(serviceState, { line: 4, character: 2 });
161
- refs.forEach(ref => console.log(`在 L${ref.line}:${ref.col} 被提到`));
162
- ```
163
-
164
- ### 悬停提示喵 (`getHoverInfo`)
165
- ```typescript
166
- type HoverInfo = {
167
- contents: {
168
- kind: 'markdown';
169
- value: string;
170
- };
171
- range: Range;
172
- };
173
- function getHoverInfo(serviceState: ServiceState, position: { line: number; character: number }): HoverInfo | undefined
174
- ```
175
-
176
- - **请求参数**:光标位置喵~
177
- - **响应格式**:`HoverInfo` 或 `undefined`喵~ `HoverInfo` 包含 `contents.value`(内容)和 `range`(悬停范围)喵~
178
- - **使用示例**:
179
- ```typescript
180
- import { getHoverInfo } from 'meaoiu';
181
- const hover = getHoverInfo(serviceState, { line: 5, character: 9 });
182
- if (hover) console.log(`悬停内容:${hover.contents.value}`);
183
- ```
184
-
185
- ### 语义高亮喵 (`getHighlightTokens` 和 `legend`)
186
- ```typescript
187
- function getHighlightTokens(serviceState: ServiceState): HighlightToken[]
188
- ```
189
-
190
- - **请求参数**:`serviceState` 喵~
191
- - **响应格式**:`HighlightToken[]`,每个 token 包含 `line`、`col`、`length`、`tokenType`、`tokenModifiers` 喵~ 配合 `legend` 使用喵~
192
- - **使用示例**:
193
- ```typescript
194
- import { getHighlightTokens, legend } from 'meaoiu';
195
- const tokens = getHighlightTokens(serviceState);
196
- // legend.tokenTypes legend.tokenModifiers 告诉你每个数字有何意味喵
197
- tokens.forEach(t => console.log(`在 L${t.line}:${t.col} 有类型 ${legend.tokenTypes[t.tokenType]}`));
198
- ```
199
-
200
- ### 内联提示喵 (`getInlayHints`)
201
- ```typescript
202
- function getInlayHints(serviceState: ServiceState): InlayHint[]
203
- ```
204
-
205
- - **请求参数**:`serviceState` 喵~
206
- - **响应格式**:`InlayHint[]`,每个提示有 `position`、`label`、`kind`、`paddingLeft`、`paddingRight` 喵~ `kind` 是 `InlayHintKind.Type` 或 `InlayHintKind.Parameter` 喵~
207
- - **使用示例**:
208
- ```typescript
209
- import { getInlayHints } from 'meaoiu';
210
- const hints = getInlayHints(serviceState);
211
- hints.forEach(h => console.log(`在 L${h.position.line}:${h.position.character} 显示 "${h.label}"`));
212
- ```
213
-
214
- ### 执行喵 (`execute`)
215
- 让编好的喵谕跑起来喵~
216
- ```typescript
217
- async function execute(
218
- sourceCode: string,
219
- ioConfig: {
220
- onPrint: (formattedString: string) => void;
221
- onPrompt: (question: string) => Promise<string>;
222
- styleize?: ((value: unknown, strValue: string) => string) | boolean;
223
- },
224
- options?: { useOnebased?: boolean, logLevel?: number },
225
- ): Promise<void>
226
- ```
227
- - **请求参数**:
228
- - `ioConfig`:必须传入输入输出函数,可以设置样式,默认(`true`)用 ANSI 颜色输出喵~
229
- - `options`:决定报错用什么坐标和输出多少废话(0 debug 1 info 2 warn 3 error)喵~
230
- - **使用示例**:
231
- ```typescript
232
- import { execute } from 'meaoiu';
233
- import readline from 'node:readline';
234
- const ioConfig = {
235
- onPrint: console.log,
236
- onPrompt: question => {
237
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
238
- return new Promise(resolve => rl.question(question, answer => {
239
- rl.close();
240
- resolve(answer);
241
- }));
242
- },
243
- styleize: (value, strValue) => value == null ? `💥${strValue}💥` : strValue,
244
- };
245
- try {
246
- await execute("蹭饭~扒[=饭, '好了喵~'=]喵~", ioConfig, { useOnebased: true, logLevel: 3 });
247
- // 输出:💥空碗💥 好了喵~
248
- } catch (error) {
249
- console.error(`坏了喵:${error}`);
250
- process.exit(1);
251
- }
252
- ```
253
-
254
- ### 小工具喵 (`rangeOf`)
255
- ```typescript
256
- function rangeOf(location: { line: number; col: number; endLine: number; endCol: number }): Range
257
- ```
258
- 方便对接 LSP 协议喵~ `location` 可以是各种节点或错误喵~
259
-
260
- ### 符号表相关喵 (`SymbolKind`, `SymbolTag`, `SymbolInfo`, `Scope`)
261
-
262
- 这些是类型定义喵,你遇见 `SymbolInfo` 时会用到喵~
263
-
264
- - `SymbolKind.FUNCTION`、`SymbolKind.VARIABLE`、`SymbolKind.PARAMETER`:符号种类喵~
265
- - `SymbolTag.NORMAL`、`SymbolTag.MOVED`、`SymbolTag.DECAYED`:符号状态喵(移动语义相关)~
266
- - `SymbolInfo`:符号的完整档案喵~
267
- - `Scope`:作用域树节点喵~
268
-
269
- ### 重新示范一次喵
270
-
271
- 最后给你一个完整的组装示例喵:
272
-
273
- ```typescript
274
- import {
275
- StateManager,
276
- getFormattedCode,
277
- getDiagnostics,
278
- getCompletions,
279
- findDefinition,
280
- findReferences,
281
- getHoverInfo,
282
- getHighlightTokens,
283
- getInlayHints,
284
- legend,
285
- SymbolKind
286
- } from 'meaoiu';
287
-
288
- // 1. 准备状态管理器
289
- const stateManager = new StateManager(true);
290
-
291
- // 2. 塞入你的大作
292
- const doc = StateManager.makeDocState(1, `
293
- 蹭 a~ a 就是 1~
294
- 想要 [= x =] 加一 [# 叼回来 x - 1~ #]~
295
- [= 3 =] 加一~
296
- `);
297
-
298
- // 3. 获取服务状态
299
- const serviceState = stateManager.useState(doc);
300
-
301
- // 4. 格式化
302
- console.log(getFormattedCode(doc.getText()));
303
-
304
- // 5. 诊断
305
- const diag = getDiagnostics(serviceState);
306
- console.log('语法错误:', diag.syntaxErrors.length);
307
- console.log('语义错误:', diag.semanticErrors.length);
308
-
309
- // 6. 补全(假设光标在第 2 行第 3 列)
310
- const completions = getCompletions(serviceState, { line: 2, character: 3 });
311
- console.log('补全建议:', completions.map(c => c.label));
312
-
313
- // 7. 定义查找(假设查找 "加一" 的定义)
314
- const def = findDefinition(serviceState, { line: 3, character: 5 });
315
- if (def?.kind === SymbolKind.FUNCTION) {
316
- console.log(`函数 "${def.name}" 定义在 L${def.declarations[0]?.line}`);
317
- }
318
-
319
- // 8. 引用查找
320
- const refs = findReferences(serviceState, { line: 2, character: 3 });
321
- console.log(`共有 ${refs.length} 处引用`);
322
-
323
- // 9. 悬停
324
- const hover = getHoverInfo(serviceState, { line: 1, character: 3 });
325
- if (hover) console.log('悬停内容:', hover.contents.value);
326
-
327
- // 10. 语义高亮
328
- const tokens = getHighlightTokens(serviceState);
329
- console.log(`生成了 ${tokens.length} 个高亮 token`);
330
-
331
- // 11. 内联提示
332
- const hints = getInlayHints(serviceState);
333
- console.log(`生成了 ${hints.length} 个内联提示`);
334
- ```
335
-
336
- 好了喵,零件清单给你了,自己拼喵!拼坏了别来找我喵~
1
+ # 喵谕 Meaoiu
2
+ > 知识好喵~
3
+ ## 这是什么喵 (简介)
4
+ 这是一门用手糊出来的、不确定是否适合正常人的编程语言喵~ 它不仅有一套**不**需要去挂精神科的**普通**语法,还极其自然地自带了代码格式化、静态诊断、自动补全等一整套工具喵~
5
+ ### 不简之介
6
+ 想懂就来这看看喵 -> **[喵谕语言半解](LANGUAGE_GUIDE.md)**
7
+
8
+ ## 怎么领回家喵 (安装)
9
+ 别问我为什么,既然是 Node.js 做的破烂,安装当然是用 npm 喵~
10
+
11
+ ```bash
12
+ npm install -g meaoiu
13
+ ```
14
+
15
+ (你也可以自己把这团代码抓下来执行 `npm install` 然后 `npm run build`,随你便喵)
16
+
17
+ ## 怎么求它施法喵 (命令接口使用)
18
+ 别告诉我你连终端模拟器都不认识喵~
19
+ 大喊 `meaoiu` 召唤它喵!
20
+ 文件名后缀是 `.miu` 喵~ 奇怪的东西不可以喵~
21
+
22
+ **咏唱你的小作文喵**:`meaoiu <你的大典.miu>`
23
+ - **--diagnose**:静态诊断喵~ 看看你的著作里藏了什么语病喵~
24
+ - **--format**:格式整理喵~ 能把你那像狗啃一样乱的缩进和换行变得像猫舔一样乱喵~
25
+ - **--definition <行:列>**:定义追溯喵~ 比如 `meaoiu 你的大典.miu --definition 2:3`,去抓这个玩具的本体喵~
26
+ - **--references <行:列>**:调查引用喵~ 找出这个玩具的各种名字喵~
27
+ - **--hover <行:列>**:悬停提示喵~ 凑数的东西喵~
28
+ - **--complete <行:列>**:补全建议喵~ 不想打字就用这个喵~ ~~(可能要打更多字)~~
29
+
30
+ ## 搞半天想自己拼喵 (编程接口使用)
31
+ >(这里抄:[Meaoiu-LanguageServer](https://github.com/P-TNPC/Meaoiu-LanguageServer))
32
+
33
+ 想自己做抓板配件?真上进喵~ 那些 LSP 零件都把肚皮露出来了喵~
34
+ 灵魂就在 `StateManager` 和 `ServiceState` 喵~
35
+
36
+ ```typescript
37
+ import { StateManager, getDiagnostics, getFormattedCode } from 'meaoiu';
38
+
39
+ // 1. 拿出状态管理器喵
40
+ // true 表示行列号从 1 开始算,适合大多数人类喵
41
+ const stateManager = new StateManager(true);
42
+
43
+ // 2. 把你的小作文塞进去,伪装成文档状态喵
44
+ const docState = StateManager.makeDocState(233, "扒[='闲话'=]喵~");
45
+
46
+ // 3. 让管理器咬住文档状态,吐出服务状态喵
47
+ const serviceState = stateManager.useState(docState);
48
+
49
+ // 4. 开始压榨各种价值喵!
50
+
51
+ // 格式化代码喵 (格式化不需要传 ServiceState,直接传源码字符串喵)
52
+ const prettyCode = getFormattedCode('【#(偷懒)#]好不好?好喵~').format();
53
+
54
+ // 诊断代码,看语病喵
55
+ const { syntaxErrors, semanticErrors } = getDiagnostics(serviceState);
56
+
57
+ // 别的魔法喵 (定义引用查找、补全等都要传入 serviceState 和 行列位置)
58
+ import { getCompletions, findDefinition, getHoverInfo } from 'meaoiu';
59
+
60
+ // 注意你的光标位置喵
61
+ const pos = { line: 1, character: 4 }; // 对应 LSP 协议,传入的列号名为 character,输出的以实际为准(常用 col)
62
+
63
+ const completions = getCompletions(serviceState, pos);
64
+ const definition = findDefinition(serviceState, pos);
65
+ const hover = getHoverInfo(serviceState, pos);
66
+ ```
67
+
68
+ 有没有看懂喵?看不懂就去复读一百遍 `ServiceState` 的源码喵!
69
+
70
+ ## 防误食小零件清单喵 (编程接口说明)
71
+
72
+ 既然你诚心诚意地想知道每个零件怎么用,我就大发慈悲地告诉你喵~
73
+
74
+ ### 灵魂玩具喵 (`StateManager` 与 `ServiceState`)
75
+
76
+ 灵魂就是这两个东西喵~ 帮你节省脑细胞(电脑的)喵~
77
+
78
+ **`StateManager`** 负责记住你的小作文版本,减少重复解析喵~
79
+ - `constructor(useOnebased = true)`:`useOnebased` 为 `true` 时行列号从 1 开始数,适合人类喵;为 `false` 时从 0 开始,适合机器喵~
80
+ - `static makeDocState(version: number, sourceCode: string): DocState`:随便捏个文档状态玩具喵~ `version` 随便写个数字,变了就重新解析喵~
81
+ - `updateState(doc: DocState): ServiceState`:强行更新状态(不管版本变没变)喵~
82
+ - `useState(doc: DocState): ServiceState`:聪明地更新状态(版本变了才重新解析)喵~
83
+ - `getParseResult(doc: DocState): ParseResult | undefined` 和 `getAnalyzeResult(doc: DocState): AnalyzeResult | undefined`:直接掏缓存喵~
84
+
85
+ **`ServiceState`** 是一次解析的成果,包含抽象语法树和符号表喵~ 我不喜欢你 new 它喵,请让 `StateManager` 喂给你喵~
86
+ - `version: number`:文档版本号喵~
87
+ - `parseResult: ParseResult`:语法解析结果,里面有 `program`(AST 根节点)和 `errors`(语法错误)喵~
88
+ - `analyzeResult: AnalyzeResult`:符号分析结果,里面有 `rootScope`、`symbolMap`、`nodeScopeMap` 和 `errors`(语义错误)喵~
89
+
90
+ ### 记仇纸条喵 (`MeaoiuError`)
91
+
92
+ 各种错误都用它的记录喵~ 让你知道为什么哈喵~
93
+
94
+ ```typescript
95
+ class MeaoiuError {
96
+ readonly message: string;
97
+ readonly phase: 0 | 1 | 2 | 3 | 4 | 5; // 错在哪个阶段
98
+ readonly line: number;
99
+ readonly col: number;
100
+ readonly endLine: number;
101
+ readonly endCol: number;
102
+ readonly messageWithPhase: string; // 如 "句法错误喵:..."
103
+ toString(): string; // 方便生成一条 "[行:列] 消息"
104
+ static readonly phaseTextTuple: readonly [string, string, string, string, string, string];
105
+ }
106
+ ```
107
+
108
+ - **字段说明**:
109
+ - `phase`:数字枚举喵~ 含义:`0 未知错误`、`1 内部错误`、`2 词法错误`、`3 句法错误`、`4 语义错误`、`5 运行错误`喵~ 可以用 `MeaoiuError.phaseTextTuple[phase]` 拿到名字喵~
110
+ - `line`/`col`/`endLine`/`endCol`:错误坐标喵~
111
+ - `message`:错误消息喵~ `messageWithPhase` 就是说了错在哪阶段的版本喵~
112
+ - **使用示例**:
113
+ ```typescript
114
+ import { getDiagnostics, MeaoiuError } from 'meaoiu';
115
+ const { syntaxErrors, semanticErrors } = getDiagnostics(serviceState);
116
+ [...syntaxErrors, ...semanticErrors].forEach(err => {
117
+ console.log(`[${MeaoiuError.phaseTextTuple[err.phase]}] L${err.line}:${err.col} ${err.message}`);
118
+ });
119
+ ```
120
+
121
+ ### 格式整理喵 (`getFormattedCode`)
122
+ ```typescript
123
+ type FormatResult = {
124
+ errors: MeaoiuError[]; // 解析错误
125
+ format: () => string; // 调用获得格式化结果
126
+ };
127
+ function getFormattedCode(sourceCode: string): FormatResult
128
+ ```
129
+
130
+ - **请求参数**:`sourceCode` —— 你乱糟糟的小人乍丶一乂字符串喵~
131
+ - **响应格式**:`FormatResult` 喵~ 包含 `errors` 数组和 `format` 函数喵~ 调用 `format()` 就能得到整理好的小作文字符串喵~(缩进、换行、括号都会变漂亮喵)
132
+ - **使用示例**:
133
+ ```typescript
134
+ import { getFormattedCode } from 'meaoiu';
135
+ const { errors, format } = getFormattedCode('扒【=零食=] 吃~');
136
+ console.log(errors); // 查看解析错误
137
+ // if (errors.length) throw new Error('再继续下去会坏掉的喵'); // 可以顺便爆炸
138
+ console.log(format()); // 输出 "扒[= 零食 =]吃~"
139
+ ```
140
+
141
+ ### 静态诊断喵 (`getDiagnostics`)
142
+ ```typescript
143
+ function getDiagnostics(serviceState: ServiceState): Diagnostics
144
+ ```
145
+
146
+ - **请求参数**:`serviceState` —— [上面](#灵魂玩具喵-statemanager-与-servicestate)说过了喵~
147
+ - **响应格式**:`{ syntaxErrors: MeaoiuError[], semanticErrors: MeaoiuError[] }` 喵~
148
+ - `syntaxErrors`:语法错误,比如括号不配对、关键词写错喵~
149
+ - `semanticErrors`:语义错误,比如变量未定义、类型不匹配、重复声明喵~
150
+ - **使用示例**:
151
+ ```typescript
152
+ import { getDiagnostics } from 'meaoiu';
153
+ const { syntaxErrors, semanticErrors } = getDiagnostics(serviceState);
154
+ syntaxErrors.forEach(err => console.error(`第 ${err.line} 行有语病喵:${err.message}`));
155
+ ```
156
+
157
+ ### 补全建议喵 (`getCompletions`)
158
+ ```typescript
159
+ function getCompletions(serviceState: ServiceState, position: { line: number; character: number }): Suggestion[]
160
+ ```
161
+
162
+ - **请求参数**:
163
+ - `serviceState`:上上面说过了喵~
164
+ - `position`:光标位置喵~ `line` 和 `character` 的行列号取决于你构造 `StateManager` 时用的 `useOnebased` 喵~
165
+ - **响应格式**:`Suggestion[]`,每个建议有 `label`(显示的文本)和 `kind`(类型)喵~ `kind` 是 `SuggestionKind` 枚举值 `3 | 6 | 14 | 18`,对应 LSP 的 `CompletionItemKind` 喵~
166
+ - **使用示例**:
167
+ ```typescript
168
+ import { getCompletions } from 'meaoiu';
169
+ const suggestions = getCompletions(serviceState, { line: 2, character: 5 });
170
+ suggestions.forEach(s => console.log(`可以补全 ${s.label} (种类 ${s.kind})`));
171
+ ```
172
+
173
+ ### 定义追溯喵 (`findDefinition`)
174
+ ```typescript
175
+ function findDefinition(serviceState: ServiceState, position: { line: number; character: number }): SymbolInfo | undefined
176
+ ```
177
+
178
+ - **请求参数**:同上喵,光标位置喵~
179
+ - **响应格式**:`SymbolInfo` 或 `undefined`(没找到)喵~ `SymbolInfo` 包含名字、种类、类型、声明位置、引用位置等喵~
180
+ - **使用示例**:
181
+ ```typescript
182
+ import { findDefinition } from 'meaoiu';
183
+ const def = findDefinition(serviceState, { line: 3, character: 7 });
184
+ if (def) console.log(`定义在 L${def.declarations[0]?.line}:${def.declarations[0]?.col}`));
185
+ ```
186
+
187
+ ### 引用调查喵 (`findReferences`)
188
+ ```typescript
189
+ function findReferences(serviceState: ServiceState, position: { line: number; character: number }): Identifier[]
190
+ ```
191
+
192
+ - **请求参数**:光标位置喵~
193
+ - **响应格式**:`Identifier[]`,该符号的所有名字喵~ 每个 `Identifier` 都有 `line`、`col`、`endLine`、`endCol` 喵~
194
+ - **使用示例**:
195
+ ```typescript
196
+ import { findReferences } from 'meaoiu';
197
+ const refs = findReferences(serviceState, { line: 4, character: 2 });
198
+ refs.forEach(ref => console.log(`在 L${ref.line}:${ref.col} 被提到`));
199
+ ```
200
+
201
+ ### 悬停提示喵 (`getHoverInfo`)
202
+ ```typescript
203
+ type MarkupKind = 'plaintext' | 'markdown';
204
+ type HoverInfo = {
205
+ contents: {
206
+ kind: MarkupKind;
207
+ value: string;
208
+ };
209
+ range: Range;
210
+ };
211
+ function getHoverInfo(
212
+ serviceState: ServiceState,
213
+ position: { line: number; character: number },
214
+ contentsKind?: MarkupKind, // 默认 'markdown'
215
+ ): HoverInfo | undefined
216
+ ```
217
+
218
+ - **请求参数**:光标位置喵~ 可选 `contentsKind` 指定内容格式喵~
219
+ - **响应格式**:`HoverInfo` 或 `undefined` 喵~ `HoverInfo` 包含 `contents.value`(内容)、`contents.kind`(内容格式)和 `range`(悬停范围)喵~
220
+ - **使用示例**:
221
+ ```typescript
222
+ import { getHoverInfo } from 'meaoiu';
223
+ const hover = getHoverInfo(serviceState, { line: 5, character: 9 }, 'plaintext');
224
+ if (hover) console.log(`悬停内容:${hover.contents.value}`);
225
+ ```
226
+
227
+ ### 语义高亮喵 (`getHighlightTokens` 和 `legend`)
228
+ ```typescript
229
+ function getHighlightTokens(serviceState: ServiceState): HighlightToken[]
230
+ ```
231
+
232
+ - **请求参数**:`serviceState` 喵~
233
+ - **响应格式**:`HighlightToken[]`,每个 token 包含 `line`、`col`、`length`、`tokenType`、`tokenModifiers` 喵~ 配合 `legend` 使用喵~
234
+ - **使用示例**:
235
+ ```typescript
236
+ import { getHighlightTokens, legend } from 'meaoiu';
237
+ const tokens = getHighlightTokens(serviceState);
238
+ // legend.tokenTypes legend.tokenModifiers 告诉你每个数字有何意味喵
239
+ tokens.forEach(t => console.log(`在 L${t.line}:${t.col} 有类型 ${legend.tokenTypes[t.tokenType]}`));
240
+ ```
241
+
242
+ ### 内联提示喵 (`getInlayHints`)
243
+ ```typescript
244
+ type InlayHint = {
245
+ position: Position;
246
+ label: string;
247
+ kind: 1 | 2; // 1 = Type, 2 = Parameter
248
+ paddingLeft?: boolean;
249
+ paddingRight: boolean;
250
+ };
251
+ function getInlayHints(serviceState: ServiceState): InlayHint[]
252
+ ```
253
+
254
+ - **请求参数**:`serviceState` 喵~
255
+ - **响应格式**:`InlayHint[]`,每个提示有 `position`、`label`、`kind`、`paddingLeft`、`paddingRight` 喵~ `kind` 为 `1`(类型提示)或 `2`(参数提示)喵~
256
+ - **使用示例**:
257
+ ```typescript
258
+ import { getInlayHints } from 'meaoiu';
259
+ const hints = getInlayHints(serviceState);
260
+ hints.forEach(h => console.log(`在 L${h.position.line}:${h.position.character} 显示 "${h.label}"`));
261
+ ```
262
+
263
+ ### 执行喵 (`execute`)
264
+ 让编好的喵谕跑起来喵~
265
+ ```typescript
266
+ async function execute(
267
+ sourceCode: string,
268
+ ioConfig: {
269
+ onPrint: (formattedString: string) => void;
270
+ onPrompt: (question: string) => Promise<string>;
271
+ styleize?: ((value: unknown, strValue: string) => string) | boolean;
272
+ },
273
+ options?: { useOnebased?: boolean, logLevel?: 0 | 1 | 2 | 3 },
274
+ ): Promise<void>
275
+ ```
276
+ - **请求参数**:
277
+ - `ioConfig`:必须传入输入输出函数,可以设置样式,默认(`true`)用 ANSI 颜色输出喵~
278
+ - `options`:决定报错用什么坐标和输出多少废话(0 debug 1 info 2 warn 3 error)喵~
279
+ - **使用示例**:
280
+ ```typescript
281
+ import { execute } from 'meaoiu';
282
+ import readline from 'node:readline';
283
+ const ioConfig = {
284
+ onPrint: console.log,
285
+ onPrompt: question => {
286
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
287
+ return new Promise(resolve => rl.question(question, answer => {
288
+ rl.close();
289
+ resolve(answer);
290
+ }));
291
+ },
292
+ styleize: (value, strValue) => value == null ? `💥${strValue}💥` : strValue,
293
+ };
294
+ try {
295
+ await execute("蹭饭~扒[=饭, '好了喵~'=]喵~", ioConfig, { useOnebased: true, logLevel: 3 });
296
+ // 输出:💥空碗💥 好了喵~
297
+ } catch (error) {
298
+ console.error(`坏了喵:${error}`);
299
+ process.exit(1);
300
+ }
301
+ ```
302
+
303
+ ### 小工具喵 (`rangeOf`)
304
+ ```typescript
305
+ function rangeOf(location: { line: number; col: number; endLine: number; endCol: number }): Range
306
+ ```
307
+ 方便对接 LSP 协议喵~ `location` 可以是各种节点或错误喵~
308
+
309
+ ### 符号表相关喵 (`SymbolKind`, `SymbolTag`, `SymbolInfo`, `Scope`)
310
+
311
+ 这些是类型定义喵,你遇见 `SymbolInfo` 时会用到喵~
312
+
313
+ - `SymbolKind`(`12 | 13 | 20`):`FUNCTION = 12`、`VARIABLE = 13`、`PARAMETER = 20` 符号种类喵~
314
+ - `SymbolTag`(`0 | 1 | 2`):`NORMAL = 0`、`MOVED = 1`、`DECAYED = 2` 符号状态喵(移动语义相关)~
315
+ - `SymbolInfo`:符号的完整档案喵~ 包含 `name`、`kind`、`tag`、`type`、`valueRef`、`declarations`、`references`、`isBuiltIn` 喵~
316
+ - `Scope`:作用域树节点喵~ 包含 `parent`、`children`、`symbols` 喵~
317
+
318
+ ### 重新示范一次喵
319
+
320
+ 最后给你一个完整的组装示例喵:
321
+
322
+ ```typescript
323
+ import {
324
+ StateManager,
325
+ getFormattedCode,
326
+ getDiagnostics,
327
+ getCompletions,
328
+ findDefinition,
329
+ findReferences,
330
+ getHoverInfo,
331
+ getHighlightTokens,
332
+ getInlayHints,
333
+ legend,
334
+ SymbolKind
335
+ } from 'meaoiu';
336
+
337
+ // 1. 准备状态管理器
338
+ const stateManager = new StateManager(true);
339
+
340
+ // 2. 塞入你的大作
341
+ const doc = StateManager.makeDocState(1, `
342
+ 蹭 a~ a 就是 1~
343
+ 想要 [= x =] 加一 [# 叼回来 x - 1~ #]~
344
+ 扒 [= 3 =] 加一~
345
+ `);
346
+
347
+ // 3. 获取服务状态
348
+ const serviceState = stateManager.useState(doc);
349
+
350
+ // 4. 格式化
351
+ console.log(getFormattedCode(doc.getText()).format());
352
+
353
+ // 5. 诊断
354
+ const diag = getDiagnostics(serviceState);
355
+ console.log('语法错误:', diag.syntaxErrors.length);
356
+ console.log('语义错误:', diag.semanticErrors.length);
357
+
358
+ // 6. 补全(假设光标在第 2 行第 3 列)
359
+ const completions = getCompletions(serviceState, { line: 2, character: 3 });
360
+ console.log('补全建议:', completions.map(c => c.label));
361
+
362
+ // 7. 定义查找(假设查找 "加一" 的定义)
363
+ const def = findDefinition(serviceState, { line: 3, character: 5 });
364
+ if (def?.kind === SymbolKind.FUNCTION) {
365
+ console.log(`函数 "${def.name}" 定义在 L${def.declarations[0]?.line}`);
366
+ }
367
+
368
+ // 8. 引用查找
369
+ const refs = findReferences(serviceState, { line: 2, character: 3 });
370
+ console.log(`共有 ${refs.length} 处引用`);
371
+
372
+ // 9. 悬停
373
+ const hover = getHoverInfo(serviceState, { line: 1, character: 3 });
374
+ if (hover) console.log('悬停内容:', hover.contents.value);
375
+
376
+ // 10. 语义高亮
377
+ const tokens = getHighlightTokens(serviceState);
378
+ console.log(`生成了 ${tokens.length} 个高亮 token`);
379
+
380
+ // 11. 内联提示
381
+ const hints = getInlayHints(serviceState);
382
+ console.log(`生成了 ${hints.length} 个内联提示`);
383
+ ```
384
+
385
+ 好了喵,零件清单给你了,自己拼喵!拼坏了别来找我喵~