forked from Bard-Gaming/Minecraft-Script
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmcs-python-bridge.mjs
More file actions
127 lines (102 loc) · 3.13 KB
/
Copy pathmcs-python-bridge.mjs
File metadata and controls
127 lines (102 loc) · 3.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import { spawn } from 'node:child_process'
import * as vscode from 'vscode'
/**
* @typedef {{ line: number, column: number, message: string, severity?: string }} McsDiagnostic
*/
/**
* @param {vscode.OutputChannel} output
* @returns {Promise<McsDiagnostic[]>}
*/
export async function lintMcsDocument(document, output) {
const sourcePath = getLintSourcePath(document)
const pythonCommand = getPythonCommand()
const args = ['-m', 'minecraft_script', 'lint', '--json', '--stdin']
if (sourcePath) {
args.push('--source', sourcePath)
}
try {
const stdout = await runPythonProcess(pythonCommand, args, document.getText())
if (!stdout.trim()) return []
const payload = JSON.parse(stdout)
return Array.isArray(payload) ? payload : []
} catch (error) {
output.appendLine(
`[MCS] Language validation failed: ${error instanceof Error ? error.stack ?? error.message : String(error)}`,
)
return []
}
}
/**
* @returns {string | undefined}
*/
function getLintSourcePath(document) {
if (document.uri.scheme === 'file' && document.uri.fsPath) {
return document.uri.fsPath
}
const configured = vscode.workspace
.getConfiguration('mcsHighlighter')
.get('lintSourcePath')
return typeof configured === 'string' && configured.trim() ? configured.trim() : undefined
}
function getPythonCommand() {
const configured = vscode.workspace
.getConfiguration('mcsHighlighter')
.get('pythonPath')
if (typeof configured === 'string' && configured.trim()) {
return configured.trim()
}
return process.platform === 'win32' ? 'py' : 'python3'
}
function getPythonArgs(command) {
if (command === 'py' && process.platform === 'win32') {
return ['-3']
}
return []
}
function runPythonProcess(command, args, stdinText) {
const pythonArgs = [...getPythonArgs(command), ...args]
return new Promise((resolve, reject) => {
const child = spawn(command, pythonArgs, {
stdio: ['pipe', 'pipe', 'pipe'],
windowsHide: true,
})
let stdout = ''
let stderr = ''
child.stdout.on('data', (chunk) => {
stdout += chunk.toString()
})
child.stderr.on('data', (chunk) => {
stderr += chunk.toString()
})
child.on('error', (error) => {
reject(error)
})
child.on('close', (code) => {
if (code === 0 || code === 1) {
resolve(stdout)
return
}
reject(new Error(stderr.trim() || `Python lint exited with code ${code}`))
})
child.stdin.write(stdinText)
child.stdin.end()
})
}
/**
* @param {vscode.TextDocument} document
* @param {McsDiagnostic} diagnostic
* @returns {vscode.Diagnostic}
*/
export function toMcsLanguageDiagnostic(document, diagnostic) {
const line = Math.min(Math.max(diagnostic.line - 1, 0), document.lineCount - 1)
const column = Math.max(diagnostic.column, 0)
const lineText = document.lineAt(line).text
const endColumn = Math.min(column + 1, lineText.length)
const result = new vscode.Diagnostic(
new vscode.Range(line, column, line, endColumn),
diagnostic.message,
vscode.DiagnosticSeverity.Error,
)
result.source = 'Minecraft Script'
return result
}