Skip to content

Commit 4667ef0

Browse files
committed
Handle attribute decorator
1 parent 40e4b69 commit 4667ef0

File tree

4 files changed

+124
-11
lines changed

4 files changed

+124
-11
lines changed

lib/__tests__/__snapshots__/transform.js.snap

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,67 @@ foo
241241
=========="
242242
`;
243243
244+
exports[`native components handles \`@attribute\` and \`@attributeBindings\` correctly 1`] = `
245+
"==========
246+
247+
import { attribute, attributeBindings } from '@ember-decorators/component';
248+
249+
@attributeBindings('foo')
250+
export default class FooComponent extends Component {
251+
@attribute('baz') bar;
252+
}
253+
254+
~~~~~~~~~~
255+
foo
256+
~~~~~~~~~~
257+
=> tagName: div
258+
~~~~~~~~~~
259+
260+
import { tagName } from '@ember-decorators/component';
261+
262+
@tagName(\\"\\")
263+
export default class FooComponent extends Component {
264+
bar;
265+
}
266+
267+
~~~~~~~~~~
268+
<div foo={{this.foo}} baz={{this.bar}} ...attributes>
269+
foo
270+
</div>
271+
=========="
272+
`;
273+
274+
exports[`native components handles \`@attribute\` correctly 1`] = `
275+
"==========
276+
277+
import { attribute } from '@ember-decorators/component';
278+
279+
export default class FooComponent extends Component {
280+
@attribute foo;
281+
@attribute('baz') bar;
282+
}
283+
284+
~~~~~~~~~~
285+
foo
286+
~~~~~~~~~~
287+
=> tagName: div
288+
~~~~~~~~~~
289+
290+
import { tagName } from '@ember-decorators/component';
291+
292+
@tagName(\\"\\")
293+
export default class FooComponent extends Component {
294+
foo;
295+
bar;
296+
}
297+
298+
~~~~~~~~~~
299+
<div foo={{this.foo}} baz={{this.bar}} ...attributes>
300+
foo
301+
</div>
302+
=========="
303+
`;
304+
244305
exports[`native components handles \`@attributeBindings\` correctly 1`] = `
245306
"==========
246307

lib/__tests__/transform.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,36 @@ describe('native components', function() {
271271
expect(generateSnapshot(source, template)).toMatchSnapshot();
272272
});
273273

274+
test('handles `@attribute` correctly', () => {
275+
let source = `
276+
import { attribute } from '@ember-decorators/component';
277+
278+
export default class FooComponent extends Component {
279+
@attribute foo;
280+
@attribute('baz') bar;
281+
}
282+
`;
283+
284+
let template = `foo`;
285+
286+
expect(generateSnapshot(source, template)).toMatchSnapshot();
287+
});
288+
289+
test('handles `@attribute` and `@attributeBindings` correctly', () => {
290+
let source = `
291+
import { attribute, attributeBindings } from '@ember-decorators/component';
292+
293+
@attributeBindings('foo')
294+
export default class FooComponent extends Component {
295+
@attribute('baz') bar;
296+
}
297+
`;
298+
299+
let template = `foo`;
300+
301+
expect(generateSnapshot(source, template)).toMatchSnapshot();
302+
});
303+
274304
test('handles `@classNames` correctly', () => {
275305
let source = `
276306
import { classNames } from '@ember-decorators/component';

lib/transform/native.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ module.exports = function transformNativeComponent(root, options) {
146146
removeDecorator(root, classDeclaration, 'attributeBindings', '@ember-decorators/component');
147147
removeDecorator(root, classDeclaration, 'classNames', '@ember-decorators/component');
148148
removeDecorator(root, classDeclaration, 'classNameBindings', '@ember-decorators/component');
149+
j(classBody).find(j.ClassProperty).forEach(path => removeDecorator(root, path, 'attribute', '@ember-decorators/component'));
150+
149151

150152
let newSource = root.toSource();
151153

lib/utils/native.js

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,16 @@ function addClassDecorator(classDeclaration, name, args) {
1717
}
1818
}
1919

20-
function isDecorator(path, name) {
20+
function isDecorator(path, name, withArgs) {
2121
let node = path.value;
22+
let isCall =
23+
node.expression.type === 'CallExpression' && node.expression.callee.type === 'Identifier';
24+
2225
return (
2326
node.type === 'Decorator' &&
24-
node.expression.type === 'CallExpression' &&
25-
node.expression.callee.type === 'Identifier' &&
26-
node.expression.callee.name === name
27+
((isCall && node.expression.callee.name === name) ||
28+
(!isCall && node.expression.name === name)) &&
29+
(withArgs === undefined || ((withArgs === true && isCall) || (withArgs === false && !isCall)))
2730
);
2831
}
2932

@@ -51,39 +54,40 @@ function findStringProperty(properties, name, defaultValue = null) {
5154
return valuePath.value.value;
5255
}
5356

54-
function findDecorator(path, name) {
57+
function findDecorator(path, name, withArgs) {
5558
let decorators = path.get('decorators');
5659
if (decorators.value === undefined) {
5760
return;
5861
}
5962

60-
let existing = decorators.filter(path => isDecorator(path, name));
63+
let existing = decorators.filter(path => isDecorator(path, name, withArgs));
6164

6265
if (existing.length > 0) {
6366
return existing[0];
6467
}
6568
}
6669

67-
function findStringDecorator(path, name, defaultValue = null) {
68-
let decorator = findDecorator(path, name);
70+
function findStringDecorator(path, name) {
71+
let decorator = findDecorator(path, name, true);
6972

7073
if (!decorator) {
71-
return defaultValue;
74+
return;
7275
}
7376

7477
return decorator.value.expression.arguments[0].value;
7578
}
7679

7780
function findTagName(path) {
78-
return findStringDecorator(path, 'tagName', 'div');
81+
let value = findStringDecorator(path, 'tagName');
82+
return value !== undefined ? value : 'div';
7983
}
8084

8185
function findElementId(path) {
8286
return findStringProperty(path, 'elementId');
8387
}
8488

8589
function findStringArrayDecorator(path, name) {
86-
let decorator = findDecorator(path, name);
90+
let decorator = findDecorator(path, name, true);
8791
if (!decorator) {
8892
return [];
8993
}
@@ -106,6 +110,22 @@ function findAttributeBindings(classDeclaration) {
106110
attrBindings.set(attr || value, value);
107111
}
108112

113+
j(classDeclaration)
114+
.find(j.ClassProperty)
115+
.forEach(path => {
116+
let value = path.node.key.name;
117+
let key = findStringDecorator(path, 'attribute');
118+
if (key === undefined) {
119+
let decorator = findDecorator(path, 'attribute', false);
120+
if (decorator) {
121+
key = value;
122+
}
123+
}
124+
if (key !== undefined) {
125+
attrBindings.set(key, value);
126+
}
127+
});
128+
109129
return attrBindings;
110130
}
111131

0 commit comments

Comments
 (0)