diff --git a/src/components/component-definition.ts b/src/components/component-definition.ts index df6e9c3..aa5e2de 100644 --- a/src/components/component-definition.ts +++ b/src/components/component-definition.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import ts from 'typescript'; -import { extractDeclaration, stringifyType } from './type-utils'; +import { extractDeclaration, stringifyType } from '../shared/type-utils'; import type { ComponentDefinition, ComponentFunction, diff --git a/src/components/extract-value-descriptions.ts b/src/components/extract-value-descriptions.ts new file mode 100644 index 0000000..6e49e66 --- /dev/null +++ b/src/components/extract-value-descriptions.ts @@ -0,0 +1,47 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import ts from 'typescript'; +import { extractDeclaration } from '../shared/type-utils'; +import { ValueDescription } from './interfaces'; + +export function extractValueDescriptions(type: ts.UnionOrIntersectionType, typeNode: ts.TypeNode | undefined) { + if (type.aliasSymbol) { + // Traverse from "variant: ButtonProps.Variant" to "type Variant = ..." + const aliasDeclaration = extractDeclaration(type.aliasSymbol); + if (ts.isTypeAliasDeclaration(aliasDeclaration)) { + typeNode = aliasDeclaration.type; + } + } + + if (!typeNode) { + return []; + } + + const maybeList = typeNode.getChildren()[0]; + // based on similar code in typedoc + // https://github.com/TypeStrong/typedoc/blob/6090b3e31471cea3728db1b03888bca5703b437e/src/lib/converter/symbols.ts#L406-L438 + if (maybeList.kind !== ts.SyntaxKind.SyntaxList) { + return []; + } + const rawComments: Array = []; + let memberIndex = 0; + for (const child of maybeList.getChildren()) { + const text = child.getFullText(); + if (text.includes('/**')) { + rawComments[memberIndex] = (rawComments[memberIndex] ?? '') + child.getFullText(); + } + + if (child.kind !== ts.SyntaxKind.BarToken) { + memberIndex++; + } + } + // Array.from to fix sparse array + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#array_methods_and_empty_slots + return Array.from(rawComments).map((comment): ValueDescription | undefined => { + if (!comment) { + return undefined; + } + const systemTags = Array.from(comment.matchAll(/@awsuiSystem\s+(\w+)/g), ([_, system]) => system); + return systemTags.length > 0 ? { systemTags } : undefined; + }); +} diff --git a/src/components/extractor.ts b/src/components/extractor.ts index 39b2517..5a79a9f 100644 --- a/src/components/extractor.ts +++ b/src/components/extractor.ts @@ -8,7 +8,7 @@ import { isOptional, stringifyType, unwrapNamespaceDeclaration, -} from './type-utils'; +} from '../shared/type-utils'; export interface ExtractedDescription { text: string | undefined; diff --git a/src/components/index.ts b/src/components/index.ts index 877eeef..b7ff56e 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -9,7 +9,7 @@ import { buildComponentDefinition } from './component-definition'; import { extractDefaultValues, extractExports, extractFunctions, extractProps } from './extractor'; import type { ComponentDefinition } from './interfaces'; import { bootstrapTypescriptProject } from '../shared/bootstrap'; -import { extractDeclaration, getDescription } from './type-utils'; +import { extractDeclaration, getDescription } from '../shared/type-utils'; function componentNameFromPath(componentPath: string) { const dashCaseName = pathe.basename(pathe.dirname(componentPath)); diff --git a/src/components/object-definition.ts b/src/components/object-definition.ts index 1737eff..73f8e95 100644 --- a/src/components/object-definition.ts +++ b/src/components/object-definition.ts @@ -2,7 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 import ts from 'typescript'; import type { TypeDefinition, UnionTypeDefinition, ValueDescription } from './interfaces'; -import { extractDeclaration, extractValueDescriptions, isOptional, stringifyType } from './type-utils'; +import { extractDeclaration, isOptional, stringifyType } from '../shared/type-utils'; +import { extractValueDescriptions } from './extract-value-descriptions'; function isArrayType(type: ts.Type) { const symbol = type.getSymbol(); diff --git a/src/components/type-utils.ts b/src/shared/type-utils.ts similarity index 64% rename from src/components/type-utils.ts rename to src/shared/type-utils.ts index 2f0cca9..a3ea480 100644 --- a/src/components/type-utils.ts +++ b/src/shared/type-utils.ts @@ -1,7 +1,6 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 import ts from 'typescript'; -import { ValueDescription } from './interfaces'; export function isOptional(type: ts.Type) { if (!type.isUnionOrIntersection()) { @@ -62,48 +61,6 @@ export function getDescription(docComment: Array, declarat }; } -export function extractValueDescriptions(type: ts.UnionOrIntersectionType, typeNode: ts.TypeNode | undefined) { - if (type.aliasSymbol) { - // Traverse from "variant: ButtonProps.Variant" to "type Variant = ..." - const aliasDeclaration = extractDeclaration(type.aliasSymbol); - if (ts.isTypeAliasDeclaration(aliasDeclaration)) { - typeNode = aliasDeclaration.type; - } - } - - if (!typeNode) { - return []; - } - - const maybeList = typeNode.getChildren()[0]; - // based on similar code in typedoc - // https://github.com/TypeStrong/typedoc/blob/6090b3e31471cea3728db1b03888bca5703b437e/src/lib/converter/symbols.ts#L406-L438 - if (maybeList.kind !== ts.SyntaxKind.SyntaxList) { - return []; - } - const rawComments: Array = []; - let memberIndex = 0; - for (const child of maybeList.getChildren()) { - const text = child.getFullText(); - if (text.includes('/**')) { - rawComments[memberIndex] = (rawComments[memberIndex] ?? '') + child.getFullText(); - } - - if (child.kind !== ts.SyntaxKind.BarToken) { - memberIndex++; - } - } - // Array.from to fix sparse array - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#array_methods_and_empty_slots - return Array.from(rawComments).map((comment): ValueDescription | undefined => { - if (!comment) { - return undefined; - } - const systemTags = Array.from(comment.matchAll(/@awsuiSystem\s+(\w+)/g), ([_, system]) => system); - return systemTags.length > 0 ? { systemTags } : undefined; - }); -} - export function extractDeclaration(symbol: ts.Symbol) { const declarations = symbol.getDeclarations(); if (!declarations || declarations.length === 0) { diff --git a/src/test-utils/extractor.ts b/src/test-utils/extractor.ts index cc4d930..c342654 100644 --- a/src/test-utils/extractor.ts +++ b/src/test-utils/extractor.ts @@ -8,7 +8,7 @@ import { isNullable, isOptional, stringifyType, -} from '../components/type-utils'; +} from '../shared/type-utils'; import { TestUtilsDoc } from './interfaces'; function getInheritedFrom(declaration: ts.Declaration, currentClassName: string) { diff --git a/src/test-utils/interfaces.ts b/src/test-utils/interfaces.ts index f6bc6a7..410d920 100644 --- a/src/test-utils/interfaces.ts +++ b/src/test-utils/interfaces.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 export interface Parameter { name: string; - typeName?: string; + typeName: string; description?: string; flags: { isOptional?: boolean }; defaultValue?: string; @@ -15,7 +15,7 @@ interface TypeArgument { export interface TestUtilMethod { name: string; description?: string; - returnType?: { + returnType: { name: string; isNullable: boolean; typeArguments?: Array; diff --git a/test/components/value-descriptions-extractor.test.ts b/test/components/value-descriptions-extractor.test.ts index d4ce22f..2111ef8 100644 --- a/test/components/value-descriptions-extractor.test.ts +++ b/test/components/value-descriptions-extractor.test.ts @@ -2,7 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 import { expect, test } from 'vitest'; import ts from 'typescript'; -import { extractDeclaration, extractValueDescriptions } from '../../src/components/type-utils'; +import { extractDeclaration } from '../../src/shared/type-utils'; +import { extractValueDescriptions } from '../../src/components/extract-value-descriptions'; import { getInMemoryProject } from './test-helpers'; function extractFromSource(source: string) { diff --git a/test/components/type-utils.test.ts b/test/shared/type-utils.test.ts similarity index 91% rename from test/components/type-utils.test.ts rename to test/shared/type-utils.test.ts index 0be1016..db4aa93 100644 --- a/test/components/type-utils.test.ts +++ b/test/shared/type-utils.test.ts @@ -3,7 +3,7 @@ import ts from 'typescript'; import { test, expect } from 'vitest'; -import { printFlags } from '../../lib/components/type-utils'; +import { printFlags } from '../../lib/shared/type-utils'; test('serialises node flags', () => { const flags = printFlags(