diff --git a/packages/website/src/components/ErrorsViewer.tsx b/packages/website/src/components/ErrorsViewer.tsx index b9f6528672be..b37597f69483 100644 --- a/packages/website/src/components/ErrorsViewer.tsx +++ b/packages/website/src/components/ErrorsViewer.tsx @@ -86,7 +86,7 @@ function ErrorBlock({ )} - {item.suggestions.length > 0 && ( + {item.suggestions && item.suggestions.length > 0 && (
{item.suggestions.map((fixer, index) => (
(); - const [markers, setMarkers] = useState(); + const [markers, setMarkers] = useState>({ + code: [], + eslintrc: [], + tsconfig: [], + }); const [ruleNames, setRuleNames] = useState([]); const [isLoading, setIsLoading] = useState(true); const [tsVersions, setTSVersion] = useState([]); @@ -165,8 +169,10 @@ function Playground(): React.JSX.Element { active={state.showAST ?? false} additionalTabsInfo={{ Errors: - markers?.reduce((prev, cur) => prev + cur.items.length, 0) || - 0, + markers[activeTab].reduce( + (prev, cur) => prev + cur.items.length, + 0, + ) || 0, }} change={showAST => setState({ showAST })} tabs={detailTabs} @@ -216,7 +222,7 @@ function Playground(): React.JSX.Element { /> ) ) : ( - + )}
diff --git a/packages/website/src/components/editor/LoadedEditor.tsx b/packages/website/src/components/editor/LoadedEditor.tsx index 0cc5dbe16299..1b7937e5244a 100644 --- a/packages/website/src/components/editor/LoadedEditor.tsx +++ b/packages/website/src/components/editor/LoadedEditor.tsx @@ -83,8 +83,23 @@ export const LoadedEditor: React.FC = ({ const markers = monaco.editor.getModelMarkers({ resource: model.uri, }); - onMarkersChange(parseMarkers(markers, codeActions, editor)); - }, [codeActions, onMarkersChange, editor, monaco.editor]); + + const errors = parseMarkers(markers, codeActions, editor); + + onMarkersChange(prev => { + const tsconfigErrors = + activeTab === 'tsconfig' && + !errors.length && + Object.values(prev[activeTab]).filter( + error => error.group === 'TypeScript', + ); + + return { + ...prev, + [activeTab]: tsconfigErrors || errors, + }; + }); + }, [activeTab, codeActions, onMarkersChange, editor, monaco.editor]); useEffect(() => { webLinter.updateParserOptions(sourceType); diff --git a/packages/website/src/components/editor/types.ts b/packages/website/src/components/editor/types.ts index 3b8b41a67944..932f7cf5d9ad 100644 --- a/packages/website/src/components/editor/types.ts +++ b/packages/website/src/components/editor/types.ts @@ -5,7 +5,9 @@ export interface CommonEditorProps extends ConfigModel { readonly activeTab: TabType; readonly onASTChange: (value: UpdateModel | undefined) => void; readonly onChange: (cfg: Partial) => void; - readonly onMarkersChange: (value: ErrorGroup[]) => void; + readonly onMarkersChange: React.Dispatch< + React.SetStateAction> + >; readonly onSelect: (position?: number) => void; readonly selectedRange?: SelectedRange; } diff --git a/packages/website/src/components/editor/useSandboxServices.ts b/packages/website/src/components/editor/useSandboxServices.ts index d3a6e7fc00e3..f28548405e15 100644 --- a/packages/website/src/components/editor/useSandboxServices.ts +++ b/packages/website/src/components/editor/useSandboxServices.ts @@ -116,6 +116,7 @@ export const useSandboxServices = ( system, lintUtils, sandboxInstance.tsvfs, + props.onMarkersChange, ); onLoaded( diff --git a/packages/website/src/components/linter/createLinter.ts b/packages/website/src/components/linter/createLinter.ts index 78f001439d87..c396a4642e03 100644 --- a/packages/website/src/components/linter/createLinter.ts +++ b/packages/website/src/components/linter/createLinter.ts @@ -7,6 +7,10 @@ import type { } from '@typescript-eslint/utils/ts-eslint'; import type * as ts from 'typescript'; +import type { + ErrorGroup, + TabType, +} from '../../../../website/src/components/types'; import type { LinterOnLint, LinterOnParse, @@ -42,6 +46,9 @@ export function createLinter( system: PlaygroundSystem, webLinterModule: WebLinterModule, vfs: typeof tsvfs, + onMarkersChange: React.Dispatch< + React.SetStateAction> + >, ): CreateLinter { const rules: CreateLinter['rules'] = new Map(); const configs = new Map(Object.entries(webLinterModule.configs)); @@ -153,6 +160,8 @@ export function createLinter( }; const applyTSConfig = (fileName: string): void => { + let error: ErrorGroup | null = null; + try { const file = system.readFile(fileName) ?? '{}'; const parsed = parseTSConfig(file).compilerOptions; @@ -160,7 +169,38 @@ export function createLinter( console.log('[Editor] Updating', fileName, compilerOptions); parser.updateConfig(compilerOptions); } catch (e) { - console.error(e); + if (e instanceof Error) { + error = { + group: 'TypeScript', + items: e.message + .trim() + .split('\n') + .map((message: string) => { + return { + message, + severity: 8, // MarkerSeverity.Error + }; + }), + uri: undefined, + }; + } + } finally { + onMarkersChange(prev => { + const activeTabErrors = Object.fromEntries( + prev.tsconfig.map(error => [error.group, error]), + ); + + if (error) { + activeTabErrors.TypeScript = error; + } else { + delete activeTabErrors.TypeScript; + } + + return { + ...prev, + tsconfig: Object.values(activeTabErrors), + }; + }); } }; diff --git a/packages/website/src/components/types.ts b/packages/website/src/components/types.ts index 181e1e5de39b..7dc1e913b1f1 100644 --- a/packages/website/src/components/types.ts +++ b/packages/website/src/components/types.ts @@ -40,10 +40,10 @@ export type SelectedRange = [number, number]; export interface ErrorItem { fixer?: { fix(): void; message: string }; - location: string; + location?: string; message: string; severity: number; - suggestions: { fix(): void; message: string }[]; + suggestions?: { fix(): void; message: string }[]; } export interface ErrorGroup {