-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
improve sketch error messages in the editor console #4092
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop-codemirror-v6
Are you sure you want to change the base?
Changes from all commits
9fbda46
4279ff3
7194832
f9a35f3
36aa31e
50dd5e4
278b9c9
3076ec8
6bbb338
20737cd
e808008
2db472d
81aea2a
70822d7
e010707
2e54aa0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -148,27 +148,47 @@ function Editor({ | |
| useEffect(() => { | ||
| const consoleErrors = consoleEvents.filter((e) => e.method === 'error'); | ||
|
|
||
| if (consoleErrors.length > 0) { | ||
| const firstError = consoleErrors[0]; | ||
| const errorObj = { stack: firstError.data[0].toString() }; | ||
| StackTrace.fromError(errorObj).then((stackLines) => { | ||
| expandConsole(); | ||
| const line = stackLines.find( | ||
| (l) => l.fileName && l.fileName.startsWith('/') | ||
| removeErrorDecorations(codemirrorView.current); | ||
|
|
||
| if (consoleErrors.length === 0) return; | ||
|
Comment on lines
+151
to
+153
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i think the decoration clearing may be better scoped to the empty-error case: if (consoleErrors.length === 0) {
removeErrorDecorations(codemirrorView.current);
return;
}readable + more stable
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i thought about scoping it but kept the unconditional clear on purpose. if a user has an error on line 5, fixes it, then introduces a new error on line 10 on the next run, skipping the clear leaves the old gutter on line 5 even though its already fixed. clear-then-add guarantees the gutters always reflect just the latest run, happy to revisit if you can think of a case where the always-clear causes flicker or perf issues There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sorry i cant get it, can you clearly state the steps to reproduce what you are saying if we move |
||
|
|
||
| const resolveFrameFromError = (errorEntry) => { | ||
| const metaStack = errorEntry.meta && errorEntry.meta.stack; | ||
| if (Array.isArray(metaStack) && metaStack.length > 0) { | ||
| return Promise.resolve( | ||
| metaStack.find((f) => f.fileName && f.fileName.startsWith('/')) || | ||
| metaStack[0] | ||
| ); | ||
| if (!line) return; | ||
| const fileNameArray = line.fileName.split('/'); | ||
| const fileName = fileNameArray.slice(-1)[0]; | ||
| const filePath = fileNameArray.slice(0, -1).join('/'); | ||
| const fileWithError = files.find( | ||
| (f) => f.name === fileName && f.filePath === filePath | ||
| } | ||
| return StackTrace.fromError({ | ||
| stack: errorEntry.data[0].toString() | ||
| }).then((stackLines) => | ||
| stackLines.find((l) => l.fileName && l.fileName.startsWith('/')) | ||
| ); | ||
| }; | ||
|
|
||
| const matchFile = (frame) => { | ||
| if (!frame || !frame.fileName) return null; | ||
| const parts = frame.fileName.split('/'); | ||
| const fileName = parts.slice(-1)[0]; | ||
| const filePath = parts.slice(0, -1).join('/'); | ||
| return files.find((f) => f.name === fileName && f.filePath === filePath); | ||
| }; | ||
|
|
||
| Promise.all(consoleErrors.map(resolveFrameFromError)).then((frames) => { | ||
| const pairs = frames | ||
| .map((frame) => ({ frame, file: matchFile(frame) })) | ||
| .filter((p) => p.frame && p.file); | ||
| if (pairs.length === 0) return; | ||
| expandConsole(); | ||
| const targetFileId = pairs[0].file.id; | ||
| setSelectedFile(targetFileId); | ||
| pairs | ||
| .filter((p) => p.file.id === targetFileId) | ||
| .forEach((p) => | ||
| addErrorDecoration(codemirrorView.current, p.frame.lineNumber) | ||
| ); | ||
| setSelectedFile(fileWithError.id); | ||
| addErrorDecoration(codemirrorView.current, line.lineNumber); | ||
| }); | ||
| } else { | ||
| removeErrorDecorations(codemirrorView.current); | ||
| } | ||
| }); | ||
| }, [consoleEvents]); | ||
|
|
||
| const editorSectionClass = classNames({ | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
using only
consoleErrors[0]actually seems reasonable to me from a UX perspective.reflects an implicit assumption that:
maybe.
that could reduce console noise while still making secondary issues discoverable contextually near the affected lines.
something similar is already done in editors/platforms like openprocessing, where the primary runtime issue is emphasized while additional diagnostics remain attached to the code locations themselves.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
targetFileId = pairs[0].file.idfor navigation/focus and every error in that file getsaddErrorDecorationso all the lines get a red gutterThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
imo showing syntax errors in the line itself will be more intuitive for beginners.