Skip to content

Commit e489ee6

Browse files
ssutarpzuraq
authored andcommitted
Validation for lifecycle hooks (#58)
Resolves #34
1 parent 2fd1618 commit e489ee6

File tree

4 files changed

+130
-0
lines changed

4 files changed

+130
-0
lines changed

transforms/ember-object/__testfixtures__/decorators.invalid.input.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,12 @@ const Foo = EmberObject.extend({
4141
return true;
4242
}).meta({ type: "Property" })
4343
});
44+
45+
// Do not transform as action name matches lifecycle hook
46+
const Foo = EmberObject.extend({
47+
actions: {
48+
click() {
49+
this.set("clicked", true);
50+
}
51+
}
52+
});

transforms/ember-object/__testfixtures__/decorators.invalid.output.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,12 @@ const Foo = EmberObject.extend({
4141
return true;
4242
}).meta({ type: "Property" })
4343
});
44+
45+
// Do not transform as action name matches lifecycle hook
46+
const Foo = EmberObject.extend({
47+
actions: {
48+
click() {
49+
this.set("clicked", true);
50+
}
51+
}
52+
});

transforms/helpers/util.js

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,92 @@ const ACTION_SUPER_EXPRESSION_COMMENT = [
6969
" for more details."
7070
];
7171

72+
const LIFECYCLE_HOOKS = [
73+
// Methods
74+
"$",
75+
"addObserver",
76+
"cacheFor",
77+
"decrementProperty",
78+
"destroy",
79+
"didReceiveAttrs",
80+
"didRender",
81+
"didUpdate",
82+
"didUpdateAttrs",
83+
"get",
84+
"getProperties",
85+
"getWithDefault",
86+
"has",
87+
"incrementProperty",
88+
"init",
89+
"notifyPropertyChange",
90+
"off",
91+
"on",
92+
"one",
93+
"readDOMAttr",
94+
"removeObserver",
95+
"rerender",
96+
"send",
97+
"set",
98+
"setProperties",
99+
"toString",
100+
"toggleProperty",
101+
"trigger",
102+
"willDestroy",
103+
"willRender",
104+
"willUpdate",
105+
106+
// Events
107+
"didInsertElement",
108+
"didReceiveAttrs",
109+
"didRender",
110+
"didUpdate",
111+
"didUpdateAttrs",
112+
"willClearRender",
113+
"willDestroyElement",
114+
"willInsertElement",
115+
"willRender",
116+
"willUpdate",
117+
118+
// Touch events
119+
"touchStart",
120+
"touchMove",
121+
"touchEnd",
122+
"touchCancel",
123+
124+
// Keyboard events
125+
"keyDown",
126+
"keyUp",
127+
"keyPress",
128+
129+
// Mouse events
130+
"mouseDown",
131+
"mouseUp",
132+
"contextMenu",
133+
"click",
134+
"doubleClick",
135+
"mouseMove",
136+
"focusIn",
137+
"focusOut",
138+
"mouseEnter",
139+
"mouseLeave",
140+
141+
// Form events
142+
"submit",
143+
"change",
144+
"focusIn",
145+
"focusOut",
146+
"input",
147+
148+
// HTML5 drag and drop events
149+
"dragStart",
150+
"drag",
151+
"dragEnter",
152+
"dragLeave",
153+
"dragOver",
154+
"dragEnd",
155+
"drop"
156+
];
157+
72158
/**
73159
* Get a property from and object, useful to get nested props without checking for null values
74160
*
@@ -224,6 +310,7 @@ module.exports = {
224310
isClassDecoratorProp,
225311
LAYOUT_DECORATOR_LOCAL_NAME,
226312
LAYOUT_DECORATOR_NAME,
313+
LIFECYCLE_HOOKS,
227314
METHOD_DECORATORS,
228315
shouldSetValue,
229316
startsWithUpperCaseLetter

transforms/helpers/validation-helper.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const minimatch = require("minimatch");
2+
const { LIFECYCLE_HOOKS, get, getPropName } = require("./util");
23

34
const UNSUPPORTED_PROP_NAMES = ["actions", "layout"];
45

@@ -69,6 +70,10 @@ function hasValidProps(
6970
);
7071
}
7172

73+
if (instanceProp.isAction) {
74+
errors = errors.concat(getLifecycleHookErrors(instanceProp));
75+
}
76+
7277
if (
7378
(!decorators &&
7479
(instanceProp.hasDecorators || instanceProp.isClassDecorator)) ||
@@ -103,6 +108,26 @@ function hasValidProps(
103108
}, []);
104109
}
105110

111+
/**
112+
* Iterate over actions and verify that the action name does not match the lifecycle hooks
113+
* The transformation is not supported if an action has the same name as lifecycle hook
114+
* Reference: https://github.com/scalvert/ember-es6-class-codemod/issues/34
115+
*
116+
* @param {EOProp} actionsProp
117+
*/
118+
function getLifecycleHookErrors(actionsProp) {
119+
const actionProps = get(actionsProp, "value.properties");
120+
return actionProps.reduce((errors, actionProp) => {
121+
const actionName = getPropName(actionProp);
122+
if (actionName && LIFECYCLE_HOOKS.includes(actionName)) {
123+
errors.push(
124+
`[${actionName}]: Transform not supported - action name matches one of the lifecycle hooks. Rename and try again. See https://github.com/scalvert/ember-es6-class-codemod/issues/34 for more details`
125+
);
126+
}
127+
return errors;
128+
}, []);
129+
}
130+
106131
/**
107132
* Returns true if object extends mixin
108133
*

0 commit comments

Comments
 (0)