diff --git a/config/jsdoc/plugins/inline-options.cjs b/config/jsdoc/plugins/inline-options.cjs index 61bd7e5990..704aa1d585 100644 --- a/config/jsdoc/plugins/inline-options.cjs +++ b/config/jsdoc/plugins/inline-options.cjs @@ -7,6 +7,47 @@ const properties = {}; +/** + * This parses the comment for `@template` annotations and returns an object with name / type pairs for all template + * values + * @param {string} comment a jsdoc comment to parse + * @return {Object} results + */ +function parseCommentForTemplates(comment) { + let remainingText = comment; + const results = {}; + while (true) { + const templateMatch = remainingText.match(/\* @template\s*([\s\S]*)/); + + if (!templateMatch) { + return results; + } + + remainingText = templateMatch[1]; + + if (remainingText[0] !== '{') { + continue; + } + + let index = 1; + let openParenthesis = 1; + while (openParenthesis > 0) { + if (remainingText[index] === '{') { + openParenthesis++; + } else if (remainingText[index] === '}') { + openParenthesis--; + } + index++; + } + const type = remainingText.slice(1, index - 1); + remainingText = remainingText.slice(index); + + const name = remainingText.match(/\s*(\S*)/)[1]; + + results[name] = type; + } +} + exports.handlers = { /** * Collects all typedefs, keyed by longname @@ -25,6 +66,7 @@ exports.handlers = { */ parseComplete: function (e) { const doclets = e.doclets; + for (let i = 0, ii = doclets.length; i < ii; ++i) { const doclet = doclets[i]; if (doclet.params) { @@ -32,14 +74,22 @@ exports.handlers = { for (let j = 0, jj = params.length; j < jj; ++j) { const param = params[j]; if (param.type && param.type.names) { - const type = param.type.names[0]; + let type = param.type.names[0]; + const genericMatches = type.match(/(^.*?)\.?<.*>/); + if (genericMatches) { + type = genericMatches[1]; + } if (type in properties) { - param.type.names[0] = type; + const templateInfo = parseCommentForTemplates(doclet.comment); params.push.apply( params, properties[type].map((p) => { const property = Object.assign({}, p); property.name = `${param.name}.${property.name}`; + if (property.type.names[0] in templateInfo) { + property.type.names[0] = + templateInfo[property.type.names[0]]; + } return property; }) ); diff --git a/src/ol/layer/BaseImage.js b/src/ol/layer/BaseImage.js index 798c38c111..8c7e38c376 100644 --- a/src/ol/layer/BaseImage.js +++ b/src/ol/layer/BaseImage.js @@ -4,6 +4,7 @@ import Layer from './Layer.js'; /** + * @template {import("../source/Image.js").default} ImageSourceType * @typedef {Object} Options * @property {string} [className='ol-layer'] A CSS class name to set to the layer element. * @property {number} [opacity=1] Opacity (0, 1). @@ -26,7 +27,7 @@ import Layer from './Layer.js'; * this layer in its layers collection, and the layer will be rendered on top. This is useful for * temporary layers. The standard way to add a layer to a map and have it managed by the map is to * use {@link module:ol/Map#addLayer}. - * @property {import("../source/Image.js").default} [source] Source for this layer. + * @property {ImageSourceType} [source] Source for this layer. * @property {Object} [properties] Arbitrary observable properties. Can be accessed with `#get()` and `#set()`. */ @@ -44,7 +45,7 @@ import Layer from './Layer.js'; */ class BaseImageLayer extends Layer { /** - * @param {Options} [opt_options] Layer options. + * @param {Options} [opt_options] Layer options. */ constructor(opt_options) { const options = opt_options ? opt_options : {}; diff --git a/src/ol/layer/BaseTile.js b/src/ol/layer/BaseTile.js index 4d6cede4ac..4207a737df 100644 --- a/src/ol/layer/BaseTile.js +++ b/src/ol/layer/BaseTile.js @@ -6,6 +6,7 @@ import TileProperty from './TileProperty.js'; import {assign} from '../obj.js'; /** + * @template {import("../source/Tile.js").default} TileSourceType * @typedef {Object} Options * @property {string} [className='ol-layer'] A CSS class name to set to the layer element. * @property {number} [opacity=1] Opacity (0, 1). @@ -26,7 +27,7 @@ import {assign} from '../obj.js'; * be visible. * @property {number} [preload=0] Preload. Load low-resolution tiles up to `preload` levels. `0` * means no preloading. - * @property {import("../source/Tile.js").default} [source] Source for this layer. + * @property {TileSourceType} [source] Source for this layer. * @property {import("../PluggableMap.js").default} [map] Sets the layer as overlay on a map. The map will not manage * this layer in its layers collection, and the layer will be rendered on top. This is useful for * temporary layers. The standard way to add a layer to a map and have it managed by the map is to @@ -49,7 +50,7 @@ import {assign} from '../obj.js'; */ class BaseTileLayer extends Layer { /** - * @param {Options} [opt_options] Tile layer options. + * @param {Options} [opt_options] Tile layer options. */ constructor(opt_options) { const options = opt_options ? opt_options : {}; diff --git a/src/ol/layer/BaseVector.js b/src/ol/layer/BaseVector.js index b7da84dbd3..8c8ad65f16 100644 --- a/src/ol/layer/BaseVector.js +++ b/src/ol/layer/BaseVector.js @@ -10,6 +10,7 @@ import { } from '../style/Style.js'; /** + * @template {import("../source/Vector.js").default|import("../source/VectorTile.js").default} VectorSourceType * @typedef {Object} Options * @property {string} [className='ol-layer'] A CSS class name to set to the layer element. * @property {number} [opacity=1] Opacity (0, 1). @@ -34,7 +35,7 @@ import { * @property {number} [renderBuffer=100] The buffer in pixels around the viewport extent used by the * renderer when getting features from the vector source for the rendering or hit-detection. * Recommended value: the size of the largest symbol, line width or label. - * @property {import("../source/Vector.js").default} [source] Source. + * @property {VectorSourceType} [source] Source. * @property {import("../PluggableMap.js").default} [map] Sets the layer as overlay on a map. The map will not manage * this layer in its layers collection, and the layer will be rendered on top. This is useful for * temporary layers. The standard way to add a layer to a map and have it managed by the map is to @@ -77,7 +78,7 @@ const Property = { */ class BaseVectorLayer extends Layer { /** - * @param {Options} [opt_options] Options. + * @param {Options} [opt_options] Options. */ constructor(opt_options) { const options = opt_options ? opt_options : {}; diff --git a/src/ol/layer/Image.js b/src/ol/layer/Image.js index 1d52dbe43f..90c49319c5 100644 --- a/src/ol/layer/Image.js +++ b/src/ol/layer/Image.js @@ -18,7 +18,7 @@ import CanvasImageLayerRenderer from '../renderer/canvas/ImageLayer.js'; */ class ImageLayer extends BaseImageLayer { /** - * @param {import("./BaseImage.js").Options} [opt_options] Layer options. + * @param {import("./BaseImage.js").Options} [opt_options] Layer options. */ constructor(opt_options) { super(opt_options); diff --git a/src/ol/layer/Layer.js b/src/ol/layer/Layer.js index f5b3cd1219..1dc67905d2 100644 --- a/src/ol/layer/Layer.js +++ b/src/ol/layer/Layer.js @@ -16,6 +16,7 @@ import {listen, unlistenByKey} from '../events.js'; */ /** + * @template {import("../source/Source.js").default} SourceType * @typedef {Object} Options * @property {string} [className='ol-layer'] A CSS class name to set to the layer element. * @property {number} [opacity=1] Opacity (0, 1). @@ -34,7 +35,7 @@ import {listen, unlistenByKey} from '../events.js'; * visible. * @property {number} [maxZoom] The maximum view zoom level (inclusive) at which this layer will * be visible. - * @property {import("../source/Source.js").default} [source] Source for this layer. If not provided to the constructor, + * @property {SourceType} [source] Source for this layer. If not provided to the constructor, * the source can be set by calling {@link module:ol/layer/Layer#setSource layer.setSource(source)} after * construction. * @property {import("../PluggableMap.js").default} [map] Map. @@ -88,7 +89,7 @@ import {listen, unlistenByKey} from '../events.js'; */ class Layer extends BaseLayer { /** - * @param {Options} options Layer options. + * @param {Options} options Layer options. */ constructor(options) { const baseOptions = assign({}, options); diff --git a/src/ol/layer/Tile.js b/src/ol/layer/Tile.js index 0898da7457..ed9dbd6554 100644 --- a/src/ol/layer/Tile.js +++ b/src/ol/layer/Tile.js @@ -18,7 +18,7 @@ import CanvasTileLayerRenderer from '../renderer/canvas/TileLayer.js'; */ class TileLayer extends BaseTileLayer { /** - * @param {import("./BaseTile.js").Options} [opt_options] Tile layer options. + * @param {import("./BaseTile.js").Options} [opt_options] Tile layer options. */ constructor(opt_options) { super(opt_options); diff --git a/src/ol/layer/Vector.js b/src/ol/layer/Vector.js index 1de881bc95..5658ed3854 100644 --- a/src/ol/layer/Vector.js +++ b/src/ol/layer/Vector.js @@ -17,7 +17,7 @@ import CanvasVectorLayerRenderer from '../renderer/canvas/VectorLayer.js'; */ class VectorLayer extends BaseVectorLayer { /** - * @param {import("./BaseVector.js").Options} [opt_options] Options. + * @param {import("./BaseVector.js").Options} [opt_options] Options. */ constructor(opt_options) { super(opt_options); diff --git a/src/ol/layer/VectorImage.js b/src/ol/layer/VectorImage.js index ecb07c0723..9c01895cd7 100644 --- a/src/ol/layer/VectorImage.js +++ b/src/ol/layer/VectorImage.js @@ -6,6 +6,7 @@ import CanvasVectorImageLayerRenderer from '../renderer/canvas/VectorImageLayer. import {assign} from '../obj.js'; /** + * @template {import("../source/Vector.js").default} VectorSourceType * @typedef {Object} Options * @property {string} [className='ol-layer'] A CSS class name to set to the layer element. * @property {number} [opacity=1] Opacity (0, 1). @@ -30,7 +31,7 @@ import {assign} from '../obj.js'; * @property {number} [renderBuffer=100] The buffer in pixels around the viewport extent used by the * renderer when getting features from the vector source for the rendering or hit-detection. * Recommended value: the size of the largest symbol, line width or label. - * @property {import("../source/Vector.js").default} [source] Source. + * @property {VectorSourceType} [source] Source. * @property {import("../PluggableMap.js").default} [map] Sets the layer as overlay on a map. The map will not manage * this layer in its layers collection, and the layer will be rendered on top. This is useful for * temporary layers. The standard way to add a layer to a map and have it managed by the map is to @@ -58,7 +59,7 @@ import {assign} from '../obj.js'; */ class VectorImageLayer extends BaseVectorLayer { /** - * @param {Options} [opt_options] Options. + * @param {Options} [opt_options] Options. */ constructor(opt_options) { const options = opt_options ? opt_options : {}; diff --git a/src/ol/layer/VectorTile.js b/src/ol/layer/VectorTile.js index 538b523a06..ca11b7f2d6 100644 --- a/src/ol/layer/VectorTile.js +++ b/src/ol/layer/VectorTile.js @@ -88,7 +88,9 @@ class VectorTileLayer extends BaseVectorLayer { delete baseOptions.preload; delete baseOptions.useInterimTilesOnError; - super(/** @type {import("./BaseVector.js").Options} */ (baseOptions)); + super( + /** @type {import("./BaseVector.js").Options} */ (baseOptions) + ); if (options.renderMode === VectorTileRenderType.IMAGE) { //FIXME deprecated - remove this check in v7. diff --git a/src/ol/layer/WebGLPoints.js b/src/ol/layer/WebGLPoints.js index 6681d95ad9..0597ebf1d0 100644 --- a/src/ol/layer/WebGLPoints.js +++ b/src/ol/layer/WebGLPoints.js @@ -7,6 +7,7 @@ import {assign} from '../obj.js'; import {parseLiteralStyle} from '../webgl/ShaderBuilder.js'; /** + * @template {import("../source/Vector.js").default} VectorSourceType * @typedef {Object} Options * @property {import('../style/literal.js').LiteralStyle} style Literal style to apply to the layer features. * @property {string} [className='ol-layer'] A CSS class name to set to the layer element. @@ -26,7 +27,7 @@ import {parseLiteralStyle} from '../webgl/ShaderBuilder.js'; * visible. * @property {number} [maxZoom] The maximum view zoom level (inclusive) at which this layer will * be visible. - * @property {import("../source/Vector.js").default} [source] Source. + * @property {VectorSourceType} [source] Source. * @property {boolean} [disableHitDetection=false] Setting this to true will provide a slight performance boost, but will * prevent all hit detection on the layer. * @property {Object} [properties] Arbitrary observable properties. Can be accessed with `#get()` and `#set()`. @@ -73,7 +74,7 @@ import {parseLiteralStyle} from '../webgl/ShaderBuilder.js'; */ class WebGLPointsLayer extends Layer { /** - * @param {Options} options Options. + * @param {Options} options Options. */ constructor(options) { const baseOptions = assign({}, options);