@@ -18,10 +18,12 @@ import {
18
18
Statement ,
19
19
isJSXExpressionContainer ,
20
20
JSXAttribute ,
21
+ Node ,
21
22
} from 'babel-types' ;
22
23
23
24
import isBlockFilename from '../utils/isBlockFilename' ;
24
25
import { classnamesHelper as generateClassName , HELPER_FN_NAME } from './classNameGenerator' ;
26
+ import { TemplateAnalysisError } from '../utils/Errors' ;
25
27
let { parse } = require ( 'path' ) ;
26
28
27
29
export interface CssBlocksVisitor {
@@ -66,17 +68,19 @@ export default function mkTransform(tranformOpts: { rewriter: Rewriter }): () =>
66
68
}
67
69
} ,
68
70
post ( state : any ) {
71
+ for ( let nodePath of this . statementsToRemove ) {
72
+ nodePath . remove ( ) ;
73
+ }
69
74
if ( this . dynamicStylesFound ) {
70
75
let firstImport = this . importsToRemove . shift ( ) ! ;
76
+ detectStrayReferenceToImport ( firstImport , this . filename ) ;
71
77
let importDecl = importDeclaration (
72
78
[ importSpecifier ( identifier ( HELPER_FN_NAME . localName ) , identifier ( HELPER_FN_NAME . moduleName ) ) ] ,
73
79
stringLiteral ( '@css-blocks/jsx' ) ) ;
74
80
firstImport . replaceWith ( importDecl ) ;
75
81
}
76
82
for ( let nodePath of this . importsToRemove ) {
77
- nodePath . remove ( ) ;
78
- }
79
- for ( let nodePath of this . statementsToRemove ) {
83
+ detectStrayReferenceToImport ( nodePath , this . filename ) ;
80
84
nodePath . remove ( ) ;
81
85
}
82
86
} ,
@@ -124,7 +128,10 @@ export default function mkTransform(tranformOpts: { rewriter: Rewriter }): () =>
124
128
}
125
129
if ( newClassAttr ) {
126
130
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 ( ) ;
128
135
}
129
136
for ( let attrPath of classAttrs ) {
130
137
attrPath . remove ( ) ;
@@ -135,3 +142,29 @@ export default function mkTransform(tranformOpts: { rewriter: Rewriter }): () =>
135
142
} ;
136
143
} ;
137
144
}
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
+ }
0 commit comments