@ui5/ts-interface-generator
Version:
Generator for TypeScript type definitions for custom UI5 controls implemented in TypeScript
285 lines (282 loc) • 12.8 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.expandDefaultKey = expandDefaultKey;
const loglevel_1 = __importDefault(require("loglevel"));
const rPlural = /(children|ies|ves|oes|ses|ches|shes|xes|s)$/i;
const mSingular = {
children: -3,
ies: "y",
ves: "f",
oes: -2,
ses: -2,
ches: -2,
shes: -2,
xes: -2,
s: -1,
};
function collectClassInfo(metadata, className) {
// !!!
// Mostly rewritten in TypeScript based on lines 732-988 in https://github.com/SAP/openui5/blob/ff8dec90ff0591e10f8bac1754a622f5d522a957/lib/jsdoc/ui5/plugin.js#L732-L988
// hence still containing commented-out traces of that JS code.
// Also, this is the reason why this code is structured and written like it is and may contain unneeded parts.
//const classDoclet: Doclet = null; // Don't need the class documentation in the generated interface - it is used from its original location
const oClassInfo = {
name: className, // was: extendCall.arguments[0].value,
//baseType : baseType,
interfaces: [],
specialSettings: {},
properties: {},
aggregations: {},
associations: {},
events: {},
methods: [],
getters: [],
annotations: {},
designtime: false,
designTime: false,
stereotype: null,
metadataClass: undefined,
defaultProperty: undefined,
defaultAggregation: undefined,
abstract: false,
final: false,
library: undefined,
};
function upper(n) {
return n.slice(0, 1).toUpperCase() + n.slice(1);
}
function each(map, defaultKey, callback) {
if (map) {
for (const n in map) {
if (Object.prototype.hasOwnProperty.call(map, n)) {
const settings = expandDefaultKey(map[n], defaultKey); // in simple cases just a string is given; this expands the string to a real configuration object
if (settings == null) {
loglevel_1.default.warn(`no valid metadata for ${n} (AST type '${map[n].name}')`);
continue;
}
callback(n, settings, map[n]);
}
}
}
}
/*
if ( extendCall.arguments.length > 2 ) {
// new class defines its own metadata class type
const metadataClass = getResolvedObjectName(extendCall.arguments[2]);
if ( metadataClass ) {
oClassInfo.metadataClass = getResolvedObjectName(extendCall.arguments[2]);
debug(`found metadata class name '${oClassInfo.metadataClass}'`);
} else {
future(`cannot understand metadata class parameter (AST node type '${extendCall.arguments[2].type}')`);
}
}
const classInfoNode = extendCall.arguments[1];
const classInfoMap = createPropertyMap(classInfoNode);
if ( classInfoMap && classInfoMap.metadata && classInfoMap.metadata.value.type !== Syntax.ObjectExpression ) {
warning(`class metadata exists but can't be analyzed. It is not of type 'ObjectExpression', but a '${classInfoMap.metadata.value.type}'.`);
return null;
}
const metadata = classInfoMap && classInfoMap.metadata && createPropertyMap(classInfoMap.metadata.value);
*/
if (metadata) {
// Read the stereotype information from the metadata
oClassInfo.stereotype =
(metadata.stereotype && metadata.stereotype) || undefined;
oClassInfo.library = (metadata.library && metadata.library) || undefined;
oClassInfo["abstract"] = !!(metadata["abstract"] && metadata["abstract"]);
oClassInfo["final"] = !!(metadata["final"] && metadata["final"]);
//oClassInfo.dnd = metadata.dnd && convertDragDropValue(metadata.dnd);
if (metadata.interfaces) {
oClassInfo.interfaces = metadata.interfaces;
}
each(metadata.specialSettings, "type", (n, settings) => {
oClassInfo.specialSettings[n] = {
name: n,
doc: settings.doc,
since: settings.since,
deprecation: settings.deprecation,
experimental: settings.experimental,
visibility: (settings.visibility && settings.visibility) || "public",
type: settings.type ? settings.type : "any",
};
});
oClassInfo.defaultProperty =
(metadata.defaultProperty && metadata.defaultProperty) || undefined;
each(metadata.properties, "type", (n, settings) => {
const N = upper(n);
let methods;
oClassInfo.properties[n] = {
name: n,
doc: settings.doc,
since: settings.since,
deprecation: settings.deprecation,
experimental: settings.experimental,
visibility: settings.visibility || "public",
type: settings.type || "string",
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
defaultValue: settings.defaultValue !== undefined ? settings.defaultValue : null, // ? convertValueWithRaw(settings.defaultValue, type, n) : null,
bindable: settings.bindable ? !!settings.bindable : false,
methods: (methods = {
get: "get" + N,
set: "set" + N,
}),
};
if (oClassInfo.properties[n].bindable) {
methods["bind"] = "bind" + N;
methods["unbind"] = "unbind" + N;
}
// if ( !settings.defaultValue ) {
// log.debug("property without defaultValue: " + oClassInfo.name + "." + n);
//}
});
oClassInfo.defaultAggregation = metadata.defaultAggregation || undefined;
each(metadata.aggregations, "type", (n, settings) => {
const N = upper(n);
let methods;
const aggr = (oClassInfo.aggregations[n] = {
name: n,
doc: settings.doc,
since: settings.since,
deprecation: settings.deprecation,
experimental: settings.experimental,
visibility: (settings.visibility && settings.visibility) || "public",
type: settings.type ? settings.type : "sap.ui.core.Control",
altTypes: settings.altTypes ? settings.altTypes : undefined,
singularName: settings.singularName
? settings.singularName
: guessSingularName(n),
cardinality: settings.multiple !== undefined && !settings.multiple
? "0..1"
: "0..n",
bindable: settings.bindable, // TODO: was: ? !!convertValue(settings.bindable) : false,
methods: (methods = {
get: "get" + N,
destroy: "destroy" + N,
}),
});
//aggr.dnd = settings.dnd && convertDragDropValue(settings.dnd, aggr.cardinality);
if (aggr.cardinality === "0..1") {
methods["set"] = "set" + N;
}
else {
const N1 = upper(aggr.singularName);
methods["insert"] = "insert" + N1;
methods["add"] = "add" + N1;
methods["remove"] = "remove" + N1;
methods["indexOf"] = "indexOf" + N1;
methods["removeAll"] = "removeAll" + N;
}
if (aggr.bindable) {
methods["bind"] = "bind" + N;
methods["unbind"] = "unbind" + N;
}
});
each(metadata.associations, "type", (n, settings) => {
const N = upper(n);
let methods;
oClassInfo.associations[n] = {
name: n,
doc: settings.doc,
since: settings.since,
deprecation: settings.deprecation,
experimental: settings.experimental,
visibility: (settings.visibility && settings.visibility) || "public",
type: settings.type ? settings.type : "sap.ui.core.Control",
singularName: settings.singularName
? settings.singularName
: guessSingularName(n),
cardinality: settings.multiple && settings.multiple ? "0..n" : "0..1",
methods: (methods = {
get: "get" + N,
}),
};
if (oClassInfo.associations[n].cardinality === "0..1") {
methods["set"] = "set" + N;
}
else {
const N1 = upper(oClassInfo.associations[n].singularName);
methods["add"] = "add" + N1;
methods["remove"] = "remove" + N1;
methods["removeAll"] = "removeAll" + N;
}
});
each(metadata.events, null, (n, settings) => {
const N = upper(n);
const info = (oClassInfo.events[n] = {
name: n,
doc: settings.doc,
since: settings.since,
deprecation: settings.deprecation,
experimental: settings.experimental,
visibility:
/* (settings.visibility && settings.visibility) || */ "public",
allowPreventDefault: !!(settings.allowPreventDefault && settings.allowPreventDefault),
enableEventBubbling: !!(settings.enableEventBubbling && settings.enableEventBubbling),
parameters: {},
methods: {
attach: "attach" + N,
detach: "detach" + N,
fire: "fire" + N,
},
});
each(settings.parameters, "type", (pName, pSettings) => {
info.parameters[pName] = {
name: pName,
doc: settings.doc,
since: settings.since,
deprecation: settings.deprecation,
experimental: settings.experimental,
type: pSettings && pSettings.type ? pSettings.type : "",
};
});
});
const designtime = metadata.designtime || metadata.designTime; // convertValue removed
if (typeof designtime === "string" || typeof designtime === "boolean") {
oClassInfo.designtime = designtime;
}
// log.debug(oClassInfo.name + ":" + JSON.stringify(oClassInfo, null, " "));
}
/*
if (currentModule.defaultExport
&& currentModule.localNames[currentModule.defaultExport]
&& currentModule.localNames[currentModule.defaultExport].class === oClassInfo.name) {
// debug("class " + oClassInfo.name + " identified as default export of module " + currentModule.module);
oClassInfo.export = "";
} else if (currentModule.defaultExportClass
&& currentModule.defaultExportClass === oClassInfo.name) {
// debug("class " + oClassInfo.name + " identified as default export of module " + currentModule.module + " (immediate return)");
oClassInfo.export = "";
}
// remember class info by name
classInfos[oClassInfo.name] = oClassInfo;
*/
return oClassInfo;
}
/**
* When for simplicitly the metadata for an API member only consists of a string instead of a full configuration
* object, then this function inflates the string to a full configuration object.
* "defaultKey" determines as which property in the configuration object the string should be used.
* Example: an association is configured as "SampleControl". This function converts this to {type: "SampleControl"}.
*/
function expandDefaultKey(node, defaultKey) {
if (node != null) {
// if, instead of an object literal only a string is given and there is a defaultKey, then wrap the literal
if (typeof node === "string" && defaultKey != null) {
const result = {};
result[defaultKey] = node;
return result;
}
}
return node;
}
function guessSingularName(sPluralName) {
return sPluralName.replace(rPlural, ($, sPlural) => {
const vRepl = mSingular[sPlural.toLowerCase()];
return typeof vRepl === "string" ? vRepl : sPlural.slice(0, vRepl);
});
}
exports.default = collectClassInfo;
//# sourceMappingURL=collectClassInfo.js.map