Skip to content

Commit 53b0cea

Browse files
committed
feat(rewriter): Raise an error if there's any stray references to a block variable.
1 parent 84e9917 commit 53b0cea

File tree

2 files changed

+67
-4
lines changed

2 files changed

+67
-4
lines changed

packages/jsx-analyzer/src/transformer/babel.ts

+37-4
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@ import {
1818
Statement,
1919
isJSXExpressionContainer,
2020
JSXAttribute,
21+
Node,
2122
} from 'babel-types';
2223

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

2729
export interface CssBlocksVisitor {
@@ -66,17 +68,19 @@ export default function mkTransform(tranformOpts: { rewriter: Rewriter }): () =>
6668
}
6769
},
6870
post(state: any) {
71+
for (let nodePath of this.statementsToRemove) {
72+
nodePath.remove();
73+
}
6974
if (this.dynamicStylesFound) {
7075
let firstImport = this.importsToRemove.shift()!;
76+
detectStrayReferenceToImport(firstImport, this.filename);
7177
let importDecl = importDeclaration(
7278
[importSpecifier(identifier(HELPER_FN_NAME.localName), identifier(HELPER_FN_NAME.moduleName))],
7379
stringLiteral('@css-blocks/jsx'));
7480
firstImport.replaceWith(importDecl);
7581
}
7682
for (let nodePath of this.importsToRemove) {
77-
nodePath.remove();
78-
}
79-
for (let nodePath of this.statementsToRemove) {
83+
detectStrayReferenceToImport(nodePath, this.filename);
8084
nodePath.remove();
8185
}
8286
},
@@ -124,7 +128,10 @@ export default function mkTransform(tranformOpts: { rewriter: Rewriter }): () =>
124128
}
125129
if (newClassAttr) {
126130
let firstClass = classAttrs.shift()!;
127-
firstClass.replaceWith(newClassAttr);
131+
//insert and remove instead of replace or else it's hard to
132+
//detect if the old node was removed or is a stray reference.
133+
firstClass.insertAfter(newClassAttr);
134+
firstClass.remove();
128135
}
129136
for (let attrPath of classAttrs) {
130137
attrPath.remove();
@@ -135,3 +142,29 @@ export default function mkTransform(tranformOpts: { rewriter: Rewriter }): () =>
135142
};
136143
};
137144
}
145+
146+
function detectStrayReferenceToImport(
147+
importDeclPath: NodePath<ImportDeclaration>,
148+
filename: string
149+
): void {
150+
for (let specifier of importDeclPath.node.specifiers) {
151+
let binding = importDeclPath.scope.getBinding(specifier.local.name);
152+
if (binding) {
153+
for (let ref of binding.referencePaths) {
154+
if (!isRemoved(ref)) {
155+
throw new TemplateAnalysisError('Stray reference to block import. Imports are removed during rewrite.', {filename, ...ref.node.loc.start});
156+
}
157+
}
158+
}
159+
}
160+
}
161+
162+
function isRemoved(path: NodePath<Node>): boolean {
163+
if (path.removed) return true;
164+
let p = path.parentPath;
165+
while (p && p.type !== 'Program') {
166+
if (p.removed) return true;
167+
p = p.parentPath;
168+
}
169+
return false;
170+
}

packages/jsx-analyzer/test/transformer/transformer-test.ts

+30
Original file line numberDiff line numberDiff line change
@@ -410,4 +410,34 @@ export class Test {
410410
});
411411
});
412412
}
413+
414+
@test 'Left over references to the block are an error'(){
415+
mock({
416+
'bar.block.css': '.root { color: red; } .foo { color: blue; }',
417+
'foo.block.css': '.root { font-family: sans-serif; } .big { font-size: 28px; }'
418+
});
419+
420+
let code = `
421+
import foo from 'foo.block.css'
422+
import objstr from 'obj-str';
423+
424+
function render(){
425+
let style = objstr({
426+
[foo]: true,
427+
});
428+
let unusedStyle = objstr({
429+
[foo.big]: true,
430+
});
431+
return ( <div class={style}></div> );
432+
}`;
433+
434+
return parse(code, 'test.tsx').then((analysis: MetaAnalysis) => {
435+
return transform(code, analysis.getAnalysis(0)).then(res => {
436+
console.log(res.jsx.code);
437+
assert.ok(false, 'should not have succeeded.');
438+
}, e => {
439+
assert.equal(e.message, 'test.tsx: [css-blocks] AnalysisError: Stray reference to block import. Imports are removed during rewrite. (test.tsx:10:11)');
440+
});
441+
});
442+
}
413443
}

0 commit comments

Comments
 (0)