@ui5/ts-interface-generator
Version:
Generator for TypeScript type definitions for custom UI5 controls implemented in TypeScript
372 lines • 17.7 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createJSDocCenterPart = createJSDocCenterPart;
exports.buildJSDocStringFromLines = buildJSDocStringFromLines;
exports.addJSDoc = addJSDoc;
const preferences_1 = __importDefault(require("./preferences"));
// converted to TypeScript after copying from https://github.com/SAP/openui5/blob/b21d5c95cbba5a6ad455a9276659e4698bc7421a/lib/jsdoc/ui5/plugin.js#L1618-L2307
// Then all type information stripped from the generated JSDoc, as well as visibility, @synthetic, @name, @function etc.
// hungarian prefixing is removed as well
let minimal;
const rEmptyLine = /^\s*$/;
// removes leading and trailing empty lines as well as duplicate empty lines within the content
function trim(lines) {
let contentSeen = false, lastLineWasEmpty = false;
lines = lines.filter((line) => {
const lineHasContent = line != null && !rEmptyLine.test(line);
contentSeen = contentSeen || lineHasContent;
if (lineHasContent) {
lastLineWasEmpty = false;
return true;
}
else if (!contentSeen) {
// all lines so far empty
return false;
}
else {
// this line is empty, but there was content before
if (!lastLineWasEmpty) {
// line is empty, but previous had content => preserve
lastLineWasEmpty = true;
return true;
}
else {
// lastLineWasEmpty
return false;
}
}
});
if (lastLineWasEmpty) {
lines.pop();
}
return lines;
}
function createJSDocCenterPart(info, lines = []) {
if (info.doc) {
lines.push(info.doc.trim());
lines.push("");
}
(info.since ? lines.push("@since " + info.since) : "",
info.deprecation !== undefined
? lines.push("@deprecated " + info.deprecation)
: "", // "undefined" check to even output the tag when there is empty text
info.experimental !== undefined
? lines.push("@experimental " + info.experimental)
: ""); // "undefined" check to even output the tag when there is empty text
return lines;
}
function buildJSDocStringFromLines(lines) {
lines = Array.prototype.concat.apply([], lines); // flatten
lines = trim(lines);
if (lines.length > 0) {
const comment = "\r\n * " + lines.join("\r\n * ") + "\r\n ";
return comment;
}
}
function addJSDoc(oClassInfo) {
let lines;
minimal = preferences_1.default.get().jsdoc !== "verbose";
oClassInfo.generatedJSDoc = {};
function isEmpty(obj) {
if (!obj) {
return true;
}
for (const n in obj) {
if (Object.prototype.hasOwnProperty.call(obj, n)) {
return false;
}
}
return true;
}
function newJSDoc(methodType, propertyName, info, lines, suffixLines) {
if (!oClassInfo.generatedJSDoc[methodType]) {
oClassInfo.generatedJSDoc[methodType] = {};
}
if (minimal) {
lines = []; // ignore generated prefix when prefs are set to "minimal"
}
lines.push("");
createJSDocCenterPart(info, lines);
if (!minimal) {
// only add generated suffix when prefs are not set to "minimal"
suffixLines && suffixLines.forEach((line) => lines.push(line));
lines.push("");
}
oClassInfo.generatedJSDoc[methodType][propertyName] =
buildJSDocStringFromLines(lines);
}
function generateParamTag(n, type, description, defaultValue) {
let s = "@param ";
if (defaultValue !== null) {
s += "[" + n + "=" + JSON.stringify(defaultValue) + "]";
}
else {
s += n;
}
s += " " + description;
return s;
}
for (const n in oClassInfo.properties) {
const info = oClassInfo.properties[n];
if (info.visibility === "hidden") {
continue;
}
newJSDoc("PropertyGet" /* MethodType.PropertyGet */, n, info, ['Gets current value of property "' + n + '".'], [
info.defaultValue !== null // && info.defaultValue.value !== null
? "Default value is: " + JSON.stringify(info.defaultValue)
: "",
'@returns Value of property "' + n + '"',
]);
newJSDoc("PropertySet" /* MethodType.PropertySet */, n, info, ['Sets a new value for property "' + n + '".'], [
'When called with a value of "null" or "undefined", the default value of the property will be restored.',
"",
info.defaultValue !== null // && info.defaultValue.value !== null
? "Default value is: " + JSON.stringify(info.defaultValue)
: "",
generateParamTag(n, info.type, 'New value for property "' + n + '"', info.defaultValue),
'@returns Reference to "this" in order to allow method chaining',
]);
if (info.bindable) {
newJSDoc("PropertyBind" /* MethodType.PropertyBind */, n, info, ['Binds property "' + n + '" to model data.'], [
"See {@link sap.ui.base.ManagedObject#bindProperty ManagedObject.bindProperty} for a ",
'detailed description of the possible properties of "oBindingInfo"',
"@param oBindingInfo The binding information",
'@returns Reference to "this" in order to allow method chaining',
]);
newJSDoc("PropertyUnbind" /* MethodType.PropertyUnbind */, n, info, ['Unbinds property "' + n + '" from model data.'], ['@returns Reference to "this" in order to allow method chaining']);
}
}
for (const n in oClassInfo.aggregations) {
const info = oClassInfo.aggregations[n];
if (info.visibility === "hidden") {
continue;
}
newJSDoc("AggregationGet" /* MethodType.AggregationGet */, n, info, [
'Gets content of aggregation "' + n + '".',
n === oClassInfo.defaultAggregation
? "Note: this is the default aggregation for " + n + "."
: "",
], [
// TODO: @returns missing?!?
]);
if (info.cardinality == "0..n") {
const n1 = info.singularName;
newJSDoc("AggregationInsert" /* MethodType.AggregationInsert */, n, info, ["Inserts a " + n1 + ' into the aggregation "' + n + '".'], [
"@param " +
n1 +
" The " +
n1 +
" to insert; if empty, nothing is inserted",
'@param index The "0"-based index the ' +
n1 +
" should be inserted at; for",
' a negative value of "iIndex", the ' +
n1 +
" is inserted at position 0; for a value",
" greater than the current size of the aggregation, the " +
n1 +
" is inserted at",
" the last position",
'@returns Reference to "this" in order to allow method chaining',
]);
newJSDoc("AggregationAdd" /* MethodType.AggregationAdd */, n, info, ["Adds some " + n1 + ' to the aggregation "' + n + '".'], [
"@param " +
n1 +
" The " +
n1 +
" to add; if empty, nothing is inserted",
'@returns Reference to "this" in order to allow method chaining',
]);
newJSDoc("AggregationRemove" /* MethodType.AggregationRemove */, n, info, ["Removes a " + n1 + ' from the aggregation "' + n + '".'], [
"@param " + n1 + " The " + n1 + " to remove or its index or id",
"@returns The removed " + n1 + ' or "null"',
]);
newJSDoc("AggregationRemoveAll" /* MethodType.AggregationRemoveAll */, n, info, [
'Removes all the controls from the aggregation "' + n + '".',
"Additionally, it unregisters them from the hosting UIArea.",
], ["@returns An array of the removed elements (might be empty)"]);
newJSDoc("AggregationIndexOf" /* MethodType.AggregationIndexOf */, n, info, [
'Checks for the provided "' +
info.type +
'" in the aggregation "' +
n +
'".',
"and returns its index if found or -1 otherwise.",
], [
"@param " + n1 + " The " + n1 + " whose index is looked for",
"@returns The index of the provided control in the aggregation if found, or -1 otherwise",
]);
}
else {
newJSDoc("AggregationSet" /* MethodType.AggregationSet */, n, info, ["Sets the aggregated " + n + "."], [
"@param " + n + " The " + n + " to set",
'@returns Reference to "this" in order to allow method chaining',
]);
}
newJSDoc("AggregationDestroy" /* MethodType.AggregationDestroy */, n, info, [
"Destroys " +
(info.cardinality === "0..n" ? "all " : "") +
"the " +
n +
' in the aggregation "' +
n +
'".',
], ['@returns Reference to "this" in order to allow method chaining']);
if (info.bindable) {
newJSDoc("AggregationBind" /* MethodType.AggregationBind */, n, info, ['Binds aggregation "' + n + '" to model data.'], [
"See {@link sap.ui.base.ManagedObject#bindAggregation ManagedObject.bindAggregation} for a ",
'detailed description of the possible properties of "oBindingInfo".',
"@param oBindingInfo The binding information",
'@returns Reference to "this" in order to allow method chaining',
]);
newJSDoc("AggregationUnbind" /* MethodType.AggregationUnbind */, n, info, ['Unbinds aggregation "' + n + '" from model data.'], ['@returns Reference to "this" in order to allow method chaining']);
}
}
for (const n in oClassInfo.associations) {
const info = oClassInfo.associations[n];
if (info.visibility === "hidden") {
continue;
}
newJSDoc("AssociationGet" /* MethodType.AssociationGet */, n, info, [
info.cardinality === "0..n"
? 'Returns array of IDs of the elements which are the current targets of the association "' +
n +
'".'
: 'ID of the element which is the current target of the association "' +
n +
'", or "null".',
], []);
if (info.cardinality === "0..n") {
const n1 = info.singularName;
newJSDoc("AssociationAdd" /* MethodType.AssociationAdd */, n, info, ["Adds some " + n1 + ' into the association "' + n + '".'], [
"@param " +
n1 +
" The " +
n +
" to add; if empty, nothing is inserted",
'@returns Reference to "this" in order to allow method chaining',
]);
newJSDoc("AssociationRemove" /* MethodType.AssociationRemove */, n, info, ["Removes an " + n1 + " from the association named " + n + "."], [
"@param " + n1 + " The " + n1 + " to be removed or its index or ID",
"@returns The removed " + n1 + ' or "null"',
]);
newJSDoc("AssociationRemoveAll" /* MethodType.AssociationRemoveAll */, n, info, ["Removes all the controls in the association named " + n + "."], ["@returns An array of the removed elements (might be empty)"]);
}
else {
newJSDoc("AssociationSet" /* MethodType.AssociationSet */, n, info, ["Sets the associated " + n + "."], [
"@param " +
n +
' ID of an element which becomes the new target of this "' +
n +
'" association; alternatively, an element instance may be given',
'@returns Reference to "this" in order to allow method chaining',
]);
}
}
for (const n in oClassInfo.events) {
const info = oClassInfo.events[n];
lines = [
info.doc ? info.doc : "",
"",
info.allowPreventDefault
? 'Listeners may prevent the default action of this event by calling the "preventDefault" method on the event object.'
: "",
"",
info.enableEventBubbling
? "This event bubbles up the control hierarchy."
: "",
"",
info.since ? "@since " + info.since : "",
info.deprecation ? "@deprecated " + info.deprecation : "",
info.experimental ? "@experimental " + info.experimental : "",
"@param oControlEvent",
"@param oControlEvent.getSource",
"@param oControlEvent.getParameters",
];
for (const pName in info.parameters) {
lines.push("@param oControlEvent.getParameters." +
pName +
" " +
(info.parameters[pName].doc || ""));
}
//newJSDoc(lines); // TODO
newJSDoc("EventAttach" /* MethodType.EventAttach */, n, info, [
'Attaches event handler "fn" to the "' +
n +
'" event of this "' +
oClassInfo.name +
'".',
], [
'When called, the context of the event handler (its "this") will be bound to "oListener" if specified, ',
'otherwise it will be bound to this "' + oClassInfo.name + '" itself.',
"",
"@param fn The function to be called when the event occurs",
'@param listener Context object to call the event handler with. Defaults to this "' +
oClassInfo.name +
'" itself',
"",
'@returns Reference to "this" in order to allow method chaining',
]);
newJSDoc("EventAttachWithData" /* MethodType.EventAttachWithData */, n, info, [
'Attaches event handler "fn" to the "' +
n +
'" event of this "' +
oClassInfo.name +
'".',
], [
'When called, the context of the event handler (its "this") will be bound to "oListener" if specified, ',
'otherwise it will be bound to this "' + oClassInfo.name + '" itself.',
"",
"@param data An application-specific payload object that will be passed to the event handler along with the event object when firing the event",
"@param fn The function to be called when the event occurs",
'@param listener Context object to call the event handler with. Defaults to this "' +
oClassInfo.name +
'" itself',
"",
'@returns Reference to "this" in order to allow method chaining',
]);
newJSDoc("EventDetach" /* MethodType.EventDetach */, n, info, [
'Detaches event handler "fn" from the "' +
n +
'" event of this "' +
oClassInfo.name +
'".',
], [
"The passed function and listener object must match the ones used for event registration.",
"",
"@param fn The function to be called, when the event occurs",
"@param listener Context object on which the given function had to be called",
'@returns Reference to "this" in order to allow method chaining',
info.since ? "@since " + info.since : "",
info.deprecation ? "@deprecated " + info.deprecation : "",
info.experimental ? "@experimental " + info.experimental : "",
]);
// build documentation for fireEvent. It contains conditional parts which makes it a bit more complicated
lines = ['Fires event "' + n + '" to attached listeners.'];
const suffixLines = [];
if (info.allowPreventDefault) {
suffixLines.push("", 'Listeners may prevent the default action of this event by calling the "preventDefault" method on the event object.', "The return value of this method indicates whether the default action should be executed.", "");
}
suffixLines.push("", "@param parameters Parameters to pass along with the event");
if (!isEmpty(info.parameters)) {
for (const pName in info.parameters) {
suffixLines.push("@param [mParameters." +
pName +
"] " +
(info.parameters[pName].doc || ""));
}
suffixLines.push("");
}
if (info.allowPreventDefault) {
suffixLines.push("@returns Whether or not to prevent the default action");
}
else {
suffixLines.push('@returns Reference to "this" in order to allow method chaining');
}
newJSDoc("EventFire" /* MethodType.EventFire */, n, info, lines, suffixLines);
}
}
//# sourceMappingURL=jsdocGenerator.js.map