Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 57 additions & 3 deletions packages/snaps-rpc-methods/scripts/generate-schema.mts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type {
PropertyAssignment,
Symbol,
Type,
TypeAliasDeclaration,
TypeNode,
VariableDeclaration,
} from 'ts-morph';
Expand Down Expand Up @@ -423,6 +424,57 @@ function getTypeAliasDeclaration(type: Type) {
return declaration?.asKind(SyntaxKind.TypeAliasDeclaration) ?? null;
}

/**
* Unwrap an `InferMatching` type node to get the underlying type, if the given
* type node is an `InferMatching` type. This is needed to get the correct
* description for certain types that are defined using `InferMatching`, such
* as `DialogParams`, since the JSDoc comments are on the underlying type rather
* than the `InferMatching` type itself. If the given declaration is not an
* `InferMatching` type, it is returned as-is.
*
* @param declaration - The type alias declaration that may be an
* `InferMatching` type.
* @returns The underlying type alias declaration if the given declaration is an
* `InferMatching` type, or the given declaration otherwise.
*/
function unwrapInferMatchingTypeNode(declaration: TypeAliasDeclaration) {
const typeNode = declaration.getTypeNodeOrThrow();
if (!typeNode.isKind(SyntaxKind.TypeReference)) {
return declaration;
}

const typeReference = typeNode.asKindOrThrow(SyntaxKind.TypeReference);
if (typeReference.getTypeName().getText() !== 'InferMatching') {
return declaration;
}

const typeArguments = typeReference.getTypeArguments();
assert(
typeArguments.length === 2,
'Expected `InferMatching` to have exactly two type arguments.',
);

const underlyingTypeNode = typeArguments[1];
const symbol = underlyingTypeNode
.asKindOrThrow(SyntaxKind.TypeReference)
.getTypeName()
.getSymbolOrThrow()
.getAliasedSymbolOrThrow();

const underlyingDeclaration = symbol
.getDeclarations()
.find((symbolDeclaration): symbolDeclaration is TypeAliasDeclaration =>
symbolDeclaration.isKind(SyntaxKind.TypeAliasDeclaration),
);

assert(
underlyingDeclaration,
'Expected declaration of underlying type not found.',
);

return underlyingDeclaration;
}

/**
* Get the description of a type node from its JSDoc comments, if it has any.
*
Expand All @@ -436,22 +488,24 @@ function getTypeNodeDescription(typeNode: TypeNode) {
.getTypeName()
.asKindOrThrow(SyntaxKind.Identifier);

const symbol = identifier.getSymbol()?.getAliasedSymbol();
const symbol =
identifier.getSymbol()?.getAliasedSymbol() ?? identifier.getSymbol();
if (!symbol) {
return null;
}

const declaration = symbol
.getDeclarations()
.find((symbolDeclarations) =>
.find((symbolDeclarations): symbolDeclarations is TypeAliasDeclaration =>
symbolDeclarations.isKind(SyntaxKind.TypeAliasDeclaration),
);

if (!declaration) {
return null;
}

const jsDocs = declaration
const unwrappedDeclaration = unwrapInferMatchingTypeNode(declaration);
const jsDocs = unwrappedDeclaration
.asKindOrThrow(SyntaxKind.TypeAliasDeclaration)
.getJsDocs();

Expand Down