Skip to content

Refactor/simplify extraction.ts#8898

Merged
cryptodev-2s merged 1 commit into
feat/messenger-docs-sitefrom
messenger-docs-site--refactor
May 26, 2026
Merged

Refactor/simplify extraction.ts#8898
cryptodev-2s merged 1 commit into
feat/messenger-docs-sitefrom
messenger-docs-site--refactor

Conversation

@mcmire
Copy link
Copy Markdown
Contributor

@mcmire mcmire commented May 26, 2026

Explanation

The goal of this commit is to make extraction.ts easier to follow. Since we are working with the TypeScript AST, we have to accept that the code will be somewhat dense, and we will need to ask maintainers to do some amount of studying to develop a mental model in their head. However, the more we can do to assist this process, the better.

To this end, this commit:

  • Adds comments to illustrate steps in the parsing process and underlying nodes in the AST that are being visited
  • Renames some functions to more accurately describe their contents
  • Removes unnecessary istanbul ignore comments in favor of either adding tests that exercise the underlying logic or using assumptions (non-null assertions).
  • Rewrite some JSDoc so it's less technical and more natural sounding

References

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

Note

Medium Risk
Changes core AST extraction logic that drives published API docs; behavior should stay equivalent but edge-case handling shifted to type-checker resolution and explicit skips.

Overview
Refactors platform-api-docs messenger extraction for readability and safer edge-case handling, without changing the public doc-generation pipeline’s overall shape.

extraction.ts is reorganized into clearer phases: find *Messenger type aliases, recursively walk Actions/Events type parameters to collect capability declarations, then extract MessengerCapabilityPacket records (renamed from ExtractedMessengerCapabilityType) via inline object literals or ControllerGetStateAction / ControllerStateChangeEvent constructors. Discovery and extraction helpers are renamed and documented with AST-oriented comments; JSDoc handling is tightened (e.g. skip nameless @param tags, bare @deprecated).

Type resolution for capability type strings and constructor namespace args now leans on the type checker (getType().isStringLiteral()) instead of dedicated template-literal / typeof helpers. Invalid shapes are skipped explicitly (missing type/handler/payload, numeric type, qualified Ns.Type references, non–string-literal constructor args, method signatures mixed into object types).

Tests in extraction.test.ts add broad coverage for those skip/fallback paths; several istanbul ignore branches are removed in favor of tests or compile-time assumptions.

generate.ts, markdown.ts, and types.ts only adopt the new type name.

Reviewed by Cursor Bugbot for commit 57ad0bd. Bugbot is set up for automated code reviews on this repo. Configure here.

@mcmire mcmire force-pushed the messenger-docs-site--refactor branch from 16024a4 to 952d871 Compare May 26, 2026 18:37
The goal of this commit is to make `extraction.ts` easier to follow.
Since we are working with the TypeScript AST, we have to accept that the
code will be somewhat dense, and we will need to ask maintainers to do
some amount of studying to develop a mental model in their head.
However the more we can do to assist this process the better.

To this end, this commit:

- Adds comments to illustrate steps in the parsing process and
  underlying nodes in the AST that are being visited
- Renames some functions to more accurately describe their contents
- Removes unnecessary `istanbul ignore` comments in favor of either
  adding tests that exercise the underlying logic or using assumptions
  (non-null assertions).
- Rewrite some JSDoc so it's less technical and more natural sounding
@mcmire mcmire force-pushed the messenger-docs-site--refactor branch from 952d871 to 57ad0bd Compare May 26, 2026 18:57
Copy link
Copy Markdown
Contributor Author

@mcmire mcmire left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @cryptodev-2s, I hope you don't mind that I made some changes to extraction.ts as I went through it and tried to understand it. Hopefully these make sense but let me know if you have any questions.

deprecatedLines.push(
comment ? `**Deprecated:** ${comment}` : '**Deprecated:**',
);
} else if (tagName === 'param' && NodeGuards.isJSDocParameterTag(tag)) {
const nameNode = tag.getNameNode();
// istanbul ignore next: `@param` tags without a name aren't valid JSDoc.
if (!nameNode) {
const paramName = nameNode.getText();
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's true that if a @param tag does not have a name, it will be flagged by the ESLint JSDoc lint rules. However, ts-morph does not care about that. We instead explicitly check for this kind of tag and ignore it.

if (NodeGuards.isTypeQuery(typeArg)) {
const type = typeArg.getType();
if (type.isStringLiteral()) {
return type.getLiteralValueOrThrow() as string;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need to have various strategies of resolving the value of a string literal. The getLiteralValueOrThrow method on the type does this already. So we can simplify this.

*/
function collectMessengerCapabilityTypeDeclarations(
function findMessengerTypeAliases(
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I split this function off from collectMessengerCapabilityTypeDeclarations because it seemed like a logical step in the process that deserved its own name.

* @returns The list of type aliases that represent messenger capabilities among
* the given messenger types.
*/
function findAllMessengerCapabilityTypeDeclarations(
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I renamed this from collectMessengerCapabilityTypeDeclarations to findAllMessengerCapabilityTypeDeclarations. This was mainly to match recursivelyFindMessengerCapabilityTypeDeclarations.

*/
function walkCapabilityTypes(
function recursivelyFindMessengerCapabilityTypeDeclarations(
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I renamed walkCapabilityTypes to recursivelyFindMessengerCapabilityTypeDeclarations as I felt like "walk" didn't accurately convey what we are trying to do. We are not merely visiting nodes, we are also capturing the capability types.

if (resolvedType.isStringLiteral()) {
// Type assertion: There aren't any type guards we can use to narrow this
// type further.
const literalValue = resolvedType.getLiteralValueOrThrow() as string;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As elsewhere, we don't need to use multiple strategies to resolve the string literal, we can just ask the type checker to resolve it for us.

if (
// istanbul ignore next: capability properties always have identifier names.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need to make this assumption, we can check for it and exercise this logic in a test.

return null;
}

// A `type` property without an explicit type wouldn't compile.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed the istanbul ignore to a non-null assertion to better highlight that we are making an assumption.

// We already determined in
// `recursivelyFindMessengerCapabilityTypeDeclarations` that the declaration
// is a type reference.
// TODO: Capture the following information ahead of time so we don't need to
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are more refactors we can do to simplify this function, but I decided to stop short of that so that this PR didn't blow up.

*/
export type ExtractedMessengerCapabilityType = {
export type MessengerCapabilityPacket = {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While it's true the information captured here does come from a capability type, I felt that saying that it is a type was confusing. Plus, we are using "item" elsewhere, so it didn't feel like we had a good term we could use consistently for this concept. I came up with "packet" as I felt like it was a good word to represent the bundle of information we've collected for a capability.

Note that I didn't update the use of "item" across the package. I only updated this type. I will make more changes in another PR to address that inconsistency.

@mcmire mcmire marked this pull request as ready for review May 26, 2026 19:37
@mcmire mcmire requested a review from a team as a code owner May 26, 2026 19:37
@cryptodev-2s cryptodev-2s merged commit 0862ed5 into feat/messenger-docs-site May 26, 2026
375 of 376 checks passed
@cryptodev-2s cryptodev-2s deleted the messenger-docs-site--refactor branch May 26, 2026 21:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants