compiler/packages/react-compiler-healthcheck/src/checks/reactCompiler.ts TYPESCRIPT 154 lines View on github.com → Search inside
1/**2 * Copyright (c) Meta Platforms, Inc. and affiliates.3 *4 * This source code is licensed under the MIT license found in the5 * LICENSE file in the root directory of this source tree.6 */78import type * as BabelCore from '@babel/core';9import {transformFromAstSync} from '@babel/core';10import * as BabelParser from '@babel/parser';11import BabelPluginReactCompiler, {12  ErrorSeverity,13  type CompilerErrorDetailOptions,14  type PluginOptions,15} from 'babel-plugin-react-compiler/src';16import {LoggerEvent as RawLoggerEvent} from 'babel-plugin-react-compiler/src/Entrypoint';17import chalk from 'chalk';1819type LoggerEvent = RawLoggerEvent & {filename: string | null};2021const SucessfulCompilation: Array<LoggerEvent> = [];22const ActionableFailures: Array<LoggerEvent> = [];23const OtherFailures: Array<LoggerEvent> = [];2425const logger = {26  logEvent(filename: string | null, rawEvent: RawLoggerEvent) {27    const event = {...rawEvent, filename};28    switch (event.kind) {29      case 'CompileSuccess': {30        SucessfulCompilation.push(event);31        return;32      }33      case 'CompileError': {34        if (isActionableDiagnostic(event.detail)) {35          ActionableFailures.push(event);36          return;37        }38        OtherFailures.push(event);39        return;40      }41      case 'CompileDiagnostic':42      case 'PipelineError':43        OtherFailures.push(event);44        return;45    }46  },47};4849const COMPILER_OPTIONS: PluginOptions = {50  noEmit: true,51  compilationMode: 'infer',52  panicThreshold: 'critical_errors',53  logger,54};5556function isActionableDiagnostic(detail: CompilerErrorDetailOptions) {57  switch (detail.severity) {58    case ErrorSeverity.InvalidReact:59    case ErrorSeverity.InvalidJS:60      return true;61    case ErrorSeverity.InvalidConfig:62    case ErrorSeverity.Invariant:63    case ErrorSeverity.CannotPreserveMemoization:64    case ErrorSeverity.Todo:65      return false;66    default:67      throw new Error(`Unhandled error severity \`${detail.severity}\``);68  }69}7071function runBabelPluginReactCompiler(72  text: string,73  file: string,74  language: 'flow' | 'typescript',75  options: PluginOptions | null,76): BabelCore.BabelFileResult {77  const ast = BabelParser.parse(text, {78    sourceFilename: file,79    plugins: [language, 'jsx'],80    sourceType: 'module',81  });82  const result = transformFromAstSync(ast, text, {83    filename: file,84    highlightCode: false,85    retainLines: true,86    plugins: [[BabelPluginReactCompiler, options]],87    sourceType: 'module',88    configFile: false,89    babelrc: false,90  });91  if (result?.code == null) {92    throw new Error(93      `Expected BabelPluginReactForget to codegen successfully, got: ${result}`,94    );95  }96  return result;97}9899function compile(sourceCode: string, filename: string) {100  try {101    runBabelPluginReactCompiler(102      sourceCode,103      filename,104      'typescript',105      COMPILER_OPTIONS,106    );107  } catch {}108}109110const JsFileExtensionRE = /(js|ts|jsx|tsx)$/;111112/**113 * Counts unique source locations (filename + function definition location)114 * in source.115 * The compiler currently occasionally emits multiple error events for a116 * single file (e.g. to report multiple rules of react violations in the117 * same pass).118 * TODO: enable non-destructive `CompilerDiagnostic` logging in dev mode,119 * and log a "CompilationStart" event for every function we begin processing.120 */121function countUniqueLocInEvents(events: Array<LoggerEvent>): number {122  const seenLocs = new Set<string>();123  let count = 0;124  for (const e of events) {125    if (e.filename != null && e.fnLoc != null) {126      seenLocs.add(`${e.filename}:${e.fnLoc.start}:${e.fnLoc.end}`);127    } else {128      // failed to dedup due to lack of source locations129      count++;130    }131  }132  return count + seenLocs.size;133}134135export default {136  run(source: string, path: string): void {137    if (JsFileExtensionRE.exec(path) !== null) {138      compile(source, path);139    }140  },141142  report(): void {143    const totalComponents =144      SucessfulCompilation.length +145      countUniqueLocInEvents(OtherFailures) +146      countUniqueLocInEvents(ActionableFailures);147    console.log(148      chalk.green(149        `Successfully compiled ${SucessfulCompilation.length} out of ${totalComponents} components.`,150      ),151    );152  },153};

Findings

✓ No findings reported for this file.

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.