Skip to content

fix(ds): generate-component-registry usa AST parser (Onda 2 PR 2.3)#103

Merged
adm01-debug merged 2 commits into
mainfrom
chore/onda-2-pr-2.3-registry-ast-parser
May 9, 2026
Merged

fix(ds): generate-component-registry usa AST parser (Onda 2 PR 2.3)#103
adm01-debug merged 2 commits into
mainfrom
chore/onda-2-pr-2.3-registry-ast-parser

Conversation

@adm01-debug
Copy link
Copy Markdown
Owner

@adm01-debug adm01-debug commented May 9, 2026

Resumo

Resolve issue do CodeRabbit no PR #97: regex /[a-zA-Z0-9]+(?=:)/g capturava prefixos Tailwind (hover:, focus:, dark:) como se fossem nomes de variants.

Bug

variants: {
  variant: {
    default: 'h-10',
    ghost: 'h-9 hover:bg-accent focus:ring-2',
        //          ^^^^^         ^^^^^
        //  Capturados como subkeys — errado!
  }
}

Antes: { variant: ['default', 'ghost', 'hover', 'focus', 'hover'] }
Depois: { variant: ['default', 'ghost'] }

Stats

Métrica Antes Depois
Ocorrências de "hover" em registry.json 45 0

Solução: TypeScript Compiler API

ts.createSourceFile() (built-in via TS 5.8.3) parseia o AST e identifica apenas PropertyAssignment no nível correto da árvore. O conteúdo das strings (className) é ignorado.

Lógica adicional: só consideramos um bloco como variants se ele tem AMBAS variants E defaultVariants (padrão CVA — Class Variance Authority). Isso filtra objetos parecidos mas não-CVA (ex: configurações de filtros que tenham uma chave "variants").

Stress-test

  • bun run build (1m) — registry regenerado no prebuild
  • ✅ Manualmente: bun run scripts/generate-component-registry.ts → 13 components with variants, 56 skipped
  • ✅ Sem deps novas — usa typescript que já estava (5.8.3)

Métricas Onda 2

Summary by CodeRabbit

Notas de Versão

  • Melhorias

    • Atualizadas opções de variantes e tamanhos em vários componentes (ex.: muted, interactive, underline, glowPurple, neon, 2xl, icon-sm, icon-lg), com conjuntos de tokens mais enxutos e consistentes.
    • Ajustes na ordem e estrutura do arquivo de registro de componentes para melhor legibilidade.
  • Chores

    • Sistema de geração de registro aprimorado para maior precisão, conta componentes processados/ignorados e grava saída formatada.

…Onda 2 PR 2.3)

Resolve issue do CodeRabbit no PR #97 (Onda 1.2): regex `/[a-zA-Z0-9]+(?=:)/g`
capturava prefixos do Tailwind dentro das strings de classes (`hover:`, `focus:`,
`dark:`) como se fossem nomes de variants.

## O bug

```ts
variants: {
  variant: {
    default: 'h-10',
    ghost: 'h-9 hover:bg-accent focus:ring-2',
        //          ^^^^^         ^^^^^
        //  Capturados como subkeys 'hover' e 'focus' — errado!
  }
}
```

Output buggado em registry.json:
```json
{ "variant": ["default", "ghost", "hover", "focus", "hover"] }
```

Output correto:
```json
{ "variant": ["default", "ghost"] }
```

## Stats: antes vs depois

| Métrica | Antes | Depois |
|---|---|---|
| Ocorrências de "hover" no registry.json | **45** | **0** |
| Ocorrências de "focus" no registry.json | 0 | 0 |
| Componentes com variants | 13 | 13 (sem mudança real) |

## Solução: TypeScript Compiler API

Substituí o regex por AST parser usando `ts.createSourceFile()` (built-in, já
nas deps via TS 5.8.3 — sem deps novas).

A função `extractVariants()` agora:

1. Cria um AST do source TSX
2. Visita cada `ObjectLiteralExpression`
3. Procura por nó com **AMBAS** as propriedades `variants` e `defaultVariants`
   (padrão CVA — Class Variance Authority — descarta objetos não-CVA)
4. Para cada variant, extrai apenas as `PropertyAssignment` no nível correto
   da árvore — strings/className NÃO são parseadas

## Componentes que tinham keys fantasma (todos corrigidos)

- icon-button: tinha 9 "hover" + 6 keys reais → agora só 6 keys reais
- card: tinha 8 "hover" + variants reais → corrigido
- (e outros 11 componentes)

## Stress-test

- ✅ `bun run build` (1m): registry regenerado durante prebuild, sem erros
- ✅ `bun run scripts/generate-component-registry.ts`: 13 with variants, 56 skipped
- ✅ TypeScript: sem erros novos
- ✅ Diff de registry.json: pesquisa de "hover" caiu de 45 → 0

## Refs

- /workspace/notes/coderabbit-feedback-pr97.md (issue do PR #97)
- TypeScript AST: https://github.com/microsoft/TypeScript/wiki/Using-the-Compiler-API
Copilot AI review requested due to automatic review settings May 9, 2026 00:19
@vercel
Copy link
Copy Markdown

vercel Bot commented May 9, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
zapp-web Ready Ready Preview, Comment May 9, 2026 0:27am

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 9, 2026

Review Change Stack
No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 06d8f5cf-d41a-4e5a-a87a-07561031714d

📥 Commits

Reviewing files that changed from the base of the PR and between d072f6c and ff907fc.

📒 Files selected for processing (2)
  • scripts/generate-component-registry.ts
  • src/components/ui/registry.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/components/ui/registry.json

Walkthrough

Refatoração do extrator de variantes para usar TypeScript AST; extractVariants agora analisa TSX e retorna Record<string,string[]> | null. O script tipa o registro, conta processados/ignorados e escreve registry.json (atualizado com novas variantes) com newline final.

Changes

Refatoração do Extrator e Atualização do Registro

Layer / File(s) Resumo
Configuração de AST
scripts/generate-component-registry.ts
Importação da API TypeScript Compiler e definição de constantes de caminhos.
Implementação do Extrator AST
scripts/generate-component-registry.ts
Substituição de regex por traversal recursivo de AST para detectar padrão CVA (objetos com variants + defaultVariants) e extrair chaves/subchaves válidas. Retorna Record<string,string[]> | null.
Tipagem e Processamento
scripts/generate-component-registry.ts
Tipo do registry alterado para Record<string,{ name: string; variants: Record<string,string[]> }>; loop atualizado para usar extractVariants(content, file) e contabilizar processed/skipped.
Saída JSON e Logging
scripts/generate-component-registry.ts
Escrita de registry.json agora inclui newline final; logs ampliados para counts processados/ignorados.
Dados de Variantes
src/components/ui/registry.json
Atualização de variantes: icon-button (+muted), card (+interactive), avatar (+2xl), badge (+glowPurple), button (+glowGradient/glowPurple/neon/neonOutline/success; +icon-sm/icon-lg sizes), input (+underline), toggle (reduzido a default/outline), skeleton (variants reduzidos; speed simplificado), sheet (+right). Remoção de variantes obsoletas (vários hover/visibility tokens) e ajustes de ordenação/fechamento JSON.

Estimated code review effort

🎯 3 (Moderado) | ⏱️ ~20 minutos

Pontos críticos a revisar (foco: bugs, segurança, performance):

  • Verificar tratamento de propriedades computadas/numeradas no extractor (são ignoradas — confirmar que não remove variantes válidas).
  • Checar caminhos de arquivo e possíveis execuções com arquivos grandes/infinitos (performance do traversal).
  • Garantir tratamento de erros sync/async ao ler/escrever arquivos (promises/try-catch) para evitar falha silenciosa ou corrupção de arquivo.
  • Confirmar que a tipagem tightened do registry não quebra consumidores downstream (evitar any não tratado).
  • Revisar logging e saída para evitar exposição acidental de conteúdo sensível em paths/filenames.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed O título refere-se ao principal objetivo do PR: substituição do parser regex por AST para o gerador de registry de componentes, evitando falsos positivos de prefixos Tailwind.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/onda-2-pr-2.3-registry-ast-parser

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
scripts/generate-component-registry.ts (1)

127-133: ⚡ Quick win

Ordene os arquivos antes do loop para saída determinística do registry.json.

Sem ordenação, a ordem pode variar por filesystem/ambiente e gerar diff ruidoso entre execuções.

💡 Diff sugerido
-const files = readdirSync(UI_DIR);
+const files = readdirSync(UI_DIR).sort((a, b) => a.localeCompare(b));
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/generate-component-registry.ts` around lines 127 - 133, Ordene a
lista retornada por readdirSync antes do loop para tornar a saída de
registry.json determinística: após const files = readdirSync(UI_DIR) (usado pelo
loop for (const file of files)), chame files.sort() ou reatribua const files =
readdirSync(UI_DIR).sort(); isso garante ordem estável entre execuções e evita
diffs ruidosos; mantenha o resto da lógica que atualiza processed e skipped
inalterada.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@scripts/generate-component-registry.ts`:
- Around line 127-133: Ordene a lista retornada por readdirSync antes do loop
para tornar a saída de registry.json determinística: após const files =
readdirSync(UI_DIR) (usado pelo loop for (const file of files)), chame
files.sort() ou reatribua const files = readdirSync(UI_DIR).sort(); isso garante
ordem estável entre execuções e evita diffs ruidosos; mantenha o resto da lógica
que atualiza processed e skipped inalterada.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 30a530b8-7bfc-4946-8ba6-e7472bc0f36e

📥 Commits

Reviewing files that changed from the base of the PR and between 008b274 and d072f6c.

📒 Files selected for processing (2)
  • scripts/generate-component-registry.ts
  • src/components/ui/registry.json

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Atualiza o gerador de src/components/ui/registry.json para usar o AST do TypeScript (Compiler API) em vez de regex, eliminando falsos positivos onde prefixos do Tailwind (hover:, focus:, etc.) eram indevidamente coletados como “variants”.

Changes:

  • Substitui o parser por regex no generate-component-registry.ts por um walker de AST via ts.createSourceFile() para coletar apenas PropertyAssignment no nível correto.
  • Restringe a detecção de “blocos CVA” para objetos que contenham variants e defaultVariants.
  • Regenera src/components/ui/registry.json, removendo entradas espúrias (ex.: hover, visible, before, after, duration) e capturando corretamente chaves string-literal (ex.: "2xl", "icon-sm").

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
scripts/generate-component-registry.ts Troca regex por AST (TypeScript Compiler API) para extrair variants com precisão e evitar falsos positivos de Tailwind.
src/components/ui/registry.json Arquivo gerado atualizado, removendo variants inválidos e refletindo corretamente as opções reais dos componentes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

filename,
content,
ts.ScriptTarget.Latest,
/* setParentNodes */ true,
Comment thread scripts/generate-component-registry.ts Outdated
Comment on lines +127 to +133
const files = readdirSync(UI_DIR);
let processed = 0;
let skipped = 0;

for (const file of files) {
if (file.endsWith('.tsx')) {
const content = readFileSync(join(UI_DIR, file), 'utf-8');
const variants = extractVariants(content);
const path = join(UI_DIR, file);
Comment on lines +52 to +59
function extractVariants(content: string, filename: string): Record<string, string[]> | null {
const sourceFile = ts.createSourceFile(
filename,
content,
ts.ScriptTarget.Latest,
/* setParentNodes */ true,
ts.ScriptKind.TSX
);
CodeRabbit no PR #103: sem sort, ordem do readdirSync varia por filesystem/ambiente,
gerando diff ruidoso entre execuções.

```diff
- const files = readdirSync(UI_DIR);
+ const files = readdirSync(UI_DIR).sort((a, b) => a.localeCompare(b));
```

Bonus: o registry.json agora fica ordenado alfabeticamente (avatar primeiro,
zoom-in último), facilitando navegação visual e diff.
filename,
content,
ts.ScriptTarget.Latest,
/* setParentNodes */ true,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggested change
/* setParentNodes */ true,
/* setParentNodes */ false,

setParentNodes is set to true but node.parent is never used, causing unnecessary memory and parsing overhead

Fix on Vercel

@adm01-debug adm01-debug merged commit efe7e75 into main May 9, 2026
10 of 11 checks passed
@adm01-debug adm01-debug deleted the chore/onda-2-pr-2.3-registry-ast-parser branch May 9, 2026 00:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants