Skip to content

Commit

Permalink
add support for checking all the public types in a file into the type…
Browse files Browse the repository at this point in the history
… library
  • Loading branch information
alicewriteswrongs committed Apr 5, 2023
1 parent e96a277 commit 2a33726
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 2 deletions.
17 changes: 15 additions & 2 deletions src/compiler/docs/generate-doc-data.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import { flatOne, normalizePath, sortBy, unique } from '@utils';
import { basename, dirname, join, relative } from 'path';

import { getTypeLibrary } from '../../compiler/transformers/type-library';
import { addFileToLibrary, getTypeLibrary } from '../../compiler/transformers/type-library';
import type * as d from '../../declarations';
import { JsonDocsValue } from '../../declarations';
import { typescriptVersion, version } from '../../version';
import { getBuildTimestamp } from '../build/build-ctx';
import { isOutputTargetDocsJson } from '../output-targets/output-utils';
import { AUTO_GENERATE_COMMENT } from './constants';

/**
* Generate metadata that will be used to generate any given documentation-related output target(s)
* Generate metadata that will be used to generate any given documentation-related
* output target(s)
*
* @param config the configuration associated with the current Stencil task run
* @param compilerCtx the current compiler context
* @param buildCtx the build context for the current Stencil task run
Expand All @@ -20,6 +23,16 @@ export const generateDocData = async (
compilerCtx: d.CompilerCtx,
buildCtx: d.BuildCtx
): Promise<d.JsonDocs> => {
const jsonOutputTargets = config.outputTargets.filter(isOutputTargetDocsJson);
const supplementalPublicTypes = jsonOutputTargets?.[0]?.supplementalPublicTypes ?? '';

if (supplementalPublicTypes !== '') {
// if supplementalPublicTypes is set then we want to add all the public
// types in that file to the type library so that specific output targets
// can make use of that data later.
addFileToLibrary(supplementalPublicTypes);
}

const typeLibrary = getTypeLibrary();

return {
Expand Down
71 changes: 71 additions & 0 deletions src/compiler/transformers/type-library.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,77 @@ export function getTypeLibrary(): d.JsonDocsTypeLibrary {
return TYPE_LIBRARY;
}

/**
* Helper function that, given a file containing interfaces to document, will
* add all the types exported from that file to the type library.
*
* This will exclude any types that are marked 'private' via JSDoc.
*
* @param filePath the path to the file of interest
*/
export function addFileToLibrary(filePath: string): void {
const program = ts.createProgram([filePath], {});
const checker = program.getTypeChecker();

const sourceFile = program.getSourceFile(filePath);

if (!sourceFile) {
return;
}

ts.forEachChild(sourceFile, (node) => {
if (isTypeDeclLike(node) && isExported(node) && isNotPrivate(node)) {
const type = checker.getTypeAtLocation(node);

if (type) {
const typeName = node.name.getText();

addToLibrary(type, typeName, checker);
}
}
});
}

/**
* The 'type declaration like' syntax node types
*/
type TypeDeclLike = ts.InterfaceDeclaration | ts.TypeAliasDeclaration | ts.EnumDeclaration;

/**
* Check that a {@link ts.Node} is a type-declaration-like node. For our
* purposes, this means that it is either an interface declaration, a type
* alias, or an enum declaration.
*
* @param node a TypeScript syntax tree node
* @returns whether or not this node is a type-declaration-like node
*/
function isTypeDeclLike(node: ts.Node): node is TypeDeclLike {
return ts.isInterfaceDeclaration(node) || ts.isTypeAliasDeclaration(node) || ts.isEnumDeclaration(node);
}

/**
* Check if a {@link ts.Declaration} is exported.
*
* @param node a TypeScript syntax tree node
* @returns whether or not this node is exported
*/
function isExported(node: TypeDeclLike): boolean {
return (ts.getCombinedModifierFlags(node) & ts.ModifierFlags.Export) !== 0;
}

/**
* Check that a {@link ts.Declaration} is not marked as 'private' via JSDoc.
*
* @param node a TypeScript syntax tree node to check
* @returns whether or not this node is marked as 'private'
*/
function isNotPrivate(node: TypeDeclLike): boolean {
const jsDocTags = ts.getJSDocTags(node);

return !jsDocTags.some((tag) => tag.tagName.text === 'private');
}


/**
* Get a string representation of the original declaration for a
* {@link ts.Type} object.
Expand Down

0 comments on commit 2a33726

Please sign in to comment.