-
-
Notifications
You must be signed in to change notification settings - Fork 187
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Improve context for errors thrown by compiler
This commit introduces a custom error object to provide additional context for errors throwing during parsing and compiling operations, improving troubleshooting. By integrating error context handling, the error messages become more informative and user-friendly, providing sequence of trace with context to aid in troubleshooting. Changes include: - Introduce custom error object that extends errors with contextual information. This replaces previous usages of `AggregateError` which is not displayed well by browsers when logged. - Improve parsing functions to encapsulate error context with more details. - Increase unit test coverage and refactor the related code to be more testable.
- Loading branch information
1 parent
7794846
commit 4212c7b
Showing
78 changed files
with
3,323 additions
and
1,245 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import { CustomError } from '@/application/Common/CustomError'; | ||
|
||
export interface ErrorWithContextWrapper { | ||
( | ||
error: Error, | ||
additionalContext: string, | ||
): Error; | ||
} | ||
|
||
export const wrapErrorWithAdditionalContext: ErrorWithContextWrapper = ( | ||
error: Error, | ||
additionalContext: string, | ||
) => { | ||
return (error instanceof ContextualError ? error : new ContextualError(error)) | ||
.withAdditionalContext(additionalContext); | ||
}; | ||
|
||
/* AggregateError is similar but isn't well-serialized or displayed by browsers */ | ||
class ContextualError extends CustomError { | ||
private readonly additionalContext = new Array<string>(); | ||
|
||
constructor( | ||
public readonly innerError: Error, | ||
) { | ||
super(); | ||
} | ||
|
||
public withAdditionalContext(additionalContext: string): this { | ||
this.additionalContext.push(additionalContext); | ||
return this; | ||
} | ||
|
||
public get message(): string { // toString() is not used when Chromium logs it on console | ||
return [ | ||
'\n', | ||
this.innerError.message, | ||
'\n', | ||
'Additional context:', | ||
...this.additionalContext.map((context, index) => `${index + 1}: ${context}`), | ||
].join('\n'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
25 changes: 25 additions & 0 deletions
25
src/application/Parser/NodeValidation/NodeDataErrorContext.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import type { CategoryData, ScriptData } from '@/application/collections/'; | ||
import { NodeDataType } from './NodeDataType'; | ||
import type { NodeData } from './NodeData'; | ||
|
||
export type NodeDataErrorContext = { | ||
readonly parentNode?: CategoryData; | ||
} & (CategoryNodeErrorContext | ScriptNodeErrorContext | UnknownNodeErrorContext); | ||
|
||
export type CategoryNodeErrorContext = { | ||
readonly type: NodeDataType.Category; | ||
readonly selfNode: CategoryData; | ||
readonly parentNode?: CategoryData; | ||
}; | ||
|
||
export type ScriptNodeErrorContext = { | ||
readonly type: NodeDataType.Script; | ||
readonly selfNode: ScriptData; | ||
readonly parentNode?: CategoryData; | ||
}; | ||
|
||
export type UnknownNodeErrorContext = { | ||
readonly type?: undefined; | ||
readonly selfNode: NodeData; | ||
readonly parentNode?: CategoryData; | ||
}; |
35 changes: 35 additions & 0 deletions
35
src/application/Parser/NodeValidation/NodeDataErrorContextMessage.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { NodeDataType } from './NodeDataType'; | ||
import type { NodeDataErrorContext } from './NodeDataErrorContext'; | ||
import type { NodeData } from './NodeData'; | ||
|
||
export interface NodeContextErrorMessageCreator { | ||
( | ||
errorMessage: string, | ||
context: NodeDataErrorContext, | ||
): string; | ||
} | ||
|
||
export const createNodeContextErrorMessage: NodeContextErrorMessageCreator = ( | ||
errorMessage, | ||
context, | ||
) => { | ||
let message = ''; | ||
if (context.type !== undefined) { | ||
message += `${NodeDataType[context.type]}: `; | ||
} | ||
message += errorMessage; | ||
message += `\n${getErrorContextDetails(context)}`; | ||
return message; | ||
}; | ||
|
||
function getErrorContextDetails(context: NodeDataErrorContext): string { | ||
let output = `Self: ${printNodeDataAsJson(context.selfNode)}`; | ||
if (context.parentNode) { | ||
output += `\nParent: ${printNodeDataAsJson(context.parentNode)}`; | ||
} | ||
return output; | ||
} | ||
|
||
function printNodeDataAsJson(node: NodeData): string { | ||
return JSON.stringify(node, undefined, 2); | ||
} |
Oops, something went wrong.