Skip to content
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

feat(compiler): Implement error codes system onto compiler modules #726

Merged
merged 36 commits into from
Oct 23, 2018

Conversation

jye-sf
Copy link
Contributor

@jye-sf jye-sf commented Oct 10, 2018

Details

Creates the 'lwc-errors' module for error handling and normalization

Implements the error codes system onto lwc compiler modules. These include:

  • postcss-plugin-lwc
  • jest-transformer
  • babel-plugin-transform-lwc-class
  • lwc-template-compiler
  • lwc-compiler

Does this PR introduce a breaking change?

  • Yes
  • No

If yes, please describe the impact and migration path for existing applications:

@@ -0,0 +1,2 @@
src/
.*
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lwc-errors module starts here

@@ -0,0 +1,90 @@
import { LWCErrorInfo, templateString } from "../shared/utils";
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Main error utilities live here.

@@ -0,0 +1,76 @@
const errors = require('../dist/commonjs/index.js');
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This babel transform was written for the engine modules, so it will be removed.

@@ -0,0 +1,215 @@
import { Level } from "../../shared/utils";
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error code metadata starts here. Looking at the whole picture might help us decide how to organize the numeric codes.

INVALID_STATIC_OBSERVEDATTRIBUTES: {
code: 0,
message: "Invalid static property \"observedAttributes\". \"observedAttributes\" cannot be used to track attribute changes. Define setters for {0} instead.",
type: "path.buildCodeFrameError",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

type was originally meant to help us surface typed errors, but doesn't seem to have any purpose if we're normalizing to CompilerError. If there are no concerns, I'll remove this property.

return new CompilerError(errorInfo.code, fullMessage, filename, location);
}

export function normalizeCompilerError(error: any, newContext?: CompilerContext): CompilerError {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

normalizeToCompilerError?

@@ -212,7 +212,7 @@ describe('Transform property', () => {
}
`, {
error: {
message: 'test.js: Boolean public property must default to false.',
message: 'Boolean public property must default to false.',
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests made to be more tolerant to changes to the overall error message.

@caridy
Copy link
Contributor

caridy commented Oct 11, 2018

this is a very very long PR, is there a doc somewhere to understand this better?

@jye-sf
Copy link
Contributor Author

jye-sf commented Oct 11, 2018

It's changed a little since then but we had a few discussions around the following docs and the linked resources:

Initial summary - https://salesforce.quip.com/3aSCA6NzEHcE
Followup discussion - https://salesforce.quip.com/VnlqAaiWdctb
More specific implementation questions - https://salesforce.quip.com/w4EjA5V5YNlY

@diervo
Copy link
Contributor

diervo commented Oct 11, 2018

this is a very very long PR, is there a doc somewhere to understand this better?

@caridy understands now how we feel with hist refactors :)

Copy link
Collaborator

@apapko apapko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here are few things that i would like to revisit:

  • Centralized vs Distributed Error Messages: should each package within the repo contain its own errors file instead of lwc-error owning all the errors? I feel like naming convention could be simplified if each package holds all its messages.
  • Naming convention scheme: If we do keep all the errors inside the lwc-errors, should each folder representing a sub-package match the name of the module it holds the errors for? ex: lwc-compiler errors will be represented as lwc-errors/src/lwc-compiler/errors.ts
  • Error type: should error type represent a package or an operation? If an invariant error is thrown from the compiler, is it sufficient to say that it was a 'transform' type? Or do we want to flag the origin, such as 'compiler'?
  • package structure: since everything is technically related to errors, do we need an extra error-info folder or will src//errors.ts be sufficient? ( current: lwc-errors/src/compiler/error-info/babel-plugin-lwc-class.ts)
  • should the generateCompilerError accept a message and a config object instead of explicitly listing all the params ( see comment below )?

@@ -293,7 +293,7 @@ describe('Transform property', () => {
}
`, {
error: {
message: 'test.js: Ambiguous attribute name tabindex. tabindex will never be called from template because its corresponding property is camel cased. Consider renaming to "tabIndex".',
message: 'Ambiguous attribute name tabindex. tabindex will never be called from template because its corresponding property is camel cased. Consider renaming to "tabIndex".',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pls wrap property name in quote? "tabindex"

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above:

Ambiguous attribute name "tabindex". "tabindex" will never be called from template because its corresponding property is camel cased. Consider renaming to "tabIndex".'

@@ -308,7 +308,7 @@ describe('Transform property', () => {
}
`, {
error: {
message: 'test.js: Ambiguous attribute name maxlength. maxlength will never be called from template because its corresponding property is camel cased. Consider renaming to "maxLength".',
message: 'Ambiguous attribute name maxlength. maxlength will never be called from template because its corresponding property is camel cased. Consider renaming to "maxLength".',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

packages/babel-plugin-transform-lwc-class/src/component.js Outdated Show resolved Hide resolved
packages/babel-plugin-transform-lwc-class/src/component.js Outdated Show resolved Hide resolved
throw new TypeError(`Expected an object with files to be compiled.`);
}
invariant(
!isUndefined(options.files) && !!Object.keys(options.files).length,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i believe we can just do

Object.keys(options.files).length

as it is a truthy value;
not unless you explicitly expect a boolean.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Meaning !! not necessary

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The invariant function does expect a boolean though. Is this worth changing the type to any?

packages/lwc-errors/src/errors-transform.js Outdated Show resolved Hide resolved
packages/lwc-errors/src/shared/utils.ts Outdated Show resolved Hide resolved
packages/lwc-errors/tsconfig.json Show resolved Hide resolved
@@ -25,7 +25,7 @@ export default function compiler(

let code = '';
const warnings: CompilationWarning[] = [];

// TODO ERROR CODES:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

@jye-sf
Copy link
Contributor Author

jye-sf commented Oct 12, 2018

Some thoughts on your thoughts; we can discuss more tomorrow too:

Centralized vs Distributed Error Messages: should each package within the repo contain its own errors file instead of lwc-error owning all the errors? I feel like naming convention could be simplified if each package holds all its messages.

With a centralized package, it's easier to validate that each error code is unique when we compile the package and we can eventually have all the error-related documentation in one place.

The other benefit was being able to organize the errors independently from how the packages are organized. Looking at the whole thing though, the errors are mostly fairly specific to their packages, so we might not want to organize them independently anymore.

If we're organizing by package anyways, I don't see why each package can't just contain its own errors file. The main concern would be verifying the error codes.

Also, would the errors docs live with each package too?

Naming convention scheme: If we do keep all the errors inside the lwc-errors, should each folder representing a sub-package match the name of the module it holds the errors for? ex: lwc-compiler errors will be represented as lwc-errors/src/lwc-compiler/errors.ts

Yeah that's one way we can organize things if we want to go with a deeper file structure. I personally feel that this would be better than the flat directory (/src/everything-here) if we decide to organize by source package.

Error type: should error type represent a package or an operation? If an invariant error is thrown from the compiler, is it sufficient to say that it was a 'transform' type? Or do we want to flag the origin, such as 'compiler'?

The error instance itself should inherently provide the origin since it is a 'CompilerError'. For type, do we still need that property? Looking at the big picture, since we're normalizing to 'CompilerError', I'm not sure it's useful anymore. If we want to surface the error's origin sub-package, maybe that would be better served by a utility that lets each sub-package prepend some message to the error. Thoughts on that?

package structure: since everything is technically related to errors, do we need an extra error-info folder or will src//errors.ts be sufficient? ( current: lwc-errors/src/compiler/error-info/babel-plugin-lwc-class.ts)

I mainly did that so it's easier to distinguish the files purely holding the error metadata from the error-related code/utilities. If that's not helpful we can definitely flatten it again, but I think I prefer the deeper directory structure.

should the generateCompilerError accept a message and a config object instead of explicitly listing all the params ( see comment below )?

Yes, that's much better

@caridy
Copy link
Contributor

caridy commented Oct 17, 2018

who can do a walk thru this PR in a quick chat this week?

@diervo
Copy link
Contributor

diervo commented Oct 17, 2018 via email

@jye-sf jye-sf force-pushed the jye/error-codes-compiler branch from 016fd49 to f7eabb4 Compare October 18, 2018 09:28
@jye-sf
Copy link
Contributor Author

jye-sf commented Oct 18, 2018

@caridy @diervo @apapko What time works for you today?

@apapko apapko changed the title wip feat(compiler): Implement error codes system onto compiler modules feat(compiler): Implement error codes system onto compiler modules Oct 18, 2018
@diervo
Copy link
Contributor

diervo commented Oct 18, 2018

Whenever @caridy can, hopefully today? Otherwise I will do another final pass and merge it EOW

@jye-sf
Copy link
Contributor Author

jye-sf commented Oct 19, 2018

Sounds good. There are a few more changes that should be ready tonight, so no rush on that final pass.

@jye-sf
Copy link
Contributor Author

jye-sf commented Oct 19, 2018

Just realized a few hours ago that the remaining changes to expose the new error shape through lwc-compiler are going to break downstream modules expecting the old error shape (aura, platform-compiler). Going to add a temporary converter to maintain the existing API so that we don't need to do any coordinated releases on a huge PR like this.

Thoughts? Also, are aura and platform-compiler the only places that use lwc-compiler, or are there more?

@diervo
Copy link
Contributor

diervo commented Oct 19, 2018

@jye-sf don't quite follow that lets talk once you are in the office, or hangouts

@jye-sf
Copy link
Contributor Author

jye-sf commented Oct 19, 2018

The diagnostics are part of the lwc-compiler API, so we hit compilation errors in platform-compiler, and anything relying on the old 'location' info will break.

// Older shape
interface CompilerOutput {
    ...
    diagnostics: Diagnostic[];
}

interface Diagnostic {
    level: DiagnosticLevel;
    message: string;
    filename?: string;
    location?: Location;
}

interface Location {
    start: number;
    length: number;
}
// New shape
interface CompilerOutput {
    ...
    diagnostics: CompilerDiagnostic[];
}

interface CompilerDiagnostic {
    code: number;
    level: Level;
    message: string;
    filename?: string;
    location?: Location;
}

interface Location {
    line: number;
    column: number;
}

startCol: number;
}
}
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our parse5 version is older, while jsdom is using a newer version. This the right way to resolve it?

export interface CssSyntaxError {
lwcCode?: number;
}
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add property to library Error object so we can pass the error code.

@@ -0,0 +1,3 @@
declare interface Error {
lwcCode?: number
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add property to library Error object so we can pass the error code.

@jye-sf jye-sf force-pushed the jye/error-codes-compiler branch from 0148960 to 828e9b8 Compare October 22, 2018 16:21
@jye-sf jye-sf removed the nomerge label Oct 23, 2018
Copy link
Collaborator

@apapko apapko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Jason and I have discussed all of the outstanding comments offline and concluded that we are going to hold off on some of them until the next pass. @jye-sf please create a git issue to track the future changes that we need to revisit.

@salesforce-best-lwc-internal
Copy link

Benchmark results

Base commit: ce341b8 | Target commit: 5a51cec

lwc-engine-benchmark

table-append-1k metric base(ce341b8) target(5a51cec) trend
benchmark-table/append/1k duration 146.90 (±3.90 ms) 147.30 (±4.00 ms) +0.4ms (0.3%) 👌
table-clear-1k metric base(ce341b8) target(5a51cec) trend
benchmark-table/clear/1k duration 6.00 (±0.30 ms) 6.20 (±0.50 ms) +0.2ms (3.3%) 👎
table-create-10k metric base(ce341b8) target(5a51cec) trend
benchmark-table/create/10k duration 862.15 (±6.35 ms) 864.60 (±5.60 ms) +2.5ms (0.3%) 👎
table-create-1k metric base(ce341b8) target(5a51cec) trend
benchmark-table/create/1k duration 114.05 (±3.05 ms) 115.25 (±2.30 ms) +1.2ms (1.1%) 👌
table-update-10th-1k metric base(ce341b8) target(5a51cec) trend
benchmark-table/update-10th/1k duration 77.50 (±4.50 ms) 75.55 (±2.35 ms) -2.0ms (2.5%) 👍
tablecmp-append-1k metric base(ce341b8) target(5a51cec) trend
benchmark-table-component/append/1k duration 236.75 (±10.45 ms) 236.05 (±14.10 ms) -0.7ms (0.3%) 👌
tablecmp-clear-1k metric base(ce341b8) target(5a51cec) trend
benchmark-table-component/clear/1k duration 11.70 (±1.30 ms) 11.75 (±1.25 ms) +0.1ms (0.4%) 👌
tablecmp-create-10k metric base(ce341b8) target(5a51cec) trend
benchmark-table-component/create/10k duration 1648.65 (±10.95 ms) 1637.85 (±10.85 ms) -10.8ms (0.7%) 👍
tablecmp-create-1k metric base(ce341b8) target(5a51cec) trend
benchmark-table-component/create/1k duration 196.90 (±4.45 ms) 199.80 (±6.05 ms) +2.9ms (1.5%) 👌
tablecmp-update-10th-1k metric base(ce341b8) target(5a51cec) trend
benchmark-table-component/update-10th/1k duration 71.40 (±5.20 ms) 71.70 (±4.50 ms) +0.3ms (0.4%) 👌
wc-append-1k metric base(ce341b8) target(5a51cec) trend
benchmark-table-wc/append/1k duration 231.85 (±8.80 ms) 237.20 (±12.60 ms) +5.3ms (2.3%) 👌
wc-clear-1k metric base(ce341b8) target(5a51cec) trend
benchmark-table-wc/clear/1k duration 23.40 (±2.05 ms) 20.40 (±2.00 ms) -3.0ms (12.8%) 👍
wc-create-10k metric base(ce341b8) target(5a51cec) trend
benchmark-table-wc/create/10k duration 1665.90 (±67.30 ms) 1734.70 (±38.80 ms) +68.8ms (4.1%) 👎
wc-create-1k metric base(ce341b8) target(5a51cec) trend
benchmark-table-wc/create/1k duration 200.15 (±6.60 ms) 204.90 (±5.40 ms) +4.8ms (2.4%) 👎
wc-update-10th-1k metric base(ce341b8) target(5a51cec) trend
benchmark-table-wc/update-10th/1k duration 72.65 (±4.85 ms) 70.15 (±4.05 ms) -2.5ms (3.4%) 👌

@jye-sf jye-sf merged commit 3ee81d5 into master Oct 23, 2018
@diervo diervo deleted the jye/error-codes-compiler branch October 24, 2018 00:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants