Skip to content

Commit

Permalink
feat(rewriter): Raise an error if there's any stray references to a b…
Browse files Browse the repository at this point in the history
…lock variable.
  • Loading branch information
chriseppstein committed Nov 30, 2017
1 parent 84e9917 commit 53b0cea
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 4 deletions.
41 changes: 37 additions & 4 deletions packages/jsx-analyzer/src/transformer/babel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ import {
Statement,
isJSXExpressionContainer,
JSXAttribute,
Node,
} from 'babel-types';

import isBlockFilename from '../utils/isBlockFilename';
import { classnamesHelper as generateClassName, HELPER_FN_NAME } from './classNameGenerator';
import { TemplateAnalysisError } from '../utils/Errors';
let { parse } = require('path');

export interface CssBlocksVisitor {
Expand Down Expand Up @@ -66,17 +68,19 @@ export default function mkTransform(tranformOpts: { rewriter: Rewriter }): () =>
}
},
post(state: any) {
for (let nodePath of this.statementsToRemove) {
nodePath.remove();
}
if (this.dynamicStylesFound) {
let firstImport = this.importsToRemove.shift()!;
detectStrayReferenceToImport(firstImport, this.filename);
let importDecl = importDeclaration(
[importSpecifier(identifier(HELPER_FN_NAME.localName), identifier(HELPER_FN_NAME.moduleName))],
stringLiteral('@css-blocks/jsx'));
firstImport.replaceWith(importDecl);
}
for (let nodePath of this.importsToRemove) {
nodePath.remove();
}
for (let nodePath of this.statementsToRemove) {
detectStrayReferenceToImport(nodePath, this.filename);
nodePath.remove();
}
},
Expand Down Expand Up @@ -124,7 +128,10 @@ export default function mkTransform(tranformOpts: { rewriter: Rewriter }): () =>
}
if (newClassAttr) {
let firstClass = classAttrs.shift()!;
firstClass.replaceWith(newClassAttr);
//insert and remove instead of replace or else it's hard to
//detect if the old node was removed or is a stray reference.
firstClass.insertAfter(newClassAttr);
firstClass.remove();
}
for (let attrPath of classAttrs) {
attrPath.remove();
Expand All @@ -135,3 +142,29 @@ export default function mkTransform(tranformOpts: { rewriter: Rewriter }): () =>
};
};
}

function detectStrayReferenceToImport(
importDeclPath: NodePath<ImportDeclaration>,
filename: string
): void {
for (let specifier of importDeclPath.node.specifiers) {
let binding = importDeclPath.scope.getBinding(specifier.local.name);
if (binding) {
for (let ref of binding.referencePaths) {
if (!isRemoved(ref)) {
throw new TemplateAnalysisError('Stray reference to block import. Imports are removed during rewrite.', {filename, ...ref.node.loc.start});
}
}
}
}
}

function isRemoved(path: NodePath<Node>): boolean {
if (path.removed) return true;
let p = path.parentPath;
while (p && p.type !== 'Program') {
if (p.removed) return true;
p = p.parentPath;
}
return false;
}
30 changes: 30 additions & 0 deletions packages/jsx-analyzer/test/transformer/transformer-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -410,4 +410,34 @@ export class Test {
});
});
}

@test 'Left over references to the block are an error'(){
mock({
'bar.block.css': '.root { color: red; } .foo { color: blue; }',
'foo.block.css': '.root { font-family: sans-serif; } .big { font-size: 28px; }'
});

let code = `
import foo from 'foo.block.css'
import objstr from 'obj-str';
function render(){
let style = objstr({
[foo]: true,
});
let unusedStyle = objstr({
[foo.big]: true,
});
return ( <div class={style}></div> );
}`;

return parse(code, 'test.tsx').then((analysis: MetaAnalysis) => {
return transform(code, analysis.getAnalysis(0)).then(res => {
console.log(res.jsx.code);
assert.ok(false, 'should not have succeeded.');
}, e => {
assert.equal(e.message, 'test.tsx: [css-blocks] AnalysisError: Stray reference to block import. Imports are removed during rewrite. (test.tsx:10:11)');
});
});
}
}

0 comments on commit 53b0cea

Please sign in to comment.