Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions protocol/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
16 changes: 10 additions & 6 deletions vscode/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -323,16 +323,20 @@ async function updatePanelContent(): Promise<void> {
);
}
} 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);
Expand Down
6 changes: 3 additions & 3 deletions webview/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ function App() {
<LoadingSpinner fileInfo={state.fileInfo} />
) : (
<>
{activeTab === 'lint' && <LintTab lintResult={state.lintResult} blocked={!!state.blockedByMetaschema} noFileSelected={state.noFileSelected} />}
{activeTab === 'format' && <FormatTab formatResult={state.formatResult} fileInfo={state.fileInfo} hasParseErrors={state.hasParseErrors} blocked={!!state.blockedByMetaschema} noFileSelected={state.noFileSelected} />}
{activeTab === 'metaschema' && <MetaschemaTab metaschemaResult={state.metaschemaResult} noFileSelected={state.noFileSelected} />}
{activeTab === 'lint' && <LintTab lintResult={state.lintResult} blocked={!!state.blockedByMetaschema} noFileSelected={state.noFileSelected} lintError={state.lintError} />}
{activeTab === 'format' && <FormatTab formatResult={state.formatResult} fileInfo={state.fileInfo} hasParseErrors={state.hasParseErrors} blocked={!!state.blockedByMetaschema} noFileSelected={state.noFileSelected} formatError={state.formatError} />}
{activeTab === 'metaschema' && <MetaschemaTab metaschemaResult={state.metaschemaResult} noFileSelected={state.noFileSelected} metaschemaError={state.metaschemaError} />}
</>
)}
</div>
Expand Down
20 changes: 19 additions & 1 deletion webview/src/components/FormatTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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();
};
Expand All @@ -32,6 +33,23 @@ export function FormatTab({ formatResult, fileInfo, hasParseErrors, blocked, noF
);
}

if (formatError) {
return (
<div className="text-center py-10 px-5">
<div className="flex justify-center mb-4">
<AlertCircle size={48} className="text-(--error)" strokeWidth={1.5} />
</div>
<div className="text-lg font-semibold text-(--vscode-fg) mb-2">
Format Command Failed
</div>
<div className="text-[13px] text-(--vscode-muted) max-w-md mx-auto mb-4">
{formatError}
</div>
<RawOutput output={formatResult.output} />
</div>
);
}

if (hasParseErrors) {
return (
<div className="text-center py-10 px-5">
Expand Down
20 changes: 18 additions & 2 deletions webview/src/components/LintTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};
Expand All @@ -30,14 +31,29 @@ export function LintTab({ lintResult, blocked, noFileSelected }: LintTabProps) {
);
}

if (lintError) {
return (
<div className="text-center py-10 px-5">
<div className="flex justify-center mb-4">
<AlertCircle size={48} className="text-(--error)" strokeWidth={1.5} />
</div>
<div className="text-lg font-semibold text-(--vscode-fg) mb-2">Lint Command Failed</div>
<div className="text-[13px] text-(--vscode-muted) max-w-md mx-auto mb-4">
{lintError}
</div>
<RawOutput output={lintResult.raw} />
</div>
);
}

if (blocked) {
return (
<div className="text-center py-10 px-5">
<div className="flex justify-center mb-4">
<AlertCircle size={48} className="text-(--error)" strokeWidth={1.5} />
</div>
<div className="text-lg font-semibold text-(--vscode-fg) mb-2">Cannot Lint Schema</div>
<div className="text-[13px] text-(--vscode-muted) max-w-md mx-auto">
<div className="textw-[13px] text-(--vscode-muted) max-w-md mx-auto">
Metaschema validation failed. Fix the metaschema errors first before running lint.
Check the Metaschema tab for more details.
</div>
Expand Down
18 changes: 17 additions & 1 deletion webview/src/components/MetaschemaTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};
Expand All @@ -34,6 +35,21 @@ export function MetaschemaTab({ metaschemaResult, noFileSelected }: MetaschemaTa
);
}

if (metaschemaError) {
return (
<div className="text-center py-10 px-5">
<div className="flex justify-center mb-4">
<AlertTriangle size={48} className="text-(--error)" strokeWidth={1.5} />
</div>
<div className="text-lg font-semibold text-(--vscode-fg) mb-2">Metaschema Command Failed</div>
<div className="text-[13px] text-(--vscode-muted) max-w-md mx-auto mb-4">
{metaschemaError}
</div>
<RawOutput output={metaschemaResult.output} />
</div>
);
}

if (metaschemaResult.exitCode === 0) {
return (
<>
Expand Down
6 changes: 3 additions & 3 deletions webview/src/components/Tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 = ({
Expand Down
18 changes: 15 additions & 3 deletions webview/src/utils/tabStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)' };
}
Expand Down Expand Up @@ -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)' };
}
Expand All @@ -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)' };
}
Expand Down