redscript-mc 1.0.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/.github/ISSUE_TEMPLATE/bug_report.md +40 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +31 -0
- package/.github/ISSUE_TEMPLATE/wrong_output.md +33 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +34 -0
- package/.github/workflows/ci.yml +29 -0
- package/.github/workflows/publish-extension.yml +35 -0
- package/LICENSE +21 -0
- package/README.md +261 -0
- package/README.zh.md +261 -0
- package/dist/__tests__/cli.test.d.ts +1 -0
- package/dist/__tests__/cli.test.js +140 -0
- package/dist/__tests__/codegen.test.d.ts +1 -0
- package/dist/__tests__/codegen.test.js +121 -0
- package/dist/__tests__/diagnostics.test.d.ts +4 -0
- package/dist/__tests__/diagnostics.test.js +149 -0
- package/dist/__tests__/e2e.test.d.ts +6 -0
- package/dist/__tests__/e2e.test.js +1528 -0
- package/dist/__tests__/lexer.test.d.ts +1 -0
- package/dist/__tests__/lexer.test.js +316 -0
- package/dist/__tests__/lowering.test.d.ts +1 -0
- package/dist/__tests__/lowering.test.js +819 -0
- package/dist/__tests__/mc-integration.test.d.ts +12 -0
- package/dist/__tests__/mc-integration.test.js +395 -0
- package/dist/__tests__/mc-syntax.test.d.ts +1 -0
- package/dist/__tests__/mc-syntax.test.js +112 -0
- package/dist/__tests__/nbt.test.d.ts +1 -0
- package/dist/__tests__/nbt.test.js +82 -0
- package/dist/__tests__/optimizer-advanced.test.d.ts +1 -0
- package/dist/__tests__/optimizer-advanced.test.js +124 -0
- package/dist/__tests__/optimizer.test.d.ts +1 -0
- package/dist/__tests__/optimizer.test.js +118 -0
- package/dist/__tests__/parser.test.d.ts +1 -0
- package/dist/__tests__/parser.test.js +717 -0
- package/dist/__tests__/repl.test.d.ts +1 -0
- package/dist/__tests__/repl.test.js +27 -0
- package/dist/__tests__/runtime.test.d.ts +1 -0
- package/dist/__tests__/runtime.test.js +276 -0
- package/dist/__tests__/structure-optimizer.test.d.ts +1 -0
- package/dist/__tests__/structure-optimizer.test.js +33 -0
- package/dist/__tests__/typechecker.test.d.ts +1 -0
- package/dist/__tests__/typechecker.test.js +364 -0
- package/dist/ast/types.d.ts +357 -0
- package/dist/ast/types.js +9 -0
- package/dist/cli.d.ts +11 -0
- package/dist/cli.js +407 -0
- package/dist/codegen/cmdblock/index.d.ts +26 -0
- package/dist/codegen/cmdblock/index.js +45 -0
- package/dist/codegen/mcfunction/index.d.ts +34 -0
- package/dist/codegen/mcfunction/index.js +413 -0
- package/dist/codegen/structure/index.d.ts +18 -0
- package/dist/codegen/structure/index.js +249 -0
- package/dist/compile.d.ts +30 -0
- package/dist/compile.js +152 -0
- package/dist/data/arena/function/__load.mcfunction +6 -0
- package/dist/data/arena/function/__tick.mcfunction +2 -0
- package/dist/data/arena/function/announce_leaders/else_1.mcfunction +3 -0
- package/dist/data/arena/function/announce_leaders/foreach_0/merge_2.mcfunction +1 -0
- package/dist/data/arena/function/announce_leaders/foreach_0/then_0.mcfunction +3 -0
- package/dist/data/arena/function/announce_leaders/foreach_0.mcfunction +7 -0
- package/dist/data/arena/function/announce_leaders/foreach_1/merge_2.mcfunction +1 -0
- package/dist/data/arena/function/announce_leaders/foreach_1/then_0.mcfunction +4 -0
- package/dist/data/arena/function/announce_leaders/foreach_1.mcfunction +6 -0
- package/dist/data/arena/function/announce_leaders/merge_2.mcfunction +1 -0
- package/dist/data/arena/function/announce_leaders/then_0.mcfunction +4 -0
- package/dist/data/arena/function/announce_leaders.mcfunction +6 -0
- package/dist/data/arena/function/arena_tick/merge_2.mcfunction +1 -0
- package/dist/data/arena/function/arena_tick/then_0.mcfunction +4 -0
- package/dist/data/arena/function/arena_tick.mcfunction +11 -0
- package/dist/data/counter/function/__load.mcfunction +5 -0
- package/dist/data/counter/function/__tick.mcfunction +2 -0
- package/dist/data/counter/function/counter_tick/merge_2.mcfunction +1 -0
- package/dist/data/counter/function/counter_tick/then_0.mcfunction +3 -0
- package/dist/data/counter/function/counter_tick.mcfunction +11 -0
- package/dist/data/minecraft/tags/function/load.json +5 -0
- package/dist/data/minecraft/tags/function/tick.json +5 -0
- package/dist/data/quiz/function/__load.mcfunction +16 -0
- package/dist/data/quiz/function/__tick.mcfunction +6 -0
- package/dist/data/quiz/function/__trigger_quiz_a_dispatch.mcfunction +4 -0
- package/dist/data/quiz/function/__trigger_quiz_b_dispatch.mcfunction +4 -0
- package/dist/data/quiz/function/__trigger_quiz_c_dispatch.mcfunction +4 -0
- package/dist/data/quiz/function/__trigger_quiz_start_dispatch.mcfunction +4 -0
- package/dist/data/quiz/function/answer_a.mcfunction +4 -0
- package/dist/data/quiz/function/answer_b.mcfunction +4 -0
- package/dist/data/quiz/function/answer_c.mcfunction +4 -0
- package/dist/data/quiz/function/ask_question/else_1.mcfunction +5 -0
- package/dist/data/quiz/function/ask_question/else_4.mcfunction +5 -0
- package/dist/data/quiz/function/ask_question/else_7.mcfunction +4 -0
- package/dist/data/quiz/function/ask_question/merge_2.mcfunction +1 -0
- package/dist/data/quiz/function/ask_question/merge_5.mcfunction +2 -0
- package/dist/data/quiz/function/ask_question/merge_8.mcfunction +2 -0
- package/dist/data/quiz/function/ask_question/then_0.mcfunction +4 -0
- package/dist/data/quiz/function/ask_question/then_3.mcfunction +4 -0
- package/dist/data/quiz/function/ask_question/then_6.mcfunction +4 -0
- package/dist/data/quiz/function/ask_question.mcfunction +7 -0
- package/dist/data/quiz/function/finish_quiz.mcfunction +6 -0
- package/dist/data/quiz/function/handle_answer/else_1.mcfunction +5 -0
- package/dist/data/quiz/function/handle_answer/else_10.mcfunction +3 -0
- package/dist/data/quiz/function/handle_answer/else_16.mcfunction +3 -0
- package/dist/data/quiz/function/handle_answer/else_4.mcfunction +3 -0
- package/dist/data/quiz/function/handle_answer/else_7.mcfunction +5 -0
- package/dist/data/quiz/function/handle_answer/merge_11.mcfunction +2 -0
- package/dist/data/quiz/function/handle_answer/merge_14.mcfunction +2 -0
- package/dist/data/quiz/function/handle_answer/merge_17.mcfunction +2 -0
- package/dist/data/quiz/function/handle_answer/merge_2.mcfunction +8 -0
- package/dist/data/quiz/function/handle_answer/merge_5.mcfunction +2 -0
- package/dist/data/quiz/function/handle_answer/merge_8.mcfunction +2 -0
- package/dist/data/quiz/function/handle_answer/then_0.mcfunction +5 -0
- package/dist/data/quiz/function/handle_answer/then_12.mcfunction +5 -0
- package/dist/data/quiz/function/handle_answer/then_15.mcfunction +6 -0
- package/dist/data/quiz/function/handle_answer/then_3.mcfunction +6 -0
- package/dist/data/quiz/function/handle_answer/then_6.mcfunction +5 -0
- package/dist/data/quiz/function/handle_answer/then_9.mcfunction +6 -0
- package/dist/data/quiz/function/handle_answer.mcfunction +11 -0
- package/dist/data/quiz/function/start_quiz.mcfunction +5 -0
- package/dist/data/shop/function/__load.mcfunction +7 -0
- package/dist/data/shop/function/__tick.mcfunction +3 -0
- package/dist/data/shop/function/__trigger_shop_buy_dispatch.mcfunction +4 -0
- package/dist/data/shop/function/complete_purchase/else_1.mcfunction +5 -0
- package/dist/data/shop/function/complete_purchase/else_4.mcfunction +5 -0
- package/dist/data/shop/function/complete_purchase/else_7.mcfunction +3 -0
- package/dist/data/shop/function/complete_purchase/merge_2.mcfunction +2 -0
- package/dist/data/shop/function/complete_purchase/merge_5.mcfunction +2 -0
- package/dist/data/shop/function/complete_purchase/merge_8.mcfunction +2 -0
- package/dist/data/shop/function/complete_purchase/then_0.mcfunction +4 -0
- package/dist/data/shop/function/complete_purchase/then_3.mcfunction +4 -0
- package/dist/data/shop/function/complete_purchase/then_6.mcfunction +4 -0
- package/dist/data/shop/function/complete_purchase.mcfunction +7 -0
- package/dist/data/shop/function/handle_shop_trigger.mcfunction +3 -0
- package/dist/data/turret/function/__load.mcfunction +5 -0
- package/dist/data/turret/function/__tick.mcfunction +4 -0
- package/dist/data/turret/function/__trigger_deploy_turret_dispatch.mcfunction +4 -0
- package/dist/data/turret/function/deploy_turret.mcfunction +8 -0
- package/dist/data/turret/function/turret_tick/at_1.mcfunction +2 -0
- package/dist/data/turret/function/turret_tick/foreach_0.mcfunction +2 -0
- package/dist/data/turret/function/turret_tick/foreach_2.mcfunction +2 -0
- package/dist/data/turret/function/turret_tick/tick_body.mcfunction +3 -0
- package/dist/data/turret/function/turret_tick/tick_skip.mcfunction +1 -0
- package/dist/data/turret/function/turret_tick.mcfunction +5 -0
- package/dist/diagnostics/index.d.ts +44 -0
- package/dist/diagnostics/index.js +140 -0
- package/dist/index.d.ts +53 -0
- package/dist/index.js +126 -0
- package/dist/ir/builder.d.ts +32 -0
- package/dist/ir/builder.js +99 -0
- package/dist/ir/types.d.ts +117 -0
- package/dist/ir/types.js +15 -0
- package/dist/lexer/index.d.ts +36 -0
- package/dist/lexer/index.js +458 -0
- package/dist/lowering/index.d.ts +106 -0
- package/dist/lowering/index.js +2041 -0
- package/dist/mc-test/client.d.ts +128 -0
- package/dist/mc-test/client.js +174 -0
- package/dist/mc-test/runner.d.ts +28 -0
- package/dist/mc-test/runner.js +150 -0
- package/dist/mc-test/setup.d.ts +11 -0
- package/dist/mc-test/setup.js +98 -0
- package/dist/mc-validator/index.d.ts +17 -0
- package/dist/mc-validator/index.js +322 -0
- package/dist/nbt/index.d.ts +86 -0
- package/dist/nbt/index.js +250 -0
- package/dist/optimizer/commands.d.ts +36 -0
- package/dist/optimizer/commands.js +349 -0
- package/dist/optimizer/passes.d.ts +34 -0
- package/dist/optimizer/passes.js +227 -0
- package/dist/optimizer/structure.d.ts +8 -0
- package/dist/optimizer/structure.js +344 -0
- package/dist/pack.mcmeta +6 -0
- package/dist/parser/index.d.ts +76 -0
- package/dist/parser/index.js +1193 -0
- package/dist/repl.d.ts +16 -0
- package/dist/repl.js +165 -0
- package/dist/runtime/index.d.ts +101 -0
- package/dist/runtime/index.js +1288 -0
- package/dist/typechecker/index.d.ts +42 -0
- package/dist/typechecker/index.js +629 -0
- package/docs/COMPILATION_STATS.md +142 -0
- package/docs/IMPLEMENTATION_GUIDE.md +512 -0
- package/docs/LANGUAGE_REFERENCE.md +415 -0
- package/docs/MC_MAPPING.md +280 -0
- package/docs/STRUCTURE_TARGET.md +80 -0
- package/docs/mc-reference/commands.md +259 -0
- package/editors/vscode/.vscodeignore +10 -0
- package/editors/vscode/LICENSE +21 -0
- package/editors/vscode/README.md +78 -0
- package/editors/vscode/build.mjs +28 -0
- package/editors/vscode/icon.png +0 -0
- package/editors/vscode/mcfunction-language-configuration.json +28 -0
- package/editors/vscode/out/extension.js +7236 -0
- package/editors/vscode/package-lock.json +566 -0
- package/editors/vscode/package.json +137 -0
- package/editors/vscode/redscript-language-configuration.json +28 -0
- package/editors/vscode/snippets/redscript.json +114 -0
- package/editors/vscode/src/codeactions.ts +89 -0
- package/editors/vscode/src/completion.ts +130 -0
- package/editors/vscode/src/extension.ts +239 -0
- package/editors/vscode/src/hover.ts +1120 -0
- package/editors/vscode/src/symbols.ts +207 -0
- package/editors/vscode/syntaxes/mcfunction.tmLanguage.json +740 -0
- package/editors/vscode/syntaxes/redscript.tmLanguage.json +357 -0
- package/editors/vscode/tsconfig.json +13 -0
- package/jest.config.js +5 -0
- package/package.json +38 -0
- package/src/__tests__/cli.test.ts +130 -0
- package/src/__tests__/codegen.test.ts +128 -0
- package/src/__tests__/diagnostics.test.ts +195 -0
- package/src/__tests__/e2e.test.ts +1721 -0
- package/src/__tests__/fixtures/mc-commands-1.21.4.json +18734 -0
- package/src/__tests__/formatter.test.ts +46 -0
- package/src/__tests__/lexer.test.ts +356 -0
- package/src/__tests__/lowering.test.ts +962 -0
- package/src/__tests__/mc-integration.test.ts +409 -0
- package/src/__tests__/mc-syntax.test.ts +96 -0
- package/src/__tests__/nbt.test.ts +58 -0
- package/src/__tests__/optimizer-advanced.test.ts +144 -0
- package/src/__tests__/optimizer.test.ts +129 -0
- package/src/__tests__/parser.test.ts +800 -0
- package/src/__tests__/repl.test.ts +33 -0
- package/src/__tests__/runtime.test.ts +289 -0
- package/src/__tests__/structure-optimizer.test.ts +38 -0
- package/src/__tests__/typechecker.test.ts +395 -0
- package/src/ast/types.ts +248 -0
- package/src/cli.ts +445 -0
- package/src/codegen/cmdblock/index.ts +63 -0
- package/src/codegen/mcfunction/index.ts +471 -0
- package/src/codegen/structure/index.ts +305 -0
- package/src/compile.ts +188 -0
- package/src/diagnostics/index.ts +186 -0
- package/src/examples/README.md +77 -0
- package/src/examples/SHOWCASE_GAME.md +43 -0
- package/src/examples/arena.rs +44 -0
- package/src/examples/counter.rs +12 -0
- package/src/examples/pvp_arena.rs +131 -0
- package/src/examples/quiz.rs +90 -0
- package/src/examples/rpg.rs +13 -0
- package/src/examples/shop.rs +30 -0
- package/src/examples/showcase_game.rs +552 -0
- package/src/examples/stdlib_demo.rs +181 -0
- package/src/examples/turret.rs +27 -0
- package/src/examples/world_manager.rs +23 -0
- package/src/formatter/index.ts +22 -0
- package/src/index.ts +161 -0
- package/src/ir/builder.ts +114 -0
- package/src/ir/types.ts +119 -0
- package/src/lexer/index.ts +555 -0
- package/src/lowering/index.ts +2406 -0
- package/src/mc-test/client.ts +259 -0
- package/src/mc-test/runner.ts +140 -0
- package/src/mc-test/setup.ts +70 -0
- package/src/mc-validator/index.ts +367 -0
- package/src/nbt/index.ts +321 -0
- package/src/optimizer/commands.ts +416 -0
- package/src/optimizer/passes.ts +233 -0
- package/src/optimizer/structure.ts +441 -0
- package/src/parser/index.ts +1437 -0
- package/src/repl.ts +165 -0
- package/src/runtime/index.ts +1403 -0
- package/src/stdlib/README.md +156 -0
- package/src/stdlib/combat.rs +20 -0
- package/src/stdlib/cooldown.rs +45 -0
- package/src/stdlib/math.rs +49 -0
- package/src/stdlib/mobs.rs +99 -0
- package/src/stdlib/player.rs +29 -0
- package/src/stdlib/strings.rs +7 -0
- package/src/stdlib/timer.rs +51 -0
- package/src/templates/README.md +126 -0
- package/src/templates/combat.rs +96 -0
- package/src/templates/economy.rs +40 -0
- package/src/templates/mini-game-framework.rs +117 -0
- package/src/templates/quest.rs +78 -0
- package/src/test_programs/zombie_game.rs +25 -0
- package/src/typechecker/index.ts +737 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import * as vscode from 'vscode'
|
|
2
|
+
|
|
3
|
+
const DECL_RE = /\b(fn|let|const|struct|enum)\s+(\w+)/g
|
|
4
|
+
|
|
5
|
+
interface DeclInfo {
|
|
6
|
+
kind: string
|
|
7
|
+
name: string
|
|
8
|
+
range: vscode.Range
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface StructFieldInfo {
|
|
12
|
+
structName: string
|
|
13
|
+
fieldName: string
|
|
14
|
+
fieldRange: vscode.Range
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function findDeclarations(doc: vscode.TextDocument): DeclInfo[] {
|
|
18
|
+
const text = doc.getText()
|
|
19
|
+
const decls: DeclInfo[] = []
|
|
20
|
+
let match: RegExpExecArray | null
|
|
21
|
+
|
|
22
|
+
DECL_RE.lastIndex = 0
|
|
23
|
+
while ((match = DECL_RE.exec(text)) !== null) {
|
|
24
|
+
const nameStart = match.index + match[0].length - match[2].length
|
|
25
|
+
const pos = doc.positionAt(nameStart)
|
|
26
|
+
const range = new vscode.Range(pos, doc.positionAt(nameStart + match[2].length))
|
|
27
|
+
decls.push({ kind: match[1], name: match[2], range })
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return decls
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Find all struct definitions and their field positions. */
|
|
34
|
+
function findStructFields(doc: vscode.TextDocument): StructFieldInfo[] {
|
|
35
|
+
const text = doc.getText()
|
|
36
|
+
const structRe = /\bstruct\s+(\w+)\s*\{([^}]*)\}/gs
|
|
37
|
+
const fields: StructFieldInfo[] = []
|
|
38
|
+
let sm: RegExpExecArray | null
|
|
39
|
+
|
|
40
|
+
while ((sm = structRe.exec(text)) !== null) {
|
|
41
|
+
const structName = sm[1]
|
|
42
|
+
const bodyStart = sm.index + sm[0].indexOf('{') + 1
|
|
43
|
+
const body = sm[2]
|
|
44
|
+
const fieldRe = /\b(\w+)\s*:/g
|
|
45
|
+
let fm: RegExpExecArray | null
|
|
46
|
+
while ((fm = fieldRe.exec(body)) !== null) {
|
|
47
|
+
const fieldStart = bodyStart + fm.index
|
|
48
|
+
const pos = doc.positionAt(fieldStart)
|
|
49
|
+
const range = new vscode.Range(pos, doc.positionAt(fieldStart + fm[1].length))
|
|
50
|
+
fields.push({ structName, fieldName: fm[1], fieldRange: range })
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return fields
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Check if cursor is on a struct literal field key (left side of : in { key: value }). */
|
|
58
|
+
function isStructLiteralField(doc: vscode.TextDocument, position: vscode.Position, word: string): string | null {
|
|
59
|
+
const line = doc.lineAt(position.line).text
|
|
60
|
+
const wordEnd = position.character + word.length
|
|
61
|
+
|
|
62
|
+
// Check if word is followed by ':' (struct literal field)
|
|
63
|
+
const afterWord = line.slice(wordEnd).trimStart()
|
|
64
|
+
if (!afterWord.startsWith(':')) return null
|
|
65
|
+
|
|
66
|
+
// Find the struct type from context: let x: StructType = { ... }
|
|
67
|
+
// Search backwards for "let <name>: <Type> = {"
|
|
68
|
+
const textBefore = doc.getText(new vscode.Range(new vscode.Position(0, 0), position))
|
|
69
|
+
// Match: let varname: TypeName = { ... (cursor is somewhere in the braces)
|
|
70
|
+
const letMatch = textBefore.match(/let\s+\w+\s*:\s*(\w+)\s*=\s*\{[^}]*$/)
|
|
71
|
+
if (letMatch) return letMatch[1]
|
|
72
|
+
|
|
73
|
+
// Also check for: return { ... } after -> TypeName
|
|
74
|
+
const fnMatch = textBefore.match(/->\s*(\w+)\s*\{[^}]*return\s*\{[^}]*$/)
|
|
75
|
+
if (fnMatch) return fnMatch[1]
|
|
76
|
+
|
|
77
|
+
return null
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function findAllOccurrences(doc: vscode.TextDocument, word: string): vscode.Location[] {
|
|
81
|
+
const text = doc.getText()
|
|
82
|
+
const re = new RegExp(`\\b${escapeRegex(word)}\\b`, 'g')
|
|
83
|
+
const locations: vscode.Location[] = []
|
|
84
|
+
let match: RegExpExecArray | null
|
|
85
|
+
|
|
86
|
+
while ((match = re.exec(text)) !== null) {
|
|
87
|
+
const pos = doc.positionAt(match.index)
|
|
88
|
+
const range = new vscode.Range(pos, doc.positionAt(match.index + word.length))
|
|
89
|
+
locations.push(new vscode.Location(doc.uri, range))
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return locations
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function escapeRegex(s: string): string {
|
|
96
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function registerSymbolProviders(context: vscode.ExtensionContext): void {
|
|
100
|
+
const selector: vscode.DocumentSelector = { language: 'redscript', scheme: 'file' }
|
|
101
|
+
|
|
102
|
+
context.subscriptions.push(
|
|
103
|
+
vscode.languages.registerDefinitionProvider(selector, {
|
|
104
|
+
provideDefinition(doc, position) {
|
|
105
|
+
// If cursor is preceded by '#', it's a #mc_name — no definition to jump to
|
|
106
|
+
if (isMcName(doc, position)) return null
|
|
107
|
+
|
|
108
|
+
const wordRange = doc.getWordRangeAtPosition(position)
|
|
109
|
+
if (!wordRange) return null
|
|
110
|
+
const word = doc.getText(wordRange)
|
|
111
|
+
|
|
112
|
+
// Check if this is a struct literal field key: { fieldName: value }
|
|
113
|
+
const structType = isStructLiteralField(doc, position, word)
|
|
114
|
+
if (structType) {
|
|
115
|
+
const structFields = findStructFields(doc)
|
|
116
|
+
const field = structFields.find(f => f.structName === structType && f.fieldName === word)
|
|
117
|
+
if (field) {
|
|
118
|
+
return new vscode.Location(doc.uri, field.fieldRange)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const decls = findDeclarations(doc)
|
|
123
|
+
const decl = decls.find(d => d.name === word)
|
|
124
|
+
if (!decl) return null
|
|
125
|
+
|
|
126
|
+
return new vscode.Location(doc.uri, decl.range)
|
|
127
|
+
}
|
|
128
|
+
})
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
context.subscriptions.push(
|
|
132
|
+
vscode.languages.registerReferenceProvider(selector, {
|
|
133
|
+
provideReferences(doc, position) {
|
|
134
|
+
// For #mc_name, find all occurrences of the full #name token
|
|
135
|
+
if (isMcName(doc, position)) {
|
|
136
|
+
const mcRange = doc.getWordRangeAtPosition(position, /#[a-zA-Z_][a-zA-Z0-9_]*/)
|
|
137
|
+
if (!mcRange) return null
|
|
138
|
+
const mcWord = doc.getText(mcRange)
|
|
139
|
+
return findAllOccurrences(doc, mcWord)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const wordRange = doc.getWordRangeAtPosition(position)
|
|
143
|
+
if (!wordRange) return null
|
|
144
|
+
const word = doc.getText(wordRange)
|
|
145
|
+
|
|
146
|
+
// Exclude bare names that appear as #name elsewhere (they're different things)
|
|
147
|
+
return findAllOccurrences(doc, word).filter(loc => {
|
|
148
|
+
// Don't include occurrences that are actually #word
|
|
149
|
+
const charBefore = loc.range.start.character > 0
|
|
150
|
+
? doc.getText(new vscode.Range(
|
|
151
|
+
loc.range.start.translate(0, -1),
|
|
152
|
+
loc.range.start
|
|
153
|
+
))
|
|
154
|
+
: ''
|
|
155
|
+
return charBefore !== '#'
|
|
156
|
+
})
|
|
157
|
+
}
|
|
158
|
+
})
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
context.subscriptions.push(
|
|
162
|
+
vscode.languages.registerRenameProvider(selector, {
|
|
163
|
+
provideRenameEdits(doc, position, newName) {
|
|
164
|
+
const wordRange = doc.getWordRangeAtPosition(position)
|
|
165
|
+
if (!wordRange) return null
|
|
166
|
+
const oldName = doc.getText(wordRange)
|
|
167
|
+
|
|
168
|
+
if (isMcName(doc, position)) return null
|
|
169
|
+
|
|
170
|
+
const edits = new vscode.WorkspaceEdit()
|
|
171
|
+
const text = doc.getText()
|
|
172
|
+
const re = new RegExp(`\\b${escapeRegex(oldName)}\\b`, 'g')
|
|
173
|
+
let match: RegExpExecArray | null
|
|
174
|
+
while ((match = re.exec(text)) !== null) {
|
|
175
|
+
if (match.index > 0 && text[match.index - 1] === '#') continue
|
|
176
|
+
const start = doc.positionAt(match.index)
|
|
177
|
+
const end = doc.positionAt(match.index + oldName.length)
|
|
178
|
+
edits.replace(doc.uri, new vscode.Range(start, end), newName)
|
|
179
|
+
}
|
|
180
|
+
return edits
|
|
181
|
+
},
|
|
182
|
+
|
|
183
|
+
prepareRename(doc, position) {
|
|
184
|
+
const wordRange = doc.getWordRangeAtPosition(position)
|
|
185
|
+
if (!wordRange) throw new Error('Cannot rename this element')
|
|
186
|
+
if (isMcName(doc, position)) {
|
|
187
|
+
throw new Error('Cannot rename MC identifiers (#name)')
|
|
188
|
+
}
|
|
189
|
+
return wordRange
|
|
190
|
+
}
|
|
191
|
+
})
|
|
192
|
+
)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/** Returns true if the cursor is on the identifier part of a #mc_name token. */
|
|
196
|
+
function isMcName(doc: vscode.TextDocument, position: vscode.Position): boolean {
|
|
197
|
+
if (position.character === 0) return false
|
|
198
|
+
const charBefore = doc.getText(new vscode.Range(
|
|
199
|
+
position.translate(0, -1),
|
|
200
|
+
position
|
|
201
|
+
))
|
|
202
|
+
if (charBefore === '#') return true
|
|
203
|
+
// Also check if we're in the middle of an #ident — look for # to the left
|
|
204
|
+
const linePrefix = doc.lineAt(position.line).text.slice(0, position.character)
|
|
205
|
+
const match = linePrefix.match(/#[a-zA-Z_][a-zA-Z0-9_]*$/)
|
|
206
|
+
return match !== null
|
|
207
|
+
}
|