From ba7c259776730a4d90303b1a839f3b86667c06b8 Mon Sep 17 00:00:00 2001 From: Chris Manson Date: Tue, 1 Oct 2024 12:17:58 +0100 Subject: [PATCH] add basic support for mixins on native classes --- lib/__tests__/__snapshots__/transform.js.snap | 62 +++++++++++++++++++ lib/__tests__/transform.js | 30 +++++++++ lib/transform.js | 16 ++++- 3 files changed, 107 insertions(+), 1 deletion(-) diff --git a/lib/__tests__/__snapshots__/transform.js.snap b/lib/__tests__/__snapshots__/transform.js.snap index d1b8c9a..cf1820b 100644 --- a/lib/__tests__/__snapshots__/transform.js.snap +++ b/lib/__tests__/__snapshots__/transform.js.snap @@ -311,6 +311,36 @@ foo ==========" `; +exports[`native components basic mixins 1`] = ` +"========== + + import Component from '@ember/component'; + import SuperMixin from 'some-place'; + + export default class FooComponent extends Component.extends(SuperMixin) { + } + +~~~~~~~~~~ +foo +~~~~~~~~~~ + => tagName: div +~~~~~~~~~~ + + import { tagName } from \\"@ember-decorators/component\\"; + import Component from '@ember/component'; + import SuperMixin from 'some-place'; + + @tagName(\\"\\") + export default class FooComponent extends Component.extends(SuperMixin) { + } + +~~~~~~~~~~ +
+ foo +
+==========" +`; + exports[`native components handles \`@attribute\` and \`@attributeBindings\` correctly 1`] = ` "========== @@ -744,3 +774,35 @@ foo ==========" `; + +exports[`native components replaces existing \`tagName\` on a mixin class 1`] = ` +"========== + + import Component from '@ember/component'; + import { tagName } from '@ember-decorators/component'; + import SomeMixin from 'somewhere'; + + @tagName('span') + export default class FooComponent extends Component.extends(SomeMixin) { + } + +~~~~~~~~~~ +foo +~~~~~~~~~~ + => tagName: span +~~~~~~~~~~ + + import Component from '@ember/component'; + import { tagName } from '@ember-decorators/component'; + import SomeMixin from 'somewhere'; + + @tagName(\\"\\") + export default class FooComponent extends Component.extends(SomeMixin) { + } + +~~~~~~~~~~ + + foo + +==========" +`; diff --git a/lib/__tests__/transform.js b/lib/__tests__/transform.js index 26f95cb..f7fff8a 100644 --- a/lib/__tests__/transform.js +++ b/lib/__tests__/transform.js @@ -304,6 +304,20 @@ describe('native components', () => { expect(generateSnapshot(source, template)).toMatchSnapshot(); }); + test('basic mixins', () => { + let source = ` + import Component from '@ember/component'; + import SuperMixin from 'some-place'; + + export default class FooComponent extends Component.extends(SuperMixin) { + } + `; + + let template = `foo`; + + expect(generateSnapshot(source, template)).toMatchSnapshot(); + }); + test('replaces existing `tagName`', () => { let source = ` import Component from '@ember/component'; @@ -319,6 +333,22 @@ describe('native components', () => { expect(generateSnapshot(source, template)).toMatchSnapshot(); }); + test('replaces existing `tagName` on a mixin class', () => { + let source = ` + import Component from '@ember/component'; + import { tagName } from '@ember-decorators/component'; + import SomeMixin from 'somewhere'; + + @tagName('span') + export default class FooComponent extends Component.extends(SomeMixin) { + } + `; + + let template = `foo`; + + expect(generateSnapshot(source, template)).toMatchSnapshot(); + }); + test('handles `elementId` correctly', () => { let source = ` import Component from '@ember/component'; diff --git a/lib/transform.js b/lib/transform.js index 77cb8c2..44ac88a 100644 --- a/lib/transform.js +++ b/lib/transform.js @@ -57,8 +57,22 @@ function checkComponentType(root) { }, }, }); + + if (classExport.length === 0) { + // find `export default class FooComponent extends Component.extends(SomeMixin) {}` AST node + classExport = root.find(j.ExportDefaultDeclaration, { + declaration: { + type: 'ClassDeclaration', + superClass: { + type: 'CallExpression', + }, + }, + }); + } + if (classExport.length === 1) { - let className = classExport.get().node.declaration.superClass.name; + const superClass = classExport.get().node.declaration.superClass; + let className = superClass.name || superClass.callee.object.name; if ( root.find(j.ImportDeclaration, node => { return (