diff --git a/protocol/types.d.ts b/protocol/types.d.ts index 0e938b0..cd98b8c 100644 --- a/protocol/types.d.ts +++ b/protocol/types.d.ts @@ -47,6 +47,9 @@ export interface PanelState { hasParseErrors?: boolean; blockedByMetaschema?: boolean; noFileSelected?: boolean; + lintError?: string; + formatError?: string; + metaschemaError?: string; } export type WebviewCommand = 'goToPosition' | 'formatSchema' | 'openExternal'; diff --git a/vscode/src/extension.ts b/vscode/src/extension.ts index cdc01d9..035f6da 100644 --- a/vscode/src/extension.ts +++ b/vscode/src/extension.ts @@ -135,11 +135,11 @@ function handleWebviewMessage(message: WebviewToExtensionMessage): void { } } - vscode.window.showErrorMessage(`Format failed: ${errorMessage}`); if (currentPanelState) { const updatedState = { ...currentPanelState, formatResult: { output: `Error: ${errorMessage}`, exitCode: null }, + formatError: errorMessage, formatLoading: false }; currentPanelState = updatedState; @@ -323,16 +323,20 @@ async function updatePanelContent(): Promise { ); } } catch (error) { - cachedCliVersion = `Error: ${(error as Error).message}`; + const errorMessage = (error as Error).message; + cachedCliVersion = `Error: ${errorMessage}`; const errorState: PanelState = { fileInfo, cliVersion: cachedCliVersion, extensionVersion, - lintResult: { raw: `Error: ${(error as Error).message}`, health: null, error: true }, - formatResult: { output: `Error: ${(error as Error).message}`, exitCode: null }, - metaschemaResult: { output: `Error: ${(error as Error).message}`, exitCode: null }, + lintResult: { raw: `Error: ${errorMessage}`, health: null, error: true }, + formatResult: { output: `Error: ${errorMessage}`, exitCode: null }, + metaschemaResult: { output: `Error: ${errorMessage}`, exitCode: null }, isLoading: false, - hasParseErrors: true + hasParseErrors: true, + lintError: errorMessage, + formatError: errorMessage, + metaschemaError: errorMessage }; currentPanelState = errorState; panelManager.updateContent(errorState); diff --git a/webview/src/App.tsx b/webview/src/App.tsx index a5e8a9a..8d6d31b 100644 --- a/webview/src/App.tsx +++ b/webview/src/App.tsx @@ -73,9 +73,9 @@ function App() { ) : ( <> - {activeTab === 'lint' && } - {activeTab === 'format' && } - {activeTab === 'metaschema' && } + {activeTab === 'lint' && } + {activeTab === 'format' && } + {activeTab === 'metaschema' && } )} diff --git a/webview/src/components/FormatTab.tsx b/webview/src/components/FormatTab.tsx index a061738..70cb975 100644 --- a/webview/src/components/FormatTab.tsx +++ b/webview/src/components/FormatTab.tsx @@ -9,9 +9,10 @@ export interface FormatTabProps { hasParseErrors?: boolean; blocked?: boolean; noFileSelected?: boolean; + formatError?: string; } -export function FormatTab({ formatResult, fileInfo, hasParseErrors, blocked, noFileSelected }: FormatTabProps) { +export function FormatTab({ formatResult, fileInfo, hasParseErrors, blocked, noFileSelected, formatError }: FormatTabProps) { const handleFormatSchema = () => { vscode.formatSchema(); }; @@ -32,6 +33,23 @@ export function FormatTab({ formatResult, fileInfo, hasParseErrors, blocked, noF ); } + if (formatError) { + return ( +
+
+ +
+
+ Format Command Failed +
+
+ {formatError} +
+ +
+ ); + } + if (hasParseErrors) { return (
diff --git a/webview/src/components/LintTab.tsx b/webview/src/components/LintTab.tsx index 43d1e98..ce4443e 100644 --- a/webview/src/components/LintTab.tsx +++ b/webview/src/components/LintTab.tsx @@ -7,9 +7,10 @@ export interface LintTabProps { lintResult: LintResult; blocked?: boolean; noFileSelected?: boolean; + lintError?: string; } -export function LintTab({ lintResult, blocked, noFileSelected }: LintTabProps) { +export function LintTab({ lintResult, blocked, noFileSelected, lintError }: LintTabProps) { const handleGoToPosition = (position: Position) => { vscode.goToPosition(position); }; @@ -30,6 +31,21 @@ export function LintTab({ lintResult, blocked, noFileSelected }: LintTabProps) { ); } + if (lintError) { + return ( +
+
+ +
+
Lint Command Failed
+
+ {lintError} +
+ +
+ ); + } + if (blocked) { return (
@@ -37,7 +53,7 @@ export function LintTab({ lintResult, blocked, noFileSelected }: LintTabProps) {
Cannot Lint Schema
-
+
Metaschema validation failed. Fix the metaschema errors first before running lint. Check the Metaschema tab for more details.
diff --git a/webview/src/components/MetaschemaTab.tsx b/webview/src/components/MetaschemaTab.tsx index 752c58a..165024b 100644 --- a/webview/src/components/MetaschemaTab.tsx +++ b/webview/src/components/MetaschemaTab.tsx @@ -6,13 +6,14 @@ import { CheckCircle, AlertTriangle, FileQuestion } from 'lucide-react'; export interface MetaschemaTabProps { metaschemaResult: MetaschemaResult; noFileSelected?: boolean; + metaschemaError?: string; } function isMetaschemaError(error: unknown): error is MetaschemaError { return typeof error === 'object' && error !== null && 'instancePosition' in error; } -export function MetaschemaTab({ metaschemaResult, noFileSelected }: MetaschemaTabProps) { +export function MetaschemaTab({ metaschemaResult, noFileSelected, metaschemaError }: MetaschemaTabProps) { const handleGoToPosition = (position: Position) => { vscode.goToPosition(position); }; @@ -34,6 +35,21 @@ export function MetaschemaTab({ metaschemaResult, noFileSelected }: MetaschemaTa ); } + if (metaschemaError) { + return ( +
+
+ +
+
Metaschema Command Failed
+
+ {metaschemaError} +
+ +
+ ); + } + if (metaschemaResult.exitCode === 0) { return ( <> diff --git a/webview/src/components/Tabs.tsx b/webview/src/components/Tabs.tsx index 379b92c..dcb0216 100644 --- a/webview/src/components/Tabs.tsx +++ b/webview/src/components/Tabs.tsx @@ -17,9 +17,9 @@ interface TabProps { } export function Tabs({ activeTab, onTabChange, state }: TabsProps) { - const lintStatus = calculateLintStatus(state.lintResult.errors?.length || 0, state.lintResult.health, state.isLoading, state.noFileSelected); - const formatStatus = calculateFormatStatus(state.formatResult.exitCode, state.formatLoading, state.fileInfo?.isYaml, state.noFileSelected); - const metaschemaStatus = calculateMetaschemaStatus(state.metaschemaResult.exitCode, state.isLoading, state.noFileSelected); + const lintStatus = calculateLintStatus(state.lintResult.errors?.length || 0, state.lintResult.health, state.isLoading, state.noFileSelected, state.lintError); + const formatStatus = calculateFormatStatus(state.formatResult.exitCode, state.formatLoading, state.fileInfo?.isYaml, state.noFileSelected, state.formatError); + const metaschemaStatus = calculateMetaschemaStatus(state.metaschemaResult.exitCode, state.isLoading, state.noFileSelected, state.metaschemaError); const lintDisabled = !!state.blockedByMetaschema; const Tab = ({ diff --git a/webview/src/utils/tabStatus.ts b/webview/src/utils/tabStatus.ts index 8acbcfb..d69807d 100644 --- a/webview/src/utils/tabStatus.ts +++ b/webview/src/utils/tabStatus.ts @@ -13,11 +13,15 @@ export function calculateLintStatus( errorCount: number, health: number | null, isLoading?: boolean, - noFileSelected?: boolean + noFileSelected?: boolean, + lintError?: string ): TabStatusResult { if (noFileSelected) { return { Icon: null, color: 'var(--vscode-muted)' }; } + if (lintError) { + return { Icon: X, color: 'var(--error)' }; + } if (isLoading) { return { Icon: HelpCircle, color: 'var(--vscode-muted)' }; } @@ -46,11 +50,15 @@ export function calculateFormatStatus( exitCode: number | null, formatLoading?: boolean, isYaml?: boolean, - noFileSelected?: boolean + noFileSelected?: boolean, + formatError?: string ): TabStatusResult { if (noFileSelected) { return { Icon: null, color: 'var(--vscode-muted)' }; } + if (formatError) { + return { Icon: X, color: 'var(--error)' }; + } if (formatLoading || exitCode === null || exitCode === undefined) { return { Icon: HelpCircle, color: 'var(--vscode-muted)' }; } @@ -70,11 +78,15 @@ export function calculateFormatStatus( export function calculateMetaschemaStatus( exitCode: number | null, isLoading?: boolean, - noFileSelected?: boolean + noFileSelected?: boolean, + metaschemaError?: string ): TabStatusResult { if (noFileSelected) { return { Icon: null, color: 'var(--vscode-muted)' }; } + if (metaschemaError) { + return { Icon: X, color: 'var(--error)' }; + } if (isLoading || exitCode === null || exitCode === undefined) { return { Icon: HelpCircle, color: 'var(--vscode-muted)' }; }