Skip to content

Commit

Permalink
feat: convert classes to UI5 in exit phase to allow additional plugins
Browse files Browse the repository at this point in the history
To ensure that other plugins can be used upfront the conversion of
the ES6 imports and classes to UI5 AMD-like syntax and Object.extend,
the plugin now runs in the exit phase of the visitor. This allows
other plugins, e.g. decorators to run before and convert the code
accordingly. This plugin only sanitizes the decorators to remove the
plugin proprietary ones to avoid conflicts with other plugins.

The plugin is now also not dependent on the plugin order anymore and
using the preset-env ensures a proper transpilation of code to a
specific target browser set.

Added tests to ensure that a proper decorator handling works when
using the plugin-proposal-decorators or that e.g the conversion of
getters/setters takes place when using the babel plugin named
plugin-transform-property-mutators as this is not part of the
preset-env by default.

Updated all dependencies of the project with this change.

Fixes #23
Fixes #25
  • Loading branch information
petermuessig committed May 29, 2023
1 parent c88dac0 commit 5a46b58
Show file tree
Hide file tree
Showing 17 changed files with 15,042 additions and 8,361 deletions.
18,255 changes: 11,913 additions & 6,342 deletions package-lock.json

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
"name": "babel-ui5",
"private": true,
"devDependencies": {
"@babel/eslint-parser": "^7.19.1",
"@commitlint/cli": "^17.4.4",
"@commitlint/config-conventional": "^17.4.4",
"@babel/eslint-parser": "^7.21.8",
"@commitlint/cli": "^17.6.3",
"@commitlint/config-conventional": "^17.6.3",
"cz-conventional-changelog": "^3.3.0",
"eslint": "^8.34.0",
"eslint-config-prettier": "^8.6.0",
"eslint": "^8.41.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-prettier": "^4.2.1",
"husky": "^8.0.3",
"lerna": "^6.5.1"
"lerna": "^6.6.2"
},
"scripts": {
"prepare": "npm run prepare:husky && npm run prepare:workspace",
Expand Down
53 changes: 50 additions & 3 deletions packages/plugin/__test__/__snapshots__/test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,35 @@ exports[`classes class-fix-with-existing-define.js 1`] = `

exports[`classic sap-ui-define.ts 1`] = `"sap.ui.define("", ["foo/bar/MyResource"]);"`;

exports[`decorators mixin.js 1`] = `
"sap.ui.define(["sap/ui/core/mvc/Controller", "../lib/decorators", "../lib/RoutingSupport"], function (Controller, ___lib_decorators, __RoutingSupport) {
function _interopRequireDefault(obj) {
return obj && obj.__esModule && typeof obj.default !== "undefined" ? obj.default : obj;
}
var _dec, _class;
const mixin = ___lib_decorators["mixin"];
const RoutingSupport = _interopRequireDefault(__RoutingSupport);
let AppController = (_dec = mixin(RoutingSupport), _dec(_class = class AppController extends Controller {}) || _class);
return AppController;
});"
`;

exports[`decorators mixin_mixed.js 1`] = `
"sap.ui.define(["sap/ui/core/mvc/Controller", "../lib/decorators", "../lib/RoutingSupport"], function (Controller, ___lib_decorators, __RoutingSupport) {
function _interopRequireDefault(obj) {
return obj && obj.__esModule && typeof obj.default !== "undefined" ? obj.default : obj;
}
const mixin = ___lib_decorators["mixin"];
const RoutingSupport = _interopRequireDefault(__RoutingSupport);
const AppController = Controller.extend("example.controller.AppController", {});
return AppController;
});"
`;

exports[`empty empty_js.js 1`] = `""`;

exports[`empty empty_ts.ts 1`] = `""`;

exports[`examples Animal.js 1`] = `
"sap.ui.define(["sap/ui/base/ManagedObject"], function (ManagedObject) {
const Animal = ManagedObject.extend("examples.Animal", {
Expand Down Expand Up @@ -1187,6 +1216,24 @@ exports[`preset-env preset-env-class.js 1`] = `
});"
`;
exports[`preset-env preset-env-property-mutators.js 1`] = `
"sap.ui.define(["sap/class", "core-js/modules/es6.object.define-properties.js"], function (SAPClass, __core_js_modules_es6objectdefine_propertiesjs) {
var MyClass = SAPClass.extend("my.MyClass", Object.defineProperties({}, {
thing: {
get: function get() {
return this._thing;
},
set: function set(value) {
this._thing = value;
},
configurable: true,
enumerable: true
}
}));
return MyClass;
});"
`;
exports[`preset-env preset-env-usage.js 1`] = `
"sap.ui.define(["sap/SAPClass", "core-js/modules/es6.object.to-string.js"], function (SAPClass, __core_js_modules_es6objectto_stringjs) {
import "core-js/modules/es6.promise.js";
Expand Down Expand Up @@ -1294,12 +1341,12 @@ exports[`typescript ts-export-default-typed-arrow-fn-with-named.1.ts 1`] = `
exports[`typescript ts-export-interface.ts 1`] = `
"sap.ui.define([], function () {
const MY_CONSTANT = "constant";
var MyEnum;
(function (MyEnum) {
var MyEnum = function (MyEnum) {
MyEnum[MyEnum["A"] = 0] = "A";
MyEnum[MyEnum["B"] = 1] = "B";
MyEnum[MyEnum["C"] = 2] = "C";
})(MyEnum || (MyEnum = {}));
return MyEnum;
}(MyEnum || {});
;
var __exports = {
__esModule: true
Expand Down
8 changes: 8 additions & 0 deletions packages/plugin/__test__/fixtures/decorators/mixin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Controller from "sap/ui/core/mvc/Controller";
import { mixin } from "../lib/decorators";
import RoutingSupport from "../lib/RoutingSupport";

@mixin(RoutingSupport)
export default class AppController extends Controller {
/* ... */
}
9 changes: 9 additions & 0 deletions packages/plugin/__test__/fixtures/decorators/mixin_mixed.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Controller from "sap/ui/core/mvc/Controller";
import { mixin } from "../lib/decorators";
import RoutingSupport from "../lib/RoutingSupport";

@namespace("example.controller")
@mixin(RoutingSupport)
export default class AppController extends Controller {
/* ... */
}
Empty file.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// This conversion will be run with preset env set to ie >= 11.
// In general, we want to ensure that the class transform does not get applied before out own.

import SAPClass from "sap/class";

/**
* @name my.MyClass
*/
export default class MyClass extends SAPClass {
get thing() {
return this._thing;
}
set thing(value) {
this._thing = value;
}
}
39 changes: 26 additions & 13 deletions packages/plugin/__test__/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ function processDirectory(dir) {
const items = readdirSync(dir);
// Process Files first
items
.filter(item => item.endsWith(".js") || item.endsWith(".ts"))
.forEach(filename => {
.filter((item) => item.endsWith(".js") || item.endsWith(".ts"))
.forEach((filename) => {
test(filename, () => {
const filePath = join(dir, filename);
let outputPath = filePath
Expand All @@ -31,6 +31,13 @@ function processDirectory(dir) {
try {
const opts = getOpts(filePath);
const presets = [];
const plugins = [
[plugin, opts], // we don't rely on the plugin order anymore!
"@babel/plugin-syntax-dynamic-import",
"@babel/plugin-syntax-object-rest-spread",
["@babel/plugin-syntax-decorators", { legacy: true }],
["@babel/plugin-syntax-class-properties", { useBuiltIns: true }],
];

if (filePath.endsWith(".ts")) {
presets.push(["@babel/preset-typescript"]);
Expand All @@ -46,19 +53,25 @@ function processDirectory(dir) {
{
targets: undefined, // default targets for preset-env is ES5
modules: false,
useBuiltIns: "usage",
useBuiltIns: "usage", // will include imports to corejs (some tests rely on this)
corejs: 2,
},
]);
}

if (filePath.endsWith("property-mutators.js")) {
plugins.push("@babel/plugin-transform-property-mutators");
}

if (filePath.includes("/decorators/")) {
plugins.push([
"@babel/plugin-proposal-decorators",
{ legacy: true },
]);
}

const result = transformFileSync(filePath, {
plugins: [
"@babel/plugin-syntax-dynamic-import",
"@babel/plugin-syntax-object-rest-spread",
["@babel/plugin-syntax-decorators", { legacy: true }],
["@babel/plugin-syntax-class-properties", { useBuiltIns: true }],
[plugin, opts],
],
plugins,
presets,
sourceRoot: __dirname,
comments: false,
Expand Down Expand Up @@ -95,9 +108,9 @@ function processDirectory(dir) {

// Recurse into directories
items
.map(name => ({ name, path: join(dir, name) }))
.filter(item => statSync(item.path).isDirectory())
.forEach(item => {
.map((name) => ({ name, path: join(dir, name) }))
.filter((item) => statSync(item.path).isDirectory())
.forEach((item) => {
describe(item.name, () => {
processDirectory(item.path);
});
Expand Down
Loading

0 comments on commit 5a46b58

Please sign in to comment.