Skip to content

Commit

Permalink
feat: Display block import references in error output.
Browse files Browse the repository at this point in the history
Closes #248.
  • Loading branch information
chriseppstein committed Sep 6, 2019
1 parent 7e030fb commit 190993f
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 3 deletions.
9 changes: 9 additions & 0 deletions packages/@css-blocks/cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,15 @@ export class CLI {
if (!errorHasRange(loc)) return;
let filename = path.relative(process.cwd(), path.resolve(loc && loc.filename || blockFileRelative));
this.println("\t" + this.chalk.bold.redBright(e.origMessage));
for (let referenceLocation of e.importStack.reverse()) {
if (referenceLocation.filename) {
referenceLocation.filename = path.relative(process.cwd(), path.resolve(referenceLocation.filename));
}
this.println(
this.chalk.bold.white("\tIn block referenced at"),
this.chalk.bold.whiteBright(charInFile(referenceLocation)),
);
}
if (hasMappedPosition(loc)) {
this.println(
this.chalk.bold.white("\tAt compiled output of"),
Expand Down
1 change: 1 addition & 0 deletions packages/@css-blocks/cli/test/cli-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ Found 1 error in 1 file.
assert.equal(cli.output,
`error\t${relFixture("basic/transitive-error.block.css")}
\tTwo distinct classes cannot be selected on the same element: .foo.bar
\tIn block referenced at test/fixtures/basic/transitive-error.block.css:1:1
\tAt ${relFixture("basic/error.block.css")}:1:5
\t1: .foo.bar {
\t2: color: red;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@block error from "./transitive-error.block.css";

:scope {
extends: error;
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,17 @@ export async function importBlocks(block: Block, factory: BlockFactory, file: st
// Import file, then parse file, then save block reference.
let blockPromise: Promise<Block> = factory.getBlockRelative(block.identifier, blockPath);

// Validate our imported block name is a valid CSS identifier.
blockPromise = blockPromise.catch((e) => {
if (e instanceof errors.CssBlockError) {
e.importStack.push(sourceRange(factory.configuration, block.stylesheet, file, atRule));
}
throw e;
});

let blockNames = parseBlockNames(blockList, true);
for (let localName of Object.keys(blockNames)) {
let remoteName = blockNames[localName];
// Validate our imported block name is a valid CSS identifier.
if (!CLASS_NAME_IDENT.test(localName)) {
throw new errors.InvalidBlockSyntax(
`Illegal block name in import. "${localName}" is not a legal CSS identifier.`,
Expand Down Expand Up @@ -104,5 +111,4 @@ export async function importBlocks(block: Block, factory: BlockFactory, file: st
}
});
return block;

}
2 changes: 1 addition & 1 deletion packages/@css-blocks/core/src/SourceLocation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export function addSourcePositions(...locations: SourcePosition[]) {
* @param node The PostCSS Node object in question.
* @returns An object representing the filename, line number and column number.
*/
export function sourceRange(configuration: Configuration, root: postcss.Root | null | undefined, filename: string, node: postcss.Node): SourceRange | SourceFile {
export function sourceRange(configuration: Configuration, root: postcss.Root | null | undefined, filename: string, node: postcss.Node): MappedSourceRange | SourceRange | SourceFile {
if (node.source && node.source.start && node.source.end) {
let {start, end} = node.source;
return sourceOrSourceMappedRange(configuration, root, filename, start, end);
Expand Down
2 changes: 2 additions & 0 deletions packages/@css-blocks/core/src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@ interface HasPrefix {
export class CssBlockError extends Error {
static prefix = "Error";
origMessage: string;
importStack: Array<SourceLocation.SourceRange | SourceLocation.MappedSourceRange | SourceLocation.SourceFile>;
private _location?: ErrorLocation;
constructor(message: string, location?: ErrorLocation) {
super(message);
this.origMessage = message;
this._location = location;
this.importStack = new Array();
super.message = this.annotatedMessage();
}

Expand Down

0 comments on commit 190993f

Please sign in to comment.