diff --git a/packages/kbn-docs-utils/src/README.md b/packages/kbn-docs-utils/src/README.md index ae93d98bd4141..ca1b17efee728 100644 --- a/packages/kbn-docs-utils/src/README.md +++ b/packages/kbn-docs-utils/src/README.md @@ -1,25 +1,25 @@ -# Autogenerated API documentation. +# Autogenerated API documentation -[RFC](https://github.com/elastic/kibana/blob/main/legacy_rfcs/text/0014_api_documentation.md). +[RFC](https://github.com/elastic/kibana/blob/main/legacy_rfcs/text/0014_api_documentation.md) This package builds and validates API documentation for Kibana plugins and packages. Use `node scripts/build_api_docs` to emit docs to `api_docs/`, or `node scripts/check_package_docs` to validate JSDoc without writing files. -## CLI commands. +## CLI commands -### Build API docs (`node scripts/build_api_docs`). +### Build API docs (`node scripts/build_api_docs`) - Generates docs into `api_docs/` using [`src/build_api_docs_cli.ts`](./build_api_docs_cli.ts). - `--plugin ` limits to a single plugin or package; `--package` is an alias. - `--references` collects references for API items. - `--stats ` is deprecated and routes validation to `check_package_docs` without writing docs. -### Check package docs (`node scripts/check_package_docs`). +### Check package docs (`node scripts/check_package_docs`) - Runs validation only (no docs written) via [`src/check_package_docs_cli.ts`](./check_package_docs_cli.ts); output folder is `api_docs_check/`. - `--plugin ` and `--package ` filter targets; omit to check all plugins. - `--check ` selects checks; defaults to `all` (equivalent to `any`, `comments`, and `exports`). - Multiple `--check` flags combine checks. - Exits with a non-zero code if any selected checks fail. -## Validation rules. +## Validation rules - `any` check: fails when API declarations use `any` (`TypeKind.AnyKind`). - `comments` check: fails when descriptions are missing for API items. - `exports` check: fails when public API items are missing from plugin exports discovered during analysis. diff --git a/packages/kbn-docs-utils/src/build_api_declarations/build_api_declaration.test.ts b/packages/kbn-docs-utils/src/build_api_declarations/build_api_declaration.test.ts index 949c1c828482d..de941807af844 100644 --- a/packages/kbn-docs-utils/src/build_api_declarations/build_api_declaration.test.ts +++ b/packages/kbn-docs-utils/src/build_api_declarations/build_api_declaration.test.ts @@ -229,9 +229,10 @@ describe('Parameter extraction', () => { const hiProp = paramObj!.children!.find((c) => c.label === 'hi'); expect(hiProp).toBeDefined(); expect(hiProp!.type).toBe(TypeKind.StringKind); + expect(hiProp!.description?.[0]).toContain('Greeting'); - // Second parameter: { fn1, fn2 }: { fn1: Function, fn2: Function } - const paramFn = def.children!.find((c) => c.label === '{ fn1, fn2 }'); + // Second parameter: fns: { fn1: Function, fn2: Function } + const paramFn = def.children!.find((c) => c.label === 'fns'); expect(paramFn).toBeDefined(); expect(paramFn!.children).toBeDefined(); expect(paramFn!.children!.length).toBe(2); @@ -239,16 +240,23 @@ describe('Parameter extraction', () => { const fn1 = paramFn!.children!.find((c) => c.label === 'fn1'); expect(fn1).toBeDefined(); expect(fn1!.type).toBe(TypeKind.FunctionKind); + const fn1Desc = fn1?.description?.[0] ?? ''; + expect(fn1Desc).toContain('first function'); const fn2 = paramFn!.children!.find((c) => c.label === 'fn2'); expect(fn2).toBeDefined(); expect(fn2!.type).toBe(TypeKind.FunctionKind); + const fn2Desc = fn2?.description?.[0] ?? ''; + expect(fn2Desc).toContain('second function'); - // Third parameter: { str }: { str: string } - const paramStr = def.children!.find((c) => c.label === '{ str }'); + // Third parameter: strObj: { str: string } + const paramStr = def.children!.find((c) => c.label === 'strObj'); expect(paramStr).toBeDefined(); expect(paramStr!.children).toBeDefined(); expect(paramStr!.children!.length).toBe(1); + + const strProp = paramStr!.children!.find((c) => c.label === 'str'); + expect(strProp?.description?.[0]).toContain('string property'); }); it('extracts nested destructured parameters', () => { @@ -262,8 +270,8 @@ describe('Parameter extraction', () => { captureReferences: false, }); - // Check nested structure: { fn1, fn2 }.fn1.foo.param - const paramFn = def.children!.find((c) => c.label === '{ fn1, fn2 }'); + // Check nested structure: fns.fn1.foo.param + const paramFn = def.children!.find((c) => c.label === 'fns'); expect(paramFn).toBeDefined(); const fn1 = paramFn!.children!.find((c) => c.label === 'fn1'); @@ -425,19 +433,12 @@ describe('Parameter extraction', () => { // First parameter has @param obj comment const paramObj = def.children!.find((c) => c.label === 'obj'); expect(paramObj).toBeDefined(); - // Current behavior: parent parameter comments are NOT extracted for TypeLiteral parameters - // This is a known limitation - when a parameter has a TypeLiteral type (destructured params), - // buildApiDeclaration is called directly without extracting the JSDoc comment for the parameter name. - // This will be fixed in Phase 4.1 expect(paramObj!.description).toBeDefined(); - // Currently, the description is empty for destructured parameters - // After Phase 4.1, this should contain the @param obj comment - expect(paramObj!.description!.length).toBe(0); + expect(paramObj!.description!.length).toBeGreaterThan(0); + expect(paramObj!.description![0]).toContain('crazy parameter'); }); - it('does not extract property-level JSDoc comments (current limitation)', () => { - // This test documents current behavior: property-level @param tags like @param obj.hi - // are not currently extracted. This will be fixed in Phase 4.1. + it('extracts property-level JSDoc comments for destructured parameters', () => { const node = nodes.find((n) => getNodeName(n) === 'crazyFunction'); expect(node).toBeDefined(); const def = buildApiDeclarationTopNode(node!, { @@ -453,11 +454,9 @@ describe('Parameter extraction', () => { const hiProp = paramObj!.children!.find((c) => c.label === 'hi'); expect(hiProp).toBeDefined(); - // Current behavior: property-level comments are not extracted - // Even if @param obj.hi existed, it wouldn't be found - // This is a known limitation that will be addressed in Phase 4.1 expect(hiProp!.description).toBeDefined(); - expect(hiProp!.description!.length).toBe(0); + expect(hiProp!.description!.length).toBeGreaterThan(0); + expect(hiProp!.description![0]).toContain('Greeting'); }); }); diff --git a/packages/kbn-docs-utils/src/build_api_declarations/build_parameter_decs.ts b/packages/kbn-docs-utils/src/build_api_declarations/build_parameter_decs.ts index 49c5e2faef103..5adf3c878e246 100644 --- a/packages/kbn-docs-utils/src/build_api_declarations/build_parameter_decs.ts +++ b/packages/kbn-docs-utils/src/build_api_declarations/build_parameter_decs.ts @@ -10,44 +10,206 @@ import type { ParameterDeclaration, JSDoc } from 'ts-morph'; import { SyntaxKind } from 'ts-morph'; import { extractImportReferences } from './extract_import_refs'; -import type { ApiDeclaration } from '../types'; +import type { ApiDeclaration, TextWithLinks } from '../types'; import { buildApiDeclaration } from './build_api_declaration'; -import { getJSDocParamComment } from './js_doc_utils'; import { buildBasicApiDeclaration } from './build_basic_api_declaration'; import type { BuildApiDecOpts } from './types'; import { buildApiId, getOptsForChild } from './utils'; /** - * A helper function to capture function parameters, whether it comes from an arrow function, a regular function or - * a function type. + * Cache for pre-parsed JSDoc parameter comments, keyed by normalized parameter name. */ -export function buildApiDecsForParameters( - params: ParameterDeclaration[], +type ParamCommentCache = Map; + +/** + * Removes braces and all whitespace in a name for cache key normalization. + */ +const normalizeForCache = (name: string): string => name.replace(/[{}\s]/g, ''); + +/** + * Removes braces and normalizes whitespace in a name. + */ +const cleanName = (name: string): string => name.replace(/[{}]/g, '').replace(/\s+/g, ' ').trim(); + +/** + * Removes braces and all whitespace in a name for tight matching. + */ +const normalizeTight = (name: string): string => + name.replace(/[{}]/g, '').replace(/\s+/g, '').trim(); + +/** + * Pre-parses all `@param` entries from JSDoc into a cache for efficient lookups. + * This avoids re-parsing raw JSDoc text for each parameter in deep object structures. + */ +const buildParamCommentCache = (jsDocs: JSDoc[] | undefined): ParamCommentCache => { + const cache: ParamCommentCache = new Map(); + + if (!jsDocs) { + return cache; + } + + for (const jsDoc of jsDocs) { + const text = jsDoc.getText(); + const lines = text.split(/\r?\n/); + + for (const line of lines) { + const trimmed = line.replace(/^\s*\*\s?/, ''); + if (!trimmed.includes('@param')) { + continue; + } + + const body = trimmed.trim().replace(/^@param\s+/, ''); + const parts = body.split(/\s+/); + if (parts.length === 0) { + continue; + } + + // Skip type annotation if present (e.g., "{string} paramName"). + let nameIndex = 0; + if (parts[0].startsWith('{')) { + while (nameIndex < parts.length && !parts[nameIndex].endsWith('}')) { + nameIndex += 1; + } + nameIndex += 1; + } + + const nameToken = parts[nameIndex]; + if (!nameToken) { + continue; + } + + const commentText = parts + .slice(nameIndex + 1) + .join(' ') + .trim(); + if (commentText) { + const normalizedKey = normalizeForCache(nameToken); + cache.set(normalizedKey, [commentText]); + } + } + } + + return cache; +}; + +/** + * Generates candidate path strings for matching JSDoc parameter comments. + * JSDoc can reference parameters in various formats, so we generate multiple variations. + */ +const generatePathCandidates = (path: string[]): string[] => { + if (path.length === 0) { + return []; + } + + const candidates = new Set(); + + // Original path with dots + candidates.add(path.join('.')); + + // Path with cleaned first element (normalized whitespace) + const cleanedFirst = cleanName(path[0]); + candidates.add([cleanedFirst, ...path.slice(1)].join('.')); + + // Path with all elements normalized tightly (no whitespace) + const tightPath = path.map(normalizeTight).join('.'); + candidates.add(tightPath); + + // For single-element paths, also include the raw name + if (path.length === 1) { + candidates.add(path[0]); + } + + return Array.from(candidates).filter(Boolean); +}; + +/** + * Looks up a parameter comment from the cache using candidate path strings. + */ +const lookupParamComment = ( + cache: ParamCommentCache, + path: string[] +): TextWithLinks | undefined => { + const candidates = generatePathCandidates(path); + for (const candidate of candidates) { + const normalizedKey = normalizeForCache(candidate); + const comment = cache.get(normalizedKey); + if (comment) { + return comment; + } + } + return undefined; +}; + +/** + * Applies JSDoc parameter comments to an API declaration and its children recursively. + * Uses a pre-built cache to avoid re-parsing JSDoc text for each node. + */ +const applyParamComments = ( + apiDec: ApiDeclaration, + cache: ParamCommentCache, + path: string[] +): void => { + if (cache.size === 0 || path.length === 0) { + return; + } + + const comment = lookupParamComment(cache, path); + + if (comment && comment.length > 0) { + apiDec.description = comment; + } + + // Recursively apply comments to children. + if (apiDec.children) { + apiDec.children.forEach((child) => { + applyParamComments(child, cache, [...path, child.label]); + }); + } +}; + +/** + * Builds an API declaration for a single parameter. + */ +const buildParameterDeclaration = ( + param: ParameterDeclaration, + index: number, parentOpts: BuildApiDecOpts, - jsDocs?: JSDoc[] -): ApiDeclaration[] { - return params.reduce((acc, param, index) => { - const id = buildApiId(`$${index + 1}`, parentOpts.id); - const opts = { - ...getOptsForChild(param, parentOpts), - id, - }; - - opts.log.debug(`Getting parameter doc def for ${opts.name} of kind ${param.getKindName()}`); - // Literal types are non primitives that aren't references to other types. We add them as a more - // defined node, with children. - // If we don't want the docs to be too deeply nested we could avoid this special handling. - if (param.getTypeNode() && param.getTypeNode()!.getKind() === SyntaxKind.TypeLiteral) { - acc.push(buildApiDeclaration(param.getTypeNode()!, opts)); - } else { - const apiDec = buildBasicApiDeclaration(param, opts); - acc.push({ - ...apiDec, + cache: ParamCommentCache +): ApiDeclaration => { + const id = buildApiId(`$${index + 1}`, parentOpts.id); + const opts = { + ...getOptsForChild(param, parentOpts), + id, + }; + + opts.log.debug(`Getting parameter doc def for ${opts.name} of kind ${param.getKindName()}`); + + const typeNode = param.getTypeNode(); + const isTypeLiteral = typeNode?.getKind() === SyntaxKind.TypeLiteral; + + // Type literals are inline object types that should be expanded with children. + // Other types are handled as basic declarations with signatures. + const apiDec = isTypeLiteral + ? buildApiDeclaration(typeNode!, opts) + : { + ...buildBasicApiDeclaration(param, opts), isRequired: param.getType().isNullable() === false, signature: extractImportReferences(param.getType().getText(), opts.plugins, opts.log), - description: jsDocs ? getJSDocParamComment(jsDocs, opts.name) : [], - }); - } - return acc; - }, [] as ApiDeclaration[]); -} + }; + + applyParamComments(apiDec, cache, [opts.name]); + return apiDec; +}; + +/** + * Builds API declarations for function parameters, whether from arrow functions, + * regular functions, or function types. + */ +export const buildApiDecsForParameters = ( + params: ParameterDeclaration[], + parentOpts: BuildApiDecOpts, + jsDocs?: JSDoc[] +): ApiDeclaration[] => { + const cache = buildParamCommentCache(jsDocs); + return params.map((param, index) => buildParameterDeclaration(param, index, parentOpts, cache)); +}; diff --git a/packages/kbn-docs-utils/src/build_api_declarations/js_doc_utils.test.ts b/packages/kbn-docs-utils/src/build_api_declarations/js_doc_utils.test.ts index 66c12f5ccf52b..30afada75bf0a 100644 --- a/packages/kbn-docs-utils/src/build_api_declarations/js_doc_utils.test.ts +++ b/packages/kbn-docs-utils/src/build_api_declarations/js_doc_utils.test.ts @@ -112,20 +112,21 @@ describe('getJSDocParamComment', () => { expect(comment[0]).toContain('crazy parameter'); }); - it('does not extract property-level parameter comments (current limitation)', () => { - // This test documents current behavior: property-level @param tags like @param obj.hi - // are not currently extracted. This will be fixed in Phase 4.1. + it('extracts property-level parameter comments for destructured params', () => { const node = getNodeByName('crazyFunction'); expect(node).toBeDefined(); - // Current behavior: property-level tags are not found const comment = getJSDocParamComment(node!, 'obj.hi'); - expect(comment).toBeDefined(); - expect(comment.length).toBe(0); // Currently returns empty, should be fixed in Phase 4.1 + expect(comment.length).toBeGreaterThan(0); + expect(comment[0]).toContain('Greeting'); - // Also test with destructured parameter name format - const comment2 = getJSDocParamComment(node!, '{ fn1, fn2 }.fn1'); - expect(comment2.length).toBe(0); // Currently returns empty + const comment2 = getJSDocParamComment(node!, 'fns.fn1'); + expect(comment2.length).toBeGreaterThan(0); + expect(comment2[0]).toContain('first function'); + + const nested = getJSDocParamComment(node!, 'fns.fn1.foo.param'); + expect(nested.length).toBeGreaterThan(0); + expect(nested[0]).toContain('nested parameter for foo'); }); it('works with JSDoc array input', () => { @@ -359,38 +360,23 @@ describe('getCommentsFromNode', () => { }); }); -describe('property-level JSDoc parameter tags (future enhancement)', () => { - it('currently does not support dot notation in parameter names', () => { - // This test documents the current limitation - // In Phase 4.1, we'll enhance getJSDocParamComment to support: - // - @param obj.prop - // - @param { fn1, fn2 }.fn1 - // - @param obj.nested.prop - +describe('property-level JSDoc parameter tags', () => { + it('supports dot notation in parameter names', () => { const node = getNodeByName('crazyFunction'); expect(node).toBeDefined(); - // Current behavior: dot notation is not supported const comment1 = getJSDocParamComment(node!, 'obj.hi'); - expect(comment1.length).toBe(0); + expect(comment1.length).toBeGreaterThan(0); - const comment2 = getJSDocParamComment(node!, 'obj.nested.prop'); - expect(comment2.length).toBe(0); - - // Future: should support destructured parameter names - const comment3 = getJSDocParamComment(node!, '{ fn1, fn2 }.fn1'); - expect(comment3.length).toBe(0); + const comment3 = getJSDocParamComment(node!, 'fns.fn1'); + expect(comment3.length).toBeGreaterThan(0); }); - it('should support nested property access patterns (future)', () => { - // This test documents expected future behavior after Phase 4.1 - // When property-level JSDoc is implemented, these should work: - // - @param obj.prop - // - @param obj.nested.prop - // - @param { destructured }.prop - // - @param { destructured }.nested.prop + it('supports nested property access patterns', () => { + const node = getNodeByName('crazyFunction'); + expect(node).toBeDefined(); - // For now, we just document that this is not yet supported - expect(true).toBe(true); // Placeholder test + const nested = getJSDocParamComment(node!, 'fns.fn1.foo.param'); + expect(nested.length).toBeGreaterThan(0); }); }); diff --git a/packages/kbn-docs-utils/src/build_api_declarations/js_doc_utils.ts b/packages/kbn-docs-utils/src/build_api_declarations/js_doc_utils.ts index 7632e737d5762..86d7d970f3ab9 100644 --- a/packages/kbn-docs-utils/src/build_api_declarations/js_doc_utils.ts +++ b/packages/kbn-docs-utils/src/build_api_declarations/js_doc_utils.ts @@ -12,69 +12,178 @@ import { Node } from 'ts-morph'; import type { TextWithLinks } from '../types'; /** - * Extracts comments out of the node to use as the description. + * Extracts comments from a node to use as the description. + * Prefers JSDoc descriptions over leading comments. */ -export function getCommentsFromNode(node: Node): TextWithLinks | undefined { - let comments: TextWithLinks | undefined; +export const getCommentsFromNode = (node: Node): TextWithLinks | undefined => { const jsDocs = getJSDocs(node); if (jsDocs) { - return getTextWithLinks(jsDocs.map((jsDoc) => jsDoc.getDescription()).join('\n')); - } else { - comments = getTextWithLinks( - node - .getLeadingCommentRanges() - .map((c) => c.getText()) - .join('\n') - ); + const description = jsDocs.map((jsDoc) => jsDoc.getDescription()).join('\n'); + return getTextWithLinks(description); } - return comments; -} + const leadingComments = node + .getLeadingCommentRanges() + .map((c) => c.getText()) + .join('\n'); -export function getJSDocs(node: Node): JSDoc[] | undefined { + return getTextWithLinks(leadingComments); +}; + +/** + * Extracts JSDoc comments from a node. + * For variable declarations, checks the grandparent (VariableStatement) for JSDoc. + */ +export const getJSDocs = (node: Node): JSDoc[] | undefined => { if (Node.isJSDocable(node)) { return node.getJsDocs(); - } else if (Node.isVariableDeclaration(node)) { - const gparent = node.getParent()?.getParent(); - if (Node.isJSDocable(gparent)) { - return gparent.getJsDocs(); + } + + if (Node.isVariableDeclaration(node)) { + const grandparent = node.getParent()?.getParent(); + + if (Node.isJSDocable(grandparent)) { + return grandparent.getJsDocs(); } } -} -export function getJSDocReturnTagComment(node: Node | JSDoc[]): TextWithLinks { + return undefined; +}; + +/** + * Extracts the @returns comment from a node or JSDoc array. + */ +export const getJSDocReturnTagComment = (node: Node | JSDoc[]): TextWithLinks => { const tags = getJSDocTags(node); const returnTag = tags.find((tag) => Node.isJSDocReturnTag(tag)); - if (returnTag) return getTextWithLinks(returnTag.getCommentText()); - return []; -} + return returnTag ? getTextWithLinks(returnTag.getCommentText()) : []; +}; + +/** + * Normalizes a parameter name by removing braces and whitespace for matching. + */ +const normalizeParamName = (name: string): string => name.replace(/[{}\s]/g, ''); + +/** + * Checks if a tag name matches any of the normalized parameter names. + * Uses exact matching only to avoid cross-parameter leakage where a tag like + * `@param options.foo` could incorrectly match a separate parameter named `foo`. + */ +const matchesParamName = (tagName: string, normalizedNames: string[]): boolean => { + const normalizedTagName = normalizeParamName(tagName); + return normalizedNames.includes(normalizedTagName); +}; + +/** + * Parses raw JSDoc text to find @param entries that ts-morph might not normalize. + * Returns the comment text if a matching parameter is found. + */ +const parseParamFromRawText = (text: string, normalizedNames: string[]): TextWithLinks | null => { + const lines = text.split(/\r?\n/); + + for (const line of lines) { + const trimmed = line.replace(/^\s*\*\s?/, ''); + if (!trimmed.includes('@param')) continue; + + const body = trimmed.trim().replace(/^@param\s+/, ''); + const parts = body.split(/\s+/); + if (parts.length === 0) { + continue; + } + + // Skip type annotation if present (e.g., "{string} paramName") + let nameIndex = 0; + if (parts[0].startsWith('{')) { + while (nameIndex < parts.length && !parts[nameIndex].endsWith('}')) { + nameIndex += 1; + } + nameIndex += 1; // Move past the type token + } + + const nameToken = parts[nameIndex]; + if (!nameToken) { + continue; + } + + const commentText = parts.slice(nameIndex + 1).join(' '); -export function getJSDocParamComment(node: Node | JSDoc[], name: string): TextWithLinks { + if (matchesParamName(nameToken, normalizedNames)) { + return getTextWithLinks(commentText.trim()); + } + } + + return null; +}; + +/** + * Extracts JSDoc parameter comment for the given parameter name(s). + * Supports both single names and dot-notation paths (e.g., "obj.prop"). + */ +export const getJSDocParamComment = ( + node: Node | JSDoc[], + name: string | string[] +): TextWithLinks => { + const names = Array.isArray(name) ? name : [name]; + const normalizedNames = names.map(normalizeParamName); + + // First, try to find parameter tag using ts-morph's normalized tags const tags = getJSDocTags(node); - const paramTag = tags.find((tag) => Node.isJSDocParameterTag(tag) && tag.getName() === name); - if (paramTag) return getTextWithLinks(paramTag.getCommentText()); + const paramTag = tags.find((tag) => { + if (!Node.isJSDocParameterTag(tag)) { + return false; + } + + return matchesParamName(tag.getName(), normalizedNames); + }); + + if (paramTag) { + return getTextWithLinks(paramTag.getCommentText()); + } + + // Fallback: parse raw JSDoc text for @param entries that ts-morph might not normalize + const jsDocs = node instanceof Array ? node : getJSDocs(node); + if (jsDocs) { + for (const jsDoc of jsDocs) { + const parsed = parseParamFromRawText(jsDoc.getText(), normalizedNames); + if (parsed) { + return parsed; + } + } + } + + // Final fallback: scan leading comments for @param tags + if (!(node instanceof Array)) { + const leadingCommentRanges = node.getLeadingCommentRanges(); + if (leadingCommentRanges.length > 0) { + const leadingText = leadingCommentRanges.map((c) => c.getText()).join('\n'); + const parsed = parseParamFromRawText(leadingText, normalizedNames); + if (parsed) { + return parsed; + } + } + } + return []; -} +}; -export function getJSDocTags(node: Node | JSDoc[]): JSDocTag[] { +/** + * Extracts all JSDoc tags from a node or JSDoc array. + */ +export const getJSDocTags = (node: Node | JSDoc[]): JSDocTag[] => { const jsDocs = node instanceof Array ? node : getJSDocs(node); - if (!jsDocs) return []; + if (!jsDocs) { + return []; + } - return jsDocs.reduce((tagsAcc, jsDoc) => { - tagsAcc.push(...jsDoc.getTags()); - return tagsAcc; - }, [] as JSDocTag[]); -} + return jsDocs.flatMap((jsDoc) => jsDoc.getTags()); +}; /** - * TODO. This feature is not implemented yet. It will be used to create links for comments + * Converts text to TextWithLinks format. + * TODO: This feature is not fully implemented yet. It will be used to create links for comments * that use {@link AnotherAPIItemInThisPlugin}. - * - * @param text */ -function getTextWithLinks(text?: string): TextWithLinks { - if (text) return [text]; - else return []; - // TODO: - // Replace `@links` in comments with relative api links. -} +const getTextWithLinks = (text?: string): TextWithLinks => { + return text ? [text] : []; + // TODO: Replace `@links` in comments with relative api links. +}; diff --git a/packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts b/packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts index 108d7998a0e0a..033d50ffe845b 100644 --- a/packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts +++ b/packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts @@ -54,9 +54,18 @@ export const arrowFn = ( * Who would write such a complicated function?? Ewwww. * * According to https://jsdoc.app/tags-param.html#parameters-with-properties, - * this is how destructured arguements should be commented. + * this is how destructured arguments should be commented. + * Use a named object and dot-notation properties rather than inline destructuring. * - * @param obj A very crazy parameter that is destructured when passing in. + * @param {Object} obj A very crazy parameter that is destructured when passing in. + * @param {string} obj.hi Greeting on the obj. + * @param {{fn1: (foo: {param: string}) => number, fn2: () => void}} fns A destructured object containing two functions. + * @param {(foo: {param: string}) => number} fns.fn1 The first function. + * @param {() => void} fns.fn2 The second function. + * @param {{param: string}} fns.fn1.foo A parameter object for fn1. + * @param {string} fns.fn1.foo.param A nested parameter for foo. + * @param {{str: string}} strObj A destructured object containing a string. + * @param {string} strObj.str The string property. * * @returns I have no idea. * @@ -64,12 +73,12 @@ export const arrowFn = ( export const crazyFunction = ( obj: { hi: string }, - { fn1, fn2 }: { fn1: (foo: { param: string }) => number; fn2: () => void }, - { str }: { str: string } + fns: { fn1: (foo: { param: string }) => number; fn2: () => void }, + strObj: { str: string } ) => () => () => - fn1({ param: str }); + fns.fn1({ param: strObj.str }); export const fnWithNonExportedRef = (a: ImNotExportedFromIndex) => a; @@ -81,7 +90,7 @@ export type NotAnArrowFnType = typeof notAnArrowFn; export const iShouldBeInternalFn = () => 'hi'; // Expected issues: -// missing comments (27): +// missing comments (18): // line 24 - a // line 24 - a // line 24 - a @@ -97,18 +106,9 @@ export const iShouldBeInternalFn = () => 'hi'; // line 28 - e // line 28 - e // line 28 - e -// line 66 - hi -// line 66 - obj -// line 67 - { fn1, fn2 } -// line 67 - fn1 -// line 67 - fn2 -// line 67 - foo -// line 67 - param -// line 68 - { str } -// line 68 - str -// line 74 - a -// line 74 - fnWithNonExportedRef -// line 76 - NotAnArrowFnType +// line 83 - a +// line 83 - fnWithNonExportedRef +// line 85 - NotAnArrowFnType // no references (40): // line 13 - notAnArrowFn // line 24 - a @@ -137,16 +137,16 @@ export const iShouldBeInternalFn = () => 'hi'; // line 46 - c // line 47 - d // line 48 - e -// line 64 - crazyFunction -// line 66 - hi -// line 66 - obj -// line 67 - { fn1, fn2 } -// line 67 - fn1 -// line 67 - fn2 -// line 67 - foo -// line 67 - param -// line 68 - { str } -// line 68 - str -// line 74 - a -// line 74 - fnWithNonExportedRef -// line 76 - NotAnArrowFnType +// line 73 - crazyFunction +// line 75 - hi +// line 75 - obj +// line 76 - fn1 +// line 76 - fn2 +// line 76 - fns +// line 76 - foo +// line 76 - param +// line 77 - str +// line 77 - strObj +// line 83 - a +// line 83 - fnWithNonExportedRef +// line 85 - NotAnArrowFnType diff --git a/packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/plugin.ts b/packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/plugin.ts index 09e6208cc75e0..bb1c09732b285 100644 --- a/packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/plugin.ts +++ b/packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/plugin.ts @@ -93,7 +93,7 @@ export interface Setup { * on the spec. We aren't sure if this is a good function so it's marked * beta. That should be clear in the docs because of the js doc tag. * - * @param searchSpec Provide the settings neccessary to create a new Search Service + * @param searchSpec Provide the settings necessary to create a new Search Service * * @returns the id of the search service. * @@ -105,7 +105,7 @@ export interface Setup { * This uses an inlined object type rather than referencing an exported type, which is discouraged. * prefer the way {@link getSearchService} is typed. * - * @param searchSpec Provide the settings neccessary to create a new Search Service + * @param searchSpec Provide the settings necessary to create a new Search Service */ getSearchService2: (searchSpec: { username: string; password: string }) => string; @@ -178,14 +178,11 @@ export class PluginA implements PluginMock { } // Expected issues: -// missing comments (10): +// missing comments (7): // line 66 - getSearchLanguage // line 110 - password -// line 110 - searchSpec // line 110 - username // line 123 - nestedVar -// line 123 - thingThree -// line 134 - obj // line 135 - fn // line 135 - foo // line 135 - param diff --git a/packages/kbn-docs-utils/src/integration_tests/api_doc_suite.test.ts b/packages/kbn-docs-utils/src/integration_tests/api_doc_suite.test.ts index 61f9408a27c4e..a1e7f34e78e45 100644 --- a/packages/kbn-docs-utils/src/integration_tests/api_doc_suite.test.ts +++ b/packages/kbn-docs-utils/src/integration_tests/api_doc_suite.test.ts @@ -243,12 +243,12 @@ describe('functions', () => { const hi = obj?.children?.find((c) => c.label === 'hi'); expect(hi).toBeDefined(); - const obj2 = fn?.children?.find((c) => c.label === '{ fn1, fn2 }'); - expect(obj2).toBeDefined(); - expect(obj2!.children?.length).toBe(2); - expect(obj2!.id).toBe('def-public.crazyFunction.$2'); + const fnsParam = fn?.children?.find((c) => c.label === 'fns'); + expect(fnsParam).toBeDefined(); + expect(fnsParam!.children?.length).toBe(2); + expect(fnsParam!.id).toBe('def-public.crazyFunction.$2'); - const fn1 = obj2?.children?.find((c) => c.label === 'fn1'); + const fn1 = fnsParam?.children?.find((c) => c.label === 'fn1'); expect(fn1).toBeDefined(); expect(fn1?.type).toBe(TypeKind.FunctionKind); expect(fn1!.id).toBe('def-public.crazyFunction.$2.fn1'); @@ -762,8 +762,8 @@ describe('validation and stats', () => { expect(objParam!.children).toBeDefined(); expect(objParam!.children!.length).toBe(1); - // Second parameter: { fn1, fn2 } - const fnParam = fn!.children?.find((c) => c.label === '{ fn1, fn2 }'); + // Second parameter: fns: { fn1, fn2 } + const fnParam = fn!.children?.find((c) => c.label === 'fns'); expect(fnParam).toBeDefined(); expect(fnParam!.children).toBeDefined(); expect(fnParam!.children!.length).toBe(2); @@ -776,19 +776,12 @@ describe('validation and stats', () => { const objParam = fn!.children?.find((c) => c.label === 'obj'); expect(objParam).toBeDefined(); - // Current behavior: parent parameter comments are NOT extracted for TypeLiteral parameters - // This is a known limitation - when a parameter has a TypeLiteral type (destructured params), - // buildApiDeclaration is called directly without extracting the JSDoc comment for the parameter name. - // This will be fixed in Phase 4.1 expect(objParam!.description).toBeDefined(); - // Currently, the description is empty for destructured parameters - // After Phase 4.1, this should contain the @param obj comment - expect(objParam!.description!.length).toBe(0); + expect(objParam!.description!.length).toBeGreaterThan(0); + expect(objParam!.description![0]).toContain('crazy parameter'); }); - it('validates property-level comments are not currently extracted (current limitation)', () => { - // This test documents current behavior: property-level @param tags are not extracted - // After Phase 4.1, this should be updated to test that property-level comments ARE extracted + it('validates property-level comments are extracted', () => { const fn = doc.client.find((c) => c.label === 'crazyFunction'); expect(fn).toBeDefined(); @@ -798,17 +791,16 @@ describe('validation and stats', () => { const hiProp = objParam!.children?.find((c) => c.label === 'hi'); expect(hiProp).toBeDefined(); - // Current behavior: property-level comments are not extracted - // Even if @param obj.hi existed in JSDoc, it wouldn't be found expect(hiProp!.description).toBeDefined(); - expect(hiProp!.description!.length).toBe(0); + expect(hiProp!.description!.length).toBeGreaterThan(0); + expect(hiProp!.description![0]).toContain('Greeting'); }); it('validates nested destructured parameters are extracted', () => { const fn = doc.client.find((c) => c.label === 'crazyFunction'); expect(fn).toBeDefined(); - const fnParam = fn!.children?.find((c) => c.label === '{ fn1, fn2 }'); + const fnParam = fn!.children?.find((c) => c.label === 'fns'); expect(fnParam).toBeDefined(); const fn1 = fnParam!.children?.find((c) => c.label === 'fn1'); @@ -964,10 +956,8 @@ describe('validation and stats', () => { }); }); - describe('property-level JSDoc validation (future enhancement)', () => { - it('documents that property-level JSDoc is not currently validated', () => { - // This test documents current limitation - // After Phase 4.1, property-level @param tags like @param obj.prop should be validated + describe('property-level JSDoc validation', () => { + it('does not flag property-level JSDoc when present', () => { const fn = doc.client.find((c) => c.label === 'crazyFunction'); expect(fn).toBeDefined(); @@ -976,21 +966,14 @@ describe('validation and stats', () => { const hiProp = objParam!.children?.find((c) => c.label === 'hi'); expect(hiProp).toBeDefined(); + expect(hiProp!.description?.length).toBeGreaterThan(0); - // Current behavior: property-level comments are not checked - // Future: should check for @param obj.hi and not flag as missing if it exists const missingComment = pluginAStats.missingComments.find((d) => d.id === hiProp!.id); - // Currently flagged as missing (false positive) - expect(missingComment).toBeDefined(); + expect(missingComment).toBeUndefined(); }); - it('documents expected future behavior for property-level validation', () => { - // After Phase 4.1 and 4.2, the validation should: - // 1. Check for property-level @param tags (e.g., @param obj.prop) - // 2. Not flag as missing if parent has comment OR property-level tag exists - // 3. Support nested property access (e.g., @param obj.nested.prop) - - // For now, this is a placeholder test documenting expected behavior + it('documents expected behavior for property-level validation', () => { + // placeholder to keep suite shape; property-level validation is active expect(true).toBe(true); }); }); diff --git a/packages/kbn-docs-utils/src/integration_tests/snapshots/plugin_a.devdocs.json b/packages/kbn-docs-utils/src/integration_tests/snapshots/plugin_a.devdocs.json index 666d308b99ef2..d02895a347fd9 100644 --- a/packages/kbn-docs-utils/src/integration_tests/snapshots/plugin_a.devdocs.json +++ b/packages/kbn-docs-utils/src/integration_tests/snapshots/plugin_a.devdocs.json @@ -409,13 +409,13 @@ "tags": [], "label": "crazyFunction", "description": [ - "\nWho would write such a complicated function?? Ewwww.\n\nAccording to https://jsdoc.app/tags-param.html#parameters-with-properties,\nthis is how destructured arguements should be commented.\n" + "\nWho would write such a complicated function?? Ewwww.\n\nAccording to https://jsdoc.app/tags-param.html#parameters-with-properties,\nthis is how destructured arguments should be commented.\nUse a named object and dot-notation properties rather than inline destructuring.\n" ], "signature": [ - "(obj: { hi: string; }, { fn1, fn2 }: { fn1: (foo: { param: string; }) => number; fn2: () => void; }, { str }: { str: string; }) => () => () => number" + "(obj: { hi: string; }, fns: { fn1: (foo: { param: string; }) => number; fn2: () => void; }, strObj: { str: string; }) => () => () => number" ], "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", - "lineNumber": 64, + "lineNumber": 73, "columnNumber": 14, "deprecated": false, "trackAdoption": false, @@ -426,9 +426,11 @@ "type": "Object", "tags": [], "label": "obj", - "description": [], + "description": [ + "A very crazy parameter that is destructured when passing in." + ], "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", - "lineNumber": 66, + "lineNumber": 75, "columnNumber": 10, "deprecated": false, "trackAdoption": false, @@ -439,9 +441,11 @@ "type": "string", "tags": [], "label": "hi", - "description": [], + "description": [ + "Greeting on the obj." + ], "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", - "lineNumber": 66, + "lineNumber": 75, "columnNumber": 12, "deprecated": false, "trackAdoption": false @@ -453,11 +457,13 @@ "id": "def-public.crazyFunction.$2", "type": "Object", "tags": [], - "label": "{ fn1, fn2 }", - "description": [], + "label": "fns", + "description": [ + "A destructured object containing two functions." + ], "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", - "lineNumber": 67, - "columnNumber": 19, + "lineNumber": 76, + "columnNumber": 10, "deprecated": false, "trackAdoption": false, "children": [ @@ -467,13 +473,15 @@ "type": "Function", "tags": [], "label": "fn1", - "description": [], + "description": [ + "The first function." + ], "signature": [ "(foo: { param: string; }) => number" ], "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", - "lineNumber": 67, - "columnNumber": 21, + "lineNumber": 76, + "columnNumber": 12, "deprecated": false, "trackAdoption": false, "children": [ @@ -483,10 +491,12 @@ "type": "Object", "tags": [], "label": "foo", - "description": [], + "description": [ + "A parameter object for fn1." + ], "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", - "lineNumber": 67, - "columnNumber": 32, + "lineNumber": 76, + "columnNumber": 23, "deprecated": false, "trackAdoption": false, "children": [ @@ -496,10 +506,12 @@ "type": "string", "tags": [], "label": "param", - "description": [], + "description": [ + "A nested parameter for foo." + ], "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", - "lineNumber": 67, - "columnNumber": 34, + "lineNumber": 76, + "columnNumber": 25, "deprecated": false, "trackAdoption": false } @@ -514,13 +526,15 @@ "type": "Function", "tags": [], "label": "fn2", - "description": [], + "description": [ + "The second function." + ], "signature": [ "() => void" ], "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", - "lineNumber": 67, - "columnNumber": 62, + "lineNumber": 76, + "columnNumber": 53, "deprecated": false, "trackAdoption": false, "children": [], @@ -533,11 +547,13 @@ "id": "def-public.crazyFunction.$3", "type": "Object", "tags": [], - "label": "{ str }", - "description": [], + "label": "strObj", + "description": [ + "A destructured object containing a string." + ], "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", - "lineNumber": 68, - "columnNumber": 14, + "lineNumber": 77, + "columnNumber": 13, "deprecated": false, "trackAdoption": false, "children": [ @@ -547,10 +563,12 @@ "type": "string", "tags": [], "label": "str", - "description": [], + "description": [ + "The string property." + ], "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", - "lineNumber": 68, - "columnNumber": 16, + "lineNumber": 77, + "columnNumber": 15, "deprecated": false, "trackAdoption": false } @@ -576,7 +594,7 @@ "ImNotExportedFromIndex" ], "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", - "lineNumber": 74, + "lineNumber": 83, "columnNumber": 14, "deprecated": false, "trackAdoption": false, @@ -592,7 +610,7 @@ "ImNotExportedFromIndex" ], "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", - "lineNumber": 74, + "lineNumber": 83, "columnNumber": 38, "deprecated": false, "trackAdoption": false, @@ -1888,7 +1906,7 @@ "" ], "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", - "lineNumber": 76, + "lineNumber": 85, "columnNumber": 1, "deprecated": false, "trackAdoption": false, @@ -2498,7 +2516,7 @@ "tags": [], "label": "searchSpec", "description": [ - "Provide the settings neccessary to create a new Search Service" + "Provide the settings necessary to create a new Search Service" ], "signature": [ { @@ -2545,7 +2563,9 @@ "type": "Object", "tags": [], "label": "searchSpec", - "description": [], + "description": [ + "Provide the settings necessary to create a new Search Service" + ], "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/plugin.ts", "lineNumber": 110, "columnNumber": 35, @@ -2648,7 +2668,9 @@ "type": "Object", "tags": [], "label": "thingThree", - "description": [], + "description": [ + "Thing three is an object with a nested var" + ], "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/plugin.ts", "lineNumber": 123, "columnNumber": 64, @@ -2697,7 +2719,9 @@ "type": "Object", "tags": [], "label": "obj", - "description": [], + "description": [ + "A funky parameter." + ], "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/plugin.ts", "lineNumber": 134, "columnNumber": 29, diff --git a/packages/kbn-docs-utils/src/integration_tests/snapshots/plugin_a.mdx b/packages/kbn-docs-utils/src/integration_tests/snapshots/plugin_a.mdx index 66f913774e3ed..d12986c1b172c 100644 --- a/packages/kbn-docs-utils/src/integration_tests/snapshots/plugin_a.mdx +++ b/packages/kbn-docs-utils/src/integration_tests/snapshots/plugin_a.mdx @@ -21,7 +21,7 @@ Contact Kibana Core for questions regarding this plugin. | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 136 | 1 | 76 | 2 | +| 136 | 1 | 64 | 2 | ## Client diff --git a/packages/kbn-docs-utils/src/integration_tests/snapshots/plugin_a.stats.json b/packages/kbn-docs-utils/src/integration_tests/snapshots/plugin_a.stats.json index 8aea98ab33e4b..db8258e3e2d4c 100644 --- a/packages/kbn-docs-utils/src/integration_tests/snapshots/plugin_a.stats.json +++ b/packages/kbn-docs-utils/src/integration_tests/snapshots/plugin_a.stats.json @@ -2,19 +2,11 @@ "counts": { "apiCount": 136, "missingExports": 2, - "missingComments": 76, + "missingComments": 64, "isAnyType": 1, "noReferences": 135 }, "missingComments": [ - { - "id": "def-public.Setup.getSearchService2.$1", - "label": "searchSpec", - "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/plugin.ts", - "type": "Object", - "lineNumber": 110, - "columnNumber": 35 - }, { "id": "def-public.Setup.getSearchService2.$1.username", "label": "username", @@ -31,14 +23,6 @@ "lineNumber": 110, "columnNumber": 55 }, - { - "id": "def-public.Setup.doTheThing.$3", - "label": "thingThree", - "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/plugin.ts", - "type": "Object", - "lineNumber": 123, - "columnNumber": 64 - }, { "id": "def-public.Setup.doTheThing.$3.nestedVar", "label": "nestedVar", @@ -47,14 +31,6 @@ "lineNumber": 123, "columnNumber": 66 }, - { - "id": "def-public.Setup.fnWithInlineParams.$1", - "label": "obj", - "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/plugin.ts", - "type": "Object", - "lineNumber": 134, - "columnNumber": 29 - }, { "id": "def-public.Setup.fnWithInlineParams.$1.fn", "label": "fn", @@ -175,84 +151,12 @@ "lineNumber": 30, "columnNumber": 18 }, - { - "id": "def-public.crazyFunction.$1", - "label": "obj", - "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", - "type": "Object", - "lineNumber": 66, - "columnNumber": 10 - }, - { - "id": "def-public.crazyFunction.$1.hi", - "label": "hi", - "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", - "type": "string", - "lineNumber": 66, - "columnNumber": 12 - }, - { - "id": "def-public.crazyFunction.$2", - "label": "{ fn1, fn2 }", - "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", - "type": "Object", - "lineNumber": 67, - "columnNumber": 19 - }, - { - "id": "def-public.crazyFunction.$2.fn1", - "label": "fn1", - "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", - "type": "Function", - "lineNumber": 67, - "columnNumber": 21 - }, - { - "id": "def-public.crazyFunction.$2.fn1.$1", - "label": "foo", - "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", - "type": "Object", - "lineNumber": 67, - "columnNumber": 32 - }, - { - "id": "def-public.crazyFunction.$2.fn1.$1.param", - "label": "param", - "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", - "type": "string", - "lineNumber": 67, - "columnNumber": 34 - }, - { - "id": "def-public.crazyFunction.$2.fn2", - "label": "fn2", - "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", - "type": "Function", - "lineNumber": 67, - "columnNumber": 62 - }, - { - "id": "def-public.crazyFunction.$3", - "label": "{ str }", - "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", - "type": "Object", - "lineNumber": 68, - "columnNumber": 14 - }, - { - "id": "def-public.crazyFunction.$3.str", - "label": "str", - "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", - "type": "string", - "lineNumber": 68, - "columnNumber": 16 - }, { "id": "def-public.fnWithNonExportedRef", "label": "fnWithNonExportedRef", "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", "type": "Function", - "lineNumber": 74, + "lineNumber": 83, "columnNumber": 14 }, { @@ -260,7 +164,7 @@ "label": "a", "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", "type": "Function", - "lineNumber": 74, + "lineNumber": 83, "columnNumber": 38 }, { @@ -268,7 +172,7 @@ "label": "NotAnArrowFnType", "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", "type": "Type", - "lineNumber": 76, + "lineNumber": 85, "columnNumber": 1 }, { @@ -1000,7 +904,7 @@ "label": "hi", "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", "type": "string", - "lineNumber": 66, + "lineNumber": 75, "columnNumber": 12 }, { @@ -1008,7 +912,7 @@ "label": "obj", "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", "type": "Object", - "lineNumber": 66, + "lineNumber": 75, "columnNumber": 10 }, { @@ -1016,63 +920,63 @@ "label": "param", "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", "type": "string", - "lineNumber": 67, - "columnNumber": 34 + "lineNumber": 76, + "columnNumber": 25 }, { "id": "def-public.crazyFunction.$2.fn1.$1", "label": "foo", "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", "type": "Object", - "lineNumber": 67, - "columnNumber": 32 + "lineNumber": 76, + "columnNumber": 23 }, { "id": "def-public.crazyFunction.$2.fn1", "label": "fn1", "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", "type": "Function", - "lineNumber": 67, - "columnNumber": 21 + "lineNumber": 76, + "columnNumber": 12 }, { "id": "def-public.crazyFunction.$2.fn2", "label": "fn2", "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", "type": "Function", - "lineNumber": 67, - "columnNumber": 62 + "lineNumber": 76, + "columnNumber": 53 }, { "id": "def-public.crazyFunction.$2", - "label": "{ fn1, fn2 }", + "label": "fns", "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", "type": "Object", - "lineNumber": 67, - "columnNumber": 19 + "lineNumber": 76, + "columnNumber": 10 }, { "id": "def-public.crazyFunction.$3.str", "label": "str", "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", "type": "string", - "lineNumber": 68, - "columnNumber": 16 + "lineNumber": 77, + "columnNumber": 15 }, { "id": "def-public.crazyFunction.$3", - "label": "{ str }", + "label": "strObj", "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", "type": "Object", - "lineNumber": 68, - "columnNumber": 14 + "lineNumber": 77, + "columnNumber": 13 }, { "id": "def-public.crazyFunction", "label": "crazyFunction", "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", "type": "Function", - "lineNumber": 64, + "lineNumber": 73, "columnNumber": 14 }, { @@ -1080,7 +984,7 @@ "label": "a", "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", "type": "Function", - "lineNumber": 74, + "lineNumber": 83, "columnNumber": 38 }, { @@ -1088,7 +992,7 @@ "label": "fnWithNonExportedRef", "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", "type": "Function", - "lineNumber": 74, + "lineNumber": 83, "columnNumber": 14 }, { @@ -1136,7 +1040,7 @@ "label": "NotAnArrowFnType", "path": "packages/kbn-docs-utils/src/integration_tests/__fixtures__/src/plugin_a/public/fns.ts", "type": "Type", - "lineNumber": 76, + "lineNumber": 85, "columnNumber": 1 }, { diff --git a/packages/kbn-docs-utils/src/integration_tests/snapshots/plugin_a_foo.mdx b/packages/kbn-docs-utils/src/integration_tests/snapshots/plugin_a_foo.mdx index fc2fe59c5cfc2..42d7c930d0447 100644 --- a/packages/kbn-docs-utils/src/integration_tests/snapshots/plugin_a_foo.mdx +++ b/packages/kbn-docs-utils/src/integration_tests/snapshots/plugin_a_foo.mdx @@ -21,7 +21,7 @@ Contact Kibana Core for questions regarding this plugin. | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 136 | 1 | 76 | 2 | +| 136 | 1 | 64 | 2 | ## Client