@@ -2432,6 +2432,21 @@ function location(doclet) {
24322432 return " #" + ui5data ( doclet ) . id + "@" + filename + ( doclet . meta . lineno != null ? ":" + doclet . meta . lineno : "" ) + ( doclet . synthetic ? "(synthetic)" : "" ) ;
24332433}
24342434
2435+ /**
2436+ * Converts a JSDoc name to a UI5 runtime metadata name.
2437+ *
2438+ * Basically, global names in dot notation don't require a conversion. Only when the JSDoc name
2439+ * is a `module:*` name, the prefix is removed and slashes are converted to dots.
2440+ *
2441+ * Note: the conversion in the opposite direction is not well-defined as not every dot has to be
2442+ * converted to a slash (e.g. not for named exports or subtypes in another module). This
2443+ * also implies that two different JSDoc names might map to the same UI5 runtime metadata
2444+ * name. API design should avoid such ambiguities.
2445+ */
2446+ function toRuntimeMetadataName ( longname ) {
2447+ return longname ?. startsWith ( "module:" ) ? longname . slice ( "module:" . length ) . replace ( / \/ / g, "." ) : longname ;
2448+ }
2449+
24352450// ---- Comment handling ---------------------------------------------------------------------------
24362451
24372452// --- comment related functions that depend on the JSdoc version (e.g. on the used parser)
@@ -2966,7 +2981,7 @@ exports.handlers = {
29662981 // add metadata to class symbols
29672982 let classInfo = classInfos [ doclet . longname ] ;
29682983 if ( classInfo == null && doclet . longname ?. startsWith ( "module:" ) ) {
2969- classInfo = classInfos [ doclet . longname . slice ( "module:" . length ) . replace ( / \/ / g , "." ) ] ;
2984+ classInfo = classInfos [ toRuntimeMetadataName ( doclet . longname ) ] ;
29702985 }
29712986 if ( classInfo ) {
29722987 // debug("class data", doclet.longname, "'" + classInfos[doclet.longname].export + "'");
@@ -3000,11 +3015,18 @@ exports.handlers = {
30003015 // derive interface implementations from UI5 metadata
30013016 if ( doclet . __ui5 . metadata . interfaces && doclet . __ui5 . metadata . interfaces . length ) {
30023017 /* eslint-disable no-loop-func */
3003- doclet . __ui5 . metadata . interfaces . forEach ( ( intf ) => {
3018+ doclet . __ui5 . metadata . interfaces . forEach ( ( rtmIntf ) => {
30043019 doclet . implements = doclet . implements || [ ] ;
3005- if ( doclet . implements . indexOf ( intf ) < 0 ) {
3006- info ( ` @implements ${ intf } derived from UI5 metadata (${ doclet . longname } )` ) ;
3007- doclet . implements . push ( intf ) ;
3020+ // add an interface only if no "matching" JSDoc interface is present already
3021+
3022+ // TODO if the JSDoc name and runtime metadata name of an interface differ,
3023+ // this today requires redundant documentation. Ideally, the JSDoc plugin
3024+ // should handle this and convert the runtime metadata name to the JSDoc name.
3025+ // Unfortunately, at this processing step here, the necessary information is
3026+ // not yet available (external APIs are loaded only later).
3027+ if ( doclet . implements . every ( ( jsdocIntf ) => toRuntimeMetadataName ( jsdocIntf ) !== rtmIntf ) ) {
3028+ info ( ` @implements ${ rtmIntf } derived from UI5 metadata (${ doclet . longname } )` ) ;
3029+ doclet . implements . push ( rtmIntf ) ;
30083030 }
30093031 } ) ;
30103032 /* eslint-enable no-loop-func */
@@ -3014,7 +3036,7 @@ exports.handlers = {
30143036 // add DataType info to typedef symbols
30153037 let typeInfo = typeInfos [ doclet . longname ] ;
30163038 if ( typeInfo == null && doclet . longname ?. startsWith ( "module:" ) ) {
3017- typeInfo = typeInfos [ doclet . longname . slice ( "module:" . length ) . replace ( / \/ / g , "." ) ] ;
3039+ typeInfo = typeInfos [ toRuntimeMetadataName ( doclet . longname ) ] ;
30183040 }
30193041 if ( typeInfo ) {
30203042 doclet . __ui5 . stereotype = 'datatype' ;
0 commit comments