mirror of
https://github.com/pybricks/pybricks-code.git
synced 2026-09-12 09:36:27 +00:00
mpy/alerts: implement compiler error
This shows the output from mpy-cross and has a button to go to the error.
This commit is contained in:
committed by
David Lechner
parent
e5ab52b250
commit
7e726fffaf
@@ -6,6 +6,7 @@ import alerts from './alerts/alerts';
|
||||
import ble from './ble/alerts';
|
||||
import explorer from './explorer/alerts';
|
||||
import firmware from './firmware/alerts';
|
||||
import mpy from './mpy/alerts';
|
||||
import type { CreateToast } from './toasterTypes';
|
||||
|
||||
/** This collects alerts from all of the subsystems of the app */
|
||||
@@ -14,6 +15,7 @@ const alertDomains = {
|
||||
ble,
|
||||
explorer,
|
||||
firmware,
|
||||
mpy,
|
||||
};
|
||||
|
||||
/** Gets the type of available alert domains. */
|
||||
|
||||
@@ -112,3 +112,12 @@ export const editorDidFailToActivateFile = createAction((uuid: UUID, error: Erro
|
||||
uuid,
|
||||
error,
|
||||
}));
|
||||
|
||||
/**
|
||||
* Requests to activate a file and show line.
|
||||
*/
|
||||
export const editorGoto = createAction((uuid: UUID, line: number) => ({
|
||||
type: 'editor.action.goto',
|
||||
uuid,
|
||||
line,
|
||||
}));
|
||||
|
||||
@@ -60,6 +60,7 @@ import {
|
||||
editorDidOpenFile,
|
||||
editorGetValueRequest,
|
||||
editorGetValueResponse,
|
||||
editorGoto,
|
||||
editorOpenFile,
|
||||
} from './actions';
|
||||
import { EditorError } from './error';
|
||||
@@ -265,6 +266,34 @@ function* handleEditorActivateFile(
|
||||
}
|
||||
}
|
||||
|
||||
function* handleEditorGoto(
|
||||
editor: monaco.editor.ICodeEditor,
|
||||
action: ReturnType<typeof editorGoto>,
|
||||
): Generator {
|
||||
yield* put(editorActivateFile(action.uuid));
|
||||
|
||||
const { didActivate, didFailToActivate } = yield* race({
|
||||
didActivate: take(editorDidActivateFile.when((a) => a.uuid === action.uuid)),
|
||||
didFailToActivate: take(
|
||||
editorDidFailToActivateFile.when((a) => a.uuid === action.uuid),
|
||||
),
|
||||
});
|
||||
|
||||
if (didFailToActivate) {
|
||||
return;
|
||||
}
|
||||
|
||||
defined(didActivate);
|
||||
|
||||
editor.revealLineInCenterIfOutsideViewport(action.line);
|
||||
editor.setSelection({
|
||||
startColumn: 1,
|
||||
startLineNumber: action.line,
|
||||
endColumn: Infinity,
|
||||
endLineNumber: action.line,
|
||||
});
|
||||
}
|
||||
|
||||
function* handleEditorDidCloseFile(
|
||||
activeFileHistory: ActiveFileHistoryManager,
|
||||
action: ReturnType<typeof editorDidCloseFile>,
|
||||
@@ -356,6 +385,7 @@ function* handleDidCreateEditor(editor: monaco.editor.ICodeEditor): Generator {
|
||||
openFiles,
|
||||
activeFileHistory,
|
||||
);
|
||||
yield* takeEvery(editorGoto, handleEditorGoto, editor);
|
||||
yield* takeEvery(editorDidCloseFile, handleEditorDidCloseFile, activeFileHistory);
|
||||
yield* fork(monitorViewState, editor);
|
||||
|
||||
|
||||
@@ -25,3 +25,18 @@ export function useFileStoragePath(uuid: UUID): string | undefined {
|
||||
const db = useContext(FileStorageContext);
|
||||
return useLiveQuery(() => db.metadata.get(uuid, (x) => x?.path));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the file path for a file UUID.
|
||||
*
|
||||
* If the file is renamed, the returned value will be automatically updated.
|
||||
*/
|
||||
export function useFileStorageUuid(path: string): UUID | undefined {
|
||||
const db = useContext(FileStorageContext);
|
||||
return useLiveQuery(() =>
|
||||
db.metadata
|
||||
.where('path')
|
||||
.equals(path)
|
||||
.first((x) => x?.uuid),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -206,6 +206,16 @@ function* handleDownloadAndRun(action: ReturnType<typeof downloadAndRun>): Gener
|
||||
});
|
||||
|
||||
if (didFailToCompile) {
|
||||
yield* put(
|
||||
alertsShowAlert(
|
||||
'mpy',
|
||||
'compilerError',
|
||||
{
|
||||
error: didFailToCompile.error,
|
||||
},
|
||||
'mpy.compilerError',
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2022 The Pybricks Authors
|
||||
|
||||
import { Button, Intent } from '@blueprintjs/core';
|
||||
import React, { useMemo } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { editorGoto } from '../../editor/actions';
|
||||
import { useFileStorageUuid } from '../../fileStorage/hooks';
|
||||
import type { CreateToast } from '../../toasterTypes';
|
||||
import { useI18n } from './i18n';
|
||||
|
||||
type CompilerErrorProps = {
|
||||
error: string[];
|
||||
};
|
||||
|
||||
const CompilerError: React.VoidFunctionComponent<CompilerErrorProps> = ({ error }) => {
|
||||
const dispatch = useDispatch();
|
||||
const i18n = useI18n();
|
||||
|
||||
const [file, line] = useMemo(() => {
|
||||
for (const line of error) {
|
||||
const match = line.match(/^ {2}File "(.*)", line (\d+)/);
|
||||
|
||||
if (match) {
|
||||
return [match[1], Number(match[2])];
|
||||
}
|
||||
}
|
||||
|
||||
return [undefined, undefined];
|
||||
}, [error]);
|
||||
|
||||
const uuid = useFileStorageUuid(file ?? '');
|
||||
|
||||
return (
|
||||
<>
|
||||
<p>{i18n.translate('compilerError.message')}</p>
|
||||
<pre className="pb-mpy-alerts-compile-error">{error.join('\n')}</pre>
|
||||
{file && uuid && (
|
||||
<Button icon="code" onClick={() => dispatch(editorGoto(uuid, line))}>
|
||||
{i18n.translate('compilerError.gotoErrorButton')}
|
||||
</Button>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const compilerError: CreateToast<CompilerErrorProps, 'dismiss' | 'gotoError'> = (
|
||||
onAction,
|
||||
props,
|
||||
) => {
|
||||
return {
|
||||
message: <CompilerError {...props} />,
|
||||
icon: 'error',
|
||||
intent: Intent.DANGER,
|
||||
timeout: 0,
|
||||
onDismiss: () => onAction('dismiss'),
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2022 The Pybricks Authors
|
||||
|
||||
import { useI18n as useShopifyI18n } from '@shopify/react-i18n';
|
||||
import type { TypedI18n } from '../../i18n';
|
||||
import type translations from './translations/en.json';
|
||||
|
||||
export function useI18n(): TypedI18n<typeof translations> {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useShopifyI18n();
|
||||
return i18n;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2022 The Pybricks Authors
|
||||
|
||||
pre.pb-mpy-alerts-compile-error {
|
||||
white-space: pre-wrap;
|
||||
word-break: keep-all;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2022 The Pybricks Authors
|
||||
|
||||
import './index.scss';
|
||||
import { compilerError } from './CompilerError';
|
||||
|
||||
// gathers all of the alert creation functions for passing up to the top level
|
||||
export default {
|
||||
compilerError,
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"compilerError": {
|
||||
"message": "Failed to compile MicroPython file.",
|
||||
"gotoErrorButton": "Goto error"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user