* start to gut and seperate the kcl lint from execute * fix type signature * re-add old codepath when not wasm * also lint in the mock * fix syntax * fix message
This commit is contained in:
@ -786,7 +786,7 @@ test('if you write invalid kcl you get inlined errors', async ({ page }) => {
|
|||||||
|
|
||||||
// error text on hover
|
// error text on hover
|
||||||
await page.hover('.cm-lint-marker-error')
|
await page.hover('.cm-lint-marker-error')
|
||||||
await expect(page.getByText('syntax: Unexpected token')).toBeVisible()
|
await expect(page.getByText('Unexpected token')).toBeVisible()
|
||||||
|
|
||||||
// select the line that's causing the error and delete it
|
// select the line that's causing the error and delete it
|
||||||
await page.getByText('$ error').click()
|
await page.getByText('$ error').click()
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { executeAst } from 'useStore'
|
import { executeAst, lintAst } from 'useStore'
|
||||||
import { Selections } from 'lib/selections'
|
import { Selections } from 'lib/selections'
|
||||||
import { KCLError, kclErrorsToDiagnostics } from './errors'
|
import { KCLError, kclErrorsToDiagnostics } from './errors'
|
||||||
import { uuidv4 } from 'lib/utils'
|
import { uuidv4 } from 'lib/utils'
|
||||||
@ -211,6 +211,9 @@ export class KclManager {
|
|||||||
ast,
|
ast,
|
||||||
engineCommandManager: this.engineCommandManager,
|
engineCommandManager: this.engineCommandManager,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
editorManager.addDiagnostics(await lintAst({ ast: ast }))
|
||||||
|
|
||||||
sceneInfra.modelingSend({ type: 'code edit during sketch' })
|
sceneInfra.modelingSend({ type: 'code edit during sketch' })
|
||||||
defaultSelectionFilter(programMemory, this.engineCommandManager)
|
defaultSelectionFilter(programMemory, this.engineCommandManager)
|
||||||
|
|
||||||
@ -261,7 +264,10 @@ export class KclManager {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
const newAst = this.safeParse(newCode)
|
const newAst = this.safeParse(newCode)
|
||||||
if (!newAst) return
|
if (!newAst) {
|
||||||
|
this.clearAst()
|
||||||
|
return
|
||||||
|
}
|
||||||
codeManager.updateCodeEditor(newCode)
|
codeManager.updateCodeEditor(newCode)
|
||||||
// Write the file to disk.
|
// Write the file to disk.
|
||||||
await codeManager.writeToFile()
|
await codeManager.writeToFile()
|
||||||
@ -278,6 +284,9 @@ export class KclManager {
|
|||||||
engineCommandManager: this.engineCommandManager,
|
engineCommandManager: this.engineCommandManager,
|
||||||
useFakeExecutor: true,
|
useFakeExecutor: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
editorManager.addDiagnostics(await lintAst({ ast: ast }))
|
||||||
|
|
||||||
this._logs = logs
|
this._logs = logs
|
||||||
this._kclErrors = errors
|
this._kclErrors = errors
|
||||||
this._programMemory = programMemory
|
this._programMemory = programMemory
|
||||||
|
@ -2,6 +2,7 @@ import init, {
|
|||||||
parse_wasm,
|
parse_wasm,
|
||||||
recast_wasm,
|
recast_wasm,
|
||||||
execute_wasm,
|
execute_wasm,
|
||||||
|
kcl_lint,
|
||||||
lexer_wasm,
|
lexer_wasm,
|
||||||
modify_ast_for_sketch_wasm,
|
modify_ast_for_sketch_wasm,
|
||||||
is_points_ccw,
|
is_points_ccw,
|
||||||
@ -20,6 +21,7 @@ import { KCLError } from './errors'
|
|||||||
import { KclError as RustKclError } from '../wasm-lib/kcl/bindings/KclError'
|
import { KclError as RustKclError } from '../wasm-lib/kcl/bindings/KclError'
|
||||||
import { EngineCommandManager } from './std/engineConnection'
|
import { EngineCommandManager } from './std/engineConnection'
|
||||||
import { ProgramReturn } from '../wasm-lib/kcl/bindings/ProgramReturn'
|
import { ProgramReturn } from '../wasm-lib/kcl/bindings/ProgramReturn'
|
||||||
|
import { Discovered } from '../wasm-lib/kcl/bindings/Discovered'
|
||||||
import { MemoryItem } from '../wasm-lib/kcl/bindings/MemoryItem'
|
import { MemoryItem } from '../wasm-lib/kcl/bindings/MemoryItem'
|
||||||
import type { Program } from '../wasm-lib/kcl/bindings/Program'
|
import type { Program } from '../wasm-lib/kcl/bindings/Program'
|
||||||
import type { Token } from '../wasm-lib/kcl/bindings/Token'
|
import type { Token } from '../wasm-lib/kcl/bindings/Token'
|
||||||
@ -205,6 +207,17 @@ export const _executor = async (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const kclLint = async (ast: Program): Promise<Array<Discovered>> => {
|
||||||
|
try {
|
||||||
|
const discovered_findings: Array<Discovered> = await kcl_lint(
|
||||||
|
JSON.stringify(ast)
|
||||||
|
)
|
||||||
|
return discovered_findings
|
||||||
|
} catch (e: any) {
|
||||||
|
return Promise.reject(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const recast = (ast: Program): string | Error => {
|
export const recast = (ast: Program): string | Error => {
|
||||||
return recast_wasm(JSON.stringify(ast))
|
return recast_wasm(JSON.stringify(ast))
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,13 @@ import {
|
|||||||
_executor,
|
_executor,
|
||||||
ProgramMemory,
|
ProgramMemory,
|
||||||
programMemoryInit,
|
programMemoryInit,
|
||||||
|
kclLint,
|
||||||
} from './lang/wasm'
|
} from './lang/wasm'
|
||||||
import { enginelessExecutor } from './lib/testHelpers'
|
import { enginelessExecutor } from './lib/testHelpers'
|
||||||
import { EngineCommandManager } from './lang/std/engineConnection'
|
import { EngineCommandManager } from './lang/std/engineConnection'
|
||||||
import { KCLError } from './lang/errors'
|
import { KCLError } from './lang/errors'
|
||||||
import { SidebarType } from 'components/ModelingSidebar/ModelingPanes'
|
import { SidebarType } from 'components/ModelingSidebar/ModelingPanes'
|
||||||
|
import { Diagnostic } from '@codemirror/lint'
|
||||||
|
|
||||||
export type ToolTip =
|
export type ToolTip =
|
||||||
| 'lineTo'
|
| 'lineTo'
|
||||||
@ -187,3 +189,24 @@ export async function executeAst({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function lintAst({
|
||||||
|
ast,
|
||||||
|
}: {
|
||||||
|
ast: Program
|
||||||
|
}): Promise<Array<Diagnostic>> {
|
||||||
|
try {
|
||||||
|
const discovered_findings = await kclLint(ast)
|
||||||
|
return discovered_findings.map((lint) => {
|
||||||
|
return {
|
||||||
|
message: lint.finding.title,
|
||||||
|
severity: 'info',
|
||||||
|
from: lint.pos[0],
|
||||||
|
to: lint.pos[1],
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} catch (e: any) {
|
||||||
|
console.log(e)
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use schemars::JsonSchema;
|
||||||
|
use serde::Serialize;
|
||||||
use tower_lsp::lsp_types::{Diagnostic, DiagnosticSeverity};
|
use tower_lsp::lsp_types::{Diagnostic, DiagnosticSeverity};
|
||||||
|
|
||||||
use crate::{executor::SourceRange, lint::Node, lsp::IntoDiagnostic};
|
use crate::{executor::SourceRange, lint::Node, lsp::IntoDiagnostic};
|
||||||
@ -22,8 +24,10 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Specific discovered lint rule Violation of a particular Finding.
|
/// Specific discovered lint rule Violation of a particular Finding.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, ts_rs::TS, Serialize, JsonSchema)]
|
||||||
|
#[ts(export)]
|
||||||
#[cfg_attr(feature = "pyo3", pyo3::pyclass)]
|
#[cfg_attr(feature = "pyo3", pyo3::pyclass)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct Discovered {
|
pub struct Discovered {
|
||||||
/// Zoo Lint Finding information.
|
/// Zoo Lint Finding information.
|
||||||
pub finding: Finding,
|
pub finding: Finding,
|
||||||
@ -83,8 +87,10 @@ impl IntoDiagnostic for Discovered {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Abstract lint problem type.
|
/// Abstract lint problem type.
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq, ts_rs::TS, Serialize, JsonSchema)]
|
||||||
|
#[ts(export)]
|
||||||
#[cfg_attr(feature = "pyo3", pyo3::pyclass)]
|
#[cfg_attr(feature = "pyo3", pyo3::pyclass)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct Finding {
|
pub struct Finding {
|
||||||
/// Unique identifier for this particular issue.
|
/// Unique identifier for this particular issue.
|
||||||
pub code: &'static str,
|
pub code: &'static str,
|
||||||
|
@ -37,11 +37,13 @@ use super::backend::{InnerHandle, UpdateHandle};
|
|||||||
use crate::{
|
use crate::{
|
||||||
ast::types::VariableKind,
|
ast::types::VariableKind,
|
||||||
executor::SourceRange,
|
executor::SourceRange,
|
||||||
lint::checks,
|
|
||||||
lsp::{backend::Backend as _, safemap::SafeMap, util::IntoDiagnostic},
|
lsp::{backend::Backend as _, safemap::SafeMap, util::IntoDiagnostic},
|
||||||
parser::PIPE_OPERATOR,
|
parser::PIPE_OPERATOR,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
use crate::lint::checks;
|
||||||
|
|
||||||
/// A subcommand for running the server.
|
/// A subcommand for running the server.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
#[cfg_attr(feature = "cli", derive(Parser))]
|
#[cfg_attr(feature = "cli", derive(Parser))]
|
||||||
@ -256,12 +258,14 @@ impl crate::lsp::backend::Backend for Backend {
|
|||||||
// This function automatically executes if we should & updates the diagnostics if we got
|
// This function automatically executes if we should & updates the diagnostics if we got
|
||||||
// errors.
|
// errors.
|
||||||
if self.execute(¶ms, ast.clone()).await.is_err() {
|
if self.execute(¶ms, ast.clone()).await.is_err() {
|
||||||
// if there was an issue, let's bail and avoid trying to lint.
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for discovered_finding in ast.lint(checks::lint_variables).into_iter().flatten() {
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
self.add_to_diagnostics(¶ms, discovered_finding).await;
|
{
|
||||||
|
for discovered_finding in ast.lint(checks::lint_variables).into_iter().flatten() {
|
||||||
|
self.add_to_diagnostics(¶ms, discovered_finding).await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ use std::{
|
|||||||
|
|
||||||
use futures::stream::TryStreamExt;
|
use futures::stream::TryStreamExt;
|
||||||
use gloo_utils::format::JsValueSerdeExt;
|
use gloo_utils::format::JsValueSerdeExt;
|
||||||
use kcl_lib::{coredump::CoreDump, engine::EngineManager, executor::ExecutorSettings};
|
use kcl_lib::{coredump::CoreDump, engine::EngineManager, executor::ExecutorSettings, lint::checks};
|
||||||
use tower_lsp::{LspService, Server};
|
use tower_lsp::{LspService, Server};
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
@ -59,6 +59,20 @@ pub async fn execute_wasm(
|
|||||||
JsValue::from_serde(&memory).map_err(|e| e.to_string())
|
JsValue::from_serde(&memory).map_err(|e| e.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// wasm_bindgen wrapper for execute
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub async fn kcl_lint(program_str: &str) -> Result<JsValue, String> {
|
||||||
|
console_error_panic_hook::set_once();
|
||||||
|
|
||||||
|
let program: kcl_lib::ast::types::Program = serde_json::from_str(program_str).map_err(|e| e.to_string())?;
|
||||||
|
let mut findings = vec![];
|
||||||
|
for discovered_finding in program.lint(checks::lint_variables).into_iter().flatten() {
|
||||||
|
findings.push(discovered_finding);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(JsValue::from_serde(&findings).map_err(|e| e.to_string())?)
|
||||||
|
}
|
||||||
|
|
||||||
// wasm_bindgen wrapper for creating default planes
|
// wasm_bindgen wrapper for creating default planes
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub async fn make_default_planes(
|
pub async fn make_default_planes(
|
||||||
|
Reference in New Issue
Block a user