-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Resolves first part of #410 Laying the groudwork and collect evaluation errors. --- Creates errors like below. Note that the formatting is not final. We should probably do some tree based output. The errors can also be inspected programatically. ``` DeclarativeStackError: [RuntimeError at Resources.SiteDistribution] Cannot read properties of undefined (reading 'bind') [TypeError at Resources.SiteDistribution.Properties.defaultBehavior.origin."aws-cdk-lib.aws_cloudfront_origins.S3Origin"] Cannot read properties of undefined (reading 'isWebsite') [RuntimeError at Resources.SiteDistribution.Properties.defaultBehavior.origin."aws-cdk-lib.aws_cloudfront_origins.S3Origin".0.Ref] No such Resource or Parameter: SiteCertificate [RuntimeError at Resources.SiteDistribution.Properties.defaultBehavior.origin."aws-cdk-lib.aws_cloudfront_origins.S3Origin".1.originAccessIdentity.Ref] No such Resource or Parameter: CloudFrontOAI [RuntimeError at Resources.SiteDistribution.Properties.certificate.Ref] No such Resource or Parameter: SiteBucket [RuntimeError at Resources.SiteDistribution.Properties.domainNames.0.Ref] No such Resource or Parameter: DomainName ```
- Loading branch information
Showing
18 changed files
with
579 additions
and
287 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,56 @@ | ||
import { AnnotatedError } from './errors'; | ||
|
||
export class AnnotationsContext { | ||
public static root(): AnnotationsContext { | ||
return new AnnotationsContext(); | ||
} | ||
|
||
public readonly children = new Array<AnnotationsContext>(); | ||
public readonly path: Array<string | number> = []; | ||
public readonly parent?: AnnotationsContext; | ||
private readonly _errorsStack: AnnotatedError[] = []; | ||
|
||
private constructor(parent?: AnnotationsContext, path?: string | number) { | ||
if (parent) { | ||
this.path.push(...parent.path); | ||
this.parent = parent; | ||
parent.children.push(this); | ||
} | ||
|
||
if (path !== undefined) { | ||
this.path.push(path); | ||
} | ||
} | ||
|
||
public get root(): boolean { | ||
return !!this.parent; | ||
} | ||
|
||
public hasErrors(): boolean { | ||
return this.errors.length > 0; | ||
} | ||
|
||
public get errors(): AnnotatedError[] { | ||
return [...this._errorsStack, ...this.children.flatMap((c) => c.errors)]; | ||
} | ||
|
||
public child(path: string | number): AnnotationsContext { | ||
return new AnnotationsContext(this, path); | ||
} | ||
|
||
public wrap<T>(fn: (ctx: AnnotationsContext) => T): T | void { | ||
try { | ||
return fn(this); | ||
} catch (error) { | ||
this.error(error as any); | ||
} | ||
} | ||
|
||
public error(error: Error) { | ||
this._errorsStack.push(new AnnotatedError(this.path, error)); | ||
} | ||
|
||
public toString(printStackStrace = false) { | ||
return this.errors.map((e) => e.toString(printStackStrace)).join('\n\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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import { AnnotationsContext } from './annotations'; | ||
|
||
function indent(text: string, spaces = 4) { | ||
const TAB = ' '.repeat(spaces); | ||
return text | ||
.split('\n') | ||
.map((l) => TAB + l) | ||
.join('\n'); | ||
} | ||
|
||
export class DeclarativeStackError extends Error { | ||
constructor(public readonly annotations: AnnotationsContext) { | ||
super(); | ||
this.name = 'DeclarativeStackError'; | ||
this.message = this.toString(); | ||
Object.setPrototypeOf(this, DeclarativeStackError.prototype); | ||
} | ||
|
||
public toString(debug = false) { | ||
return `${this.name}:\n\n${this.annotations.toString(debug)}`; | ||
} | ||
} | ||
|
||
/** | ||
* Thrown by the Evaluator | ||
*/ | ||
export class RuntimeError extends Error { | ||
public static wrap(error: any) { | ||
return new RuntimeError(error.message, error.stack); | ||
} | ||
|
||
constructor(message: string, stack?: string) { | ||
super(message); | ||
this.name = 'RuntimeError'; | ||
if (stack) { | ||
this.stack = stack; | ||
} | ||
Object.setPrototypeOf(this, RuntimeError.prototype); | ||
} | ||
} | ||
|
||
/** | ||
* Annotation any Error with additional info | ||
*/ | ||
export class AnnotatedError { | ||
constructor( | ||
public readonly stack: Array<string | number>, | ||
public readonly error: Error | ||
) {} | ||
|
||
public toString(printStackStrace = false) { | ||
const details = this.renderErrorDetails(printStackStrace); | ||
return `[${this.error.name} at ${this.renderStack()}]\n${indent(details)}`; | ||
} | ||
|
||
protected renderErrorDetails(printStackStrace = false): string { | ||
if (printStackStrace) { | ||
return this.error.stack ?? this.error.message; | ||
} | ||
return this.error.message; | ||
} | ||
|
||
protected renderStack(): string { | ||
return this.stack | ||
.map((s) => (s.toString().includes('.') ? `"${s}"` : s)) | ||
.join('.'); | ||
} | ||
} |
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,3 @@ | ||
export * from './annotations'; | ||
export * from './errors'; | ||
export * from './unparse'; |
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,28 @@ | ||
import { | ||
INTRINSIC_NAME_MAP, | ||
TemplateExpression, | ||
UserIntrinsicExpression, | ||
} from '../parser/template'; | ||
|
||
export function unparseExpression(x: TemplateExpression): any { | ||
switch (x.type) { | ||
case 'string': | ||
case 'number': | ||
case 'boolean': | ||
return x.value; | ||
case 'null': | ||
return null; | ||
case 'array': | ||
return x.array.map(unparseExpression); | ||
case 'object': | ||
return Object.fromEntries( | ||
Object.entries(x.fields).map(([k, v]) => [k, unparseExpression(v)]) | ||
); | ||
default: | ||
return x; | ||
} | ||
} | ||
|
||
export function intrinsicToLongForm(fn: UserIntrinsicExpression['fn']): string { | ||
return INTRINSIC_NAME_MAP?.[fn] ?? fn; | ||
} |
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
Oops, something went wrong.