@ui5/webcomponents-tools 0.0.0-e818f286e → 0.0.0-ebd9a4db3

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