Skip to content

Commit 2fd1618

Browse files
ssutarpzuraq
authored andcommitted
Update decorator syntax (#57)
Fix for: #56 #55
1 parent eacaf01 commit 2fd1618

File tree

6 files changed

+75
-116
lines changed

6 files changed

+75
-116
lines changed

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

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
1-
import { attribute, className, classNames, layout, tagName } from "@ember-decorators/component";
1+
import { attribute, className, classNames, tagName, layout as templateLayout } from "@ember-decorators/component";
22

33
import {
44
filter,
55
map as computedMap,
66
sum as add,
7-
overridableReads as enoWay,
8-
overridableReads,
7+
oneWay as enoWay,
98
reads,
9+
readOnly,
1010
alias,
1111
} from "@ember-decorators/object/computed";
1212

1313
import { get, set } from "@ember/object";
14-
import { action, readOnly, volatile, computed, observes as watcher } from "@ember-decorators/object";
14+
import { action, computed, observes as watcher } from "@ember-decorators/object";
1515
import { controller } from "@ember-decorators/controller";
1616
import { service } from "@ember-decorators/service";
1717
import { on } from "@ember-decorators/object/evented";
18-
import templateLayout from "components/templates/foo";
18+
import layout from "components/templates/foo";
1919
import { someActionUtil } from "some/action/util";
2020

2121
@tagName("div")
@@ -99,8 +99,7 @@ class Foo extends EmberObject {
9999
/**
100100
Computed fullname
101101
*/
102-
@computed("firstName", "lastName")
103-
@readOnly
102+
@(computed("firstName", "lastName").readOnly())
104103
get fullName() {
105104
return super.fullName &&
106105
`${this.get("firstName")} ${this.get("lastName")}`;
@@ -141,26 +140,23 @@ class Foo extends EmberObject {
141140
/**
142141
* Fname2
143142
*/
144-
@computed("firstName", "lastName")
145-
@readOnly
143+
@(computed("firstName", "lastName").readOnly())
146144
get fName2() {
147145
return true;
148146
}
149147

150148
/**
151149
* Fname3
152150
*/
153-
@computed("firstName", "lastName")
154-
@volatile
151+
@(computed("firstName", "lastName").volatile())
155152
get fName3() {
156153
return true;
157154
}
158155

159156
/**
160157
* Lname
161158
*/
162-
@alias("firstName", "lastName")
163-
@readOnly
159+
@(alias("firstName", "lastName").readOnly())
164160
lName;
165161

166162
/**
@@ -172,13 +168,13 @@ class Foo extends EmberObject {
172168
/**
173169
* Lname2
174170
*/
175-
@reads("description")
171+
@readOnly("description")
176172
lName2;
177173

178174
/**
179175
* Lname3
180176
*/
181-
@overridableReads("description", "lastName")
177+
@reads("description", "lastName")
182178
lName3;
183179

184180
/**
@@ -190,10 +186,9 @@ class Foo extends EmberObject {
190186
/**
191187
* Lname5
192188
*/
193-
@add("description", "lastName")
194-
@readOnly
189+
@(add("description", "lastName").readOnly())
195190
lName5;
196191
}
197192

198-
@layout(templateLayout)
193+
@templateLayout(layout)
199194
class Foo extends EmberObject {}

transforms/helpers/EOProp.js

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ const {
33
getPropName,
44
getPropType,
55
getModifier,
6-
isClassDecoratorProp
6+
isClassDecoratorProp,
7+
LAYOUT_DECORATOR_LOCAL_NAME,
8+
LAYOUT_DECORATOR_NAME
79
} = require("./util");
810

911
/**
@@ -59,6 +61,24 @@ class EOProp {
5961
return isClassDecoratorProp(this.name);
6062
}
6163

64+
get classDecoratorName() {
65+
if (
66+
this.name === LAYOUT_DECORATOR_NAME &&
67+
this.value.name === LAYOUT_DECORATOR_NAME
68+
) {
69+
return LAYOUT_DECORATOR_LOCAL_NAME;
70+
}
71+
return this.name;
72+
}
73+
74+
get isLayoutDecorator() {
75+
return this.classDecoratorName === LAYOUT_DECORATOR_NAME;
76+
}
77+
78+
get isTemplateLayoutDecorator() {
79+
return this.classDecoratorName === LAYOUT_DECORATOR_LOCAL_NAME;
80+
}
81+
6282
get isCallExpression() {
6383
return this.type === "CallExpression";
6484
}
@@ -95,10 +115,6 @@ class EOProp {
95115
return this.modifiers.length === 2 && this.hasVolatile && this.hasReadOnly;
96116
}
97117

98-
get isLayout() {
99-
return this.name === "layout";
100-
}
101-
102118
get isTagName() {
103119
return this.name === "tagName";
104120
}
@@ -172,12 +188,6 @@ class EOProp {
172188
}
173189
}
174190

175-
setLayoutValue(value) {
176-
if (this.type === "Identifier") {
177-
this.value.name = value;
178-
}
179-
}
180-
181191
setRuntimeData({
182192
// computedProperties = [],
183193
// observedProperties = [],

transforms/helpers/decorator-helper.js

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ function createClassDecorator(j, classDecoratorProp) {
2828
decoratorArgs = [classDecoratorProp.value];
2929
}
3030
return j.decorator(
31-
j.callExpression(j.identifier(classDecoratorProp.name), [...decoratorArgs])
31+
j.callExpression(j.identifier(classDecoratorProp.classDecoratorName), [
32+
...decoratorArgs
33+
])
3234
);
3335
}
3436

@@ -42,30 +44,33 @@ function createClassDecorator(j, classDecoratorProp) {
4244
* @returns {Decorator[]}
4345
*/
4446
function createCallExpressionDecorators(j, decoratorName, instanceProp) {
47+
if (instanceProp.isVolatileReadOnly) {
48+
return [];
49+
}
50+
4551
const decoratorArgs =
4652
!instanceProp.hasMapDecorator &&
4753
!instanceProp.hasFilterDecorator &&
4854
instanceProp.hasNonLiteralArg
4955
? instanceProp.callExprArgs.slice(0, -1)
5056
: instanceProp.callExprArgs.slice(0);
5157

52-
if (instanceProp.isVolatileReadOnly) {
53-
return [];
58+
const decoratorExpr = instanceProp.modifiers.reduce(
59+
(callExpr, modifier) =>
60+
j.callExpression(
61+
j.memberExpression(callExpr, modifier.prop),
62+
modifier.args
63+
),
64+
j.callExpression(j.identifier(decoratorName), decoratorArgs)
65+
);
66+
67+
if (!instanceProp.modifiers.length) {
68+
return j.decorator(decoratorExpr);
5469
}
5570

56-
return instanceProp.modifiers.reduce(
57-
(decorators, modifier) => {
58-
if (modifier.args.length !== 0) {
59-
decorators.push(
60-
j.decorator(j.callExpression(modifier.prop), modifier.args)
61-
);
62-
} else {
63-
decorators.push(j.decorator(modifier.prop));
64-
}
65-
return decorators;
66-
},
67-
[j.decorator(j.callExpression(j.identifier(decoratorName), decoratorArgs))]
68-
);
71+
// If has modifiers wrap decorators in anonymous call expression
72+
// it transforms @computed('').readOnly() => @(computed('').readOnly())
73+
return j.decorator(j.callExpression(j.identifier(""), [decoratorExpr]));
6974
}
7075

7176
/**

transforms/helpers/parse-helper.js

Lines changed: 5 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ const {
77
get,
88
getOptions,
99
getRuntimeData,
10-
LAYOUT_IMPORT_SPECIFIER,
11-
META_DECORATORS,
1210
METHOD_DECORATORS,
1311
startsWithUpperCaseLetter
1412
} = require("./util");
@@ -68,9 +66,6 @@ function getEmberObjectProps(
6866
prop.setRuntimeData(runtimeData);
6967
instanceProps.push(prop);
7068
}
71-
if (prop.isLayout) {
72-
prop.setLayoutValue(LAYOUT_IMPORT_SPECIFIER);
73-
}
7469
});
7570

7671
// Assign decoator names to the binding props if any
@@ -127,7 +122,7 @@ function getDecoratorInfo(specifier, importPropDecoratorMap) {
127122
decoratorName = localName;
128123
} else {
129124
if (isMetaDecorator) {
130-
decoratorName = META_DECORATORS[importedName] || localName;
125+
decoratorName = localName;
131126
} else {
132127
decoratorName = importPropDecoratorMap[importedName];
133128
}
@@ -175,18 +170,12 @@ function getSpecifierLocalIdentifier(specifier) {
175170
*/
176171
function setSpecifierProps(specifier, importPropDecoratorMap) {
177172
const isMetaDecorator = !importPropDecoratorMap;
178-
const importedName = get(specifier, "imported.name");
179173
const decoratorImportedName = get(
180174
importPropDecoratorMap,
181175
get(specifier, "imported.name")
182176
);
183177
specifier.local = getSpecifierLocalIdentifier(specifier);
184-
if (isMetaDecorator) {
185-
const metaDecoratorName = META_DECORATORS[importedName];
186-
if (metaDecoratorName) {
187-
specifier.imported.name = metaDecoratorName;
188-
}
189-
} else {
178+
if (!isMetaDecorator) {
190179
specifier.imported.name = decoratorImportedName;
191180
}
192181
// Needed one more time as we changed the imported name
@@ -232,12 +221,11 @@ function getDecoratorsToImport(instanceProps, decoratorsMap = {}) {
232221
attribute: specs.attribute || prop.hasAttributeDecorator,
233222
className: specs.className || prop.hasClassNameDecorator,
234223
classNames: specs.classNames || prop.isClassNames,
235-
layout: specs.layout || prop.isLayout,
224+
layout: specs.layout || prop.isLayoutDecorator,
225+
templateLayout: specs.templateLayout || prop.isTemplateLayoutDecorator,
236226
off: specs.off || prop.hasOffDecorator,
237-
readOnly: specs.readOnly || prop.hasReadOnly,
238227
tagName: specs.tagName || prop.isTagName,
239-
unobserves: specs.unobserves || prop.hasUnobservesDecorator,
240-
volatile: specs.volatile || prop.hasVolatile
228+
unobserves: specs.unobserves || prop.hasUnobservesDecorator
241229
};
242230
}, decoratorsMap);
243231
}
@@ -375,45 +363,6 @@ function getEmberObjectCallExpressions(j, root) {
375363
);
376364
}
377365

378-
/**
379-
* Extracts the layout property name
380-
*
381-
* @param {Object} j - jscodeshift lib reference
382-
* @param {File} root
383-
* @returns {String} Name of the layout property
384-
*/
385-
function getLayoutPropertyName(j, root) {
386-
const layoutPropCollection = root.find(j.Property, {
387-
key: {
388-
type: "Identifier",
389-
name: "layout"
390-
}
391-
});
392-
if (layoutPropCollection.length) {
393-
const layoutProp = layoutPropCollection.get();
394-
return get(layoutProp, "value.value.name");
395-
}
396-
}
397-
398-
/**
399-
* Update the layout import name
400-
*
401-
* @param {Object} j - jscodeshift lib reference
402-
* @param {File} root
403-
*/
404-
function updateLayoutImportDeclaration(j, root, layoutName) {
405-
if (!layoutName) {
406-
return;
407-
}
408-
const layoutIdentifier = root
409-
.find(j.ImportDefaultSpecifier, { local: { name: layoutName } })
410-
.find(j.Identifier);
411-
412-
if (layoutIdentifier.length) {
413-
layoutIdentifier.get().value.name = LAYOUT_IMPORT_SPECIFIER;
414-
}
415-
}
416-
417366
/**
418367
* Returns the variable name
419368
*
@@ -544,7 +493,6 @@ function replaceEmberObjectExpressions(j, root, filePath, options = {}) {
544493
}
545494
// Parse the import statements
546495
const importedDecoratedProps = getImportedDecoratedProps(j, root);
547-
const layoutName = getLayoutPropertyName(j, root);
548496
let transformed = false;
549497
let decoratorsToImportMap = {};
550498

@@ -603,7 +551,6 @@ function replaceEmberObjectExpressions(j, root, filePath, options = {}) {
603551
key => decoratorsToImportMap[key]
604552
);
605553
createDecoratorImportDeclarations(j, root, decoratorsToImport);
606-
updateLayoutImportDeclaration(j, root, layoutName);
607554
logger.info(`[${filePath}]: SUCCESS`);
608555
}
609556
return transformed;

transforms/helpers/transform-helper.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
const {
22
ACTION_SUPER_EXPRESSION_COMMENT,
3+
LAYOUT_DECORATOR_LOCAL_NAME,
4+
LAYOUT_DECORATOR_NAME,
35
get,
46
getPropName,
57
shouldSetValue
@@ -435,8 +437,12 @@ function createEmberDecoratorSpecifiers(
435437
return pathSpecifiers
436438
.filter(specifier => decoratorsToImport.includes(specifier))
437439
.map(specifier => {
440+
const importedSpecifier =
441+
specifier === LAYOUT_DECORATOR_LOCAL_NAME
442+
? LAYOUT_DECORATOR_NAME
443+
: specifier;
438444
return j.importSpecifier(
439-
j.identifier(specifier),
445+
j.identifier(importedSpecifier),
440446
j.identifier(specifier)
441447
);
442448
});

0 commit comments

Comments
 (0)