Fix a recast bug and don't delete the user's code if parsing fails (#5663)
Signed-off-by: Nick Cameron <nrc@ncameron.org>
This commit is contained in:
@ -450,7 +450,7 @@ impl Literal {
|
||||
if self.raw.contains('.') && value.fract() == 0.0 {
|
||||
format!("{value:?}{suffix}")
|
||||
} else {
|
||||
format!("{}{suffix}", self.raw)
|
||||
self.raw.clone()
|
||||
}
|
||||
}
|
||||
LiteralValue::String(ref s) => {
|
||||
@ -1540,7 +1540,7 @@ tabs_l = startSketchOn({
|
||||
radius = hole_diam / 2
|
||||
), %)
|
||||
|> extrude(-thk, %)
|
||||
|> patternLinear3d(axis = [0, -1, 0], repetitions = 1, distance = length - 10)
|
||||
|> patternLinear3d(axis = [0, -1, 0], repetitions = 1, distance = length - 10ft)
|
||||
"#;
|
||||
let program = crate::parsing::top_level_parse(some_program_string).unwrap();
|
||||
|
||||
@ -1657,7 +1657,7 @@ tabs_l = startSketchOn({
|
||||
radius = hole_diam / 2,
|
||||
), %)
|
||||
|> extrude(-thk, %)
|
||||
|> patternLinear3d(axis = [0, -1, 0], repetitions = 1, distance = length - 10)
|
||||
|> patternLinear3d(axis = [0, -1, 0], repetitions = 1, distance = length - 10ft)
|
||||
"#
|
||||
);
|
||||
}
|
||||
|
@ -452,7 +452,7 @@ export class KclManager {
|
||||
|
||||
// NOTE: this always updates the code state and editor.
|
||||
// DO NOT CALL THIS from codemirror ever.
|
||||
async executeAstMock(ast: Program = this._ast) {
|
||||
async executeAstMock(ast: Program) {
|
||||
await this.ensureWasmInit()
|
||||
|
||||
const newCode = recast(ast)
|
||||
@ -462,6 +462,8 @@ export class KclManager {
|
||||
}
|
||||
const newAst = await this.safeParse(newCode)
|
||||
if (!newAst) {
|
||||
// By clearning the AST we indicate to our callers that there was an issue with execution and
|
||||
// the pre-execution state should be restored.
|
||||
this.clearAst()
|
||||
return
|
||||
}
|
||||
@ -474,10 +476,6 @@ export class KclManager {
|
||||
})
|
||||
|
||||
this._logs = logs
|
||||
this.addDiagnostics(kclErrorsToDiagnostics(errors))
|
||||
// Add warnings and non-fatal errors
|
||||
this.addDiagnostics(complilationErrorsToDiagnostics(execState.errors))
|
||||
|
||||
this._execState = execState
|
||||
this._variables = execState.variables
|
||||
if (!errors.length) {
|
||||
@ -494,6 +492,8 @@ export class KclManager {
|
||||
const ast = await this.safeParse(codeManager.code)
|
||||
|
||||
if (!ast) {
|
||||
// By clearning the AST we indicate to our callers that there was an issue with execution and
|
||||
// the pre-execution state should be restored.
|
||||
this.clearAst()
|
||||
return
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import toast from 'react-hot-toast'
|
||||
import { editorManager } from 'lib/singletons'
|
||||
import { Annotation, Transaction } from '@codemirror/state'
|
||||
import { EditorView, KeyBinding } from '@codemirror/view'
|
||||
import { recast, Program } from 'lang/wasm'
|
||||
import { recast, Program, parse } from 'lang/wasm'
|
||||
import { err, reportRejection } from 'lib/trap'
|
||||
import { Compartment } from '@codemirror/state'
|
||||
import { history } from '@codemirror/commands'
|
||||
@ -165,8 +165,20 @@ export default class CodeManager {
|
||||
}
|
||||
|
||||
async updateEditorWithAstAndWriteToFile(ast: Program) {
|
||||
// We clear the AST when there it cannot be parsed, so if we are trying to write an empty AST, its
|
||||
// probably because of an earlier error. That's a bad state to be in and it's not going to be
|
||||
// pretty, but at the least, lets not permanently delete the user's code.
|
||||
// If you want to clear the scene, call updateCodeStateEditor directly.
|
||||
if (ast.body.length === 0) return
|
||||
const newCode = recast(ast)
|
||||
if (err(newCode)) return
|
||||
// Test to see if we can parse the recast code, and never update the editor with bad code.
|
||||
// This should never happen ideally and should mean there is a bug in recast.
|
||||
const result = parse(newCode)
|
||||
if (err(result)) {
|
||||
console.log('Recast code could not be parsed:', result, ast)
|
||||
return
|
||||
}
|
||||
this.updateCodeStateEditor(newCode)
|
||||
this.writeToFile().catch(reportRejection)
|
||||
}
|
||||
|
Reference in New Issue
Block a user