Skip to content

Commit 491cfa2

Browse files
committed
Use SilentError pattern
1 parent 21c9c65 commit 491cfa2

3 files changed

Lines changed: 39 additions & 72 deletions

File tree

lib/index.js

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
const pkgDir = require('pkg-dir');
22
const globby = require('globby');
33
const debug = require('debug')('tagless-ember-components-codemod');
4+
const chalk = require('chalk');
45

6+
const SilentError = require('./silent-error');
57
const { transform } = require('./transform');
68

79
async function run() {
@@ -17,11 +19,19 @@ async function runForPath(path, options = {}) {
1719
// TODO check for ember-component-css dependency
1820

1921
log(` 🔍 Searching for component files...`);
20-
let componentPaths = await globby('app/components/**/*.js', { cwd: path });
21-
debug('componentPaths = %O', componentPaths);
22-
23-
for (let componentPath of componentPaths) {
24-
transform(componentPath);
22+
let paths = await globby('app/components/**/*.js', { cwd: path });
23+
debug('componentPaths = %O', paths);
24+
25+
for (let path of paths) {
26+
try {
27+
transform(path);
28+
} catch (error) {
29+
if (error instanceof SilentError) {
30+
console.log(chalk.yellow(`${chalk.dim(path)}: ${error.message}`));
31+
} else {
32+
console.log(chalk.red(`${chalk.dim(path)}: ${error.stack}`));
33+
}
34+
}
2535
}
2636

2737
debug('runForPath() finished');

lib/silent-error.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
class SilentError extends Error {}
2+
3+
module.exports = SilentError;

lib/transform.js

Lines changed: 21 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
const fs = require('fs');
2-
const chalk = require('chalk');
32
const stringUtils = require('ember-cli-string-utils');
43
const j = require('jscodeshift').withParser('ts');
54
const debug = require('debug')('tagless-ember-components-codemod');
65

6+
const SilentError = require('./silent-error');
7+
78
const EVENT_HANDLER_METHODS = [
89
// Touch events
910
'touchStart',
@@ -43,8 +44,6 @@ const EVENT_HANDLER_METHODS = [
4344
];
4445

4546
function transform(componentPath) {
46-
let dimPath = chalk.dim(componentPath);
47-
4847
let source = fs.readFileSync(componentPath, 'utf8');
4948

5049
let root = j(source);
@@ -62,10 +61,7 @@ function transform(componentPath) {
6261
});
6362

6463
if (exportDefaultDeclarations.length !== 1) {
65-
console.log(
66-
chalk.yellow(`${dimPath}: Could not find \`export default Component.extend({ ... });\``)
67-
);
68-
return;
64+
throw new SilentError(`Could not find \`export default Component.extend({ ... });\``);
6965
}
7066

7167
let exportDefaultDeclaration = exportDefaultDeclarations.get();
@@ -77,22 +73,14 @@ function transform(componentPath) {
7773

7874
let objectArg = extendObjectArgs[0];
7975
if (!objectArg) {
80-
console.log(
81-
chalk.yellow(
82-
`${dimPath}: Could not find object argument in \`export default Component.extend({ ... });\``
83-
)
76+
throw new SilentError(
77+
`Could not find object argument in \`export default Component.extend({ ... });\``
8478
);
85-
return;
8679
}
8780

8881
// find `tagName` property if it exists
8982
let properties = objectArg.get('properties');
90-
9183
let tagName = findTagName(properties);
92-
if (tagName.constructor.name === 'NodePath') {
93-
console.log(chalk.yellow(`${dimPath}: Unexpected \`tagName\` value: ${j(tagName).toSource()}`));
94-
return;
95-
}
9684

9785
// skip tagless components (silent)
9886
if (tagName === '') {
@@ -108,62 +96,28 @@ function transform(componentPath) {
10896
property: { name: 'element' },
10997
});
11098
if (thisElementPaths.length !== 0) {
111-
console.log(
112-
chalk.yellow(`${dimPath}: Using \`this.element\` is not supported in tagless components`)
113-
);
114-
return;
99+
throw new SilentError(`Using \`this.element\` is not supported in tagless components`);
115100
}
116101

117102
// skip components that use `click()` etc.
118103
for (let methodName of EVENT_HANDLER_METHODS) {
119104
let handlerMethod = properties.filter(path => isMethod(path, methodName))[0];
120105
if (handlerMethod) {
121-
console.log(
122-
chalk.yellow(`${dimPath}: Using \`${methodName}()\` is not supported in tagless components`)
123-
);
124-
return;
106+
throw new SilentError(`Using \`${methodName}()\` is not supported in tagless components`);
125107
}
126108
}
127109

128110
// analyze `elementId`, `attributeBindings`, `classNames` and `classNameBindings`
129111
let elementId = findElementId(properties);
130-
if (elementId !== null && elementId.constructor.name === 'NodePath') {
131-
console.log(
132-
chalk.yellow(`${dimPath}: Unexpected \`elementId\` value: ${j(elementId).toSource()}`)
133-
);
134-
return;
135-
}
136112
debug(`${componentPath}: elementId: %o`, elementId);
137113

138114
let attributeBindings = findAttributeBindings(properties);
139-
if (attributeBindings.constructor.name === 'NodePath') {
140-
console.log(
141-
chalk.yellow(
142-
`${dimPath}: Unexpected \`attributeBindings\` value: ${j(attributeBindings).toSource()}`
143-
)
144-
);
145-
return;
146-
}
147115
debug(`${componentPath}: attributeBindings: %o`, attributeBindings);
148116

149117
let classNames = findClassNames(properties);
150-
if (classNames.constructor.name === 'NodePath') {
151-
console.log(
152-
chalk.yellow(`${dimPath}: Unexpected \`classNames\` value: ${j(classNames).toSource()}`)
153-
);
154-
return;
155-
}
156118
debug(`${componentPath}: classNames: %o`, classNames);
157119

158120
let classNameBindings = findClassNameBindings(properties);
159-
if (classNameBindings.constructor.name === 'NodePath') {
160-
console.log(
161-
chalk.yellow(
162-
`${dimPath}: Unexpected \`classNameBindings\` value: ${j(classNameBindings).toSource()}`
163-
)
164-
);
165-
return;
166-
}
167121
debug(`${componentPath}: classNameBindings: %o`, classNameBindings);
168122

169123
// TODO skip on error (warn incl. please report)
@@ -191,12 +145,12 @@ function findTagName(properties) {
191145
return 'div';
192146
}
193147

194-
let tagNamePath = tagNameProperty.get('value');
195-
if (tagNamePath.value.type === 'StringLiteral') {
196-
return tagNamePath.value.value;
148+
let elementIdPath = tagNameProperty.get('value');
149+
if (elementIdPath.value.type !== 'StringLiteral') {
150+
throw new SilentError(`Unexpected \`tagName\` value: ${j(elementIdPath).toSource()}`);
197151
}
198152

199-
return tagNamePath;
153+
return elementIdPath.value.value;
200154
}
201155

202156
function findElementId(properties) {
@@ -206,11 +160,11 @@ function findElementId(properties) {
206160
}
207161

208162
let elementIdPath = elementIdProperty.get('value');
209-
if (elementIdPath.value.type === 'StringLiteral') {
210-
return elementIdPath.value.value;
163+
if (elementIdPath.value.type !== 'StringLiteral') {
164+
throw new SilentError(`Unexpected \`elementId\` value: ${j(elementIdPath).toSource()}`);
211165
}
212166

213-
return elementIdPath;
167+
return elementIdPath.value.value;
214168
}
215169

216170
function findAttributeBindings(properties) {
@@ -221,15 +175,15 @@ function findAttributeBindings(properties) {
221175

222176
let arrayPath = attrBindingsProperty.get('value');
223177
if (arrayPath.value.type !== 'ArrayExpression') {
224-
return arrayPath;
178+
throw new SilentError(`Unexpected \`attributeBindings\` value: ${j(arrayPath).toSource()}`);
225179
}
226180

227181
let elements = arrayPath.get('elements').value;
228182

229183
let attrBindings = new Map();
230184
for (let element of elements) {
231185
if (element.type !== 'StringLiteral') {
232-
return arrayPath;
186+
throw new SilentError(`Unexpected \`attributeBindings\` value: ${j(arrayPath).toSource()}`);
233187
}
234188

235189
let [from, to] = element.value.split(':');
@@ -247,15 +201,15 @@ function findClassNames(properties) {
247201

248202
let arrayPath = classNamesProperty.get('value');
249203
if (arrayPath.value.type !== 'ArrayExpression') {
250-
return arrayPath;
204+
throw new SilentError(`Unexpected \`classNames\` value: ${j(arrayPath).toSource()}`);
251205
}
252206

253207
let elements = arrayPath.get('elements').value;
254208

255209
let classNames = [];
256210
for (let element of elements) {
257211
if (element.type !== 'StringLiteral') {
258-
return arrayPath;
212+
throw new SilentError(`Unexpected \`classNames\` value: ${j(arrayPath).toSource()}`);
259213
}
260214

261215
classNames.push(element.value);
@@ -274,15 +228,15 @@ function findClassNameBindings(properties) {
274228

275229
let arrayPath = classNameBindingsProperty.get('value');
276230
if (arrayPath.value.type !== 'ArrayExpression') {
277-
return arrayPath;
231+
throw new SilentError(`Unexpected \`classNameBindings\` value: ${j(arrayPath).toSource()}`);
278232
}
279233

280234
let elements = arrayPath.get('elements').value;
281235

282236
let classNameBindings = new Map();
283237
for (let element of elements) {
284238
if (element.type !== 'StringLiteral') {
285-
return arrayPath;
239+
throw new SilentError(`Unexpected \`classNameBindings\` value: ${j(arrayPath).toSource()}`);
286240
}
287241

288242
let parts = element.value.split(':');
@@ -294,7 +248,7 @@ function findClassNameBindings(properties) {
294248
} else if (parts.length === 3) {
295249
classNameBindings.set(parts[0], [parts[1] || null, parts[2]]);
296250
} else {
297-
return arrayPath;
251+
throw new SilentError(`Unexpected \`classNameBindings\` value: ${j(arrayPath).toSource()}`);
298252
}
299253
}
300254

0 commit comments

Comments
 (0)