Skip to content

Commit

Permalink
Add support fo multiple decorators
Browse files Browse the repository at this point in the history
  • Loading branch information
Santosh Sutar committed Aug 25, 2018
1 parent 11d6a57 commit dc9df39
Show file tree
Hide file tree
Showing 9 changed files with 470 additions and 307 deletions.
14 changes: 10 additions & 4 deletions transforms/ember-object/__testfixtures__/decorators.input.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { alias, sum as add } from "@ember/object/computed";
import { get, set, observer, computed } from "@ember/object";
import { get, set, observer as watcher, computed } from "@ember/object";
import { inject as controller } from "@ember/controller";
import { inject as service } from "@ember/service";
import { on } from "@ember/object/evented";
Expand All @@ -11,8 +11,12 @@ const Foo = EmberObject.extend({
a: "",
b: service("store"),
myController: controller("abc"),
observedProp: observer("xyz"),
event: on("click"),
observedProp: watcher("xyz", function() {
return "observed";
}),
event: on("click", function() {
return "abc";
}),

actions: {
/**
Expand All @@ -28,7 +32,9 @@ const Foo = EmberObject.extend({

var comp = EmberObject.extend({
classNameBindings: ["isEnabled:enabled:disabled", "a:b:c", "c:d"],
isEnabled: false,
isEnabled: computed("a", "c", function() {
return false;
}),
a: true,
c: "",
attributeBindings: ["customHref:href"],
Expand Down
28 changes: 18 additions & 10 deletions transforms/ember-object/__testfixtures__/decorators.output.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { alias, sum as add } from "@ember/object/computed";
import { get, set, observer, computed } from "@ember/object";
import { inject as controller } from "@ember/controller";
import { inject as service } from "@ember/service";
import { on } from "@ember/object/evented";
import { sum as add, alias } from "@ember-decorators/object/computed";
import { get, set } from "@ember/object";
import { computed, observes as watcher } from "@ember-decorators/object";
import { controller as controller } from "@ember-decorators/controller";
import { service as service } from "@ember-decorators/service";
import { on } from "@ember-decorators/object/evented";
import layout from "components/templates/foo";

@tagName("div")
Expand All @@ -16,11 +17,15 @@ class Foo extends EmberObject {
@controller("abc")
myController;

@observes("xyz")
observedProp;
@watcher("xyz")
get observedProp() {
return "observed";
}

@on("click")
event;
event() {
return "abc";
}

/**
Comments
Expand All @@ -38,8 +43,11 @@ class Foo extends EmberObject {
}

class Comp extends EmberObject {
@computed("a", "c")
@className("enabled", "disabled")
isEnabled = false;
get isEnabled() {
return false;
}

@className("b", "c")
a = true;
Expand Down Expand Up @@ -74,7 +82,7 @@ class Foo extends EmberObject {
Computed description
*/
@computed("fullName", "age", "country")
description() {
get description() {
return `${this.get(
"fullName"
)}; Age: ${this.get("age")}; Country: ${this.get("country")}`;
Expand Down
13 changes: 7 additions & 6 deletions transforms/ember-object/__testfixtures__/mixins.output.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { alias, sum as add } from "@ember/object/computed";
import { get, set, observer, computed } from "@ember/object";
import { inject as controller } from "@ember/controller";
import { inject as service } from "@ember/service";
import { on } from "@ember/object/evented";
import { sum as add, alias } from "@ember-decorators/object/computed";
import { get, set } from "@ember/object";
import { computed, observes } from "@ember-decorators/object";
import { controller as controller } from "@ember-decorators/controller";
import { service as service } from "@ember-decorators/service";
import { on } from "@ember-decorators/object/evented";
import layout from "components/templates/foo";
import MixinA from "mixins/A";
import MixinB from "mixins/B";
Expand Down Expand Up @@ -82,7 +83,7 @@ class Foo extends EmberObject.extend(MixinA, MixinB) {
Computed description
*/
@computed("fullName", "age", "country")
description() {
get description() {
return `${this.get(
"fullName"
)}; Age: ${this.get("age")}; Country: ${this.get("country")}`;
Expand Down
103 changes: 103 additions & 0 deletions transforms/helpers/EOProp.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
const {
get,
getPropName,
getPropType,
getPropCalleeName,
isClassDecoratorProp,
METHOD_DECORATORS
} = require("./util");

/**
* Ember Objet Property
*
* A wrapper object for ember object properties
*/
class EOProp {
constructor(eoProp) {
this._prop = eoProp;
this.decoratorNames = [];
}

get value() {
return get(this._prop, "value");
}

get kind() {
let kind = get(this._prop, "kind");
if (kind === "init" && this.hasDecorators && !this.hasMethodDecorator) {
kind = "get";
}
return kind;
}

get key() {
return get(this._prop, "key");
}

get name() {
return getPropName(this._prop);
}

get type() {
return getPropType(this._prop);
}

get calleeName() {
return getPropCalleeName(this._prop);
}

get comments() {
return this._prop.comments;
}

get computed() {
return this._prop.computed;
}

get isClassDecorator() {
return isClassDecoratorProp(this.name);
}

get isCallExpression() {
return this.type === "CallExpression";
}

get hasDecorators() {
return this.decoratorNames.length;
}

get callExprArgs() {
return get(this._prop, "value.arguments") || [];
}

get hasNonLiteralArg() {
return this.callExprArgs.some(arg => arg.type !== "Literal");
}

get hasMethodDecorator() {
return this.decoratorNames.some(decoratormName =>
METHOD_DECORATORS.includes(decoratormName)
);
}

setDecorators(importedDecoratedProps) {
if (this.isCallExpression) {
const decoratorName = importedDecoratedProps[this.calleeName];
if (decoratorName) {
this.decoratorNames.push(decoratorName);
}
}
}

addBindingProps(attributeBindingsProps, classNameBindingsProps) {
if (attributeBindingsProps[this.name]) {
this.decoratorNames.push("attribute");
this.propList = attributeBindingsProps[this.name];
} else if (classNameBindingsProps[this.name]) {
this.decoratorNames.push("className");
this.propList = classNameBindingsProps[this.name];
}
}
}

module.exports = EOProp;
46 changes: 23 additions & 23 deletions transforms/helpers/decorator-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,15 @@ function withDecorators(to, decorators = []) {
* Creates a list of class decorators `tagName` and `classNames`
*
* @param {Object} j - jscodeshift lib reference
* @param {Property[]} classDecoratorProps
* @param {Property} classDecoratorProp
* @returns {Decorator[]}
*/
function createClassDecorators(j, classDecoratorProps = []) {
return classDecoratorProps.map(classDecoratorProp => {
return j.decorator(
j.callExpression(j.identifier(classDecoratorProp.key.name), [
classDecoratorProp.value
])
);
});
function createClassDecorator(j, classDecoratorProp) {
return j.decorator(
j.callExpression(j.identifier(classDecoratorProp.key.name), [
classDecoratorProp.value
])
);
}

/**
Expand All @@ -40,7 +38,7 @@ function createClassDecorators(j, classDecoratorProps = []) {
* @returns {Decorator[]}
*/
function createCallExpressionDecorators(j, decoratorName, instanceProp) {
if (decoratorName === "computed") {
if (instanceProp.hasNonLiteralArg) {
const decoratorArgs = get(instanceProp, "value.arguments").slice(0, -1);
return [
j.decorator(j.callExpression(j.identifier(decoratorName), decoratorArgs))
Expand All @@ -49,10 +47,7 @@ function createCallExpressionDecorators(j, decoratorName, instanceProp) {
// clone the instance prop value
const instancePropValue = JSON.parse(JSON.stringify(instanceProp.value));
instancePropValue.callee.name = decoratorName;
if (
instanceProp.decoratorName &&
get(instanceProp, "value.callee.object.callee.name")
) {
if (get(instanceProp, "value.callee.object.callee.name")) {
const decoratorArgs = get(instancePropValue, "callee.object.arguments");
instancePropValue.callee.object = get(
instancePropValue,
Expand Down Expand Up @@ -101,19 +96,24 @@ function createBindingDecorators(j, decoratorName, instanceProp) {
* @returns {Decorator[]}
*/
function createInstancePropDecorators(j, instanceProp) {
const decoratorName = instanceProp.decoratorName;
if (!decoratorName) {
return [];
}
if (decoratorName === "className" || decoratorName === "attribute") {
return createBindingDecorators(j, decoratorName, instanceProp);
}
return createCallExpressionDecorators(j, decoratorName, instanceProp);
return instanceProp.decoratorNames.reduce((decorators, decoratorName) => {
if (!decoratorName) {
return decorators;
}
if (decoratorName === "className" || decoratorName === "attribute") {
return decorators.concat(
createBindingDecorators(j, decoratorName, instanceProp)
);
}
return decorators.concat(
createCallExpressionDecorators(j, decoratorName, instanceProp)
);
}, []);
}

module.exports = {
withDecorators,
createClassDecorators,
createClassDecorator,
createActionDecorators,
createCallExpressionDecorators,
createInstancePropDecorators
Expand Down
Loading

0 comments on commit dc9df39

Please sign in to comment.