@ui5/webcomponents-tools 1.24.0-rc.4 → 2.0.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +271 -0
- package/components-package/nps.js +4 -11
- package/components-package/wdio.js +404 -405
- package/icons-collection/nps.js +2 -2
- package/lib/create-new-component/index.js +4 -11
- package/lib/generate-json-imports/i18n.js +3 -35
- package/lib/generate-json-imports/themes.js +2 -29
- package/lib/i18n/defaults.js +1 -1
- package/package.json +2 -3
- package/components-package/wdio.sync.js +0 -368
- package/lib/create-new-component/jsFileContentTemplate.js +0 -73
- package/lib/generate-custom-elements-manifest/index.js +0 -271
- package/lib/jsdoc/config.json +0 -29
- package/lib/jsdoc/configTypescript.json +0 -29
- package/lib/jsdoc/plugin.js +0 -2468
- package/lib/jsdoc/preprocess.js +0 -146
- package/lib/jsdoc/template/publish.js +0 -4120
package/lib/jsdoc/plugin.js
DELETED
@@ -1,2468 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
* JSDoc3 plugin for UI5 documentation generation.
|
3
|
-
*
|
4
|
-
* (c) Copyright 2009-2018 SAP SE or an SAP affiliate company.
|
5
|
-
* Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
|
6
|
-
*/
|
7
|
-
|
8
|
-
/* global require, exports, env */
|
9
|
-
/* eslint strict: [2, "global"]*/
|
10
|
-
|
11
|
-
'use strict';
|
12
|
-
|
13
|
-
/**
|
14
|
-
* UI5 plugin for JSDoc3 (3.3.0-alpha5)
|
15
|
-
*
|
16
|
-
* The plugin adds the following SAPUI5 specific tag definitions to JSDoc3
|
17
|
-
*
|
18
|
-
* disclaimer
|
19
|
-
*
|
20
|
-
* experimental
|
21
|
-
*
|
22
|
-
* final
|
23
|
-
*
|
24
|
-
* interface
|
25
|
-
*
|
26
|
-
* implements
|
27
|
-
*
|
28
|
-
* slot
|
29
|
-
*
|
30
|
-
* appenddocs
|
31
|
-
*
|
32
|
-
* tagname
|
33
|
-
*
|
34
|
-
* native
|
35
|
-
*
|
36
|
-
* noattribute
|
37
|
-
*
|
38
|
-
* formEvents
|
39
|
-
*
|
40
|
-
* formProperty
|
41
|
-
*
|
42
|
-
* allowPreventDefault
|
43
|
-
*
|
44
|
-
* It furthermore listens to the following JSDoc3 events to implement additional functionality
|
45
|
-
*
|
46
|
-
* parseBegin
|
47
|
-
* to create short names for all file that are to be parsed
|
48
|
-
*
|
49
|
-
* fileBegin
|
50
|
-
* to write some line to the log (kind of a progress indicator)
|
51
|
-
*
|
52
|
-
* jsdocCommentFound
|
53
|
-
* to pre-process comments, empty lines are used as paragraph markers
|
54
|
-
* a default visibility is added, legacy tag combinations used in JSdoc2 are converted to JSDoc3 conventions
|
55
|
-
*
|
56
|
-
* newDoclet
|
57
|
-
*
|
58
|
-
* parseComplete
|
59
|
-
* remove undocumented/ignored/private doclets or duplicate doclets
|
60
|
-
*
|
61
|
-
*
|
62
|
-
* Last but not least, it implements an astNodeVisitor to detect UI5 specific "extend" calls and to create
|
63
|
-
* documentation for the properties, aggregations etc. that are created with the "extend" call.
|
64
|
-
*
|
65
|
-
* @module plugins/sapui5-jsdoc
|
66
|
-
*/
|
67
|
-
|
68
|
-
/* imports */
|
69
|
-
var Syntax = require('jsdoc/src/syntax').Syntax;
|
70
|
-
var Doclet = require('jsdoc/doclet').Doclet;
|
71
|
-
var fs = require('jsdoc/fs');
|
72
|
-
var path = require('jsdoc/path');
|
73
|
-
var pluginConfig = (env.conf && env.conf.templates && env.conf.templates.ui5) || {};
|
74
|
-
|
75
|
-
/* ---- global vars---- */
|
76
|
-
|
77
|
-
/**
|
78
|
-
* Potential path prefixes.
|
79
|
-
*
|
80
|
-
* Will be determined in the handler for the parseBegin event
|
81
|
-
*/
|
82
|
-
var pathPrefixes = [];
|
83
|
-
|
84
|
-
/**
|
85
|
-
* Prefixes of the UI5 unified resource name for the source files is NOT part of the file name.
|
86
|
-
* (e.g. when a common root namespaces has been omitted from the folder structure).
|
87
|
-
*
|
88
|
-
* The prefix will be prepended to all resource names.
|
89
|
-
*/
|
90
|
-
var resourceNamePrefixes = [];
|
91
|
-
|
92
|
-
/**
|
93
|
-
* A UI5 specific unique Id for all doclets.
|
94
|
-
*/
|
95
|
-
var docletUid = 0;
|
96
|
-
|
97
|
-
var currentProgram;
|
98
|
-
|
99
|
-
/**
|
100
|
-
* Information about the current module.
|
101
|
-
*
|
102
|
-
* The info object is created in the 'fileBegin' event handler and the 'resource' and 'module' properties
|
103
|
-
* are derived from the filename provided by the event. The derived information is only correct, when the
|
104
|
-
* resource name prefix is known for the directory from which a source is loaded (prefixes can be configured
|
105
|
-
* via sapui5.resourceNamePrefixes, for UI5 libraries it is empty by default).
|
106
|
-
*
|
107
|
-
* During AST visiting, the 'name' property and the 'localeNames' map will be filled.
|
108
|
-
* 'name' will be the name of the class defined by the module (assuming that there is only one).
|
109
|
-
* 'localNames' will contain information objects for each parameter of an AMD Factory function and for
|
110
|
-
* all shortcut variables that are defined top-level in the module factory function (e.g. something like
|
111
|
-
* var ButtonDesign = coreLibrary.ButtonDesign; ).
|
112
|
-
* An info object for a local name either can have a 'value' property (simple, constant value) or it can
|
113
|
-
* have a 'module' and optionally a 'path' value. In that case, the local name represents an AMD
|
114
|
-
* module import or a shortcut derived from such an import.
|
115
|
-
*
|
116
|
-
* See {@link getREsolvedObjectName} how the knowledge about locale names is used.
|
117
|
-
*
|
118
|
-
* @type {{name:string,resource:string,module:string,localName:Object<string,object>}}
|
119
|
-
*/
|
120
|
-
var currentModule;
|
121
|
-
|
122
|
-
var currentSource;
|
123
|
-
|
124
|
-
/**
|
125
|
-
* Cached UI5 metadata for encountered UI5 classes.
|
126
|
-
*
|
127
|
-
* The metadata is collected from the 'metadata' property of 'extend' calls. It is stored
|
128
|
-
* in this map keyed by the name of the class (as defined in the first parameter of the extend call).
|
129
|
-
* Only after all files have been parsed, the collected information can be associated with the
|
130
|
-
* corresponding JSDoc doclet (e.g. with the class documentation).
|
131
|
-
*/
|
132
|
-
var classInfos = Object.create(null);
|
133
|
-
|
134
|
-
/**
|
135
|
-
*
|
136
|
-
*/
|
137
|
-
var typeInfos = Object.create(null);
|
138
|
-
|
139
|
-
/**
|
140
|
-
* Cached designtime info for encountered sources.
|
141
|
-
*
|
142
|
-
* The designtime information is collected only for files named '*.designtime.js'.
|
143
|
-
* It is stored in this map keyed by the corresponding module name (e.g. 'sap/m/designtime/Button.designtime').
|
144
|
-
* Only after all files have been parsed, the collected information can be associated with runtime metadata
|
145
|
-
* that refers to that designtime module name.
|
146
|
-
*/
|
147
|
-
var designtimeInfos = Object.create(null);
|
148
|
-
|
149
|
-
/* ---- private functions ---- */
|
150
|
-
|
151
|
-
function ui5data(doclet) {
|
152
|
-
return doclet.__ui5 || (doclet.__ui5 = { id: ++docletUid });
|
153
|
-
}
|
154
|
-
|
155
|
-
var pendingMessageHeader;
|
156
|
-
|
157
|
-
function msgHeader(str) {
|
158
|
-
pendingMessageHeader = str;
|
159
|
-
}
|
160
|
-
|
161
|
-
function debug() {
|
162
|
-
if ( env.opts.debug ) {
|
163
|
-
console.log.apply(console, arguments);
|
164
|
-
}
|
165
|
-
}
|
166
|
-
|
167
|
-
function info() {
|
168
|
-
if ( env.opts.verbose || env.opts.debug ) {
|
169
|
-
if ( pendingMessageHeader ) {
|
170
|
-
console.log("");
|
171
|
-
pendingMessageHeader = null;
|
172
|
-
}
|
173
|
-
console.log.apply(console, arguments);
|
174
|
-
}
|
175
|
-
}
|
176
|
-
|
177
|
-
function warning(msg) {
|
178
|
-
if ( pendingMessageHeader ) {
|
179
|
-
if ( !env.opts.verbose && !env.opts.debug ) {
|
180
|
-
console.log(pendingMessageHeader);
|
181
|
-
} else {
|
182
|
-
console.log("");
|
183
|
-
}
|
184
|
-
pendingMessageHeader = null;
|
185
|
-
}
|
186
|
-
var args = Array.prototype.slice.apply(arguments);
|
187
|
-
// args[0] = "**** warning: " + args[0]; // TODO: fix warnings. For the moment disable them
|
188
|
-
console.log.apply(console, args);
|
189
|
-
}
|
190
|
-
|
191
|
-
function error(msg) {
|
192
|
-
if ( pendingMessageHeader && !env.opts.verbose && !env.opts.debug ) {
|
193
|
-
if ( !env.opts.verbose && !env.opts.debug ) {
|
194
|
-
console.log(pendingMessageHeader);
|
195
|
-
} else {
|
196
|
-
console.log("");
|
197
|
-
}
|
198
|
-
pendingMessageHeader = null;
|
199
|
-
}
|
200
|
-
var args = Array.prototype.slice.apply(arguments);
|
201
|
-
args[0] = "**** error: " + args[0];
|
202
|
-
// console.log.apply(console, args); // TODO: fix warnings. For the moment disable them
|
203
|
-
}
|
204
|
-
|
205
|
-
//---- path handling ---------------------------------------------------------
|
206
|
-
|
207
|
-
function ensureEndingSlash(path) {
|
208
|
-
path = path || '';
|
209
|
-
return path && path.slice(-1) !== '/' ? path + '/' : path;
|
210
|
-
}
|
211
|
-
|
212
|
-
function getRelativePath(filename) {
|
213
|
-
var relative = path.resolve(filename);
|
214
|
-
for ( var i = 0; i < pathPrefixes.length; i++ ) {
|
215
|
-
if ( relative.indexOf(pathPrefixes[i]) === 0 ) {
|
216
|
-
relative = relative.slice(pathPrefixes[i].length);
|
217
|
-
break;
|
218
|
-
}
|
219
|
-
}
|
220
|
-
return relative.replace(/\\/g, '/');
|
221
|
-
}
|
222
|
-
|
223
|
-
function getResourceName(filename) {
|
224
|
-
var resource = path.resolve(filename);
|
225
|
-
for ( var i = 0; i < pathPrefixes.length; i++ ) {
|
226
|
-
if ( resource.indexOf(pathPrefixes[i]) === 0 ) {
|
227
|
-
resource = resourceNamePrefixes[i] + resource.slice(pathPrefixes[i].length);
|
228
|
-
break;
|
229
|
-
}
|
230
|
-
}
|
231
|
-
return resource.replace(/\\/g, '/');
|
232
|
-
}
|
233
|
-
|
234
|
-
function getModuleName(resource) {
|
235
|
-
return resource.replace(/\.js$/,'');
|
236
|
-
}
|
237
|
-
|
238
|
-
/*
|
239
|
-
* resolves relative AMD module identifiers relative to a given base name
|
240
|
-
*/
|
241
|
-
function resolveModuleName(base, name) {
|
242
|
-
var stack = base.split('/');
|
243
|
-
stack.pop();
|
244
|
-
name.split('/').forEach(function(segment, i) {
|
245
|
-
if ( segment == '..' ) {
|
246
|
-
stack.pop();
|
247
|
-
} else if ( segment === '.' ) {
|
248
|
-
// ignore
|
249
|
-
} else {
|
250
|
-
if ( i === 0 ) {
|
251
|
-
stack = [];
|
252
|
-
}
|
253
|
-
stack.push(segment);
|
254
|
-
}
|
255
|
-
});
|
256
|
-
return stack.join('/');
|
257
|
-
}
|
258
|
-
|
259
|
-
// ---- AMD handling
|
260
|
-
|
261
|
-
function analyzeModuleDefinition(node) {
|
262
|
-
var args = node.arguments;
|
263
|
-
var arg = 0;
|
264
|
-
if ( arg < args.length
|
265
|
-
&& args[arg].type === Syntax.Literal && typeof args[arg].value === 'string' ) {
|
266
|
-
warning("module explicitly defined a module name '" + args[arg].value + "'");
|
267
|
-
currentModule.name = args[arg].value;
|
268
|
-
arg++;
|
269
|
-
}
|
270
|
-
if ( arg < args.length && args[arg].type === Syntax.ArrayExpression ) {
|
271
|
-
currentModule.dependencies = convertValue(args[arg], "string[]");
|
272
|
-
arg++;
|
273
|
-
}
|
274
|
-
if ( arg < args.length && args[arg].type === Syntax.FunctionExpression ) {
|
275
|
-
currentModule.factory = args[arg];
|
276
|
-
arg++;
|
277
|
-
}
|
278
|
-
if ( currentModule.dependencies && currentModule.factory ) {
|
279
|
-
for ( var i = 0; i < currentModule.dependencies.length && i < currentModule.factory.params.length; i++ ) {
|
280
|
-
var name = currentModule.factory.params[i].name;
|
281
|
-
var module = resolveModuleName(currentModule.module, currentModule.dependencies[i]);
|
282
|
-
debug(" import " + name + " from '" + module + "'");
|
283
|
-
currentModule.localNames[name] = {
|
284
|
-
module: module
|
285
|
-
// no (or empty) path
|
286
|
-
};
|
287
|
-
}
|
288
|
-
}
|
289
|
-
if ( currentModule.factory ) {
|
290
|
-
collectShortcuts(currentModule.factory.body);
|
291
|
-
}
|
292
|
-
}
|
293
|
-
|
294
|
-
/**
|
295
|
-
* Searches the given body for variable declarations that can be evaluated statically,
|
296
|
-
* either because they refer to known AMD modukle imports (e.g. shortcut varialbes)
|
297
|
-
* or because they have a (design time) constant value.
|
298
|
-
*
|
299
|
-
* @param {ASTNode} body
|
300
|
-
*/
|
301
|
-
function collectShortcuts(body) {
|
302
|
-
|
303
|
-
function checkAssignment(name, valueNode) {
|
304
|
-
if ( valueNode.type === Syntax.Literal ) {
|
305
|
-
currentModule.localNames[name] = {
|
306
|
-
value: valueNode.value
|
307
|
-
};
|
308
|
-
debug("compile time constant found ", name, valueNode.value);
|
309
|
-
} else if ( valueNode.type === Syntax.MemberExpression ) {
|
310
|
-
var _import = getLeftmostName(valueNode);
|
311
|
-
var local = _import && currentModule.localNames[_import];
|
312
|
-
if ( typeof local === 'object' && local.module ) {
|
313
|
-
currentModule.localNames[name] = {
|
314
|
-
module: local.module,
|
315
|
-
path: getObjectName(valueNode).split('.').slice(1).join('.') // TODO chaining if local has path
|
316
|
-
};
|
317
|
-
debug(" found local shortcut: ", name, currentModule.localNames[name]);
|
318
|
-
}
|
319
|
-
} else if ( isRequireSyncCall(valueNode) || isProbingRequireCall(valueNode) ) {
|
320
|
-
if ( valueNode.arguments[0]
|
321
|
-
&& valueNode.arguments[0].type === Syntax.Literal
|
322
|
-
&& typeof valueNode.arguments[0].value === 'string' ) {
|
323
|
-
currentModule.localNames[name] = {
|
324
|
-
module: valueNode.arguments[0].value
|
325
|
-
// no (or empty) path
|
326
|
-
};
|
327
|
-
debug(" found local import: %s = %s('%s')", name, valueNode.callee.property.name, valueNode.arguments[0].value);
|
328
|
-
}
|
329
|
-
} else if ( isExtendCall(valueNode) ) {
|
330
|
-
currentModule.localNames[name] = {
|
331
|
-
class: valueNode.arguments[0].value
|
332
|
-
// no (or empty) path
|
333
|
-
};
|
334
|
-
debug(" found local class definition: %s = .extend('%s', ...)", name, valueNode.arguments[0].value);
|
335
|
-
}
|
336
|
-
}
|
337
|
-
|
338
|
-
if ( body.type === Syntax.BlockStatement ) {
|
339
|
-
body.body.forEach(function ( stmt ) {
|
340
|
-
// console.log(stmt);
|
341
|
-
if ( stmt.type === Syntax.VariableDeclaration ) {
|
342
|
-
stmt.declarations.forEach(function(decl) {
|
343
|
-
if ( decl.init ) {
|
344
|
-
checkAssignment(decl.id.name, decl.init);
|
345
|
-
}
|
346
|
-
})
|
347
|
-
} else if ( stmt.type === Syntax.ExpressionStatement
|
348
|
-
&& stmt.expression.type === Syntax.AssignmentExpression
|
349
|
-
&& stmt.expression.left.type === Syntax.Identifier ) {
|
350
|
-
checkAssignment(stmt.expression.left.name, stmt.expression.right);
|
351
|
-
}
|
352
|
-
});
|
353
|
-
}
|
354
|
-
}
|
355
|
-
|
356
|
-
// ---- text handling ---------------------------------------------------------
|
357
|
-
|
358
|
-
var rPlural = /(children|ies|ves|oes|ses|ches|shes|xes|s)$/i;
|
359
|
-
var mSingular = {'children' : -3, 'ies' : 'y', 'ves' : 'f', 'oes' : -2, 'ses' : -2, 'ches' : -2, 'shes' : -2, 'xes' : -2, 's' : -1 };
|
360
|
-
|
361
|
-
function guessSingularName(sPluralName) {
|
362
|
-
return sPluralName.replace(rPlural, function($,sPlural) {
|
363
|
-
var vRepl = mSingular[sPlural.toLowerCase()];
|
364
|
-
return typeof vRepl === "string" ? vRepl : sPlural.slice(0,vRepl);
|
365
|
-
});
|
366
|
-
}
|
367
|
-
|
368
|
-
/**
|
369
|
-
* Creates a map of property values from an AST 'object literal' node.
|
370
|
-
*
|
371
|
-
* The values in the map are again AST 'property' nodes (representing key/value pairs).
|
372
|
-
* It would be more convenient to just return the values, but the property node is needed
|
373
|
-
* to find the corresponding (preceding) documentation comment.
|
374
|
-
*
|
375
|
-
* @param node
|
376
|
-
* @param defaultKey
|
377
|
-
* @returns {Map<string,Property>}
|
378
|
-
*/
|
379
|
-
function createPropertyMap(node, defaultKey) {
|
380
|
-
|
381
|
-
var result;
|
382
|
-
|
383
|
-
if ( node != null ) {
|
384
|
-
|
385
|
-
// if, instead of an object literal only a literal is given and there is a defaultKey, then wrap the literal in a map
|
386
|
-
if ( node.type === Syntax.Literal && defaultKey != null ) {
|
387
|
-
result = {};
|
388
|
-
result[defaultKey] = { type: Syntax.Property, value: node };
|
389
|
-
return result;
|
390
|
-
}
|
391
|
-
|
392
|
-
if ( node.type != Syntax.ObjectExpression ) {
|
393
|
-
// something went wrong, it's not an object literal
|
394
|
-
error("not an object literal:" + node.type + ":" + node.value);
|
395
|
-
// console.log(node.toSource());
|
396
|
-
return undefined;
|
397
|
-
}
|
398
|
-
|
399
|
-
// invariant: node.type == Syntax.ObjectExpression
|
400
|
-
result = {};
|
401
|
-
for (var i = 0; i < node.properties.length; i++) {
|
402
|
-
var prop = node.properties[i];
|
403
|
-
var name;
|
404
|
-
//console.log("objectproperty " + prop.type);
|
405
|
-
if ( prop.key.type === Syntax.Identifier ) {
|
406
|
-
name = prop.key.name;
|
407
|
-
} else if ( prop.key.type === Syntax.Literal ) {
|
408
|
-
name = String(prop.key.value);
|
409
|
-
} else {
|
410
|
-
name = prop.key.toSource();
|
411
|
-
}
|
412
|
-
//console.log("objectproperty " + prop.type + ":" + name);
|
413
|
-
result[name] = prop;
|
414
|
-
}
|
415
|
-
}
|
416
|
-
return result;
|
417
|
-
}
|
418
|
-
|
419
|
-
function isExtendCall(node) {
|
420
|
-
|
421
|
-
return (
|
422
|
-
node
|
423
|
-
&& node.type === Syntax.CallExpression
|
424
|
-
&& node.callee.type === Syntax.MemberExpression
|
425
|
-
&& node.callee.property.type === Syntax.Identifier
|
426
|
-
&& node.callee.property.name === 'extend'
|
427
|
-
&& node.arguments.length >= 2
|
428
|
-
&& node.arguments[0].type === Syntax.Literal
|
429
|
-
&& typeof node.arguments[0].value === "string"
|
430
|
-
&& node.arguments[1].type === Syntax.ObjectExpression
|
431
|
-
);
|
432
|
-
|
433
|
-
}
|
434
|
-
|
435
|
-
function isSapUiDefineCall(node) {
|
436
|
-
|
437
|
-
return (
|
438
|
-
node
|
439
|
-
&& node.type === Syntax.CallExpression
|
440
|
-
&& node.callee.type === Syntax.MemberExpression
|
441
|
-
&& node.callee.object.type === Syntax.MemberExpression
|
442
|
-
&& node.callee.object.object.type === Syntax.Identifier
|
443
|
-
&& node.callee.object.object.name === 'sap'
|
444
|
-
&& node.callee.object.property.type === Syntax.Identifier
|
445
|
-
&& node.callee.object.property.name === 'ui'
|
446
|
-
&& node.callee.property.type === Syntax.Identifier
|
447
|
-
&& node.callee.property.name === 'define'
|
448
|
-
);
|
449
|
-
|
450
|
-
}
|
451
|
-
|
452
|
-
function isCreateDataTypeCall(node) {
|
453
|
-
return (
|
454
|
-
node
|
455
|
-
&& node.type === Syntax.CallExpression
|
456
|
-
&& node.callee.type === Syntax.MemberExpression
|
457
|
-
&& /^(sap\.ui\.base\.)?DataType$/.test(getObjectName(node.callee.object))
|
458
|
-
&& node.callee.property.type === Syntax.Identifier
|
459
|
-
&& node.callee.property.name === 'createType'
|
460
|
-
);
|
461
|
-
}
|
462
|
-
|
463
|
-
function isRequireSyncCall(node) {
|
464
|
-
return (
|
465
|
-
node
|
466
|
-
&& node.type === Syntax.CallExpression
|
467
|
-
&& node.callee.type === Syntax.MemberExpression
|
468
|
-
&& node.callee.object.type === Syntax.MemberExpression
|
469
|
-
&& node.callee.object.object.type === Syntax.Identifier
|
470
|
-
&& node.callee.object.object.name === 'sap'
|
471
|
-
&& node.callee.object.property.type === Syntax.Identifier
|
472
|
-
&& node.callee.object.property.name === 'ui'
|
473
|
-
&& node.callee.property.type === Syntax.Identifier
|
474
|
-
&& node.callee.property.name === 'requireSync'
|
475
|
-
);
|
476
|
-
}
|
477
|
-
|
478
|
-
function isProbingRequireCall(node) {
|
479
|
-
return (
|
480
|
-
node
|
481
|
-
&& node.type === Syntax.CallExpression
|
482
|
-
&& node.callee.type === Syntax.MemberExpression
|
483
|
-
&& node.callee.object.type === Syntax.MemberExpression
|
484
|
-
&& node.callee.object.object.type === Syntax.Identifier
|
485
|
-
&& node.callee.object.object.name === 'sap'
|
486
|
-
&& node.callee.object.property.type === Syntax.Identifier
|
487
|
-
&& node.callee.object.property.name === 'ui'
|
488
|
-
&& node.callee.property.type === Syntax.Identifier
|
489
|
-
&& node.callee.property.name === 'require'
|
490
|
-
&& node.arguments.length === 1
|
491
|
-
&& node.arguments[0].type === Syntax.Literal
|
492
|
-
&& typeof node.arguments[0].value === 'string' // TODO generalize to statically analyzable constants
|
493
|
-
);
|
494
|
-
}
|
495
|
-
|
496
|
-
function getObjectName(node) {
|
497
|
-
if ( node.type === Syntax.MemberExpression && !node.computed && node.property.type === Syntax.Identifier ) {
|
498
|
-
var prefix = getObjectName(node.object);
|
499
|
-
return prefix ? prefix + "." + node.property.name : null;
|
500
|
-
} else if ( node.type === Syntax.Identifier ) {
|
501
|
-
return /* scope[node.name] ? scope[node.name] : */ node.name;
|
502
|
-
} else {
|
503
|
-
return null;
|
504
|
-
}
|
505
|
-
}
|
506
|
-
|
507
|
-
/*
|
508
|
-
* Checks whether the node is a qualified name (a.b.c) and if so,
|
509
|
-
* returns the leftmost identifier a
|
510
|
-
*/
|
511
|
-
function getLeftmostName(node) {
|
512
|
-
while ( node.type === Syntax.MemberExpression ) {
|
513
|
-
node = node.object;
|
514
|
-
}
|
515
|
-
if ( node.type === Syntax.Identifier ) {
|
516
|
-
return node.name;
|
517
|
-
}
|
518
|
-
// return undefined;
|
519
|
-
}
|
520
|
-
|
521
|
-
function getResolvedObjectName(node) {
|
522
|
-
var name = getObjectName(node);
|
523
|
-
var _import = getLeftmostName(node);
|
524
|
-
var local = _import && currentModule.localNames[_import];
|
525
|
-
if ( local && (local.class || local.module) ) {
|
526
|
-
var resolvedName;
|
527
|
-
if ( local.class ) {
|
528
|
-
resolvedName = local.class;
|
529
|
-
} else {
|
530
|
-
resolvedName = local.module.replace(/\//g, ".").replace(/\.library$/, "");
|
531
|
-
if ( local.path ) {
|
532
|
-
resolvedName = resolvedName + "." + local.path;
|
533
|
-
}
|
534
|
-
}
|
535
|
-
if ( name.indexOf('.') > 0 ) {
|
536
|
-
resolvedName = resolvedName + name.slice(name.indexOf('.'));
|
537
|
-
}
|
538
|
-
debug("resolved " + name + " to " + resolvedName);
|
539
|
-
return resolvedName;
|
540
|
-
}
|
541
|
-
return name;
|
542
|
-
}
|
543
|
-
|
544
|
-
function convertValue(node, type, propertyName) {
|
545
|
-
|
546
|
-
var value;
|
547
|
-
|
548
|
-
if ( node.type === Syntax.Literal ) {
|
549
|
-
|
550
|
-
// 'string' or number or true or false
|
551
|
-
return node.value;
|
552
|
-
|
553
|
-
} else if ( node.type === Syntax.UnaryExpression
|
554
|
-
&& node.prefix
|
555
|
-
&& node.argument.type === Syntax.Literal
|
556
|
-
&& typeof node.argument.value === 'number'
|
557
|
-
&& ( node.operator === '-' || node.operator === '+' )) {
|
558
|
-
|
559
|
-
// -n or +n
|
560
|
-
value = node.argument.value;
|
561
|
-
return node.operator === '-' ? -value : value;
|
562
|
-
|
563
|
-
} else if ( node.type === Syntax.MemberExpression && type ) {
|
564
|
-
|
565
|
-
// enum value (a.b.c)
|
566
|
-
value = getResolvedObjectName(node);
|
567
|
-
if ( value.indexOf(type + ".") === 0 ) {
|
568
|
-
// starts with fully qualified enum name -> cut off name
|
569
|
-
return value.slice(type.length + 1);
|
570
|
-
// } else if ( value.indexOf(type.split(".").slice(-1)[0] + ".") === 0 ) {
|
571
|
-
// // unqualified name might be a local name (just a guess - would need static code analysis for proper solution)
|
572
|
-
// return value.slice(type.split(".").slice(-1)[0].length + 1);
|
573
|
-
} else {
|
574
|
-
warning("did not understand default value '%s'%s, falling back to source", value, propertyName ? " of property '" + propertyName + "'" : "");
|
575
|
-
return value;
|
576
|
-
}
|
577
|
-
|
578
|
-
} else if ( node.type === Syntax.Identifier ) {
|
579
|
-
if ( node.name === 'undefined') {
|
580
|
-
// undefined
|
581
|
-
return undefined;
|
582
|
-
}
|
583
|
-
var local = currentModule.localNames[node.name];
|
584
|
-
if ( typeof local === 'object' && 'value' in local ) {
|
585
|
-
// TODO check type
|
586
|
-
return local.value;
|
587
|
-
}
|
588
|
-
} else if ( node.type === Syntax.ArrayExpression ) {
|
589
|
-
|
590
|
-
if ( node.elements.length === 0 ) {
|
591
|
-
// empty array literal
|
592
|
-
return "[]"; // TODO return this string or an empty array
|
593
|
-
}
|
594
|
-
|
595
|
-
if ( type && type.slice(-2) === "[]" ) {
|
596
|
-
var componentType = type.slice(0,-2);
|
597
|
-
return node.elements.map( function(elem) {
|
598
|
-
return convertValue(elem, componentType, propertyName);
|
599
|
-
});
|
600
|
-
}
|
601
|
-
|
602
|
-
} else if ( node.type === Syntax.ObjectExpression ) {
|
603
|
-
|
604
|
-
if ( node.properties.length === 0 && (type === 'object' || type === 'any') ) {
|
605
|
-
return {};
|
606
|
-
}
|
607
|
-
|
608
|
-
}
|
609
|
-
|
610
|
-
value = '???';
|
611
|
-
if ( currentSource && node.range ) {
|
612
|
-
value = currentSource.slice( node.range[0], node.range[1] );
|
613
|
-
}
|
614
|
-
error("unexpected type of default value (type='%s', source='%s')%s, falling back to '%s'", node.type, node.toString(), propertyName ? " of property '" + propertyName + "'" : "", value);
|
615
|
-
return value;
|
616
|
-
}
|
617
|
-
|
618
|
-
function convertStringArray(node) {
|
619
|
-
if ( node.type !== Syntax.ArrayExpression ) {
|
620
|
-
throw new Error("not an array");
|
621
|
-
}
|
622
|
-
var result = [];
|
623
|
-
for ( var i = 0; i < node.elements.length; i++ ) {
|
624
|
-
if ( node.elements[i].type !== Syntax.Literal || typeof node.elements[i].value !== 'string' ) {
|
625
|
-
throw new Error("not a string literal");
|
626
|
-
}
|
627
|
-
result.push(node.elements[i].value);
|
628
|
-
}
|
629
|
-
// console.log(result);
|
630
|
-
return result;
|
631
|
-
}
|
632
|
-
|
633
|
-
function convertDragDropValue(node, cardinality) {
|
634
|
-
var mDragDropValue;
|
635
|
-
var mDefaults = { draggable : false, droppable: false };
|
636
|
-
|
637
|
-
if ( node.type === Syntax.ObjectExpression ) {
|
638
|
-
mDragDropValue = (node.properties || []).reduce(function(oObject, oProperty) {
|
639
|
-
var sKey = convertValue(oProperty.key);
|
640
|
-
if (mDefaults.hasOwnProperty(sKey)) {
|
641
|
-
oObject[sKey] = convertValue(oProperty.value);
|
642
|
-
}
|
643
|
-
return oObject;
|
644
|
-
}, {});
|
645
|
-
} else if ( node.type === Syntax.Literal ) {
|
646
|
-
mDragDropValue = {
|
647
|
-
draggable : node.value,
|
648
|
-
droppable : node.value
|
649
|
-
};
|
650
|
-
} else {
|
651
|
-
throw new Error("not a valid dnd node");
|
652
|
-
}
|
653
|
-
|
654
|
-
return Object.assign(mDefaults, mDragDropValue);
|
655
|
-
}
|
656
|
-
|
657
|
-
function collectClassInfo(extendCall, classDoclet) {
|
658
|
-
|
659
|
-
var baseType;
|
660
|
-
if ( classDoclet && classDoclet.augments && classDoclet.augments.length === 1 ) {
|
661
|
-
baseType = classDoclet.augments[0];
|
662
|
-
}
|
663
|
-
if ( extendCall.callee.type === Syntax.MemberExpression ) {
|
664
|
-
var baseCandidate = getResolvedObjectName(extendCall.callee.object);
|
665
|
-
if ( baseCandidate && baseType == null ) {
|
666
|
-
baseType = baseCandidate;
|
667
|
-
} else if ( baseCandidate !== baseType ) {
|
668
|
-
error("documented base type '" + baseType + "' doesn't match technical base type '" + baseCandidate + "'");
|
669
|
-
}
|
670
|
-
}
|
671
|
-
|
672
|
-
var oClassInfo = {
|
673
|
-
name : extendCall.arguments[0].value,
|
674
|
-
baseType : baseType,
|
675
|
-
interfaces : [],
|
676
|
-
doc : classDoclet && classDoclet.description,
|
677
|
-
deprecation : classDoclet && classDoclet.deprecated,
|
678
|
-
since : classDoclet && classDoclet.since,
|
679
|
-
experimental : classDoclet && classDoclet.experimental,
|
680
|
-
specialSettings : {},
|
681
|
-
properties : {},
|
682
|
-
aggregations : {},
|
683
|
-
associations : {},
|
684
|
-
events : {},
|
685
|
-
methods : {},
|
686
|
-
annotations : {},
|
687
|
-
designtime: false
|
688
|
-
};
|
689
|
-
|
690
|
-
function upper(n) {
|
691
|
-
return n.slice(0,1).toUpperCase() + n.slice(1);
|
692
|
-
}
|
693
|
-
|
694
|
-
function each(node, defaultKey, callback) {
|
695
|
-
var map,n,settings,doclet;
|
696
|
-
|
697
|
-
map = node && createPropertyMap(node.value);
|
698
|
-
if ( map ) {
|
699
|
-
for (n in map ) {
|
700
|
-
if ( map.hasOwnProperty(n) ) {
|
701
|
-
doclet = getLeadingDoclet(map[n]);
|
702
|
-
settings = createPropertyMap(map[n].value, defaultKey);
|
703
|
-
if ( settings == null ) {
|
704
|
-
error("no valid metadata for " + n + " (AST type '" + map[n].value.type + "')");
|
705
|
-
continue;
|
706
|
-
}
|
707
|
-
|
708
|
-
callback(n, settings, doclet, map[n]);
|
709
|
-
}
|
710
|
-
}
|
711
|
-
}
|
712
|
-
}
|
713
|
-
|
714
|
-
var classInfoNode = extendCall.arguments[1];
|
715
|
-
var classInfoMap = createPropertyMap(classInfoNode);
|
716
|
-
if ( classInfoMap && classInfoMap.metadata && classInfoMap.metadata.value.type !== Syntax.ObjectExpression ) {
|
717
|
-
warning("class metadata exists but can't be analyzed. It is not of type 'ObjectExpression', but a '" + classInfoMap.metadata.value.type + "'.");
|
718
|
-
return null;
|
719
|
-
}
|
720
|
-
|
721
|
-
var metadata = classInfoMap && classInfoMap.metadata && createPropertyMap(classInfoMap.metadata.value);
|
722
|
-
if ( metadata ) {
|
723
|
-
|
724
|
-
debug(" analyzing metadata for '" + oClassInfo.name + "'");
|
725
|
-
|
726
|
-
oClassInfo["abstract"] = !!(metadata["abstract"] && metadata["abstract"].value.value);
|
727
|
-
oClassInfo["final"] = !!(metadata["final"] && metadata["final"].value.value);
|
728
|
-
oClassInfo.dnd = metadata.dnd && convertDragDropValue(metadata.dnd.value);
|
729
|
-
|
730
|
-
if ( metadata.interfaces ) {
|
731
|
-
oClassInfo.interfaces = convertStringArray(metadata.interfaces.value);
|
732
|
-
}
|
733
|
-
|
734
|
-
each(metadata.specialSettings, "type", function(n, settings, doclet) {
|
735
|
-
oClassInfo.specialSettings[n] = {
|
736
|
-
name : n,
|
737
|
-
doc : doclet && doclet.description,
|
738
|
-
since : doclet && doclet.since,
|
739
|
-
deprecation : doclet && doclet.deprecated,
|
740
|
-
experimental : doclet && doclet.experimental,
|
741
|
-
visibility : (settings.visibility && settings.visibility.value.value) || "public",
|
742
|
-
type : settings.type ? settings.type.value.value : "any"
|
743
|
-
};
|
744
|
-
});
|
745
|
-
|
746
|
-
oClassInfo.defaultProperty = (metadata.defaultProperty && metadata.defaultProperty.value.value) || undefined;
|
747
|
-
|
748
|
-
each(metadata.properties, "type", function(n, settings, doclet) {
|
749
|
-
var type;
|
750
|
-
var N = upper(n);
|
751
|
-
var methods;
|
752
|
-
oClassInfo.properties[n] = {
|
753
|
-
name : n,
|
754
|
-
doc : doclet && doclet.description,
|
755
|
-
since : doclet && doclet.since,
|
756
|
-
deprecation : doclet && doclet.deprecated,
|
757
|
-
experimental : doclet && doclet.experimental,
|
758
|
-
readonly : doclet && doclet.readonly,
|
759
|
-
visibility : (settings.visibility && settings.visibility.value.value) || "public",
|
760
|
-
type : (type = settings.type ? settings.type.value.value : "string"),
|
761
|
-
defaultValue : settings.defaultValue ? convertValue(settings.defaultValue.value, type, n) : null,
|
762
|
-
group : settings.group ? settings.group.value.value : 'Misc',
|
763
|
-
bindable : settings.bindable ? !!convertValue(settings.bindable.value) : false,
|
764
|
-
methods: (methods = {
|
765
|
-
"get": "get" + N,
|
766
|
-
"set": "set" + N
|
767
|
-
})
|
768
|
-
};
|
769
|
-
if ( oClassInfo.properties[n].bindable ) {
|
770
|
-
methods["bind"] = "bind" + N;
|
771
|
-
methods["unbind"] = "unbind" + N;
|
772
|
-
}
|
773
|
-
// if ( !settings.defaultValue ) {
|
774
|
-
// console.log("property without defaultValue: " + oClassInfo.name + "." + n);
|
775
|
-
//}
|
776
|
-
if ( oClassInfo.properties[n].visibility !== 'public' ) {
|
777
|
-
error("Property '" + n + "' uses visibility '" + oClassInfo.properties[n].visibility + "' which is not supported by the runtime");
|
778
|
-
}
|
779
|
-
});
|
780
|
-
|
781
|
-
oClassInfo.defaultAggregation = (metadata.defaultAggregation && metadata.defaultAggregation.value.value) || undefined;
|
782
|
-
|
783
|
-
each(metadata.aggregations, "type", function(n, settings, doclet) {
|
784
|
-
var N = upper(n);
|
785
|
-
var methods;
|
786
|
-
var aggr = oClassInfo.aggregations[n] = {
|
787
|
-
name: n,
|
788
|
-
doc : doclet && doclet.description,
|
789
|
-
deprecation : doclet && doclet.deprecated,
|
790
|
-
since : doclet && doclet.since,
|
791
|
-
experimental : doclet && doclet.experimental,
|
792
|
-
visibility : (settings.visibility && settings.visibility.value.value) || "public",
|
793
|
-
type : settings.type ? settings.type.value.value : "sap.ui.core.Control",
|
794
|
-
altTypes: settings.altTypes ? convertStringArray(settings.altTypes.value) : undefined,
|
795
|
-
singularName : settings.singularName ? settings.singularName.value.value : guessSingularName(n),
|
796
|
-
cardinality : (settings.multiple && !settings.multiple.value.value) ? "0..1" : "0..n",
|
797
|
-
bindable : settings.bindable ? !!convertValue(settings.bindable.value) : false,
|
798
|
-
methods: (methods = {
|
799
|
-
"get": "get" + N,
|
800
|
-
"destroy": "destroy" + N
|
801
|
-
})
|
802
|
-
};
|
803
|
-
|
804
|
-
aggr.dnd = settings.dnd && convertDragDropValue(settings.dnd.value, aggr.cardinality);
|
805
|
-
|
806
|
-
if ( aggr.cardinality === "0..1" ) {
|
807
|
-
methods["set"] = "set" + N;
|
808
|
-
} else {
|
809
|
-
var N1 = upper(aggr.singularName);
|
810
|
-
methods["insert"] = "insert" + N1;
|
811
|
-
methods["add"] = "add" + N1;
|
812
|
-
methods["remove"] = "remove" + N1;
|
813
|
-
methods["indexOf"] = "indexOf" + N1;
|
814
|
-
methods["removeAll"] = "removeAll" + N;
|
815
|
-
}
|
816
|
-
if ( aggr.bindable ) {
|
817
|
-
methods["bind"] = "bind" + N;
|
818
|
-
methods["unbind"] = "unbind" + N;
|
819
|
-
}
|
820
|
-
});
|
821
|
-
|
822
|
-
each(metadata.associations, "type", function(n, settings, doclet) {
|
823
|
-
var N = upper(n);
|
824
|
-
var methods;
|
825
|
-
oClassInfo.associations[n] = {
|
826
|
-
name: n,
|
827
|
-
doc : doclet && doclet.description,
|
828
|
-
deprecation : doclet && doclet.deprecated,
|
829
|
-
since : doclet && doclet.since,
|
830
|
-
experimental : doclet && doclet.experimental,
|
831
|
-
visibility : (settings.visibility && settings.visibility.value.value) || "public",
|
832
|
-
type : settings.type ? settings.type.value.value : "sap.ui.core.Control",
|
833
|
-
singularName : settings.singularName ? settings.singularName.value.value : guessSingularName(n),
|
834
|
-
cardinality : (settings.multiple && settings.multiple.value.value) ? "0..n" : "0..1",
|
835
|
-
methods: (methods = {
|
836
|
-
"get": "get" + N
|
837
|
-
})
|
838
|
-
};
|
839
|
-
if ( oClassInfo.associations[n].cardinality === "0..1" ) {
|
840
|
-
methods["set"] = "set" + N;
|
841
|
-
} else {
|
842
|
-
var N1 = upper(oClassInfo.associations[n].singularName);
|
843
|
-
methods["add"] = "add" + N1;
|
844
|
-
methods["remove"] = "remove" + N1;
|
845
|
-
methods["removeAll"] = "removeAll" + N;
|
846
|
-
}
|
847
|
-
if ( oClassInfo.associations[n].visibility !== 'public' ) {
|
848
|
-
error("Association '" + n + "' uses visibility '" + oClassInfo.associations[n].visibility + "' which is not supported by the runtime");
|
849
|
-
}
|
850
|
-
});
|
851
|
-
|
852
|
-
each(metadata.events, null, function(n, settings, doclet) {
|
853
|
-
var N = upper(n);
|
854
|
-
var info = oClassInfo.events[n] = {
|
855
|
-
name: n,
|
856
|
-
doc : doclet && doclet.description,
|
857
|
-
deprecation : doclet && doclet.deprecated,
|
858
|
-
since : doclet && doclet.since,
|
859
|
-
experimental : doclet && doclet.experimental,
|
860
|
-
visibility : /* (settings.visibility && settings.visibility.value.value) || */ "public",
|
861
|
-
allowPreventDefault : !!(settings.allowPreventDefault && settings.allowPreventDefault.value.value),
|
862
|
-
parameters : {},
|
863
|
-
methods: {
|
864
|
-
"attach": "attach" + N,
|
865
|
-
"detach": "detach" + N,
|
866
|
-
"fire": "fire" + N
|
867
|
-
}
|
868
|
-
};
|
869
|
-
each(settings.parameters, "type", function(pName, pSettings, pDoclet) {
|
870
|
-
info.parameters[pName] = {
|
871
|
-
name : pName,
|
872
|
-
doc : pDoclet && pDoclet.description,
|
873
|
-
deprecation : pDoclet && pDoclet.deprecated,
|
874
|
-
since : pDoclet && pDoclet.since,
|
875
|
-
experimental : pDoclet && pDoclet.experimental,
|
876
|
-
type : pSettings && pSettings.type ? pSettings.type.value.value : ""
|
877
|
-
};
|
878
|
-
});
|
879
|
-
});
|
880
|
-
|
881
|
-
var designtime = (metadata.designtime && convertValue(metadata.designtime.value)) || (metadata.designTime && convertValue(metadata.designTime.value));
|
882
|
-
if ( typeof designtime === 'string' || typeof designtime === 'boolean' ) {
|
883
|
-
oClassInfo.designtime = designtime;
|
884
|
-
}
|
885
|
-
// console.log(oClassInfo.name + ":" + JSON.stringify(oClassInfo, null, " "));
|
886
|
-
}
|
887
|
-
|
888
|
-
// remember class info by name
|
889
|
-
classInfos[oClassInfo.name] = oClassInfo;
|
890
|
-
|
891
|
-
return oClassInfo;
|
892
|
-
}
|
893
|
-
|
894
|
-
function collectDesigntimeInfo(dtNode) {
|
895
|
-
|
896
|
-
function each(node, defaultKey, callback) {
|
897
|
-
var map,n,settings,doclet;
|
898
|
-
|
899
|
-
map = node && createPropertyMap(node.value);
|
900
|
-
if ( map ) {
|
901
|
-
for (n in map ) {
|
902
|
-
if ( map.hasOwnProperty(n) ) {
|
903
|
-
doclet = getLeadingDoclet(map[n], true);
|
904
|
-
settings = createPropertyMap(map[n].value, defaultKey);
|
905
|
-
if ( settings == null ) {
|
906
|
-
error("no valid metadata for " + n + " (AST type '" + map[n].value.type + "')");
|
907
|
-
continue;
|
908
|
-
}
|
909
|
-
|
910
|
-
callback(n, settings, doclet, map[n]);
|
911
|
-
}
|
912
|
-
}
|
913
|
-
}
|
914
|
-
}
|
915
|
-
|
916
|
-
var oDesigntimeInfo;
|
917
|
-
|
918
|
-
var map = createPropertyMap(dtNode.argument);
|
919
|
-
|
920
|
-
if (map.annotations) {
|
921
|
-
|
922
|
-
oDesigntimeInfo = {
|
923
|
-
annotations: {}
|
924
|
-
};
|
925
|
-
|
926
|
-
each(map.annotations, null, function(n, settings, doclet) {
|
927
|
-
var appliesTo = [],
|
928
|
-
targets = [],
|
929
|
-
i, oAnno, iPos;
|
930
|
-
|
931
|
-
if (settings.appliesTo) {
|
932
|
-
for (i = 0; i < settings.appliesTo.value.elements.length; i++) {
|
933
|
-
appliesTo.push(settings.appliesTo.value.elements[i].value);
|
934
|
-
}
|
935
|
-
}
|
936
|
-
|
937
|
-
if (settings.target) {
|
938
|
-
for (i = 0; i < settings.target.value.elements.length; i++) {
|
939
|
-
targets.push(settings.target.value.elements[i].value);
|
940
|
-
}
|
941
|
-
}
|
942
|
-
|
943
|
-
oDesigntimeInfo.annotations[n] = {
|
944
|
-
name: n,
|
945
|
-
doc : doclet && doclet.description,
|
946
|
-
deprecation : doclet && doclet.deprecated,
|
947
|
-
since : doclet && doclet.since || settings.since && settings.since.value.value,
|
948
|
-
namespace: settings.namespace && settings.namespace.value.value,
|
949
|
-
annotation: settings.annotation && settings.annotation.value.value,
|
950
|
-
appliesTo: appliesTo,
|
951
|
-
target: targets,
|
952
|
-
interpretation: settings.interpretation && settings.interpretation.value.value,
|
953
|
-
defaultValue: settings.defaultValue && settings.defaultValue.value.value
|
954
|
-
};
|
955
|
-
|
956
|
-
oAnno = oDesigntimeInfo.annotations[n].annotation;
|
957
|
-
iPos = oAnno && oAnno.lastIndexOf(".");
|
958
|
-
|
959
|
-
if ( !oDesigntimeInfo.annotations[n].namespace && iPos > 0 ) {
|
960
|
-
oDesigntimeInfo.annotations[n].namespace = oAnno.slice(0, iPos);
|
961
|
-
oDesigntimeInfo.annotations[n].annotation = oAnno.slice(iPos + 1);
|
962
|
-
}
|
963
|
-
})
|
964
|
-
}
|
965
|
-
|
966
|
-
return oDesigntimeInfo;
|
967
|
-
}
|
968
|
-
|
969
|
-
function determineValueRangeBorder(range, expression, varname, inverse) {
|
970
|
-
if ( expression.type === Syntax.BinaryExpression ) {
|
971
|
-
var value;
|
972
|
-
if ( expression.left.type === Syntax.Identifier && expression.left.name === varname && expression.right.type === Syntax.Literal ) {
|
973
|
-
value = expression.right.value;
|
974
|
-
} else if ( expression.left.type === Syntax.Literal && expression.right.type === Syntax.Identifier && expression.right.name === varname ) {
|
975
|
-
inverse = !inverse;
|
976
|
-
value = expression.left.value;
|
977
|
-
} else {
|
978
|
-
return false;
|
979
|
-
}
|
980
|
-
switch (expression.operator) {
|
981
|
-
case '<':
|
982
|
-
range[inverse ? 'minExclusive' : 'maxExclusive'] = value;
|
983
|
-
break;
|
984
|
-
case '<=':
|
985
|
-
range[inverse ? 'minInclusive' : 'maxInclusive'] = value;
|
986
|
-
break;
|
987
|
-
case '>=':
|
988
|
-
range[inverse ? 'maxInclusive' : 'minInclusive'] = value;
|
989
|
-
break;
|
990
|
-
case '>':
|
991
|
-
range[inverse ? 'maxExclusive' : 'minExclusive'] = value;
|
992
|
-
break;
|
993
|
-
default:
|
994
|
-
return false;
|
995
|
-
}
|
996
|
-
return true;
|
997
|
-
}
|
998
|
-
return false;
|
999
|
-
}
|
1000
|
-
|
1001
|
-
function determineValueRange(expression, varname, inverse) {
|
1002
|
-
var range = {};
|
1003
|
-
if ( expression.type === Syntax.LogicalExpression
|
1004
|
-
&& expression.operator === '&&'
|
1005
|
-
&& expression.left.type === Syntax.BinaryExpression
|
1006
|
-
&& expression.right.type === Syntax.BinaryExpression
|
1007
|
-
&& determineValueRangeBorder(range, expression.left, varname, inverse)
|
1008
|
-
&& determineValueRangeBorder(range, expression.right, varname, inverse) ) {
|
1009
|
-
return range;
|
1010
|
-
} else if ( expression.type === Syntax.BinaryExpression
|
1011
|
-
&& determineValueRangeBorder(range, expression, varname, inverse) ) {
|
1012
|
-
return range;
|
1013
|
-
}
|
1014
|
-
return undefined;
|
1015
|
-
}
|
1016
|
-
|
1017
|
-
function collectDataTypeInfo(extendCall, classDoclet) {
|
1018
|
-
var args = extendCall.arguments,
|
1019
|
-
i = 0,
|
1020
|
-
name, def, base, pattern, range;
|
1021
|
-
|
1022
|
-
if ( i < args.length && args[i].type === Syntax.Literal && typeof args[i].value === 'string' ) {
|
1023
|
-
name = args[i++].value;
|
1024
|
-
}
|
1025
|
-
if ( i < args.length && args[i].type === Syntax.ObjectExpression ) {
|
1026
|
-
def = createPropertyMap(args[i++]);
|
1027
|
-
}
|
1028
|
-
if ( i < args.length ) {
|
1029
|
-
if ( args[i].type === Syntax.Literal && typeof args[i].value === 'string' ) {
|
1030
|
-
base = args[i++].value;
|
1031
|
-
} else if ( args[i].type === Syntax.CallExpression
|
1032
|
-
&& args[i].callee.type === Syntax.MemberExpression
|
1033
|
-
&& /^(sap\.ui\.base\.)?DataType$/.test(getObjectName(args[i].callee.object))
|
1034
|
-
&& args[i].callee.property.type === Syntax.Identifier
|
1035
|
-
&& args[i].callee.property.name === 'getType'
|
1036
|
-
&& args[i].arguments.length === 1
|
1037
|
-
&& args[i].arguments[0].type === Syntax.Literal
|
1038
|
-
&& typeof args[i].arguments[0].value === 'string' ) {
|
1039
|
-
base = args[i++].arguments[0].value;
|
1040
|
-
} else {
|
1041
|
-
error("could not identify base type of data type '" + name + "'");
|
1042
|
-
}
|
1043
|
-
} else {
|
1044
|
-
base = "any";
|
1045
|
-
}
|
1046
|
-
|
1047
|
-
if ( def
|
1048
|
-
&& def.isValid
|
1049
|
-
&& def.isValid.value.type === Syntax.FunctionExpression
|
1050
|
-
&& def.isValid.value.params.length === 1
|
1051
|
-
&& def.isValid.value.params[0].type === Syntax.Identifier
|
1052
|
-
&& def.isValid.value.body.body.length === 1 ) {
|
1053
|
-
var varname = def.isValid.value.params[0].name;
|
1054
|
-
var stmt = def.isValid.value.body.body[0];
|
1055
|
-
if ( stmt.type === Syntax.ReturnStatement && stmt.argument ) {
|
1056
|
-
if ( stmt.argument.type === Syntax.CallExpression
|
1057
|
-
&& stmt.argument.callee.type === Syntax.MemberExpression
|
1058
|
-
&& stmt.argument.callee.object.type === Syntax.Literal
|
1059
|
-
&& stmt.argument.callee.object.regex
|
1060
|
-
&& stmt.argument.callee.property.type === Syntax.Identifier
|
1061
|
-
&& stmt.argument.callee.property.name === 'test' ) {
|
1062
|
-
pattern = stmt.argument.callee.object.regex.pattern;
|
1063
|
-
// console.log(pattern);
|
1064
|
-
} else {
|
1065
|
-
range = determineValueRange(stmt.argument, varname, false);
|
1066
|
-
}
|
1067
|
-
} else if ( stmt.type === Syntax.IfStatement
|
1068
|
-
&& stmt.consequent.type === Syntax.BlockStatement
|
1069
|
-
&& stmt.consequent.body.length === 1
|
1070
|
-
&& stmt.consequent.body[0].type === Syntax.ReturnStatement
|
1071
|
-
&& stmt.consequent.body[0].argument
|
1072
|
-
&& stmt.consequent.body[0].argument.type === Syntax.Literal
|
1073
|
-
&& typeof stmt.consequent.body[0].argument.value === 'boolean'
|
1074
|
-
&& stmt.alternate.type === Syntax.BlockStatement
|
1075
|
-
&& stmt.alternate.body.length === 1
|
1076
|
-
&& stmt.alternate.body[0].type === Syntax.ReturnStatement
|
1077
|
-
&& stmt.alternate.body[0].argument
|
1078
|
-
&& stmt.alternate.body[0].argument.type === Syntax.Literal
|
1079
|
-
&& typeof stmt.alternate.body[0].argument.value === 'boolean'
|
1080
|
-
&& stmt.consequent.body[0].argument.value !== typeof stmt.alternate.body[0].argument.value ) {
|
1081
|
-
var inverse = stmt.alternate.body[0].argument.value;
|
1082
|
-
range = determineValueRange(stmt.test, varname, inverse);
|
1083
|
-
} else {
|
1084
|
-
console.log(stmt);
|
1085
|
-
}
|
1086
|
-
}
|
1087
|
-
|
1088
|
-
// remember type info by name
|
1089
|
-
if ( name && def && base ) {
|
1090
|
-
typeInfos[name] = {
|
1091
|
-
name: name,
|
1092
|
-
def: def,
|
1093
|
-
pattern: pattern,
|
1094
|
-
range: range,
|
1095
|
-
base: base
|
1096
|
-
};
|
1097
|
-
// console.log("found data type:", typeInfos[name]);
|
1098
|
-
}
|
1099
|
-
}
|
1100
|
-
|
1101
|
-
var rEmptyLine = /^\s*$/;
|
1102
|
-
|
1103
|
-
function createAutoDoc(oClassInfo, classComment, node, parser, filename, commentAlreadyProcessed) {
|
1104
|
-
|
1105
|
-
var newStyle = !!pluginConfig.newStyle,
|
1106
|
-
includeSettings = !!pluginConfig.includeSettingsInConstructor,
|
1107
|
-
rawClassComment = getRawComment(classComment),
|
1108
|
-
p,n,n1,pName,info,lines,link;
|
1109
|
-
|
1110
|
-
function isEmpty(obj) {
|
1111
|
-
if ( !obj ) {
|
1112
|
-
return true;
|
1113
|
-
}
|
1114
|
-
for (var n in obj) {
|
1115
|
-
if ( obj.hasOwnProperty(n) ) {
|
1116
|
-
return false;
|
1117
|
-
}
|
1118
|
-
}
|
1119
|
-
return true;
|
1120
|
-
}
|
1121
|
-
|
1122
|
-
function jsdocCommentFound(comment) {
|
1123
|
-
parser.emit('jsdocCommentFound', {
|
1124
|
-
event:'jsdocCommentFound',
|
1125
|
-
comment : comment,
|
1126
|
-
lineno : node.loc.start.line,
|
1127
|
-
filename : filename,
|
1128
|
-
range : [ node.range[0], node.range[0] ]
|
1129
|
-
}, parser);
|
1130
|
-
}
|
1131
|
-
|
1132
|
-
function removeDuplicateEmptyLines(lines) {
|
1133
|
-
var lastWasEmpty = false,
|
1134
|
-
i,j,l,line;
|
1135
|
-
|
1136
|
-
for (i = 0, j = 0, l = lines.length; i < l; i++) {
|
1137
|
-
line = lines[i];
|
1138
|
-
if ( line == null || rEmptyLine.test(line) ) {
|
1139
|
-
if ( !lastWasEmpty ) {
|
1140
|
-
lines[j++] = line;
|
1141
|
-
}
|
1142
|
-
lastWasEmpty = true;
|
1143
|
-
} else {
|
1144
|
-
lines[j++] = line;
|
1145
|
-
lastWasEmpty = false;
|
1146
|
-
}
|
1147
|
-
}
|
1148
|
-
return j < i ? lines.slice(0,j) : lines;
|
1149
|
-
}
|
1150
|
-
|
1151
|
-
function newJSDoc(lines) {
|
1152
|
-
//console.log("add completely new jsdoc comment to prog " + node.type + ":" + node.nodeId + ":" + Object.keys(node));
|
1153
|
-
|
1154
|
-
lines = removeDuplicateEmptyLines(lines);
|
1155
|
-
lines.push("@synthetic");
|
1156
|
-
|
1157
|
-
var comment = " * " + lines.join("\r\n * ");
|
1158
|
-
jsdocCommentFound("/**\r\n" + comment + "\r\n */")
|
1159
|
-
|
1160
|
-
var m = /@name\s+([^\r\n\t ]+)/.exec(comment);
|
1161
|
-
debug(" creating synthetic comment '" + (m && m[1]) + "'");
|
1162
|
-
}
|
1163
|
-
|
1164
|
-
function rname(prefix,n,_static) {
|
1165
|
-
return (_static ? "." : "#") + prefix + n.slice(0,1).toUpperCase() + n.slice(1);
|
1166
|
-
}
|
1167
|
-
|
1168
|
-
function name(prefix,n,_static) {
|
1169
|
-
return oClassInfo.name + rname(prefix,n,_static);
|
1170
|
-
}
|
1171
|
-
|
1172
|
-
/*
|
1173
|
-
* creates a JSDoc type string from the given metadata info object.
|
1174
|
-
* It takes into account the type, the altTypes and the cardinality
|
1175
|
-
* (the latter only if componentTypeOnly is not set).
|
1176
|
-
*/
|
1177
|
-
function makeTypeString(aggr, componentTypeOnly) {
|
1178
|
-
var s = aggr.type;
|
1179
|
-
if ( aggr.altTypes ) {
|
1180
|
-
s = s + "|" + aggr.altTypes.join("|");
|
1181
|
-
}
|
1182
|
-
if ( !componentTypeOnly && aggr.cardinality === "0..n" ) {
|
1183
|
-
// if multiple types are allowed, use Array.<> for proper grouping
|
1184
|
-
if ( aggr.altTypes ) {
|
1185
|
-
s = "Array.<" + s + ">";
|
1186
|
-
} else {
|
1187
|
-
s = s + "[]";
|
1188
|
-
}
|
1189
|
-
}
|
1190
|
-
return s;
|
1191
|
-
}
|
1192
|
-
|
1193
|
-
// function shortname(s) {
|
1194
|
-
// return s.slice(s.lastIndexOf('.') + 1);
|
1195
|
-
// }
|
1196
|
-
|
1197
|
-
var HUNGARIAN_PREFIXES = {
|
1198
|
-
'int' : 'i',
|
1199
|
-
'boolean' : 'b',
|
1200
|
-
'float' : 'f',
|
1201
|
-
'string' : 's',
|
1202
|
-
'function' : 'fn',
|
1203
|
-
'object' : 'o',
|
1204
|
-
'regexp' : 'r',
|
1205
|
-
'jQuery' : '$',
|
1206
|
-
'any' : 'o',
|
1207
|
-
'variant' : 'v',
|
1208
|
-
'map' : 'm'
|
1209
|
-
};
|
1210
|
-
|
1211
|
-
function varname(n, type, property) {
|
1212
|
-
var prefix = HUNGARIAN_PREFIXES[type] || (property ? "s" : "o");
|
1213
|
-
return prefix + n.slice(0,1).toUpperCase() + n.slice(1);
|
1214
|
-
}
|
1215
|
-
|
1216
|
-
// add a list of the possible settings if and only if
|
1217
|
-
// - documentation for the constructor exists
|
1218
|
-
// - no (generated) documentation for settings exists already
|
1219
|
-
// - a suitable place for inserting the settings can be found
|
1220
|
-
var m = /(?:^|\r\n|\n|\r)[ \t]*\**[ \t]*@[a-zA-Z]/.exec(rawClassComment);
|
1221
|
-
p = m ? m.index : -1;
|
1222
|
-
var hasSettingsDocs = rawClassComment.indexOf("The supported settings are:") >= 0;
|
1223
|
-
|
1224
|
-
// heuristic to recognize a ManagedObject
|
1225
|
-
var isManagedObject = (
|
1226
|
-
/@extends\s+sap\.ui\.(?:base\.ManagedObject|core\.(?:Element|Control|Component))(?:\s|$)/.test(rawClassComment)
|
1227
|
-
|| oClassInfo.library
|
1228
|
-
|| !isEmpty(oClassInfo.specialSettings)
|
1229
|
-
|| !isEmpty(oClassInfo.properties)
|
1230
|
-
|| !isEmpty(oClassInfo.aggregations)
|
1231
|
-
|| !isEmpty(oClassInfo.associations)
|
1232
|
-
|| !isEmpty(oClassInfo.events)
|
1233
|
-
);
|
1234
|
-
|
1235
|
-
if ( p >= 0 && !hasSettingsDocs ) {
|
1236
|
-
lines = [
|
1237
|
-
""
|
1238
|
-
];
|
1239
|
-
|
1240
|
-
if ( isManagedObject ) { // only a ManagedObject has settings
|
1241
|
-
|
1242
|
-
if ( oClassInfo.name !== "sap.ui.base.ManagedObject" ) {
|
1243
|
-
// add the hint for the general description only when the current class is not ManagedObject itself
|
1244
|
-
lines.push(
|
1245
|
-
"",
|
1246
|
-
"Accepts an object literal <code>mSettings</code> that defines initial",
|
1247
|
-
"property values, aggregated and associated objects as well as event handlers.",
|
1248
|
-
"See {@link sap.ui.base.ManagedObject#constructor} for a general description of the syntax of the settings object."
|
1249
|
-
);
|
1250
|
-
}
|
1251
|
-
|
1252
|
-
// add the settings section only if there are any settings
|
1253
|
-
if ( !isEmpty(oClassInfo.properties)
|
1254
|
-
|| !isEmpty(oClassInfo.aggregations)
|
1255
|
-
|| !isEmpty(oClassInfo.associations)
|
1256
|
-
|| !isEmpty(oClassInfo.events) ) {
|
1257
|
-
|
1258
|
-
lines.push(
|
1259
|
-
"",
|
1260
|
-
includeSettings ? "" : "@ui5-settings",
|
1261
|
-
"The supported settings are:",
|
1262
|
-
"<ul>"
|
1263
|
-
);
|
1264
|
-
if ( !isEmpty(oClassInfo.properties) ) {
|
1265
|
-
lines.push("<li>Properties");
|
1266
|
-
lines.push("<ul>");
|
1267
|
-
for (n in oClassInfo.properties) {
|
1268
|
-
lines.push("<li>{@link " + rname("get", n) + " " + n + "} : " + oClassInfo.properties[n].type + (oClassInfo.properties[n].defaultValue !== null ? " (default: " + oClassInfo.properties[n].defaultValue + ")" : "") + (oClassInfo.defaultProperty == n ? " (default)" : "") + "</li>");
|
1269
|
-
}
|
1270
|
-
lines.push("</ul>");
|
1271
|
-
lines.push("</li>");
|
1272
|
-
}
|
1273
|
-
if ( !isEmpty(oClassInfo.aggregations) ) {
|
1274
|
-
lines.push("<li>Aggregations");
|
1275
|
-
lines.push("<ul>");
|
1276
|
-
for (n in oClassInfo.aggregations) {
|
1277
|
-
if ( oClassInfo.aggregations[n].visibility !== "hidden" ) {
|
1278
|
-
lines.push("<li>{@link " + rname("get", n) + " " + n + "} : " + makeTypeString(oClassInfo.aggregations[n]) + (oClassInfo.defaultAggregation == n ? " (default)" : "") + "</li>");
|
1279
|
-
}
|
1280
|
-
}
|
1281
|
-
lines.push("</ul>");
|
1282
|
-
lines.push("</li>");
|
1283
|
-
}
|
1284
|
-
if ( !isEmpty(oClassInfo.associations) ) {
|
1285
|
-
lines.push("<li>Associations");
|
1286
|
-
lines.push("<ul>");
|
1287
|
-
for (n in oClassInfo.associations) {
|
1288
|
-
lines.push("<li>{@link " + rname("get", n) + " " + n + "} : (sap.ui.core.ID | " + oClassInfo.associations[n].type + ")" + (oClassInfo.associations[n].cardinality === "0..n" ? "[]" : "") + "</li>");
|
1289
|
-
}
|
1290
|
-
lines.push("</ul>");
|
1291
|
-
lines.push("</li>");
|
1292
|
-
}
|
1293
|
-
if ( !isEmpty(oClassInfo.events) ) {
|
1294
|
-
lines.push("<li>Events");
|
1295
|
-
lines.push("<ul>");
|
1296
|
-
for (n in oClassInfo.events) {
|
1297
|
-
lines.push("<li>{@link " + "#event:" + n + " " + n + "} : fnListenerFunction or [fnListenerFunction, oListenerObject] or [oData, fnListenerFunction, oListenerObject]</li>");
|
1298
|
-
}
|
1299
|
-
lines.push("</ul>");
|
1300
|
-
lines.push("</li>");
|
1301
|
-
}
|
1302
|
-
lines.push("</ul>");
|
1303
|
-
|
1304
|
-
// add the reference to the base class only if this is not ManagedObject and if the base class is known
|
1305
|
-
if ( oClassInfo.name !== "sap.ui.base.ManagedObject" && oClassInfo.baseType ) {
|
1306
|
-
lines.push(
|
1307
|
-
"",
|
1308
|
-
"In addition, all settings applicable to the base type {@link " + oClassInfo.baseType + "#constructor " + oClassInfo.baseType + "}",
|
1309
|
-
"can be used as well."
|
1310
|
-
);
|
1311
|
-
}
|
1312
|
-
lines.push("");
|
1313
|
-
|
1314
|
-
} else if ( oClassInfo.name !== "sap.ui.base.ManagedObject" && oClassInfo.baseType && oClassInfo.hasOwnProperty("abstract") ) {
|
1315
|
-
|
1316
|
-
// if a class has no settings, but metadata, point at least to the base class - if it makes sense
|
1317
|
-
lines.push(
|
1318
|
-
"",
|
1319
|
-
newStyle && !includeSettings ? "@ui5-settings" : "",
|
1320
|
-
"This class does not have its own settings, but all settings applicable to the base type",
|
1321
|
-
"{@link " + oClassInfo.baseType + "#constructor " + oClassInfo.baseType + "} can be used."
|
1322
|
-
);
|
1323
|
-
|
1324
|
-
}
|
1325
|
-
}
|
1326
|
-
|
1327
|
-
debug(" enhancing constructor documentation with settings");
|
1328
|
-
var enhancedComment =
|
1329
|
-
rawClassComment.slice(0,p) +
|
1330
|
-
"\n * " + removeDuplicateEmptyLines(lines).join("\n * ") +
|
1331
|
-
(commentAlreadyProcessed ? "@ui5-updated-doclet\n * " : "") +
|
1332
|
-
rawClassComment.slice(p);
|
1333
|
-
enhancedComment = preprocessComment({ comment : enhancedComment, lineno : classComment.lineno });
|
1334
|
-
|
1335
|
-
if ( commentAlreadyProcessed ) {
|
1336
|
-
jsdocCommentFound(enhancedComment);
|
1337
|
-
} else {
|
1338
|
-
setRawComment(classComment, enhancedComment);
|
1339
|
-
}
|
1340
|
-
|
1341
|
-
}
|
1342
|
-
|
1343
|
-
newJSDoc([
|
1344
|
-
"Returns a metadata object for class " + oClassInfo.name + ".",
|
1345
|
-
"",
|
1346
|
-
"@returns {sap.ui.base.Metadata} Metadata object describing this class",
|
1347
|
-
"@public",
|
1348
|
-
"@static",
|
1349
|
-
"@name " + name("getMetadata", "", true),
|
1350
|
-
"@function"
|
1351
|
-
]);
|
1352
|
-
|
1353
|
-
if ( !oClassInfo["final"] ) {
|
1354
|
-
newJSDoc([
|
1355
|
-
"Creates a new subclass of class " + oClassInfo.name + " with name <code>sClassName</code>",
|
1356
|
-
"and enriches it with the information contained in <code>oClassInfo</code>.",
|
1357
|
-
"",
|
1358
|
-
"<code>oClassInfo</code> might contain the same kind of information as described in {@link " + (oClassInfo.baseType ? oClassInfo.baseType + ".extend" : "sap.ui.base.Object.extend Object.extend") + "}.",
|
1359
|
-
"",
|
1360
|
-
"@param {string} sClassName Name of the class being created",
|
1361
|
-
"@param {object} [oClassInfo] Object literal with information about the class",
|
1362
|
-
"@param {function} [FNMetaImpl] Constructor function for the metadata object; if not given, it defaults to <code>sap.ui.core.ElementMetadata</code>",
|
1363
|
-
"@returns {function} Created class / constructor function",
|
1364
|
-
"@public",
|
1365
|
-
"@static",
|
1366
|
-
"@name " + name("extend", "", true),
|
1367
|
-
"@function"
|
1368
|
-
]);
|
1369
|
-
}
|
1370
|
-
|
1371
|
-
for (n in oClassInfo.properties ) {
|
1372
|
-
info = oClassInfo.properties[n];
|
1373
|
-
if ( info.visibility === 'hidden' ) {
|
1374
|
-
continue;
|
1375
|
-
}
|
1376
|
-
// link = newStyle ? "{@link #setting:" + n + " " + n + "}" : "<code>" + n + "</code>";
|
1377
|
-
link = "{@link " + (newStyle ? "#setting:" + n : rname("get", n)) + " " + n + "}";
|
1378
|
-
newJSDoc([
|
1379
|
-
"Gets current value of property " + link + ".",
|
1380
|
-
"",
|
1381
|
-
!newStyle && info.doc ? info.doc : "",
|
1382
|
-
"",
|
1383
|
-
info.defaultValue !== null ? "Default value is <code>" + (info.defaultValue === "" ? "empty string" : info.defaultValue) + "</code>." : "",
|
1384
|
-
"@returns {" + info.type + "} Value of property <code>" + n + "</code>",
|
1385
|
-
info.since ? "@since " + info.since : "",
|
1386
|
-
info.deprecation ? "@deprecated " + info.deprecation : "",
|
1387
|
-
info.experimental ? "@experimental " + info.experimental : "",
|
1388
|
-
"@public",
|
1389
|
-
"@name " + name("get",n),
|
1390
|
-
"@function"
|
1391
|
-
]);
|
1392
|
-
newJSDoc([
|
1393
|
-
"Sets a new value for property " + link + ".",
|
1394
|
-
"",
|
1395
|
-
!newStyle && info.doc ? info.doc : "",
|
1396
|
-
"",
|
1397
|
-
"When called with a value of <code>null</code> or <code>undefined</code>, the default value of the property will be restored.",
|
1398
|
-
"",
|
1399
|
-
info.defaultValue !== null ? "Default value is <code>" + (info.defaultValue === "" ? "empty string" : info.defaultValue) + "</code>." : "",
|
1400
|
-
"@param {" + info.type + "} " + varname(n,info.type,true) + " New value for property <code>" + n + "</code>",
|
1401
|
-
"@returns {" + oClassInfo.name + "} Reference to <code>this</code> in order to allow method chaining",
|
1402
|
-
info.since ? "@since " + info.since : "",
|
1403
|
-
info.deprecation ? "@deprecated " + info.deprecation : "",
|
1404
|
-
info.experimental ? "@experimental " + info.experimental : "",
|
1405
|
-
"@public",
|
1406
|
-
"@name " + name("set",n),
|
1407
|
-
"@function"
|
1408
|
-
]);
|
1409
|
-
if ( info.bindable ) {
|
1410
|
-
newJSDoc([
|
1411
|
-
"Binds property " + link + " to model data.",
|
1412
|
-
"",
|
1413
|
-
"See {@link sap.ui.base.ManagedObject#bindProperty ManagedObject.bindProperty} for a ",
|
1414
|
-
"detailed description of the possible properties of <code>oBindingInfo</code>",
|
1415
|
-
"@param {object} oBindingInfo The binding information",
|
1416
|
-
"@returns {" + oClassInfo.name + "} Reference to <code>this</code> in order to allow method chaining",
|
1417
|
-
info.since ? "@since " + info.since : "",
|
1418
|
-
info.deprecation ? "@deprecated " + info.deprecation : "",
|
1419
|
-
info.experimental ? "@experimental " + info.experimental : "",
|
1420
|
-
"@public",
|
1421
|
-
"@name " + name("bind",n),
|
1422
|
-
"@function"
|
1423
|
-
]);
|
1424
|
-
newJSDoc([
|
1425
|
-
"Unbinds property " + link + " from model data.",
|
1426
|
-
"@returns {" + oClassInfo.name + "} Reference to <code>this</code> in order to allow method chaining",
|
1427
|
-
info.since ? "@since " + info.since : "",
|
1428
|
-
info.deprecation ? "@deprecated " + info.deprecation : "",
|
1429
|
-
info.experimental ? "@experimental " + info.experimental : "",
|
1430
|
-
"@public",
|
1431
|
-
"@name " + name("unbind",n),
|
1432
|
-
"@function"
|
1433
|
-
]);
|
1434
|
-
}
|
1435
|
-
}
|
1436
|
-
|
1437
|
-
for (n in oClassInfo.aggregations ) {
|
1438
|
-
info = oClassInfo.aggregations[n];
|
1439
|
-
if ( info.visibility === 'hidden' ) {
|
1440
|
-
continue;
|
1441
|
-
}
|
1442
|
-
// link = newStyle ? "{@link #setting:" + n + " " + n + "}" : "<code>" + n + "</code>";
|
1443
|
-
link = "{@link " + (newStyle ? "#setting:" + n : rname("get", n)) + " " + n + "}";
|
1444
|
-
newJSDoc([
|
1445
|
-
"Gets content of aggregation " + link + ".",
|
1446
|
-
"",
|
1447
|
-
!newStyle && info.doc ? info.doc : "",
|
1448
|
-
"",
|
1449
|
-
n === info.defaultAggregation ? "<strong>Note</strong>: this is the default aggregation for " + n + "." : "",
|
1450
|
-
"@returns {" + makeTypeString(info) + "}",
|
1451
|
-
info.since ? "@since " + info.since : "",
|
1452
|
-
info.deprecation ? "@deprecated " + info.deprecation : "",
|
1453
|
-
info.experimental ? "@experimental " + info.experimental : "",
|
1454
|
-
"@public",
|
1455
|
-
"@name " + name("get",n),
|
1456
|
-
"@function"
|
1457
|
-
]);
|
1458
|
-
if ( info.cardinality == "0..n" ) {
|
1459
|
-
n1 = info.singularName;
|
1460
|
-
newJSDoc([
|
1461
|
-
"Inserts a " + n1 + " into the aggregation " + link + ".",
|
1462
|
-
"",
|
1463
|
-
"@param {" + makeTypeString(info, true) + "}",
|
1464
|
-
" " + varname(n1,info.altTypes ? "variant" : info.type) + " The " + n1 + " to insert; if empty, nothing is inserted",
|
1465
|
-
"@param {int}",
|
1466
|
-
" iIndex The <code>0</code>-based index the " + n1 + " should be inserted at; for",
|
1467
|
-
" a negative value of <code>iIndex</code>, the " + n1 + " is inserted at position 0; for a value",
|
1468
|
-
" greater than the current size of the aggregation, the " + n1 + " is inserted at",
|
1469
|
-
" the last position",
|
1470
|
-
"@returns {" + oClassInfo.name + "} Reference to <code>this</code> in order to allow method chaining",
|
1471
|
-
info.since ? "@since " + info.since : "",
|
1472
|
-
info.deprecation ? "@deprecated " + info.deprecation : "",
|
1473
|
-
info.experimental ? "@experimental " + info.experimental : "",
|
1474
|
-
"@public",
|
1475
|
-
"@name " + name("insert",n1),
|
1476
|
-
"@function"
|
1477
|
-
]);
|
1478
|
-
newJSDoc([
|
1479
|
-
"Adds some " + n1 + " to the aggregation " + link + ".",
|
1480
|
-
|
1481
|
-
"@param {" + makeTypeString(info, true) + "}",
|
1482
|
-
" " + varname(n1,info.altTypes ? "variant" : info.type) + " The " + n1 + " to add; if empty, nothing is inserted",
|
1483
|
-
"@returns {" + oClassInfo.name + "} Reference to <code>this</code> in order to allow method chaining",
|
1484
|
-
info.since ? "@since " + info.since : "",
|
1485
|
-
info.deprecation ? "@deprecated " + info.deprecation : "",
|
1486
|
-
info.experimental ? "@experimental " + info.experimental : "",
|
1487
|
-
"@public",
|
1488
|
-
"@name " + name("add",n1),
|
1489
|
-
"@function"
|
1490
|
-
]);
|
1491
|
-
newJSDoc([
|
1492
|
-
"Removes a " + n1 + " from the aggregation " + link + ".",
|
1493
|
-
"",
|
1494
|
-
"@param {int | string | " + makeTypeString(info, true) + "} " + varname(n1,"variant") + " The " + n1 + " to remove or its index or id",
|
1495
|
-
"@returns {" + makeTypeString(info, true) + "} The removed " + n1 + " or <code>null</code>",
|
1496
|
-
info.since ? "@since " + info.since : "",
|
1497
|
-
info.deprecation ? "@deprecated " + info.deprecation : "",
|
1498
|
-
info.experimental ? "@experimental " + info.experimental : "",
|
1499
|
-
"@public",
|
1500
|
-
"@name " + name("remove", n1),
|
1501
|
-
"@function"
|
1502
|
-
]);
|
1503
|
-
newJSDoc([
|
1504
|
-
"Removes all the controls from the aggregation " + link + ".",
|
1505
|
-
"",
|
1506
|
-
"Additionally, it unregisters them from the hosting UIArea.",
|
1507
|
-
"@returns {" + makeTypeString(info) + "} An array of the removed elements (might be empty)",
|
1508
|
-
info.since ? "@since " + info.since : "",
|
1509
|
-
info.deprecation ? "@deprecated " + info.deprecation : "",
|
1510
|
-
info.experimental ? "@experimental " + info.experimental : "",
|
1511
|
-
"@public",
|
1512
|
-
"@name " + name("removeAll", n),
|
1513
|
-
"@function"
|
1514
|
-
]);
|
1515
|
-
newJSDoc([
|
1516
|
-
"Checks for the provided <code>" + info.type + "</code> in the aggregation " + link + ".",
|
1517
|
-
"and returns its index if found or -1 otherwise.",
|
1518
|
-
"@param {" + makeTypeString(info, true) + "}",
|
1519
|
-
" " + varname(n1, info.altTypes ? "variant" : info.type) + " The " + n1 + " whose index is looked for",
|
1520
|
-
"@returns {int} The index of the provided control in the aggregation if found, or -1 otherwise",
|
1521
|
-
info.since ? "@since " + info.since : "",
|
1522
|
-
info.deprecation ? "@deprecated " + info.deprecation : "",
|
1523
|
-
info.experimental ? "@experimental " + info.experimental : "",
|
1524
|
-
"@public",
|
1525
|
-
"@name " + name("indexOf", n1),
|
1526
|
-
"@function"
|
1527
|
-
]);
|
1528
|
-
} else {
|
1529
|
-
newJSDoc([
|
1530
|
-
"Sets the aggregated " + link + ".",
|
1531
|
-
"@param {" + makeTypeString(info) + "} " + varname(n, info.altTypes ? "variant" : info.type) + " The " + n + " to set",
|
1532
|
-
"@returns {" + oClassInfo.name + "} Reference to <code>this</code> in order to allow method chaining",
|
1533
|
-
info.since ? "@since " + info.since : "",
|
1534
|
-
info.deprecation ? "@deprecated " + info.deprecation : "",
|
1535
|
-
info.experimental ? "@experimental " + info.experimental : "",
|
1536
|
-
"@public",
|
1537
|
-
"@name " + name("set", n),
|
1538
|
-
"@function"
|
1539
|
-
]);
|
1540
|
-
}
|
1541
|
-
newJSDoc([
|
1542
|
-
"Destroys " + (info.cardinality === "0..n" ? "all " : "") + "the " + n + " in the aggregation " + link + ".",
|
1543
|
-
"@returns {" + oClassInfo.name + "} Reference to <code>this</code> in order to allow method chaining",
|
1544
|
-
info.since ? "@since " + info.since : "",
|
1545
|
-
info.deprecation ? "@deprecated " + info.deprecation : "",
|
1546
|
-
info.experimental ? "@experimental " + info.experimental : "",
|
1547
|
-
"@public",
|
1548
|
-
"@name " + name("destroy", n),
|
1549
|
-
"@function"
|
1550
|
-
]);
|
1551
|
-
if ( info.bindable ) {
|
1552
|
-
newJSDoc([
|
1553
|
-
"Binds aggregation " + link + " to model data.",
|
1554
|
-
"",
|
1555
|
-
"See {@link sap.ui.base.ManagedObject#bindAggregation ManagedObject.bindAggregation} for a ",
|
1556
|
-
"detailed description of the possible properties of <code>oBindingInfo</code>.",
|
1557
|
-
"@param {object} oBindingInfo The binding information",
|
1558
|
-
"@returns {" + oClassInfo.name + "} Reference to <code>this</code> in order to allow method chaining",
|
1559
|
-
info.since ? "@since " + info.since : "",
|
1560
|
-
info.deprecation ? "@deprecated " + info.deprecation : "",
|
1561
|
-
info.experimental ? "@experimental " + info.experimental : "",
|
1562
|
-
"@public",
|
1563
|
-
"@name " + name("bind",n),
|
1564
|
-
"@function"
|
1565
|
-
]);
|
1566
|
-
newJSDoc([
|
1567
|
-
"Unbinds aggregation " + link + " from model data.",
|
1568
|
-
"@returns {" + oClassInfo.name + "} Reference to <code>this</code> in order to allow method chaining",
|
1569
|
-
info.since ? "@since " + info.since : "",
|
1570
|
-
info.deprecation ? "@deprecated " + info.deprecation : "",
|
1571
|
-
info.experimental ? "@experimental " + info.experimental : "",
|
1572
|
-
"@public",
|
1573
|
-
"@name " + name("unbind",n),
|
1574
|
-
"@function"
|
1575
|
-
]);
|
1576
|
-
}
|
1577
|
-
}
|
1578
|
-
|
1579
|
-
for (n in oClassInfo.associations ) {
|
1580
|
-
info = oClassInfo.associations[n];
|
1581
|
-
if ( info.visibility === 'hidden' ) {
|
1582
|
-
continue;
|
1583
|
-
}
|
1584
|
-
// link = newStyle ? "{@link #setting:" + n + " " + n + "}" : "<code>" + n + "</code>";
|
1585
|
-
link = "{@link " + (newStyle ? "#setting:" + n : rname("get", n)) + " " + n + "}";
|
1586
|
-
newJSDoc([
|
1587
|
-
info.cardinality === "0..n" ?
|
1588
|
-
"Returns array of IDs of the elements which are the current targets of the association " + link + "." :
|
1589
|
-
"ID of the element which is the current target of the association " + link + ", or <code>null</code>.",
|
1590
|
-
"",
|
1591
|
-
newStyle && info.doc ? info.doc : "",
|
1592
|
-
"",
|
1593
|
-
"@returns {sap.ui.core.ID" + (info.cardinality === "0..n" ? "[]" : "") + "}",
|
1594
|
-
info.since ? "@since " + info.since : "",
|
1595
|
-
info.deprecation ? "@deprecated " + info.deprecation : "",
|
1596
|
-
info.experimental ? "@experimental " + info.experimental : "",
|
1597
|
-
"@public",
|
1598
|
-
"@name " + name("get",n),
|
1599
|
-
"@function"
|
1600
|
-
]);
|
1601
|
-
if ( info.cardinality === "0..n" ) {
|
1602
|
-
n1 = info.singularName;
|
1603
|
-
newJSDoc([
|
1604
|
-
"Adds some " + n1 + " into the association " + link + ".",
|
1605
|
-
"",
|
1606
|
-
"@param {sap.ui.core.ID | " + info.type + "} " + varname(n1, "variant") + " The " + n + " to add; if empty, nothing is inserted",
|
1607
|
-
"@returns {" + oClassInfo.name + "} Reference to <code>this</code> in order to allow method chaining",
|
1608
|
-
info.since ? "@since " + info.since : "",
|
1609
|
-
info.deprecation ? "@deprecated " + info.deprecation : "",
|
1610
|
-
info.experimental ? "@experimental " + info.experimental : "",
|
1611
|
-
"@public",
|
1612
|
-
"@name " + name("add",n1),
|
1613
|
-
"@function"
|
1614
|
-
]);
|
1615
|
-
newJSDoc([
|
1616
|
-
"Removes an " + n1 + " from the association named " + link + ".",
|
1617
|
-
"@param {int | sap.ui.core.ID | " + info.type + "} " + varname(n1,"variant") + " The " + n1 + " to be removed or its index or ID",
|
1618
|
-
"@returns {sap.ui.core.ID} The removed " + n1 + " or <code>null</code>",
|
1619
|
-
info.since ? "@since " + info.since : "",
|
1620
|
-
info.deprecation ? "@deprecated " + info.deprecation : "",
|
1621
|
-
info.experimental ? "@experimental " + info.experimental : "",
|
1622
|
-
"@public",
|
1623
|
-
"@name " + name("remove", n1),
|
1624
|
-
"@function"
|
1625
|
-
]);
|
1626
|
-
newJSDoc([
|
1627
|
-
"Removes all the controls in the association named " + link + ".",
|
1628
|
-
"@returns {sap.ui.core.ID[]} An array of the removed elements (might be empty)",
|
1629
|
-
info.since ? "@since " + info.since : "",
|
1630
|
-
info.deprecation ? "@deprecated " + info.deprecation : "",
|
1631
|
-
info.experimental ? "@experimental " + info.experimental : "",
|
1632
|
-
"@public",
|
1633
|
-
"@name " + name("removeAll", n),
|
1634
|
-
"@function"
|
1635
|
-
]);
|
1636
|
-
} else {
|
1637
|
-
newJSDoc([
|
1638
|
-
"Sets the associated " + link + ".",
|
1639
|
-
"@param {sap.ui.core.ID | " + info.type + "} " + varname(n, info.type) + " ID of an element which becomes the new target of this " + n + " association; alternatively, an element instance may be given",
|
1640
|
-
"@returns {" + oClassInfo.name + "} Reference to <code>this</code> in order to allow method chaining",
|
1641
|
-
info.since ? "@since " + info.since : "",
|
1642
|
-
info.deprecation ? "@deprecated " + info.deprecation : "",
|
1643
|
-
info.experimental ? "@experimental " + info.experimental : "",
|
1644
|
-
"@public",
|
1645
|
-
"@name " + name("set", n),
|
1646
|
-
"@function"
|
1647
|
-
]);
|
1648
|
-
}
|
1649
|
-
}
|
1650
|
-
|
1651
|
-
for (n in oClassInfo.events ) {
|
1652
|
-
info = oClassInfo.events[n];
|
1653
|
-
//link = newStyle ? "{@link #event:" + n + " " + n + "}" : "<code>" + n + "</code>";
|
1654
|
-
link = "{@link #event:" + n + " " + n + "}";
|
1655
|
-
|
1656
|
-
lines = [
|
1657
|
-
info.doc ? info.doc : "",
|
1658
|
-
"",
|
1659
|
-
"@name " + oClassInfo.name + "#" + n,
|
1660
|
-
"@event",
|
1661
|
-
info.since ? "@since " + info.since : "",
|
1662
|
-
info.deprecation ? "@deprecated " + info.deprecation : "",
|
1663
|
-
info.experimental ? "@experimental " + info.experimental : "",
|
1664
|
-
"@param {sap.ui.base.Event} oControlEvent",
|
1665
|
-
"@param {sap.ui.base.EventProvider} oControlEvent.getSource",
|
1666
|
-
"@param {object} oControlEvent.getParameters"
|
1667
|
-
];
|
1668
|
-
for (pName in info.parameters ) {
|
1669
|
-
lines.push(
|
1670
|
-
"@param {" + (info.parameters[pName].type || "") + "} oControlEvent.getParameters." + pName + " " + (info.parameters[pName].doc || "")
|
1671
|
-
);
|
1672
|
-
}
|
1673
|
-
lines.push("@public");
|
1674
|
-
newJSDoc(lines);
|
1675
|
-
|
1676
|
-
newJSDoc([
|
1677
|
-
"Attaches event handler <code>fnFunction</code> to the " + link + " event of this <code>" + oClassInfo.name + "</code>.",
|
1678
|
-
"",
|
1679
|
-
"When called, the context of the event handler (its <code>this</code>) will be bound to <code>oListener</code> if specified, ",
|
1680
|
-
"otherwise it will be bound to this <code>" + oClassInfo.name + "</code> itself.",
|
1681
|
-
"",
|
1682
|
-
!newStyle && info.doc ? info.doc : "",
|
1683
|
-
"",
|
1684
|
-
"@param {object}",
|
1685
|
-
" [oData] An application-specific payload object that will be passed to the event handler along with the event object when firing the event",
|
1686
|
-
"@param {function}",
|
1687
|
-
" fnFunction The function to be called when the event occurs",
|
1688
|
-
"@param {object}",
|
1689
|
-
" [oListener] Context object to call the event handler with. Defaults to this <code>" + oClassInfo.name + "</code> itself",
|
1690
|
-
"",
|
1691
|
-
"@returns {" + oClassInfo.name + "} Reference to <code>this</code> in order to allow method chaining",
|
1692
|
-
"@public",
|
1693
|
-
info.since ? "@since " + info.since : "",
|
1694
|
-
info.deprecation ? "@deprecated " + info.deprecation : "",
|
1695
|
-
info.experimental ? "@experimental " + info.experimental : "",
|
1696
|
-
"@name " + name("attach", n),
|
1697
|
-
"@function"
|
1698
|
-
]);
|
1699
|
-
newJSDoc([
|
1700
|
-
"Detaches event handler <code>fnFunction</code> from the " + link + " event of this <code>" + oClassInfo.name + "</code>.",
|
1701
|
-
"",
|
1702
|
-
"The passed function and listener object must match the ones used for event registration.",
|
1703
|
-
"",
|
1704
|
-
"@param {function}",
|
1705
|
-
" fnFunction The function to be called, when the event occurs",
|
1706
|
-
"@param {object}",
|
1707
|
-
" oListener Context object on which the given function had to be called",
|
1708
|
-
"@returns {" + oClassInfo.name + "} Reference to <code>this</code> in order to allow method chaining",
|
1709
|
-
info.since ? "@since " + info.since : "",
|
1710
|
-
info.deprecation ? "@deprecated " + info.deprecation : "",
|
1711
|
-
info.experimental ? "@experimental " + info.experimental : "",
|
1712
|
-
"@public",
|
1713
|
-
"@name " + name("detach", n),
|
1714
|
-
"@function"
|
1715
|
-
]);
|
1716
|
-
|
1717
|
-
// build documentation for fireEvent. It contains conditional parts which makes it a bit more complicated
|
1718
|
-
lines = [
|
1719
|
-
"Fires event " + link + " to attached listeners."
|
1720
|
-
];
|
1721
|
-
if ( info.allowPreventDefault ) {
|
1722
|
-
lines.push(
|
1723
|
-
"",
|
1724
|
-
"Listeners may prevent the default action of this event by using the <code>preventDefault</code>-method on the event object.",
|
1725
|
-
"");
|
1726
|
-
}
|
1727
|
-
lines.push(
|
1728
|
-
"",
|
1729
|
-
"@param {object} [mParameters] Parameters to pass along with the event"
|
1730
|
-
);
|
1731
|
-
if ( !isEmpty(info.parameters) ) {
|
1732
|
-
for (pName in info.parameters) {
|
1733
|
-
lines.push(
|
1734
|
-
"@param {" + (info.parameters[pName].type || "any") + "} [mParameters." + pName + "] " + (info.parameters[pName].doc || "")
|
1735
|
-
);
|
1736
|
-
}
|
1737
|
-
lines.push("");
|
1738
|
-
}
|
1739
|
-
if ( info.allowPreventDefault ) {
|
1740
|
-
lines.push("@returns {boolean} Whether or not to prevent the default action");
|
1741
|
-
} else {
|
1742
|
-
lines.push("@returns {" + oClassInfo.name + "} Reference to <code>this</code> in order to allow method chaining");
|
1743
|
-
}
|
1744
|
-
lines.push(
|
1745
|
-
"@protected",
|
1746
|
-
info.since ? "@since " + info.since : "",
|
1747
|
-
info.deprecation ? "@deprecated " + info.deprecation : "",
|
1748
|
-
info.experimental ? "@experimental " + info.experimental : "",
|
1749
|
-
"@name " + name("fire", n),
|
1750
|
-
"@function"
|
1751
|
-
);
|
1752
|
-
newJSDoc(lines);
|
1753
|
-
}
|
1754
|
-
|
1755
|
-
}
|
1756
|
-
|
1757
|
-
function createDataTypeAutoDoc(oTypeInfo, classComment, node, parser, filename) {
|
1758
|
-
}
|
1759
|
-
|
1760
|
-
/**
|
1761
|
-
* Creates a human readable location info for a given doclet.
|
1762
|
-
* @param doclet
|
1763
|
-
* @returns {String}
|
1764
|
-
*/
|
1765
|
-
function location(doclet) {
|
1766
|
-
var filename = (doclet.meta && doclet.meta.filename) || "unknown";
|
1767
|
-
return " #" + ui5data(doclet).id + "@" + filename + (doclet.meta.lineno != null ? ":" + doclet.meta.lineno : "") + (doclet.synthetic ? "(synthetic)" : "");
|
1768
|
-
}
|
1769
|
-
|
1770
|
-
// ---- Comment handling ---------------------------------------------------------------------------
|
1771
|
-
|
1772
|
-
// --- comment related functions that depend on the JSdoc version (e.g. on the used parser)
|
1773
|
-
|
1774
|
-
var isDocComment;
|
1775
|
-
var getLeadingCommentNode;
|
1776
|
-
|
1777
|
-
// JSDoc added the node type <code>Syntax.File</code> with the same change that activated Babylon
|
1778
|
-
// See https://github.com/jsdoc3/jsdoc/commit/ffec4a42291de6d68e6240f304b68d6abb82a869
|
1779
|
-
if ( Syntax.File === 'File' ) {
|
1780
|
-
|
1781
|
-
// JSDoc starting with version 3.5.0
|
1782
|
-
|
1783
|
-
isDocComment = function isDocCommentBabylon(comment) {
|
1784
|
-
return comment && comment.type === 'CommentBlock' && comment.value && comment.value.charAt(0) === '*';
|
1785
|
-
}
|
1786
|
-
|
1787
|
-
getLeadingCommentNode = function getLeadingCommentNodeBabylon(node, longname) {
|
1788
|
-
var leadingComments = node.leadingComments;
|
1789
|
-
if ( Array.isArray(leadingComments) ) {
|
1790
|
-
// in babylon, all comments are already attached to the node
|
1791
|
-
// and the last one is the closest one and should win
|
1792
|
-
// non-block comments have to be filtered out
|
1793
|
-
leadingComments = leadingComments.filter(isDocComment);
|
1794
|
-
if ( leadingComments.length > 0 ) {
|
1795
|
-
return leadingComments[leadingComments.length - 1];
|
1796
|
-
}
|
1797
|
-
}
|
1798
|
-
}
|
1799
|
-
|
1800
|
-
} else {
|
1801
|
-
|
1802
|
-
// JSDoc versions before 3.5.0
|
1803
|
-
|
1804
|
-
isDocComment = function isDoccommentEsprima(comment) {
|
1805
|
-
return comment && comment.type === 'Block';
|
1806
|
-
};
|
1807
|
-
|
1808
|
-
getLeadingCommentNode = function getLeadingCommentNodeEsprima(node, longname) {
|
1809
|
-
var comment,
|
1810
|
-
leadingComments = node.leadingComments;
|
1811
|
-
|
1812
|
-
// when espree is used, JSDOc attached the leading comment and the first one was picked
|
1813
|
-
if (Array.isArray(leadingComments) && leadingComments.length && leadingComments[0].raw) {
|
1814
|
-
comment = leadingComments[0];
|
1815
|
-
}
|
1816
|
-
|
1817
|
-
// also check all comments attached to the Program node (if found) whether they refer to the same longname
|
1818
|
-
// TODO check why any matches here override the direct leading comment from above
|
1819
|
-
if ( longname && currentProgram && currentProgram.leadingComments && currentProgram.leadingComments.length ) {
|
1820
|
-
leadingComments = currentProgram.leadingComments;
|
1821
|
-
var rLongname = new RegExp("@(name|alias|class|namespace)\\s+" + longname.replace(/\./g, '\\.'));
|
1822
|
-
for ( var i = 0; i < leadingComments.length; i++ ) {
|
1823
|
-
var raw = getRawComment(leadingComments[i]);
|
1824
|
-
if ( /^\/\*\*[\s\S]*\*\/$/.test(raw) && rLongname.test(raw) ) {
|
1825
|
-
comment = leadingComments[i];
|
1826
|
-
// console.log("\n\n**** alternative comment found for " + longname + " on program level\n\n", comment);
|
1827
|
-
break;
|
1828
|
-
}
|
1829
|
-
}
|
1830
|
-
}
|
1831
|
-
|
1832
|
-
return comment;
|
1833
|
-
}
|
1834
|
-
}
|
1835
|
-
|
1836
|
-
//--- comment related functions that are independent from the JSdoc version
|
1837
|
-
|
1838
|
-
function getLeadingComment(node) {
|
1839
|
-
var comment = getLeadingCommentNode(node);
|
1840
|
-
return comment ? getRawComment(comment) : null;
|
1841
|
-
}
|
1842
|
-
|
1843
|
-
function getLeadingDoclet(node, preprocess) {
|
1844
|
-
var comment = getLeadingComment(node)
|
1845
|
-
if ( comment && preprocess ) {
|
1846
|
-
comment = preprocessComment({comment:comment, lineno: node.loc.start.line });
|
1847
|
-
}
|
1848
|
-
return comment ? new Doclet(comment, {}) : null;
|
1849
|
-
}
|
1850
|
-
|
1851
|
-
/**
|
1852
|
-
* Determines the raw comment string (source code form, including leading and trailing comment markers / *...* /) from a comment node.
|
1853
|
-
* Works for Esprima and Babylon based JSDoc versions.
|
1854
|
-
* @param commentNode
|
1855
|
-
* @returns
|
1856
|
-
*/
|
1857
|
-
function getRawComment(commentNode) {
|
1858
|
-
// in esprima, there's a 'raw' property, in babylon, the 'raw' string has to be reconstructed from the 'value' by adding the markers
|
1859
|
-
return commentNode ? commentNode.raw || '/*' + commentNode.value + '*/' : '';
|
1860
|
-
}
|
1861
|
-
|
1862
|
-
function setRawComment(commentNode, newRawComment) {
|
1863
|
-
if ( commentNode.raw ) {
|
1864
|
-
commentNode.raw = newRawComment;
|
1865
|
-
}
|
1866
|
-
commentNode.value = newRawComment.slice(2, -2);
|
1867
|
-
}
|
1868
|
-
|
1869
|
-
/**
|
1870
|
-
* Removes the mandatory comment markers and the optional but common asterisks at the beginning of each JSDoc comment line.
|
1871
|
-
*
|
1872
|
-
* The result is easier to parse/analyze.
|
1873
|
-
*
|
1874
|
-
* Implementation is a 1:1 copy from JSDoc's lib/jsdoc/doclet.js (closure function, not directly reusable)
|
1875
|
-
*
|
1876
|
-
* @param {string} docletSrc the source comment with or without block comment markers
|
1877
|
-
* @returns {string} the unwrapped content of the JSDoc comment
|
1878
|
-
*
|
1879
|
-
*/
|
1880
|
-
function unwrap(docletSrc) {
|
1881
|
-
if (!docletSrc) { return ''; }
|
1882
|
-
|
1883
|
-
// note: keep trailing whitespace for @examples
|
1884
|
-
// extra opening/closing stars are ignored
|
1885
|
-
// left margin is considered a star and a space
|
1886
|
-
// use the /m flag on regex to avoid having to guess what this platform's newline is
|
1887
|
-
docletSrc =
|
1888
|
-
docletSrc.replace(/^\/\*\*+/, '') // remove opening slash+stars
|
1889
|
-
.replace(/\**\*\/$/, "\\Z") // replace closing star slash with end-marker
|
1890
|
-
.replace(/^\s*(\* ?|\\Z)/gm, '') // remove left margin like: spaces+star or spaces+end-marker
|
1891
|
-
.replace(/\s*\\Z$/g, ''); // remove end-marker
|
1892
|
-
|
1893
|
-
return docletSrc;
|
1894
|
-
}
|
1895
|
-
|
1896
|
-
/**
|
1897
|
-
* Inverse operation of unwrap.
|
1898
|
-
*
|
1899
|
-
* The prefix for lines is fixed to be " * ", lines are separated with '\n', independent from the platform.
|
1900
|
-
*/
|
1901
|
-
function wrap(lines) {
|
1902
|
-
if ( typeof lines === "string" ) {
|
1903
|
-
lines = lines.split(/\r\n?|\n/);
|
1904
|
-
}
|
1905
|
-
return "/**\n * " + lines.join('\n * ') + "\n */";
|
1906
|
-
}
|
1907
|
-
|
1908
|
-
/**
|
1909
|
-
* Preprocesses a JSDoc comment string to ensure some UI5 standards.
|
1910
|
-
*
|
1911
|
-
* @param {event} e Event for the new comment
|
1912
|
-
* @returns {event}
|
1913
|
-
*/
|
1914
|
-
function preprocessComment(e) {
|
1915
|
-
|
1916
|
-
var src = e.comment;
|
1917
|
-
|
1918
|
-
// add a default visibility
|
1919
|
-
if ( !/@private|@public|@protected|@sap-restricted|@ui5-restricted/.test(src) ) {
|
1920
|
-
src = unwrap(src);
|
1921
|
-
src = src + "\n@private";
|
1922
|
-
src = wrap(src);
|
1923
|
-
// console.log("added default visibility to '" + src + "'");
|
1924
|
-
}
|
1925
|
-
|
1926
|
-
if ( /@class/.test(src) && /@static/.test(src) ) {
|
1927
|
-
warning("combination of @class and @static is no longer supported with jsdoc3, converting it to @namespace and @classdesc: (line " + e.lineno + ")");
|
1928
|
-
src = unwrap(src);
|
1929
|
-
src = src.replace(/@class/, "@classdesc").replace(/@static/, "@namespace");
|
1930
|
-
src = wrap(src);
|
1931
|
-
//console.log(src);
|
1932
|
-
}
|
1933
|
-
|
1934
|
-
return src;
|
1935
|
-
|
1936
|
-
}
|
1937
|
-
|
1938
|
-
// ---- other functionality ---------------------------------------------------------------------------
|
1939
|
-
|
1940
|
-
// HACK: override cli.exit() to avoid that JSDoc3 exits the VM
|
1941
|
-
if ( pluginConfig.noExit ) {
|
1942
|
-
info("disabling exit() call");
|
1943
|
-
require( path.join(global.env.dirname, 'cli') ).exit = function(retval) {
|
1944
|
-
info("cli.exit(): do nothing (ret val=" + retval + ")");
|
1945
|
-
};
|
1946
|
-
}
|
1947
|
-
|
1948
|
-
|
1949
|
-
// ---- exports ----------------------------------------------------------------------------------------
|
1950
|
-
|
1951
|
-
exports.defineTags = function(dictionary) {
|
1952
|
-
|
1953
|
-
/**
|
1954
|
-
* a special value that is not 'falsy' but results in an empty string when output
|
1955
|
-
* Used for the disclaimer and experimental tag
|
1956
|
-
*/
|
1957
|
-
var EMPTY = {
|
1958
|
-
toString: function() { return ""; }
|
1959
|
-
};
|
1960
|
-
|
1961
|
-
/**
|
1962
|
-
* A sapui5 specific tag to add a disclaimer to a symbol
|
1963
|
-
*/
|
1964
|
-
dictionary.defineTag('disclaimer', {
|
1965
|
-
// value is optional
|
1966
|
-
onTagged: function(doclet, tag) {
|
1967
|
-
doclet.disclaimer = tag.value || EMPTY;
|
1968
|
-
}
|
1969
|
-
});
|
1970
|
-
|
1971
|
-
/**
|
1972
|
-
* A sapui5 specific tag to mark a symbol as experimental.
|
1973
|
-
*/
|
1974
|
-
dictionary.defineTag('experimental', {
|
1975
|
-
// value is optional
|
1976
|
-
onTagged: function(doclet, tag) {
|
1977
|
-
doclet.experimental = tag.value || EMPTY;
|
1978
|
-
}
|
1979
|
-
});
|
1980
|
-
|
1981
|
-
/**
|
1982
|
-
* Re-introduce the deprecated 'final tag. JSDoc used it as a synonym for readonly, but we use it to mark classes as final
|
1983
|
-
*/
|
1984
|
-
dictionary.defineTag('final', {
|
1985
|
-
mustNotHaveValue: true,
|
1986
|
-
onTagged: function(doclet, tag) {
|
1987
|
-
doclet.final_ = true;
|
1988
|
-
}
|
1989
|
-
});
|
1990
|
-
|
1991
|
-
/**
|
1992
|
-
* Introduce a new kind of symbol: 'interface'
|
1993
|
-
* 'interface' is like 'class', but without a constructor.
|
1994
|
-
* Support for 'interface' might not be complete (only standard UI5 use cases tested)
|
1995
|
-
*/
|
1996
|
-
dictionary.defineTag('interface', {
|
1997
|
-
//mustNotHaveValue: true,
|
1998
|
-
onTagged: function(doclet, tag) {
|
1999
|
-
// debug("setting kind of " + doclet.name + " to 'interface'");
|
2000
|
-
doclet.kind = 'interface';
|
2001
|
-
if ( tag.value ) {
|
2002
|
-
doclet.classdesc = tag.value;
|
2003
|
-
}
|
2004
|
-
}
|
2005
|
-
});
|
2006
|
-
|
2007
|
-
/**
|
2008
|
-
* Classes can declare that they implement a set of interfaces
|
2009
|
-
*/
|
2010
|
-
dictionary.defineTag('implements', {
|
2011
|
-
mustHaveValue: true,
|
2012
|
-
onTagged: function(doclet, tag) {
|
2013
|
-
// console.log("setting implements of " + doclet.name + " to 'interface'");
|
2014
|
-
if ( tag.value ) {
|
2015
|
-
doclet.implements = doclet.implements || [];
|
2016
|
-
tag.value.split(/\s*,\s*/g).forEach(function($) {
|
2017
|
-
if ( doclet.implements.indexOf($) < 0 ) {
|
2018
|
-
doclet.implements.push($);
|
2019
|
-
}
|
2020
|
-
});
|
2021
|
-
}
|
2022
|
-
}
|
2023
|
-
});
|
2024
|
-
|
2025
|
-
/**
|
2026
|
-
* Set the visibility of a doclet to 'restricted'.
|
2027
|
-
*/
|
2028
|
-
dictionary.defineTag('ui5-restricted', {
|
2029
|
-
onTagged: function(doclet, tag) {
|
2030
|
-
doclet.access = 'restricted';
|
2031
|
-
if ( tag.value ) {
|
2032
|
-
ui5data(doclet).stakeholders = tag.value.trim().split(/(?:\s*,\s*|\s+)/);
|
2033
|
-
}
|
2034
|
-
}
|
2035
|
-
});
|
2036
|
-
dictionary.defineSynonym('ui5-restricted', 'sap-restricted');
|
2037
|
-
|
2038
|
-
/**
|
2039
|
-
* Mark a doclet as synthetic.
|
2040
|
-
*
|
2041
|
-
* Used for doclets that the autodoc generation creates. This helps the template
|
2042
|
-
* later to recognize such doclets and maybe filter them out.
|
2043
|
-
*/
|
2044
|
-
dictionary.defineTag('synthetic', {
|
2045
|
-
mustNotHaveValue: true,
|
2046
|
-
onTagged: function(doclet, tag) {
|
2047
|
-
doclet.synthetic = true;
|
2048
|
-
}
|
2049
|
-
});
|
2050
|
-
|
2051
|
-
/**
|
2052
|
-
* Mark a doclet that intentionally updates a previous doclet
|
2053
|
-
*/
|
2054
|
-
dictionary.defineTag('ui5-updated-doclet', {
|
2055
|
-
mustNotHaveValue: true,
|
2056
|
-
onTagged: function(doclet, tag) {
|
2057
|
-
ui5data(doclet).updatedDoclet = true;
|
2058
|
-
}
|
2059
|
-
});
|
2060
|
-
|
2061
|
-
/**
|
2062
|
-
* The @hideconstructor tag tells JSDoc that the generated documentation should not display the constructor for a class.
|
2063
|
-
* Note: this tag will be natively available in JSDoc >= 3.5.0
|
2064
|
-
*/
|
2065
|
-
dictionary.defineTag('hideconstructor', {
|
2066
|
-
mustNotHaveValue: true,
|
2067
|
-
onTagged: function(doclet, tag) {
|
2068
|
-
doclet.hideconstructor = true;
|
2069
|
-
}
|
2070
|
-
});
|
2071
|
-
|
2072
|
-
dictionary.defineTag('slot', {
|
2073
|
-
onTagged: function(doclet, tag) {
|
2074
|
-
doclet.slot = true;
|
2075
|
-
if (tag.value) {
|
2076
|
-
doclet.propertyName = tag.value;
|
2077
|
-
}
|
2078
|
-
}
|
2079
|
-
});
|
2080
|
-
|
2081
|
-
dictionary.defineTag('appenddocs', {
|
2082
|
-
mustHaveValue: false,
|
2083
|
-
onTagged: function(doclet, tag) {
|
2084
|
-
doclet.appenddocs = tag.value;
|
2085
|
-
}
|
2086
|
-
});
|
2087
|
-
|
2088
|
-
dictionary.defineTag('tagname', {
|
2089
|
-
mustHaveValue: true,
|
2090
|
-
onTagged: function(doclet, tag) {
|
2091
|
-
doclet.tagname = tag.value;
|
2092
|
-
}
|
2093
|
-
});
|
2094
|
-
|
2095
|
-
dictionary.defineTag('allowPreventDefault', {
|
2096
|
-
mustHaveValue: false,
|
2097
|
-
onTagged: function(doclet, tag) {
|
2098
|
-
doclet.allowPreventDefault = true;
|
2099
|
-
}
|
2100
|
-
});
|
2101
|
-
|
2102
|
-
dictionary.defineTag('native', {
|
2103
|
-
mustHaveValue: false,
|
2104
|
-
onTagged: function(doclet, tag) {
|
2105
|
-
doclet.native = true;
|
2106
|
-
}
|
2107
|
-
});
|
2108
|
-
|
2109
|
-
dictionary.defineTag('noattribute', {
|
2110
|
-
mustHaveValue: false,
|
2111
|
-
onTagged: function(doclet, tag) {
|
2112
|
-
doclet.noattribute = true;
|
2113
|
-
}
|
2114
|
-
});
|
2115
|
-
|
2116
|
-
dictionary.defineTag('formEvents', {
|
2117
|
-
mustHaveValue: false,
|
2118
|
-
onTagged: function(doclet, tag) {
|
2119
|
-
if (tag.value) {
|
2120
|
-
doclet.formEvents = doclet.formEvents || [];
|
2121
|
-
tag.value.split(" ").forEach(function($) {
|
2122
|
-
if ( doclet.formEvents.indexOf($) < 0 ) {
|
2123
|
-
doclet.formEvents.push($);
|
2124
|
-
}
|
2125
|
-
});
|
2126
|
-
}
|
2127
|
-
}
|
2128
|
-
});
|
2129
|
-
|
2130
|
-
dictionary.defineTag('formProperty', {
|
2131
|
-
mustHaveValue: false,
|
2132
|
-
onTagged: function(doclet, tag) {
|
2133
|
-
doclet.formProperty = true;
|
2134
|
-
}
|
2135
|
-
});
|
2136
|
-
|
2137
|
-
dictionary.defineTag('formAssociated', {
|
2138
|
-
mustHaveValue: false,
|
2139
|
-
onTagged: function(doclet, tag) {
|
2140
|
-
doclet.formAssociated = doclet.formAssociated || true;
|
2141
|
-
}
|
2142
|
-
});
|
2143
|
-
};
|
2144
|
-
|
2145
|
-
exports.handlers = {
|
2146
|
-
|
2147
|
-
/**
|
2148
|
-
* Before all files are parsed, determine the common path prefix of all filenames
|
2149
|
-
*/
|
2150
|
-
parseBegin : function(e) {
|
2151
|
-
|
2152
|
-
pathPrefixes = env.opts._.reduce(function(result, fileOrDir) {
|
2153
|
-
fileOrDir = path.resolve( path.normalize(fileOrDir) );
|
2154
|
-
if ( fs.statSync(fileOrDir).isDirectory() ) {
|
2155
|
-
// ensure a trailing path separator
|
2156
|
-
if ( fileOrDir.indexOf(path.sep, fileOrDir.length - path.sep.length) < 0 ) {
|
2157
|
-
fileOrDir += path.sep;
|
2158
|
-
}
|
2159
|
-
result.push(fileOrDir);
|
2160
|
-
}
|
2161
|
-
return result;
|
2162
|
-
}, []);
|
2163
|
-
resourceNamePrefixes = pluginConfig.resourceNamePrefixes || [];
|
2164
|
-
if ( !Array.isArray(resourceNamePrefixes) ) {
|
2165
|
-
resourceNamePrefixes = [resourceNamePrefixes];
|
2166
|
-
}
|
2167
|
-
resourceNamePrefixes.forEach(ensureEndingSlash);
|
2168
|
-
while ( resourceNamePrefixes.length < pathPrefixes.length ) {
|
2169
|
-
resourceNamePrefixes.push('');
|
2170
|
-
}
|
2171
|
-
|
2172
|
-
debug("path prefixes " + JSON.stringify(pathPrefixes));
|
2173
|
-
debug("resource name prefixes " + JSON.stringify(resourceNamePrefixes));
|
2174
|
-
},
|
2175
|
-
|
2176
|
-
/**
|
2177
|
-
* Log each file before it is parsed
|
2178
|
-
*/
|
2179
|
-
fileBegin: function (e) {
|
2180
|
-
currentProgram = undefined;
|
2181
|
-
currentModule = {
|
2182
|
-
name: null,
|
2183
|
-
resource: getResourceName(e.filename),
|
2184
|
-
module: getModuleName(getResourceName(e.filename)),
|
2185
|
-
localNames: Object.create(null)
|
2186
|
-
};
|
2187
|
-
},
|
2188
|
-
|
2189
|
-
fileComplete: function (e) {
|
2190
|
-
// debug("module info after parsing: ", currentModule);
|
2191
|
-
currentSource = undefined;
|
2192
|
-
currentProgram = undefined;
|
2193
|
-
currentModule = undefined;
|
2194
|
-
},
|
2195
|
-
|
2196
|
-
jsdocCommentFound: function(e) {
|
2197
|
-
// console.log("jsdocCommentFound: " + e.comment);
|
2198
|
-
e.comment = preprocessComment(e);
|
2199
|
-
},
|
2200
|
-
|
2201
|
-
symbolFound: function(e) {
|
2202
|
-
// console.log("symbolFound: " + e.comment);
|
2203
|
-
},
|
2204
|
-
|
2205
|
-
newDoclet: function(e) {
|
2206
|
-
|
2207
|
-
var _ui5data = ui5data(e.doclet);
|
2208
|
-
|
2209
|
-
// remove code: this is a try to reduce the required heap size
|
2210
|
-
if ( e.doclet.meta ) {
|
2211
|
-
if ( e.doclet.meta.code ) {
|
2212
|
-
e.doclet.meta.code = {};
|
2213
|
-
}
|
2214
|
-
var filepath = (e.doclet.meta.path && e.doclet.meta.path !== 'null' ) ? path.join(e.doclet.meta.path, e.doclet.meta.filename) : e.doclet.meta.filename;
|
2215
|
-
e.doclet.meta.__shortpath = getRelativePath(filepath);
|
2216
|
-
_ui5data.resource = currentModule.resource;
|
2217
|
-
_ui5data.module = currentModule.name || currentModule.module;
|
2218
|
-
}
|
2219
|
-
|
2220
|
-
|
2221
|
-
// JSDoc 3 has a bug when it encounters a property in an object literal with an empty string as name
|
2222
|
-
// (e.g. { "" : something } will result in a doclet without longname
|
2223
|
-
if ( !e.doclet.longname ) {
|
2224
|
-
if ( e.doclet.memberof ) {
|
2225
|
-
e.doclet.longname = e.doclet.memberof + "." + e.doclet.name; // TODO '.' depends on scope?
|
2226
|
-
warning("found doclet without longname, derived longname: " + e.doclet.longname + " " + location(e.doclet));
|
2227
|
-
} else {
|
2228
|
-
error("found doclet without longname, could not derive longname " + location(e.doclet));
|
2229
|
-
}
|
2230
|
-
return;
|
2231
|
-
}
|
2232
|
-
|
2233
|
-
// try to detect misused memberof
|
2234
|
-
if ( e.doclet.memberof && e.doclet.longname.indexOf(e.doclet.memberof) !== 0 ) {
|
2235
|
-
warning("potentially unsupported use of @name and @memberof " + location(e.doclet));
|
2236
|
-
//console.log(e.doclet);
|
2237
|
-
}
|
2238
|
-
|
2239
|
-
if ( e.doclet.returns
|
2240
|
-
&& e.doclet.returns.length > 0
|
2241
|
-
&& e.doclet.returns[0]
|
2242
|
-
&& e.doclet.returns[0].type
|
2243
|
-
&& e.doclet.returns[0].type.names
|
2244
|
-
&& e.doclet.returns[0].type.names[0] === 'this'
|
2245
|
-
&& e.doclet.memberof ) {
|
2246
|
-
warning("fixing return type 'this' with " + e.doclet.memberof);
|
2247
|
-
e.doclet.returns[0].type.names[0] = e.doclet.memberof;
|
2248
|
-
}
|
2249
|
-
},
|
2250
|
-
|
2251
|
-
beforeParse : function(e) {
|
2252
|
-
msgHeader("parsing " + getRelativePath(e.filename));
|
2253
|
-
currentSource = e.source;
|
2254
|
-
},
|
2255
|
-
|
2256
|
-
parseComplete : function(e) {
|
2257
|
-
|
2258
|
-
var doclets = e.doclets;
|
2259
|
-
var l = doclets.length,i,j,doclet;
|
2260
|
-
//var noprivate = !env.opts.private;
|
2261
|
-
var rAnonymous = /^<anonymous>(~|$)/;
|
2262
|
-
|
2263
|
-
// remove undocumented symbols, ignored symbols, anonymous functions and their members, scope members
|
2264
|
-
for (i = 0, j = 0; i < l; i++) {
|
2265
|
-
|
2266
|
-
doclet = doclets[i];
|
2267
|
-
if ( !doclet.undocumented &&
|
2268
|
-
!doclet.ignore &&
|
2269
|
-
!(doclet.memberof && rAnonymous.test(doclet.memberof)) &&
|
2270
|
-
doclet.longname.indexOf("~") < 0 ) {
|
2271
|
-
doclets[j++] = doclet;
|
2272
|
-
}
|
2273
|
-
}
|
2274
|
-
if ( j < l ) {
|
2275
|
-
doclets.splice(j, l - j);
|
2276
|
-
info("removed " + (l - j) + " undocumented, ignored or anonymous symbols");
|
2277
|
-
l = j;
|
2278
|
-
}
|
2279
|
-
|
2280
|
-
// sort doclets by name, synthetic, lineno, uid
|
2281
|
-
// 'ignore' is a combination of criteria, see function above
|
2282
|
-
debug("sorting doclets by name");
|
2283
|
-
doclets.sort(function(a,b) {
|
2284
|
-
if ( a.longname === b.longname ) {
|
2285
|
-
if ( a.synthetic === b.synthetic ) {
|
2286
|
-
if ( a.meta && b.meta && a.meta.filename == b.meta.filename ) {
|
2287
|
-
if ( a.meta.lineno !== b.meta.lineno ) {
|
2288
|
-
return a.meta.lineno < b.meta.lineno ? -1 : 1;
|
2289
|
-
}
|
2290
|
-
}
|
2291
|
-
return a.__ui5.id - b.__ui5.id;
|
2292
|
-
}
|
2293
|
-
return a.synthetic && !b.synthetic ? -1 : 1;
|
2294
|
-
}
|
2295
|
-
return a.longname < b.longname ? -1 : 1;
|
2296
|
-
});
|
2297
|
-
debug("sorting doclets by name done.");
|
2298
|
-
|
2299
|
-
for (i = 0, j = 0; i < l; i++) {
|
2300
|
-
|
2301
|
-
doclet = doclets[i];
|
2302
|
-
|
2303
|
-
// add metadata to symbol
|
2304
|
-
if ( classInfos[doclet.longname] ) {
|
2305
|
-
doclet.__ui5.metadata = classInfos[doclet.longname];
|
2306
|
-
|
2307
|
-
// add designtime infos, if configured
|
2308
|
-
var designtimeModule = doclet.__ui5.metadata.designtime;
|
2309
|
-
if ( designtimeModule && typeof designtimeModule !== 'string' ) {
|
2310
|
-
designtimeModule = doclet.__ui5.module + ".designtime";
|
2311
|
-
}
|
2312
|
-
if ( designtimeModule && designtimeInfos[designtimeModule] ) {
|
2313
|
-
info("associating designtime data with class metadata: ", designtimeModule);
|
2314
|
-
// TODO do a more generic merge or maybe add whole information as "designtime" information
|
2315
|
-
doclet.__ui5.metadata.annotations = designtimeInfos[designtimeModule].annotations;
|
2316
|
-
}
|
2317
|
-
|
2318
|
-
// derive extends from UI5 APIs
|
2319
|
-
if ( doclet.__ui5.metadata.baseType
|
2320
|
-
&& !(doclet.augments && doclet.augments.length > 0) ) {
|
2321
|
-
doclet.augments = doclet.augments || [];
|
2322
|
-
info(" @extends " + doclet.__ui5.metadata.baseType + " derived from UI5 APIs (" + doclet.longname + ")");
|
2323
|
-
doclet.augments.push(doclet.__ui5.metadata.baseType);
|
2324
|
-
}
|
2325
|
-
|
2326
|
-
// derive interface implementations from UI5 metadata
|
2327
|
-
if ( doclet.__ui5.metadata.interfaces && doclet.__ui5.metadata.interfaces.length ) {
|
2328
|
-
doclet.__ui5.metadata.interfaces.forEach(function(intf) {
|
2329
|
-
doclet.implements = doclet.implements || [];
|
2330
|
-
if ( doclet.implements.indexOf(intf) < 0 ) {
|
2331
|
-
info(" @implements " + intf + " derived from UI5 metadata (" + doclet.longname + ")");
|
2332
|
-
doclet.implements.push(intf);
|
2333
|
-
}
|
2334
|
-
})
|
2335
|
-
}
|
2336
|
-
}
|
2337
|
-
|
2338
|
-
if ( typeInfos[doclet.longname] ) {
|
2339
|
-
doclet.__ui5.stereotype = 'datatype';
|
2340
|
-
doclet.__ui5.metadata = {
|
2341
|
-
basetype: typeInfos[doclet.longname].base,
|
2342
|
-
pattern: typeInfos[doclet.longname].pattern,
|
2343
|
-
range: typeInfos[doclet.longname].range
|
2344
|
-
};
|
2345
|
-
}
|
2346
|
-
|
2347
|
-
// check for duplicates: last one wins
|
2348
|
-
if ( j > 0 && doclets[j - 1].longname === doclet.longname ) {
|
2349
|
-
if ( !doclets[j - 1].synthetic && !doclet.__ui5.updatedDoclet ) {
|
2350
|
-
// replacing synthetic comments or updating comments are trivial case. Just log non-trivial duplicates
|
2351
|
-
debug("ignoring duplicate doclet for " + doclet.longname + ":" + location(doclet) + " overrides " + location(doclets[j - 1]));
|
2352
|
-
}
|
2353
|
-
doclets[j - 1] = doclet;
|
2354
|
-
} else {
|
2355
|
-
doclets[j++] = doclet;
|
2356
|
-
}
|
2357
|
-
}
|
2358
|
-
|
2359
|
-
if ( j < l ) {
|
2360
|
-
doclets.splice(j, l - j);
|
2361
|
-
info("removed " + (l - j) + " duplicate symbols - " + doclets.length + " remaining");
|
2362
|
-
}
|
2363
|
-
|
2364
|
-
if ( pluginConfig.saveSymbols ) {
|
2365
|
-
|
2366
|
-
fs.mkPath(env.opts.destination);
|
2367
|
-
|
2368
|
-
fs.writeFileSync(path.join(env.opts.destination, "symbols-parseComplete.json"), JSON.stringify(e.doclets, null, "\t"), 'utf8');
|
2369
|
-
|
2370
|
-
}
|
2371
|
-
|
2372
|
-
}
|
2373
|
-
};
|
2374
|
-
|
2375
|
-
exports.astNodeVisitor = {
|
2376
|
-
|
2377
|
-
visitNode: function(node, e, parser, currentSourceName) {
|
2378
|
-
|
2379
|
-
|
2380
|
-
var comment;
|
2381
|
-
|
2382
|
-
if ( node.type === Syntax.Program ) {
|
2383
|
-
currentProgram = node;
|
2384
|
-
}
|
2385
|
-
|
2386
|
-
function processExtendCall(extendCall, comment, commentAlreadyProcessed) {
|
2387
|
-
var doclet = comment && new Doclet(getRawComment(comment), {});
|
2388
|
-
var classInfo = collectClassInfo(extendCall, doclet);
|
2389
|
-
if ( classInfo ) {
|
2390
|
-
createAutoDoc(classInfo, comment, extendCall, parser, currentSourceName, commentAlreadyProcessed);
|
2391
|
-
}
|
2392
|
-
}
|
2393
|
-
|
2394
|
-
function processDataType(createCall, comment) {
|
2395
|
-
var doclet = comment && new Doclet(getRawComment(comment), {});
|
2396
|
-
var typeInfo = collectDataTypeInfo(createCall, doclet);
|
2397
|
-
if ( typeInfo ) {
|
2398
|
-
createDataTypeAutoDoc(typeInfo, comment, createCall, parser, currentSourceName);
|
2399
|
-
}
|
2400
|
-
}
|
2401
|
-
|
2402
|
-
if ( node.type === Syntax.ExpressionStatement ) {
|
2403
|
-
if ( isSapUiDefineCall(node.expression) ) {
|
2404
|
-
analyzeModuleDefinition(node.expression);
|
2405
|
-
/*
|
2406
|
-
} else if ( isJQuerySapDeclareCall(node.expression)
|
2407
|
-
&& node.expression.arguments.length > 0
|
2408
|
-
&& node.expression.arguments[0].type === Syntax.Literal
|
2409
|
-
&& typeof node.expression.arguments[0].value === "string" ) {
|
2410
|
-
warning("module has explicit module name " + node.expression.arguments[0].value);
|
2411
|
-
*/
|
2412
|
-
}
|
2413
|
-
|
2414
|
-
}
|
2415
|
-
|
2416
|
-
if (node.type === Syntax.ReturnStatement && node.argument && node.argument.type === Syntax.ObjectExpression && /\.designtime\.js$/.test(currentSourceName) ) {
|
2417
|
-
|
2418
|
-
// assume this node to return designtime metadata. Collect it and remember it by its module name
|
2419
|
-
var oDesigntimeInfo = collectDesigntimeInfo(node);
|
2420
|
-
if ( oDesigntimeInfo ) {
|
2421
|
-
designtimeInfos[currentModule.module] = oDesigntimeInfo;
|
2422
|
-
info("collected designtime info " + currentModule.module);
|
2423
|
-
}
|
2424
|
-
|
2425
|
-
} else if ( node.type === Syntax.ExpressionStatement && isExtendCall(node.expression) ) {
|
2426
|
-
|
2427
|
-
// Something.extend(...) -- return value (new class) is not used in an assignment
|
2428
|
-
|
2429
|
-
// className = node.expression.arguments[0].value;
|
2430
|
-
comment = getLeadingCommentNode(node) || getLeadingCommentNode(node.expression);
|
2431
|
-
// console.log("ast node with comment " + comment);
|
2432
|
-
processExtendCall(node.expression, comment);
|
2433
|
-
|
2434
|
-
} else if ( node.type === Syntax.VariableDeclaration ) {
|
2435
|
-
node.declarations.forEach(function(decl, idx) {
|
2436
|
-
if ( isExtendCall(decl.init) ) {
|
2437
|
-
// var NewClass = Something.extend(...)
|
2438
|
-
|
2439
|
-
// className = node.declarations[0].init.arguments[0].value;
|
2440
|
-
comment = (idx === 0 ? getLeadingCommentNode(node) : undefined) || getLeadingCommentNode(decl);
|
2441
|
-
// console.log("ast node with comment " + comment);
|
2442
|
-
processExtendCall(decl.init, comment);
|
2443
|
-
}
|
2444
|
-
})
|
2445
|
-
|
2446
|
-
} else if ( node.type === Syntax.ReturnStatement && isExtendCall(node.argument) ) {
|
2447
|
-
|
2448
|
-
// return Something.extend(...)
|
2449
|
-
|
2450
|
-
var className = node.argument.arguments[0].value;
|
2451
|
-
comment = getLeadingCommentNode(node, className) || getLeadingCommentNode(node.argument, className);
|
2452
|
-
// console.log("ast node with comment " + comment);
|
2453
|
-
processExtendCall(node.argument, comment, true);
|
2454
|
-
} else if ( node.type === Syntax.ExpressionStatement && node.expression.type === Syntax.AssignmentExpression ) {
|
2455
|
-
|
2456
|
-
if ( isCreateDataTypeCall(node.expression.right) ) {
|
2457
|
-
|
2458
|
-
// thisLib.TypeName = DataType.createType( ... )
|
2459
|
-
comment = getLeadingCommentNode(node) || getLeadingCommentNode(node.expression);
|
2460
|
-
processDataType(node.expression.right);
|
2461
|
-
// TODO remember knowledge about type and its name (left hand side of assignment)
|
2462
|
-
|
2463
|
-
}
|
2464
|
-
|
2465
|
-
}
|
2466
|
-
}
|
2467
|
-
|
2468
|
-
};
|