ui5plugin-parser
Version:
1,100 lines (1,099 loc) • 63.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CustomJSClass = void 0;
/* eslint-disable @typescript-eslint/no-var-requires */
const commentParser = require("comment-parser");
const path = require("path");
const ParserPool_1 = require("../../../../parser/pool/ParserPool");
const AbstractCustomClass_1 = require("../AbstractCustomClass");
const LineColumn = require("line-column");
const acornLoose = require("acorn-loose");
class CustomJSClass extends AbstractCustomClass_1.AbstractCustomClass {
constructor(className, syntaxAnalyser, parser, documentText) {
super(className, parser);
this.classText = "";
this.parentClassNameDotNotation = "";
this.methods = [];
this.fields = [];
this.comments = [];
this.acornMethodsAndFields = [];
this.syntaxAnalyser = syntaxAnalyser;
this.fsPath = this.parser.fileReader.getClassFSPathFromClassName(this.className) ?? "";
this._readFileContainingThisClassCode(documentText); //todo: rename. not always reading anyore.
this.UIDefine = this._getUIDefine();
this.acornClassBody = this._getThisClassBodyAcorn();
this._fillParentClassName();
this._fillUI5Metadata();
this._fillMethodsAndFields();
this._enrichMemberInfoWithJSDocs();
this._enrichClassInfoWithJSDocs();
this._enrichMethodParamsWithHungarianNotation();
this._fillIsAbstract();
this._enrichVariablesWithJSDocTypesAndVisibility();
}
_enrichClassInfoWithJSDocs() {
if (this.acornReturnedClassExtendBody) {
const comment = this.comments.find(comment => {
const positionDifference = this.acornReturnedClassExtendBody.start - comment.end;
return positionDifference < 100 && positionDifference > 0;
});
const ui5ModelTag = comment?.jsdoc?.tags?.find((tag) => tag.tag === "ui5model");
if (ui5ModelTag) {
this.defaultModelClassName = ui5ModelTag.type;
}
if (comment?.jsdoc?.description) {
this.description = comment?.jsdoc?.description;
}
const abstractTag = comment?.jsdoc?.tags?.find((tag) => tag.tag === "abstract");
if (abstractTag) {
this.abstract = true;
}
}
}
getMembers() {
return super.getMembers();
}
_fillIsAbstract() {
this.abstract =
this.abstract ||
!!this.methods.find(method => method.abstract) ||
!!this.fields.find(field => field.abstract);
}
_enrichMemberInfoWithJSDocs() {
if (this.acornClassBody) {
//instance methods
let methods = this.acornClassBody.properties?.filter((node) => node.value.type === "FunctionExpression" || node.value.type === "ArrowFunctionExpression") || [];
const fields = this.acornClassBody.properties?.filter((node) => node.value.type !== "FunctionExpression" && node.value.type !== "ArrowFunctionExpression") || [];
//static methods
//TODO: Move this
const UIDefineBody = this.getUIDefineAcornBody();
if (UIDefineBody && this.classBodyAcornVariableName) {
const thisClassVariableAssignments = UIDefineBody.filter((node) => {
return (node.type === "ExpressionStatement" &&
(node.expression?.left?.object?.name === this.classBodyAcornVariableName ||
node.expression?.left?.object?.object?.name === this.classBodyAcornVariableName));
});
const staticMethods = thisClassVariableAssignments
.filter(node => {
const assignmentBody = node.expression.right;
return (assignmentBody.type === "ArrowFunctionExpression" ||
assignmentBody.type === "FunctionExpression");
})
.map(node => ({
key: {
name: node.expression.left.property.name,
start: node.expression.left.property.start,
end: node.expression.left.property.end,
type: "Identifier"
},
value: node.expression.right,
start: node.expression.left.object.start,
end: node.expression.right.end,
type: "Property"
}));
methods = methods.concat(staticMethods);
}
this.acornMethodsAndFields = this.acornMethodsAndFields.concat(methods);
methods?.forEach((method) => {
const methodName = method.key.name || method.key.value;
const params = method.value.params;
const comment = this.comments.find(comment => {
const positionDifference = method.start - comment.end;
return positionDifference < 15 && positionDifference > 0;
});
if (comment) {
const paramTags = comment.jsdoc?.tags?.filter((tag) => tag.tag === "param");
const returnTag = comment.jsdoc?.tags?.find((tag) => tag.tag === "return" || tag.tag === "returns");
const asyncTag = comment.jsdoc?.tags?.find((tag) => tag.tag === "async");
const isPrivate = !!comment.jsdoc?.tags?.find((tag) => tag.tag === "private");
const isPublic = !!comment.jsdoc?.tags?.find((tag) => tag.tag === "public");
const isProtected = !!comment.jsdoc?.tags?.find((tag) => tag.tag === "protected");
const isIgnored = !!comment.jsdoc?.tags?.find((tag) => tag.tag === "ui5ignore");
const isAbstract = !!comment.jsdoc?.tags?.find((tag) => tag.tag === "abstract");
const isStatic = !!comment.jsdoc?.tags?.find((tag) => tag.tag === "static");
const isDeprecated = !!comment.jsdoc?.tags?.find((tag) => tag.tag === "deprecated");
const UIMethod = this.methods.find(method => method.name === methodName);
if (paramTags && UIMethod) {
paramTags.forEach((tag) => {
this._fillParamJSTypesFromTag(tag, params, UIMethod);
});
}
if (UIMethod) {
if (isPrivate || isPublic || isProtected) {
UIMethod.visibility = isPrivate
? "private"
: isProtected
? "protected"
: isPublic
? "public"
: UIMethod.visibility;
}
if (asyncTag) {
UIMethod.returnType = "Promise";
}
if (returnTag) {
UIMethod.returnType = returnTag.type;
}
if (comment.jsdoc) {
UIMethod.description = comment.jsdoc.description;
}
if (isIgnored) {
UIMethod.ui5ignored = true;
}
if (isAbstract) {
UIMethod.abstract = true;
}
if (isStatic) {
UIMethod.static = true;
}
if (isDeprecated) {
UIMethod.deprecated = true;
}
if (paramTags) {
UIMethod.params.forEach((param, i) => {
const jsDocParam = paramTags[i];
if (jsDocParam) {
param.isOptional = jsDocParam.optional;
}
});
}
}
}
});
fields.forEach((field) => {
const fieldName = field.key.name || field.key.value;
const comment = this.comments.find(comment => {
const positionDifference = field.start - comment.end;
return positionDifference < 15 && positionDifference > 0;
});
if (comment) {
const isPrivate = !!comment.jsdoc?.tags?.find((tag) => tag.tag === "private");
const isPublic = !!comment.jsdoc?.tags?.find((tag) => tag.tag === "public");
const isProtected = !!comment.jsdoc?.tags?.find((tag) => tag.tag === "protected");
const fieldType = comment.jsdoc?.tags?.find((tag) => tag.tag === "type");
const ui5ignored = comment.jsdoc?.tags?.find((tag) => tag.tag === "ui5ignore");
const isAbstract = !!comment.jsdoc?.tags?.find((tag) => tag.tag === "abstract");
const isStatic = !!comment.jsdoc?.tags?.find((tag) => tag.tag === "static");
const isDeprecated = !!comment.jsdoc?.tags?.find((tag) => tag.tag === "deprecated");
const UIField = this.fields.find(field => field.name === fieldName);
if (UIField) {
if (isPrivate || isPublic || isProtected) {
UIField.visibility = isPrivate
? "private"
: isProtected
? "protected"
: isPublic
? "public"
: UIField.visibility;
}
if (comment.jsdoc) {
UIField.description = comment.jsdoc.description;
}
if (fieldType) {
UIField.type = fieldType.type;
}
if (ui5ignored) {
UIField.ui5ignored = true;
}
if (isAbstract) {
UIField.abstract = true;
}
if (isStatic) {
UIField.static = true;
}
if (isDeprecated) {
UIField.deprecated = true;
}
}
}
});
}
}
_fillParamJSTypesFromTag(tag, params, method) {
const tagNameParts = tag.name.split(".");
if (tagNameParts.length > 1) {
const paramName = tagNameParts.shift();
const param = params.find((param) => param.name === paramName);
if (param) {
if (!param.customData) {
param.customData = {};
}
this._fillFieldsRecursively(param.customData, tagNameParts, tag);
}
}
else {
const param = params.find((param) => param.name === tag.name);
if (param) {
param.jsType = tag.type;
const UIParam = method.params.find(param => param.name === tag.name);
if (UIParam && param.jsType) {
UIParam.type = param.jsType;
}
}
}
}
_fillFieldsRecursively(object, keys, tag) {
const key = keys.shift();
if (key) {
object[key] = typeof object[key] !== "object" ? {} : object[key];
if (keys.length > 0) {
this._fillFieldsRecursively(object[key], keys, tag);
}
else {
object[key] = tag.type;
}
}
}
_enrichMethodParamsWithHungarianNotation() {
this.methods.forEach(method => {
method.params.forEach(param => {
if (param.type === "any" || !param.type) {
param.type = CustomJSClass.getTypeFromHungarianNotation(param.name) || "any";
}
});
});
}
_readFileContainingThisClassCode(documentText) {
if (!documentText) {
documentText = this.parser.fileReader.getDocumentTextFromCustomClassName(this.className);
}
this.classText = documentText || "";
if (documentText) {
try {
this.fileContent = acornLoose.parse(documentText, {
ecmaVersion: 11,
locations: true,
onComment: (isBlock, text, start, end, startLoc, endLoc) => {
if (isBlock && text?.startsWith("*")) {
this.comments.push({
text: text,
start: start,
end: end,
jsdoc: commentParser.parse(`/*${text}*/`)[0],
loc: {
start: startLoc,
end: endLoc
}
});
}
}
});
}
catch (error) {
console.error(error);
this.fileContent = null;
}
}
else {
this.classExists = false;
}
}
_getUIDefine() {
let UIDefine = [];
if (this.fileContent) {
const args = this._getUIDefineItself()?.expression?.arguments;
if (args && args.length >= 2) {
const UIDefinePaths = args[0].elements?.map((part) => part.value) || [];
const UIDefineClassNames = args[1].params?.map((part) => part.name) || [];
UIDefine = UIDefinePaths.filter(path => !!path).map((classPath, index) => {
return {
path: classPath,
className: UIDefineClassNames[index],
classNameDotNotation: this._generateClassNameDotNotationFor(classPath),
start: args[0].elements[index].start,
end: args[0].elements[index].end,
node: args[0].elements[index]
};
});
}
}
return UIDefine;
}
_generateClassNameDotNotationFor(classPath) {
let className = classPath.replace(/\//g, ".");
if (classPath?.startsWith(".")) {
const manifest = ParserPool_1.default.getManifestForClass(this.className);
if (manifest && this.fsPath) {
const normalizedManifestPath = path.normalize(manifest.fsPath);
const importClassPath = path.resolve(path.dirname(this.fsPath), classPath);
const relativeToManifest = path.relative(normalizedManifestPath, importClassPath);
const pathRelativeToManifestDotNotation = relativeToManifest.split(path.sep).join(".");
className = `${manifest.componentName}.${pathRelativeToManifestDotNotation}`;
}
}
if (className.endsWith(".controller")) {
className = className.substring(0, className.length - ".controller".length);
}
return className;
}
_getThisClassBodyAcorn() {
const body = this.fileContent;
let classBody;
const returnKeyword = this._getReturnKeywordFromBody();
if (returnKeyword && body) {
classBody = this._getClassBodyFromPartAcorn(returnKeyword.argument);
}
return classBody;
}
_getReturnKeywordFromBody() {
let returnKeyword;
const UIDefineBody = this.getUIDefineAcornBody();
if (UIDefineBody) {
returnKeyword = UIDefineBody.find((body) => body.type === "ReturnStatement");
}
return returnKeyword;
}
_getClassBodyFromPartAcorn(part) {
const bodyParts = this.getUIDefineAcornBody();
if (!part || !bodyParts) {
return null;
}
let classBody;
if (part.type === "CallExpression") {
classBody = this._getClassBodyFromClassExtendAcorn(part);
this.acornReturnedClassExtendBody = part;
if (classBody) {
if (part.callee.object.name) {
this._parentVariableName = part.callee.object.name;
}
else if (part.callee.object.object?.name === "sap" && part.callee.object.property?.name === "ui") {
this.parentClassNameDotNotation = this._getParentNameFromManifest() || "";
}
}
}
else if (part.type === "ObjectExpression") {
classBody = part;
}
else if (part.type === "Identifier") {
const variable = bodyParts
.filter((body) => body.type === "VariableDeclaration")
.find((variable) => variable.declarations.find((declaration) => declaration.id.name === part.name));
if (variable) {
const neededDeclaration = variable.declarations.find((declaration) => declaration.id.name === part.name);
classBody = this._getClassBodyFromPartAcorn(neededDeclaration.init);
this.acornReturnedClassExtendBody = neededDeclaration.init;
this.classBodyAcornVariableName = part.name;
}
}
return classBody;
}
_getParentNameFromManifest() {
let parentName;
const manifest = ParserPool_1.default.getManifestForClass(this.className);
if (manifest?.content &&
manifest?.content["sap.ui5"]?.extends?.extensions &&
manifest?.content["sap.ui5"]?.extends?.extensions["sap.ui.controllerExtensions"]) {
const mControllerExtensions = manifest.content["sap.ui5"].extends.extensions["sap.ui.controllerExtensions"];
parentName = Object.keys(mControllerExtensions).find(sControllerName => {
return mControllerExtensions[sControllerName].controllerName === this.className;
});
}
return parentName;
}
_getClassBodyFromClassExtendAcorn(part) {
let classBody;
if (this._isThisPartAClassBodyAcorn(part)) {
classBody = part.arguments[1];
}
return classBody;
}
_isThisPartAClassBodyAcorn(part) {
const propertyName = part?.callee?.property?.name;
return propertyName === "extend" || propertyName === "declareStaticClass" || propertyName === "controller";
}
isAssignmentStatementForThisVariable(node) {
return (node.type === "AssignmentExpression" &&
node.operator === "=" &&
node.left?.type === "MemberExpression" &&
node.left?.property?.name &&
node.left?.object?.type === "ThisExpression");
}
_fillMethods() {
return [];
}
_fillFields() {
return [];
}
_fillParentClassName() {
if (this._parentVariableName) {
const parentClassUIDefine = this.UIDefine.find(UIDefine => UIDefine.className === this._parentVariableName);
if (parentClassUIDefine) {
this.parentClassNameDotNotation = parentClassUIDefine.classNameDotNotation;
}
}
}
_fillMethodsAndFields() {
if (this.acornClassBody?.properties) {
this.acornClassBody.properties.forEach((property) => {
const name = property.key?.name || property.key?.value;
if (property.value?.type === "FunctionExpression" ||
property.value?.type === "ArrowFunctionExpression") {
const method = {
name: name,
params: this._generateParamTextForMethod(property.value.params),
returnType: property.returnType || property.value.async ? "Promise" : "void",
position: property.start,
description: "",
visibility: name?.startsWith("_") ? "private" : "public",
acornParams: property.value.params,
node: property.value,
isEventHandler: false,
owner: this.className,
loc: property.key.loc,
static: false,
abstract: false,
deprecated: false,
ui5ignored: false,
mentionedInTheXMLDocument: false
};
this.methods.push(method);
}
else if (property.value?.type === "Identifier" || property.value?.type === "Literal") {
this.fields.push({
name: name,
type: property.jsType,
node: property,
description: property.jsType || "",
visibility: name?.startsWith("_") ? "private" : "public",
owner: this.className,
loc: property.key.loc,
static: false,
abstract: false,
deprecated: false,
ui5ignored: false,
mentionedInTheXMLDocument: false
});
this.acornMethodsAndFields.push(property);
}
else if (property.value?.type === "ObjectExpression") {
this.fields.push({
name: name,
type: "map",
description: "map",
node: property,
customData: this._generateCustomDataForObject(property.value),
visibility: name?.startsWith("_") ? "private" : "public",
owner: this.className,
loc: property.key.loc,
static: false,
abstract: false,
deprecated: false,
ui5ignored: false,
mentionedInTheXMLDocument: false
});
this.acornMethodsAndFields.push(property);
}
else if (property.value?.type === "MemberExpression") {
this.fields.push({
name: name,
type: undefined,
description: "",
node: property,
visibility: name?.startsWith("_") ? "private" : "public",
owner: this.className,
loc: property.key.loc,
static: false,
abstract: false,
deprecated: false,
ui5ignored: false,
mentionedInTheXMLDocument: false
});
this.acornMethodsAndFields.push(property);
}
else if (property.value?.type === "ArrayExpression") {
this.fields.push({
name: name,
type: "any[]",
description: "",
node: property,
visibility: name?.startsWith("_") ? "private" : "public",
owner: this.className,
loc: property.key.loc,
static: false,
abstract: false,
deprecated: false,
ui5ignored: false,
mentionedInTheXMLDocument: false
});
this.acornMethodsAndFields.push(property);
}
else if (property.value?.type === "NewExpression") {
this.fields.push({
name: name,
type: undefined,
description: "",
node: property,
visibility: name?.startsWith("_") ? "private" : "public",
owner: this.className,
loc: property.key.loc,
static: false,
abstract: false,
deprecated: false,
ui5ignored: false,
mentionedInTheXMLDocument: false
});
this.acornMethodsAndFields.push(property);
}
});
this.acornClassBody.properties?.forEach((property) => {
if (property.value?.type === "FunctionExpression" ||
property.value?.type === "ArrowFunctionExpression") {
const assignmentExpressions = this.syntaxAnalyser
.expandAllContent(property.value.body)
.filter((node) => node.type === "AssignmentExpression");
assignmentExpressions?.forEach((node) => {
if (this.isAssignmentStatementForThisVariable(node)) {
const field = this.fields.find(field => field.name === node.left.property.name);
if (field) {
field.type = field.type || node.left.property.name.jsType;
field.node = node.left;
}
else {
this.fields.push({
name: node.left.property.name,
type: node.left.property.name.jsType,
description: node.left.property.name.jsType || "",
visibility: node.left.property.name?.startsWith("_") ? "private" : "public",
node: node.left,
owner: this.className,
loc: node.left.property.loc,
static: false,
abstract: false,
deprecated: false,
ui5ignored: false,
mentionedInTheXMLDocument: false
});
}
}
});
}
});
this._fillMethodsAndFieldsFromPrototype();
//remove duplicates
this.fields = this.fields.reduce((accumulator, field) => {
const existingField = accumulator.find(accumulatedField => accumulatedField.name === field.name);
if (existingField && field.type && !existingField.type) {
accumulator[accumulator.indexOf(existingField)] = field;
}
else if (!existingField) {
accumulator.push(field);
}
return accumulator;
}, []);
this.fields.push({
name: "prototype",
description: "Prototype of the class",
type: this.className,
visibility: "public",
owner: this.className,
static: false,
abstract: false,
deprecated: false,
ui5ignored: false,
mentionedInTheXMLDocument: false
});
}
this._fillMethodsFromMetadata();
const constructorMethod = this.methods.find(method => method.name === "constructor");
if (constructorMethod) {
constructorMethod.returnType = this.className;
}
}
_generateParamTextForMethod(acornParams) {
const params = acornParams.map((param) => {
let name = "";
if (param.type === "Identifier") {
name = param.name || "Unknown";
}
else if (param.type === "AssignmentPattern") {
name = param.left?.name || "Unknown";
}
else {
name = "Unknown";
}
return {
name: name,
description: "",
type: param.jsType || "any",
isOptional: false
};
});
return params;
}
_generateCustomDataForObject(node, looseObject = {}) {
node.properties?.forEach((property) => {
looseObject[property.key.name] = {};
if (property.value.type === "ObjectExpression") {
this._generateCustomDataForObject(property.value, looseObject[property.key.name]);
}
});
return looseObject;
}
getUIDefineAcornBody() {
const UIDefineBody = this._getUIDefineItself()?.expression?.arguments[1]?.body?.body ||
this._getUIDefineItself()?.expression?.arguments[2]?.body?.body;
return UIDefineBody;
}
_getUIDefineItself() {
const uiDefineItself = this.fileContent?.body?.find((body) => {
return ((body.expression?.arguments?.[1]?.body?.body ||
body.expression?.arguments?.[2]?.body?.body));
});
return uiDefineItself;
}
_fillMethodsAndFieldsFromPrototype() {
const UIDefineBody = this.getUIDefineAcornBody();
if (UIDefineBody && this.classBodyAcornVariableName) {
const thisClassVariableAssignments = UIDefineBody.filter((node) => {
return (node.type === "ExpressionStatement" &&
(node.expression?.left?.object?.name === this.classBodyAcornVariableName ||
node.expression?.left?.object?.object?.name === this.classBodyAcornVariableName));
});
thisClassVariableAssignments?.forEach(node => {
const assignmentBody = node.expression?.right;
const isMethod = assignmentBody?.type === "ArrowFunctionExpression" || assignmentBody?.type === "FunctionExpression";
const isField = !isMethod;
const name = node?.expression?.left?.property?.name;
const isStatic = node.expression?.left?.object?.property?.name !== "prototype";
if (isMethod) {
const method = {
name: name,
params: assignmentBody.params.map((param) => ({
name: param.name,
description: `${param.name} parameter`,
type: param.jsType || ""
})),
returnType: assignmentBody.returnType || assignmentBody.async ? "Promise" : "void",
position: node.expression.left.property.start,
description: "",
visibility: name?.startsWith("_") ? "private" : "public",
acornParams: assignmentBody.params,
node: assignmentBody,
isEventHandler: false,
owner: this.className,
loc: node.expression.left.property.loc,
static: isStatic,
abstract: false,
deprecated: false,
ui5ignored: false,
mentionedInTheXMLDocument: false
};
this.methods.push(method);
}
else if (isField) {
this.fields.push({
name: name,
visibility: name?.startsWith("_") ? "private" : "public",
type: typeof assignmentBody.value,
description: assignmentBody.jsType || "",
node: node.expression.left,
owner: this.className,
loc: node.expression.left.property.loc,
static: isStatic,
abstract: false,
deprecated: false,
ui5ignored: false,
mentionedInTheXMLDocument: false
});
}
});
}
}
static generateDescriptionForMethod(method) {
return `(${method.params.map(param => param.name).join(", ")}) : ${method.returnType ? method.returnType : "void"}`;
}
fillTypesFromHungarionNotation() {
this.fields.forEach(field => {
if (!field.type) {
field.type = CustomJSClass.getTypeFromHungarianNotation(field.name);
}
});
}
static getTypeFromHungarianNotation(variable = "") {
let type;
if (variable.length >= 2) {
const map = {
$: "Element",
o: "object",
a: "any[]",
i: "int",
f: "float",
m: "map",
s: "string",
b: "boolean",
p: "Promise",
d: "Date",
r: "RegExp",
v: "any",
fn: "function"
};
variable = variable.replace("_", "").replace("this.", "");
const firstChar = variable[0];
const secondChar = variable[1];
if (firstChar && secondChar && map[firstChar] && secondChar === secondChar.toUpperCase()) {
type = map[firstChar];
}
}
return type;
}
_fillMethodsFromMetadata() {
const additionalMethods = [];
this._fillPropertyMethods(additionalMethods);
this._fillAggregationMethods(additionalMethods);
this._fillEventMethods(additionalMethods);
this._fillAssociationMethods(additionalMethods);
this.methods = this.methods.concat(additionalMethods);
}
_fillPropertyMethods(aMethods) {
this.properties?.forEach(property => {
const propertyWithFirstBigLetter = `${property.name[0].toUpperCase()}${property.name.substring(1, property.name.length)}`;
const getterName = `get${propertyWithFirstBigLetter}`;
const setterName = `set${propertyWithFirstBigLetter}`;
aMethods.push({
name: getterName,
description: `Getter for property ${property.name}`,
params: [],
returnType: property.type || "void",
visibility: property.visibility,
isEventHandler: false,
owner: this.className,
static: false,
abstract: false,
deprecated: false,
mentionedInTheXMLDocument: false,
ui5ignored: false
});
aMethods.push({
name: setterName,
description: `Setter for property ${property.name}`,
params: [
{
name: `v${propertyWithFirstBigLetter}`,
type: "any",
description: "Property for setting its value",
isOptional: false
}
],
returnType: this.className,
visibility: property.visibility,
isEventHandler: false,
owner: this.className,
static: false,
abstract: false,
deprecated: false,
mentionedInTheXMLDocument: false,
ui5ignored: false
});
});
}
_fillAggregationMethods(additionalMethods) {
this.aggregations?.forEach(aggregation => {
if (!aggregation.singularName) {
return;
}
const aggregationWithFirstBigLetter = `${aggregation.singularName[0].toUpperCase()}${aggregation.singularName.substring(1, aggregation.singularName.length)}`;
let aMethods = [];
if (aggregation.multiple) {
aMethods = [
{
name: `get${aggregationWithFirstBigLetter}s`,
returnType: `${aggregation.type}[]`,
params: []
},
{
name: `add${aggregationWithFirstBigLetter}`,
returnType: this.className,
params: [
{
name: `v${aggregationWithFirstBigLetter}`,
type: aggregation.type,
description: aggregation.type,
isOptional: false
}
]
},
{
name: `insert${aggregationWithFirstBigLetter}`,
returnType: this.className,
params: [
{
name: `v${aggregationWithFirstBigLetter}`,
type: aggregation.type,
description: aggregation.type,
isOptional: false
},
{
name: `v${aggregationWithFirstBigLetter}`,
type: "number",
description: "index the item should be inserted at",
isOptional: false
}
]
},
{
name: `indexOf${aggregationWithFirstBigLetter}`,
returnType: "int",
params: [
{
name: `v${aggregationWithFirstBigLetter}`,
type: aggregation.type,
description: aggregation.type,
isOptional: false
}
]
},
{
name: `remove${aggregationWithFirstBigLetter}`,
returnType: `${aggregation.type}`,
params: [
{
name: `v${aggregationWithFirstBigLetter}`,
type: aggregation.type,
description: aggregation.type,
isOptional: false
}
]
},
{
name: `removeAll${aggregationWithFirstBigLetter}s`,
returnType: `${aggregation.type}[]`,
params: []
},
{
name: `destroy${aggregationWithFirstBigLetter}s`,
returnType: this.className,
params: []
},
{
name: `bind${aggregationWithFirstBigLetter}s`,
returnType: this.className,
params: [
{
name: "oBindingInfo",
type: "object",
description: "The binding information",
isOptional: false
}
]
},
{
name: `unbind${aggregationWithFirstBigLetter}s`,
returnType: this.className,
params: []
}
];
}
else {
aMethods = [
{
name: `get${aggregationWithFirstBigLetter}`,
returnType: `${aggregation.type}`,
params: []
},
{
name: `set${aggregationWithFirstBigLetter}`,
returnType: this.className,
params: [
{
name: `v${aggregationWithFirstBigLetter}`,
type: aggregation.type,
description: aggregation.type,
isOptional: false
}
]
},
{
name: `bind${aggregationWithFirstBigLetter}`,
returnType: this.className,
params: [
{
name: "oBindingInfo",
type: "object",
description: "The binding information",
isOptional: false
}
]
},
{
name: `unbind${aggregationWithFirstBigLetter}`,
returnType: this.className,
params: []
}
];
}
aMethods.forEach(method => {
additionalMethods.push({
name: method.name,
description: `Generic method from "${aggregation.name}" aggregation`,
params: method.params,
returnType: method.returnType,
visibility: aggregation.visibility,
isEventHandler: false,
owner: this.className,
static: false,
abstract: false,
deprecated: false,
mentionedInTheXMLDocument: false,
ui5ignored: false
});
});
});
}
_fillEventMethods(aMethods) {
this.events?.forEach(event => {
const eventWithFirstBigLetter = `${event.name[0].toUpperCase()}${event.name.substring(1, event.name.length)}`;
const aEventMethods = [
{
name: `fire${eventWithFirstBigLetter}`,
params: [
{
name: "mEventParams",
type: "map",
isOptional: true,
description: "Event params"
}
]
},
{
name: `attach${eventWithFirstBigLetter}`,
params: [
{
name: "fnHandler",
type: "function",
isOptional: false,
description: "Event Handler"
},
{
name: "oContext",
type: "object",
isOptional: true,
description: "context of the event handler"
}
]
},
{
name: `detach${eventWithFirstBigLetter}`,
params: [
{
name: "fnHandler",
type: "function",
isOptional: false,
description: "Event Handler"
},
{
name: "oContext",
type: "object",
isOptional: true,
description: "context of the event handler"
}
]
}
];
aEventMethods?.forEach(eventMethod => {
aMethods.push({
name: eventMethod.name,
description: `Generic method for event ${event.name}`,
params: eventMethod.params,
returnType: this.className,
visibility: event.visibility,
isEventHandler: false,
owner: this.className,
static: false,
abstract: false,
deprecated: false,
mentionedInTheXMLDocument: false,
ui5ignored: false
});
});
});
}
_fillAssociationMethods(additionalMethods) {
this.associations?.forEach(association => {
const associationWithFirstBigLetter = `${association.singularName[0].toUpperCase()}${association.singularName.substring(1, association.singularName.length)}`;
let aMethods = [];
if (association.multiple) {
aMethods = [
{
name: `get${associationWithFirstBigLetter}`,
params: []
},
{
name: `add${associationWithFirstBigLetter}`,
params: [
{
name: `v${associationWithFirstBigLetter}`,
type: association.type || "any",
isOptional: false,
description: `Add ${associationWithFirstBigLetter}`
}
]
},
{
name: `remove${associationWithFirstBigLetter}`,
params: [
{
name: `v${associationWithFirstBigLetter}`,
type: association.type || "any",
isOptional: false,
description: `Remove ${associationWithFirstBigLetter}`
}
]
},
{
name: `removeAll${associationWithFirstBigLetter}s`,
params: []
}
];
}
else {
aMethods = [
{
name: `get${associationWithFirstBigLetter}`,
params: []
},
{
name: `set${associationWithFirstBigLetter}`,
params: [
{
name: `v${associationWithFirstBigLetter}`,
type: association.type || "any",
isOptional: false,
description: `Set ${associationWithFirstBigLetter}`
}
]
}
];
}
aMethods?.forEach(method => {
additionalMethods.push({
name: method.name,
description: `Generic method from ${association.name} association`,
params: method.params,
returnType: association.type || this.className,
visibility: association.visibility,
isEventHandler: false,
owner: this.className,
static: false,
abstract: false,
deprecated: false,
mentionedInTheXMLDocument: false,
ui5ignored: false
});
});
});
}
_fillUI5Metadata() {
if (this.acornClassBody?.properties) {
const metadataExists = !!this.acornClassBody.properties?.find((property) => property.key?.name === "metadata" || property.key?.value === "metadata");
const customMetadataExists = !!this.acornClassBody.properties?.find((property) => property.key?.name === "customMetadata" || property.key?.value === "customMetadata");
if (metadataExists) {
const metadataObject = this.acornClassBody.properties?.find((property) => property.key?.name === "metadata" || property.key?.value === "metadata");
this.aggregations = this._fillAggregations(metadataObject);
this.events = this._fillEvents(metadataObject);
this.properties = this._fillProperties(metadataObject);
this.associations = this._fillAssociations(metadataObject);
this.interfaces = this._fillInterfaces(metadataObject);
}
if (customMetadataExists) {
const customMetadataObject = this.acornClassBody.properties?.find((property) => property.key?.name === "customMetadata" || property.key?.value === "customMetadata");
this.associations.push(...this._fillAssociations(customMetadataObject));