aboutsummaryrefslogtreecommitdiff
path: root/scripts/apidocs/processing/method.ts
diff options
context:
space:
mode:
authorST-DDT <[email protected]>2024-04-01 10:21:18 +0200
committerGitHub <[email protected]>2024-04-01 10:21:18 +0200
commit6191a5d883048b694404dbf42527caba395828ea (patch)
treed0f18f17789cb0bbdb5d6087f1a95772438dfe27 /scripts/apidocs/processing/method.ts
parent7dae52bfcd93c41ec9d2c4dd4d96a07f31c3dfc1 (diff)
downloadfaker-6191a5d883048b694404dbf42527caba395828ea.tar.xz
faker-6191a5d883048b694404dbf42527caba395828ea.zip
docs: rewrite api-docs generation using ts-morph (#2628)
Diffstat (limited to 'scripts/apidocs/processing/method.ts')
-rw-r--r--scripts/apidocs/processing/method.ts197
1 files changed, 197 insertions, 0 deletions
diff --git a/scripts/apidocs/processing/method.ts b/scripts/apidocs/processing/method.ts
new file mode 100644
index 00000000..b9d1aa38
--- /dev/null
+++ b/scripts/apidocs/processing/method.ts
@@ -0,0 +1,197 @@
+import type {
+ ClassDeclaration,
+ FunctionDeclaration,
+ InterfaceDeclaration,
+ MethodSignature,
+ Project,
+} from 'ts-morph';
+import {
+ SyntaxKind,
+ type ConstructorDeclaration,
+ type MethodDeclaration,
+} from 'ts-morph';
+import { groupBy } from '../../../src/internal/group-by';
+import { valuesForKeys } from '../utils/value-checks';
+import { newProcessingError } from './error';
+import type {
+ RawApiDocsSignature,
+ SignatureLikeDeclaration,
+} from './signature';
+import { processSignatures } from './signature';
+import type { RawApiDocsSource } from './source';
+import { getSourcePath as getSource } from './source';
+
+/**
+ * Represents a method in the raw API docs.
+ */
+export interface RawApiDocsMethod {
+ /**
+ * The name of the method.
+ */
+ name: string;
+ /**
+ * The signatures of the method.
+ */
+ signatures: RawApiDocsSignature[];
+ /**
+ * The source of the method.
+ */
+ source: RawApiDocsSource;
+}
+
+// Constructors
+
+export function processClassConstructors(
+ clazz: ClassDeclaration
+): RawApiDocsMethod[] {
+ return processConstructors(clazz.getConstructors());
+}
+
+function processConstructors(
+ constructors: ConstructorDeclaration[]
+): RawApiDocsMethod[] {
+ return processMethodLikes(constructors, () => 'constructor');
+}
+
+// Class Methods
+
+export function processClassMethods(
+ clazz: ClassDeclaration
+): RawApiDocsMethod[] {
+ return processMethods(getAllMethods(clazz));
+}
+
+function getAllMethods(clazz: ClassDeclaration): MethodDeclaration[] {
+ const parents: ClassDeclaration[] = [clazz];
+ let parent: ClassDeclaration | undefined = clazz;
+ while ((parent = parent.getBaseClass()) != null) {
+ parents.unshift(parent);
+ }
+
+ const methods: Record<string, MethodDeclaration> = {};
+
+ for (const parent of parents) {
+ for (const method of parent.getMethods()) {
+ methods[method.getName()] = method;
+ }
+ }
+
+ return Object.values(methods).sort((a, b) =>
+ a.getName().localeCompare(b.getName())
+ );
+}
+
+type NamedMethodLikeDeclaration = MethodLikeDeclaration &
+ Pick<MethodDeclaration, 'getName'>;
+
+function processMethods(
+ methods: NamedMethodLikeDeclaration[]
+): RawApiDocsMethod[] {
+ return processMethodLikes(methods, (v) => v.getName());
+}
+
+// Interface Methods
+
+export function processInterfaceMethods(
+ iface: InterfaceDeclaration
+): RawApiDocsMethod[] {
+ return processMethodSignatures(iface.getMethods());
+}
+
+function processMethodSignatures(
+ methods: MethodSignature[]
+): RawApiDocsMethod[] {
+ const groupedSignatures = groupBy(methods, (v) => v.getName());
+
+ const methodLikes: NamedMethodLikeDeclaration[] = Object.values(
+ groupedSignatures
+ ).map((signatures) => {
+ const signature = signatures[0];
+
+ return {
+ getName: () => signature.getName(),
+ hasModifier: () => false,
+ getOverloads: () => signatures,
+ getTypeParameters: () => signature.getTypeParameters(),
+ getParameters: () => signature.getParameters(),
+ getReturnType: () => signature.getReturnType(),
+ getJsDocs: () => signature.getJsDocs(),
+ getSourceFile: () => signature.getSourceFile(),
+ getStart: () => signature.getStart(),
+ getText: () => signature.getText(),
+ };
+ });
+
+ return processMethods(methodLikes);
+}
+
+// Functions
+
+function getAllFunctions(
+ project: Project
+): Record<string, FunctionDeclaration> {
+ return Object.fromEntries(
+ project
+ .getSourceFiles()
+ .flatMap((file) => file.getFunctions())
+ .map((fn) => [fn.getNameOrThrow(), fn] as const)
+ );
+}
+
+export function processProjectFunctions(
+ project: Project,
+ ...names: string[]
+): RawApiDocsMethod[] {
+ return processMethodLikes(
+ valuesForKeys(getAllFunctions(project), names),
+ (f) => f.getNameOrThrow()
+ );
+}
+
+// Method-likes
+
+type MethodLikeDeclaration = SignatureLikeDeclaration &
+ Pick<MethodDeclaration, 'hasModifier'> & {
+ getOverloads(): SignatureLikeDeclaration[];
+ };
+
+function processMethodLikes<T extends MethodLikeDeclaration>(
+ methods: T[],
+ nameResolver: (value: T) => string
+): RawApiDocsMethod[] {
+ return methods
+ .filter((method) => !method.hasModifier(SyntaxKind.PrivateKeyword))
+ .map((method) => {
+ const name = nameResolver(method);
+ try {
+ return processMethodLike(name, method);
+ } catch (error) {
+ throw newProcessingError({
+ type: 'method',
+ name,
+ source: method,
+ cause: error,
+ });
+ }
+ })
+ .sort((a, b) => a.name.localeCompare(b.name));
+}
+
+export function processMethodLike(
+ name: string,
+ method: MethodLikeDeclaration
+): RawApiDocsMethod {
+ console.log(` - ${name}`);
+ const overloads = method.getOverloads();
+ const signatureData: SignatureLikeDeclaration[] =
+ overloads.length > 0 ? overloads : [method];
+
+ const signatures = processSignatures(name, signatureData, method);
+ const source = getSource(method);
+
+ return {
+ name,
+ signatures,
+ source,
+ };
+}