test parse errors are thrown (#294)
This commit is contained in:
@ -1,4 +1,5 @@
|
|||||||
import { parser_wasm } from './abstractSyntaxTree'
|
import { parser_wasm } from './abstractSyntaxTree'
|
||||||
|
import { KCLUnexpectedError } from './errors'
|
||||||
import { initPromise } from './rust'
|
import { initPromise } from './rust'
|
||||||
|
|
||||||
beforeAll(() => initPromise)
|
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 { initPromise } from './rust'
|
||||||
import { Token } from './tokeniser'
|
import { Token } from './tokeniser'
|
||||||
import { KCLError } from './errors'
|
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 => {
|
export const parser_wasm = (code: string): Program => {
|
||||||
try {
|
try {
|
||||||
const program: Program = parse_js(code)
|
const program: Program = parse_js(code)
|
||||||
return program
|
return program
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
const parsed: {
|
const parsed: RustKclError = JSON.parse(e.toString())
|
||||||
kind: string
|
const kclError = new KCLError(
|
||||||
msg: string
|
|
||||||
sourceRanges: [number, number][]
|
|
||||||
} = JSON.parse(e.toString())
|
|
||||||
const kclError: KCLError = new KCLError(
|
|
||||||
parsed.kind,
|
parsed.kind,
|
||||||
parsed.msg,
|
parsed.kind === 'invalid_expression' ? parsed.kind : parsed.msg,
|
||||||
parsed.sourceRanges
|
parsed.kind === 'invalid_expression'
|
||||||
|
? [[parsed.start, parsed.end]]
|
||||||
|
: rangeTypeFix(parsed.sourceRanges)
|
||||||
)
|
)
|
||||||
|
|
||||||
console.log(kclError)
|
console.log(kclError)
|
||||||
@ -31,15 +33,13 @@ export async function asyncParser(code: string): Promise<Program> {
|
|||||||
const program: Program = parse_js(code)
|
const program: Program = parse_js(code)
|
||||||
return program
|
return program
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
const parsed: {
|
const parsed: RustKclError = JSON.parse(e.toString())
|
||||||
kind: string
|
const kclError = new KCLError(
|
||||||
msg: string
|
|
||||||
sourceRanges: [number, number][]
|
|
||||||
} = JSON.parse(e.toString())
|
|
||||||
const kclError: KCLError = new KCLError(
|
|
||||||
parsed.kind,
|
parsed.kind,
|
||||||
parsed.msg,
|
parsed.kind === 'invalid_expression' ? parsed.kind : parsed.msg,
|
||||||
parsed.sourceRanges
|
parsed.kind === 'invalid_expression'
|
||||||
|
? [[parsed.start, parsed.end]]
|
||||||
|
: rangeTypeFix(parsed.sourceRanges)
|
||||||
)
|
)
|
||||||
|
|
||||||
console.log(kclError)
|
console.log(kclError)
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
import { Diagnostic } from '@codemirror/lint'
|
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 {
|
export class KCLError {
|
||||||
kind: string | undefined
|
kind: ExtractKind<RustKclError> | 'name'
|
||||||
sourceRanges: [number, number][]
|
sourceRanges: [number, number][]
|
||||||
msg: string
|
msg: string
|
||||||
constructor(
|
constructor(
|
||||||
kind: string | undefined,
|
kind: ExtractKind<RustKclError> | 'name',
|
||||||
msg: string,
|
msg: string,
|
||||||
sourceRanges: [number, number][]
|
sourceRanges: [number, number][]
|
||||||
) {
|
) {
|
||||||
@ -39,11 +41,18 @@ export class KCLTypeError extends KCLError {
|
|||||||
|
|
||||||
export class KCLUnimplementedError extends KCLError {
|
export class KCLUnimplementedError extends KCLError {
|
||||||
constructor(msg: string, sourceRanges: [number, number][]) {
|
constructor(msg: string, sourceRanges: [number, number][]) {
|
||||||
super('unimplemented feature', msg, sourceRanges)
|
super('unimplemented', msg, sourceRanges)
|
||||||
Object.setPrototypeOf(this, KCLUnimplementedError.prototype)
|
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 {
|
export class KCLValueAlreadyDefined extends KCLError {
|
||||||
constructor(key: string, sourceRanges: [number, number][]) {
|
constructor(key: string, sourceRanges: [number, number][]) {
|
||||||
super('name', `Key ${key} was already defined elsewhere`, sourceRanges)
|
super('name', `Key ${key} was already defined elsewhere`, sourceRanges)
|
||||||
|
@ -13,6 +13,8 @@ pub enum KclError {
|
|||||||
Type(KclErrorDetails),
|
Type(KclErrorDetails),
|
||||||
#[error("unimplemented: {0:?}")]
|
#[error("unimplemented: {0:?}")]
|
||||||
Unimplemented(KclErrorDetails),
|
Unimplemented(KclErrorDetails),
|
||||||
|
#[error("unexpected: {0:?}")]
|
||||||
|
Unexpected(KclErrorDetails),
|
||||||
#[error("value already defined: {0:?}")]
|
#[error("value already defined: {0:?}")]
|
||||||
ValueAlreadyDefined(KclErrorDetails),
|
ValueAlreadyDefined(KclErrorDetails),
|
||||||
#[error("undefined value: {0:?}")]
|
#[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]],
|
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