Skip to content

Commit ed75ed4

Browse files
committed
[INTERNAL] lib/processors/jsdoc: remove duplicates after processingComplete
Processing of @Augments, @mixin and @borrows tags might produce new duplicates which are not yet visible during the `parseComplete` event. Moving the cleanup to `processingComplete` fixes this. The merge of the additional data that the UI5 AST visitor collected, is still done in `parseComplete` so that it is available when doclets are cloned during the processing of @Augments, @mixin and @borrows tags. Cherry-picked from UI5/openui5@96f6f095d.
1 parent d99a195 commit ed75ed4

File tree

1 file changed

+85
-51
lines changed

1 file changed

+85
-51
lines changed

lib/processors/jsdoc/lib/ui5/plugin.js

Lines changed: 85 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -2915,53 +2915,20 @@ exports.handlers = {
29152915
currentSource = e.source;
29162916
},
29172917

2918+
/**
2919+
* Event `parseComplete` is fired by JSDoc after all files have been parsed,
2920+
* but before inheritance, mixins or borrows are processed.
2921+
*
2922+
* We use this event to merge our additional data into the doclets collected by JSDoc.
2923+
* The merge must happen before doclets are cloned during the prcessing of augments or borrows.
2924+
*/
29182925
parseComplete : function(e) {
2919-
29202926
const doclets = e.doclets;
2921-
const rAnonymous = /^<anonymous>(~|$)/;
2922-
2923-
// remove undocumented symbols, ignored symbols, anonymous functions and their members, scope members
2924-
let l = doclets.length, i, j;
2925-
for (i = 0, j = 0; i < l; i++) {
2926-
2927+
const l = doclets.length;
2928+
for (let i = 0; i < l; i++) {
29272929
const doclet = doclets[i];
2928-
if ( !doclet.undocumented &&
2929-
!doclet.ignore &&
2930-
!(doclet.memberof && rAnonymous.test(doclet.memberof)) &&
2931-
doclet.longname.indexOf("~") < 0 ) {
2932-
doclets[j++] = doclet;
2933-
}
2934-
}
2935-
if ( j < l ) {
2936-
doclets.splice(j, l - j);
2937-
info(`removed ${l - j} undocumented, ignored or anonymous symbols`);
2938-
l = j;
2939-
}
29402930

2941-
// sort doclets by name, synthetic, lineno, uid
2942-
// 'ignore' is a combination of criteria, see function above
2943-
debug("sorting doclets by name");
2944-
doclets.sort((a, b) => {
2945-
if ( a.longname === b.longname ) {
2946-
if ( a.synthetic === b.synthetic ) {
2947-
if ( a.meta && b.meta && a.meta.filename == b.meta.filename ) {
2948-
if ( a.meta.lineno !== b.meta.lineno ) {
2949-
return a.meta.lineno < b.meta.lineno ? -1 : 1;
2950-
}
2951-
}
2952-
return a.__ui5.id - b.__ui5.id;
2953-
}
2954-
return a.synthetic && !b.synthetic ? -1 : 1;
2955-
}
2956-
return a.longname < b.longname ? -1 : 1;
2957-
});
2958-
debug("sorting doclets by name done.");
2959-
2960-
for (i = 0, j = 0; i < l; i++) {
2961-
2962-
const doclet = doclets[i];
2963-
2964-
// add metadata to symbol
2931+
// add metadata to class symbols
29652932
if ( classInfos[doclet.longname] ) {
29662933
// debug("class data", doclet.longname, "'" + classInfos[doclet.longname].export + "'");
29672934
if ( doclet.__ui5.export === undefined ) {
@@ -3005,6 +2972,7 @@ exports.handlers = {
30052972
}
30062973
}
30072974

2975+
// add DataType info to typedef symbols
30082976
if ( typeInfos[doclet.longname] ) {
30092977
doclet.__ui5.stereotype = 'datatype';
30102978
doclet.__ui5.metadata = {
@@ -3014,6 +2982,7 @@ exports.handlers = {
30142982
};
30152983
}
30162984

2985+
// add enum values to enum keys (for enum symbols)
30172986
if ( (doclet.kind === 'member' || doclet.kind === 'constant') && doclet.isEnum && Array.isArray(doclet.properties) ) {
30182987
// determine unique enum identifier from key set
30192988
let enumID = doclet.properties.map(function(prop) {
@@ -3036,31 +3005,96 @@ exports.handlers = {
30363005
}
30373006
}
30383007
}
3008+
}
3009+
},
3010+
3011+
/**
3012+
* Event `processingComplete` is fired by JSDoc after all files have been parsed,
3013+
* and after inheritance, mixins and borrows have been processed.
3014+
*
3015+
* The `e.doclets` contains the symbols that will be given to templates for publishing.
3016+
*
3017+
* We use this event to remove symbols that are not of interest:
3018+
* - undocumented When JSDoc finds a class, function, object or member without a
3019+
* JSDoc comment, it creates a doclet with a truthy `undocumented`
3020+
* property
3021+
* - ignore A symbol that has been marked with `@ignore` in the source code
3022+
* - anonymous JSDoc could not infer a name for the symbol, neither from source
3023+
* code nor from JSDoc comments
3024+
* - local Local entities (e.g. local vars) can't be addressed from the outside
3025+
* and therefore are generally not considered as API in UI5
3026+
* - duplicates This plugin generates doclets for the accessor methods of
3027+
* managed properties, aggregations, events, associations.
3028+
* Developers might have created JSDoc comments for the same methods,
3029+
* either because they have overridden them in code or because they
3030+
* wanted to detail the method contract. If such duplicate doclets
3031+
* are detected, the developer created doclets are preferred. If
3032+
* multiple developer created doclets for the same entity exist in the
3033+
* same file, the last one wins. If multiple doclets exists across
3034+
* files, the one created last wins (but usually, this indicates a
3035+
* copy & paste error)
3036+
*
3037+
* The cleanup is done in `processingComplete` as the processing of `@augments` or
3038+
* `@borrows` tags might have created new non-interesting symbols.
3039+
*/
3040+
processingComplete(e) {
3041+
const doclets = e.doclets;
3042+
3043+
// sort doclets by name, synthetic, lineno, uid for easier detection of duplicates
3044+
debug("sorting doclets by name");
3045+
doclets.sort((a, b) => {
3046+
if ( a.longname === b.longname ) {
3047+
if ( a.synthetic === b.synthetic ) {
3048+
if ( a.meta && b.meta && a.meta.filename == b.meta.filename ) {
3049+
if ( a.meta.lineno !== b.meta.lineno ) {
3050+
return a.meta.lineno < b.meta.lineno ? -1 : 1;
3051+
}
3052+
}
3053+
return a.__ui5.id - b.__ui5.id;
3054+
}
3055+
return a.synthetic && !b.synthetic ? -1 : 1;
3056+
}
3057+
return a.longname < b.longname ? -1 : 1;
3058+
});
3059+
debug("sorting doclets by name done.");
3060+
3061+
// cleanup doclets
3062+
const rAnonymous = /^<anonymous>(~|$)/;
3063+
const l = doclets.length;
3064+
let j = 0;
3065+
for (let i = 0; i < l; i++) {
3066+
const doclet = doclets[i];
3067+
3068+
// skip undocumented, ignored, anonymous entities as well as local entities
3069+
if (doclet.undocumented
3070+
|| doclet.ignore
3071+
|| (doclet.memberof && rAnonymous.test(doclet.memberof))
3072+
|| doclet.longname.includes("~") ) {
3073+
continue;
3074+
}
30393075

30403076
// check for duplicates: last one wins
30413077
if ( j > 0 && doclets[j - 1].longname === doclet.longname ) {
30423078
if ( !doclets[j - 1].synthetic && !doclet.__ui5.updatedDoclet ) {
3043-
// replacing synthetic comments or updating comments are trivial case. Just log non-trivial duplicates
3079+
// replacing synthetic comments or updating comments are trivial cases. Just log non-trivial duplicates
30443080
debug(`ignoring duplicate doclet for ${doclet.longname}: ${location(doclet)} overrides ${location(doclets[j - 1])}`);
30453081
}
30463082
doclets[j - 1] = doclet;
3047-
} else {
3048-
doclets[j++] = doclet;
3083+
continue;
30493084
}
3085+
3086+
doclets[j++] = doclet;
30503087
}
30513088

30523089
if ( j < l ) {
30533090
doclets.splice(j, l - j);
3054-
info(`removed ${l - j} duplicate symbols - ${doclets.length} remaining`);
3091+
info(`processingComplete: removed ${l - j} undocumented, ignored, anonymous, local or duplicate symbols - ${doclets.length} remaining`);
30553092
}
30563093

30573094
if ( pluginConfig.saveSymbols ) {
3058-
30593095
fs.mkPath(env.opts.destination);
3060-
fs.writeFileSync(path.join(env.opts.destination, "symbols-parseComplete.json"), JSON.stringify(e.doclets, null, "\t"), 'utf8');
3061-
3096+
fs.writeFileSync(path.join(env.opts.destination, "symbols-processingComplete.json"), JSON.stringify(e.doclets, null, "\t"), 'utf8');
30623097
}
3063-
30643098
}
30653099
};
30663100

0 commit comments

Comments
 (0)