test parse errors are thrown (#294)
This commit is contained in:
@ -1,4 +1,5 @@
|
||||
import { parser_wasm } from './abstractSyntaxTree'
|
||||
import { KCLUnexpectedError } from './errors'
|
||||
import { initPromise } from './rust'
|
||||
|
||||
beforeAll(() => initPromise)
|
||||
@ -1706,3 +1707,19 @@ describe('should recognise callExpresions in binaryExpressions', () => {
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe('parsing errors', () => {
|
||||
it('should return an error when there is a unexpected closed curly brace', async () => {
|
||||
const code = `const myVar = startSketchAt([}], %)`
|
||||
|
||||
let _theError
|
||||
try {
|
||||
const result = expect(parser_wasm(code))
|
||||
console.log('result', result)
|
||||
} catch (e) {
|
||||
_theError = e
|
||||
}
|
||||
const theError = _theError as any
|
||||
expect(theError).toEqual(new KCLUnexpectedError('Brace', [[29, 30]]))
|
||||
})
|
||||
})
|
||||
|
@ -3,21 +3,23 @@ import { parse_js } from '../wasm-lib/pkg/wasm_lib'
|
||||
import { initPromise } from './rust'
|
||||
import { Token } from './tokeniser'
|
||||
import { KCLError } from './errors'
|
||||
import { KclError as RustKclError } from '../wasm-lib/bindings/KclError'
|
||||
|
||||
const rangeTypeFix = (ranges: number[][]): [number, number][] =>
|
||||
ranges.map(([start, end]) => [start, end])
|
||||
|
||||
export const parser_wasm = (code: string): Program => {
|
||||
try {
|
||||
const program: Program = parse_js(code)
|
||||
return program
|
||||
} catch (e: any) {
|
||||
const parsed: {
|
||||
kind: string
|
||||
msg: string
|
||||
sourceRanges: [number, number][]
|
||||
} = JSON.parse(e.toString())
|
||||
const kclError: KCLError = new KCLError(
|
||||
const parsed: RustKclError = JSON.parse(e.toString())
|
||||
const kclError = new KCLError(
|
||||
parsed.kind,
|
||||
parsed.msg,
|
||||
parsed.sourceRanges
|
||||
parsed.kind === 'invalid_expression' ? parsed.kind : parsed.msg,
|
||||
parsed.kind === 'invalid_expression'
|
||||
? [[parsed.start, parsed.end]]
|
||||
: rangeTypeFix(parsed.sourceRanges)
|
||||
)
|
||||
|
||||
console.log(kclError)
|
||||
@ -31,15 +33,13 @@ export async function asyncParser(code: string): Promise<Program> {
|
||||
const program: Program = parse_js(code)
|
||||
return program
|
||||
} catch (e: any) {
|
||||
const parsed: {
|
||||
kind: string
|
||||
msg: string
|
||||
sourceRanges: [number, number][]
|
||||
} = JSON.parse(e.toString())
|
||||
const kclError: KCLError = new KCLError(
|
||||
const parsed: RustKclError = JSON.parse(e.toString())
|
||||
const kclError = new KCLError(
|
||||
parsed.kind,
|
||||
parsed.msg,
|
||||
parsed.sourceRanges
|
||||
parsed.kind === 'invalid_expression' ? parsed.kind : parsed.msg,
|
||||
parsed.kind === 'invalid_expression'
|
||||
? [[parsed.start, parsed.end]]
|
||||
: rangeTypeFix(parsed.sourceRanges)
|
||||
)
|
||||
|
||||
console.log(kclError)
|
||||
|
@ -1,11 +1,13 @@
|
||||
import { Diagnostic } from '@codemirror/lint'
|
||||
import { KclError as RustKclError } from '../wasm-lib/bindings/KclError'
|
||||
|
||||
type ExtractKind<T> = T extends { kind: infer K } ? K : never
|
||||
export class KCLError {
|
||||
kind: string | undefined
|
||||
kind: ExtractKind<RustKclError> | 'name'
|
||||
sourceRanges: [number, number][]
|
||||
msg: string
|
||||
constructor(
|
||||
kind: string | undefined,
|
||||
kind: ExtractKind<RustKclError> | 'name',
|
||||
msg: string,
|
||||
sourceRanges: [number, number][]
|
||||
) {
|
||||
@ -39,11 +41,18 @@ export class KCLTypeError extends KCLError {
|
||||
|
||||
export class KCLUnimplementedError extends KCLError {
|
||||
constructor(msg: string, sourceRanges: [number, number][]) {
|
||||
super('unimplemented feature', msg, sourceRanges)
|
||||
super('unimplemented', msg, sourceRanges)
|
||||
Object.setPrototypeOf(this, KCLUnimplementedError.prototype)
|
||||
}
|
||||
}
|
||||
|
||||
export class KCLUnexpectedError extends KCLError {
|
||||
constructor(msg: string, sourceRanges: [number, number][]) {
|
||||
super('unexpected', msg, sourceRanges)
|
||||
Object.setPrototypeOf(this, KCLUnexpectedError.prototype)
|
||||
}
|
||||
}
|
||||
|
||||
export class KCLValueAlreadyDefined extends KCLError {
|
||||
constructor(key: string, sourceRanges: [number, number][]) {
|
||||
super('name', `Key ${key} was already defined elsewhere`, sourceRanges)
|
||||
|
@ -13,6 +13,8 @@ pub enum KclError {
|
||||
Type(KclErrorDetails),
|
||||
#[error("unimplemented: {0:?}")]
|
||||
Unimplemented(KclErrorDetails),
|
||||
#[error("unexpected: {0:?}")]
|
||||
Unexpected(KclErrorDetails),
|
||||
#[error("value already defined: {0:?}")]
|
||||
ValueAlreadyDefined(KclErrorDetails),
|
||||
#[error("undefined value: {0:?}")]
|
||||
|
@ -614,9 +614,9 @@ fn make_value(tokens: &[Token], index: usize) -> Result<ValueReturn, KclError> {
|
||||
});
|
||||
}
|
||||
|
||||
Err(KclError::Unimplemented(KclErrorDetails {
|
||||
Err(KclError::Unexpected(KclErrorDetails {
|
||||
source_ranges: vec![[current_token.start as i32, current_token.end as i32]],
|
||||
message: format!("expression with token type {:?}", current_token.token_type),
|
||||
message: format!("{:?}", current_token.token_type),
|
||||
}))
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user