@fluentui/react-compiler-analyzer 0.0.0-experimental.rc-analyzer.20260430-fc3bb2e193.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +185 -0
  3. package/bin/react-compiler-analyzer.js +10 -0
  4. package/dist/README.md +185 -0
  5. package/dist/package.json +24 -0
  6. package/dist/src/analyzer.d.ts +9 -0
  7. package/dist/src/analyzer.js +271 -0
  8. package/dist/src/analyzer.js.map +1 -0
  9. package/dist/src/cli.d.ts +1 -0
  10. package/dist/src/cli.js +19 -0
  11. package/dist/src/cli.js.map +1 -0
  12. package/dist/src/commands/coverage.d.ts +13 -0
  13. package/dist/src/commands/coverage.js +65 -0
  14. package/dist/src/commands/coverage.js.map +1 -0
  15. package/dist/src/commands/directives.d.ts +11 -0
  16. package/dist/src/commands/directives.js +60 -0
  17. package/dist/src/commands/directives.js.map +1 -0
  18. package/dist/src/commands/shared.d.ts +18 -0
  19. package/dist/src/commands/shared.js +79 -0
  20. package/dist/src/commands/shared.js.map +1 -0
  21. package/dist/src/compiler-utils.d.ts +29 -0
  22. package/dist/src/compiler-utils.js +29 -0
  23. package/dist/src/compiler-utils.js.map +1 -0
  24. package/dist/src/coverage-analyzer.d.ts +9 -0
  25. package/dist/src/coverage-analyzer.js +177 -0
  26. package/dist/src/coverage-analyzer.js.map +1 -0
  27. package/dist/src/coverage-fixer.d.ts +12 -0
  28. package/dist/src/coverage-fixer.js +71 -0
  29. package/dist/src/coverage-fixer.js.map +1 -0
  30. package/dist/src/coverage-reporter.d.ts +16 -0
  31. package/dist/src/coverage-reporter.js +167 -0
  32. package/dist/src/coverage-reporter.js.map +1 -0
  33. package/dist/src/discovery.d.ts +14 -0
  34. package/dist/src/discovery.js +70 -0
  35. package/dist/src/discovery.js.map +1 -0
  36. package/dist/src/fixer.d.ts +9 -0
  37. package/dist/src/fixer.js +79 -0
  38. package/dist/src/fixer.js.map +1 -0
  39. package/dist/src/index.d.ts +1 -0
  40. package/dist/src/index.js +6 -0
  41. package/dist/src/index.js.map +1 -0
  42. package/dist/src/manual-memo-plugin.d.ts +16 -0
  43. package/dist/src/manual-memo-plugin.js +82 -0
  44. package/dist/src/manual-memo-plugin.js.map +1 -0
  45. package/dist/src/reporter.d.ts +9 -0
  46. package/dist/src/reporter.js +117 -0
  47. package/dist/src/reporter.js.map +1 -0
  48. package/dist/src/types.d.ts +70 -0
  49. package/dist/src/types.js +7 -0
  50. package/dist/src/types.js.map +1 -0
  51. package/package.json +24 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ # Change Log - @fluentui/react-compiler-analyzer
2
+
3
+ This log was last generated on Thu, 30 Apr 2026 17:45:04 GMT and should not be manually modified.
4
+
5
+ <!-- Start content -->
6
+
7
+ ## [0.0.0-experimental.rc-analyzer.20260430-fc3bb2e193.0](https://github.com/microsoft/fluentui/tree/@fluentui/react-compiler-analyzer_v0.0.0-experimental.rc-analyzer.20260430-fc3bb2e193.0)
8
+
9
+ Thu, 30 Apr 2026 17:45:04 GMT
10
+
11
+ ### Changes
12
+
13
+ - Release experimental tools experimental.rc-analyzer.20260430-fc3bb2e193 ([commit](https://github.com/microsoft/fluentui/commit/not available) by fluentui-internal@service.microsoft.com)
package/README.md ADDED
@@ -0,0 +1,185 @@
1
+ # @fluentui/react-compiler-analyzer
2
+
3
+ Analyzes React Compiler behavior on TypeScript source files. Two commands:
4
+
5
+ - **`directives`** — Detects redundant `'use no memo'` directives by checking whether the compiler actually needs to bail out.
6
+ - **`coverage`** — Reports which functions the React Compiler will memoize, skip, or bail out on. Also detects manual memoization (`useMemo`, `useCallback`, `React.memo`) and identifies migration candidates.
7
+
8
+ ## `directives`
9
+
10
+ Detects redundant `'use no memo'` directives that were added conservatively during the React Compiler migration. Most are redundant — the compiler bails out on its own for patterns it can't safely optimize.
11
+
12
+ ```bash
13
+ react-compiler-analyzer directives <path> [options]
14
+ ```
15
+
16
+ ### How it works
17
+
18
+ For each source file containing `'use no memo'`:
19
+
20
+ 1. **Parse** — finds all directive locations and checks for `// justified: <reason>` comments
21
+ 2. **Strip** — creates an in-memory copy with non-justified directives removed (no files written)
22
+ 3. **Analyze** — runs `babel-plugin-react-compiler` with `noEmit: true` and a custom `Logger`
23
+ 4. **Classify** each directive:
24
+
25
+ | Status | Meaning | `--fix` action |
26
+ | ------------- | --------------------------------------------------------------------- | --------------------------------------- |
27
+ | **Redundant** | Compiler emits `CompileError` / `PipelineError` — it bails out anyway | Removes the directive |
28
+ | **Active** | Compiler emits `CompileSuccess` — the directive prevents optimization | Annotates with `// justified: <reason>` |
29
+ | **Skipped** | Directive already has a `// justified:` comment | No change |
30
+
31
+ ### Options
32
+
33
+ | Flag | Type | Default | Description |
34
+ | ------- | --------- | ------- | --------------------------------------------------------- |
35
+ | `--fix` | `boolean` | `false` | Auto-remove redundant directives and annotate active ones |
36
+
37
+ When `--fix` annotates an active directive it uses:
38
+
39
+ ```ts
40
+ 'use no memo'; // justified: compiler would optimize useFoo — manual opt-out to preserve runtime behavior
41
+ ```
42
+
43
+ This format satisfies the `@nx/workspace-no-unjustified-use-no-memo` ESLint rule (in `tools/eslint-rules/`), which enforces that every `'use no memo'` carries a justification comment.
44
+
45
+ Exit code `1` when redundant directives exist and `--fix` is not applied (useful for CI gating).
46
+
47
+ ### Examples
48
+
49
+ ```bash
50
+ # Detect redundant directives
51
+ react-compiler-analyzer directives ./packages/react-components/react-tree/library/src
52
+
53
+ # Auto-fix: remove redundant + annotate active
54
+ react-compiler-analyzer directives ./library/src --fix
55
+
56
+ # Show full compiler error reasons
57
+ react-compiler-analyzer directives ./src --full-reasons
58
+ ```
59
+
60
+ ## `coverage`
61
+
62
+ Reports which functions the React Compiler will memoize, skip, or bail out on. Detects manual memoization and identifies migration candidates.
63
+
64
+ ```bash
65
+ react-compiler-analyzer coverage <path> [options]
66
+ ```
67
+
68
+ ### Options
69
+
70
+ | Flag | Type | Default | Description |
71
+ | ------------ | --------- | --------- | ------------------------------------------------------------------------- |
72
+ | `--mode` | `string` | `"infer"` | React Compiler compilation mode. Choices: `infer`, `annotation`, `all` |
73
+ | `--annotate` | `boolean` | `false` | Insert `'use memo'` into compilable functions that use manual memoization |
74
+
75
+ ### `--annotate`
76
+
77
+ Supports a gradual migration workflow. A function is a **migration candidate** when:
78
+
79
+ 1. The React Compiler reports `CompileSuccess` (it can fully optimize the function)
80
+ 2. The function contains manual memoization (`useMemo`, `useCallback`, `React.memo`)
81
+
82
+ The flag inserts `'use memo';` at the top of each candidate's function body:
83
+
84
+ **Before:**
85
+
86
+ ```tsx
87
+ export function useTree_unstable(props: TreeProps) {
88
+ const sorted = useMemo(() => sortItems(props.items), [props.items]);
89
+ }
90
+ ```
91
+
92
+ **After:**
93
+
94
+ ```tsx
95
+ export function useTree_unstable(props: TreeProps) {
96
+ 'use memo';
97
+ const sorted = useMemo(() => sortItems(props.items), [props.items]);
98
+ }
99
+ ```
100
+
101
+ It does **not** remove `useMemo`/`useCallback`/`React.memo` calls, does not modify functions the compiler cannot compile, and is idempotent (running twice is safe).
102
+
103
+ **Recommended workflow:**
104
+
105
+ 1. **Audit** — Run `coverage` without `--annotate` to review migration candidates
106
+ 2. **Annotate** — Run with `--annotate` to opt-in candidates to compiler optimization
107
+ 3. **Verify** — Run tests, check bundle size
108
+ 4. **Clean up** (optional) — Remove now-redundant manual memoization calls
109
+
110
+ ### Examples
111
+
112
+ ```bash
113
+ # Report which functions will be memoized
114
+ react-compiler-analyzer coverage ./packages/react-components/react-button/library/src
115
+
116
+ # Per-function detail tables
117
+ react-compiler-analyzer coverage ./library/src --verbose
118
+
119
+ # Use annotation compilation mode
120
+ react-compiler-analyzer coverage ./library/src --mode annotation
121
+
122
+ # Auto-annotate migration candidates
123
+ react-compiler-analyzer coverage ./library/src --annotate
124
+
125
+ # Save report to a file
126
+ react-compiler-analyzer coverage ./src > report.md
127
+ ```
128
+
129
+ ## Shared options
130
+
131
+ | Argument / Flag | Type | Default | Description |
132
+ | ---------------- | ---------- | ------- | ---------------------------------------------------------------- |
133
+ | `<path>` | `string` | — | **Required.** Directory to scan for `.ts`/`.tsx` files |
134
+ | `--verbose` | `boolean` | `false` | Print per-function detail tables |
135
+ | `--full-reasons` | `boolean` | `false` | Show full compiler error messages instead of truncated summaries |
136
+ | `--concurrency` | `number` | `10` | Max parallel file processing |
137
+ | `--exclude` | `string[]` | _(1)_ | Glob patterns to exclude (tests, stories, mocks) |
138
+
139
+ _(1)_ Default excludes: `**/__tests__/**`, `**/testing/**`, `**/__mocks__/**`, `**/*.spec.*`, `**/*.test.*`, `**/*.stories.*`, `**/*.cy.*`
140
+
141
+ The package name shown in the report is derived from the nearest `package.json` found by walking up from `<path>`.
142
+
143
+ ## Nx integration
144
+
145
+ ```jsonc
146
+ // project.json
147
+ {
148
+ "targets": {
149
+ "analyze-compiler": {
150
+ "command": "react-compiler-analyzer directives ./library/src"
151
+ },
152
+ "compiler-coverage": {
153
+ "command": "react-compiler-analyzer coverage ./library/src"
154
+ }
155
+ }
156
+ }
157
+ ```
158
+
159
+ ## Architecture
160
+
161
+ ```
162
+ src/
163
+ ├── cli.ts — CLI entry: yargs setup and command registration
164
+ ├── commands/
165
+ │ ├── shared.ts — Shared options builder, path/concurrency validation, defaults
166
+ │ ├── directives.ts — CommandModule for 'directives' (builder + handler)
167
+ │ └── coverage.ts — CommandModule for 'coverage' (builder + handler, --annotate)
168
+ ├── discovery.ts — File discovery utilities (findPackageName, glob helpers)
169
+ ├── analyzer.ts — Directive engine: parsing, source stripping, babel transforms, event correlation
170
+ ├── coverage-analyzer.ts — Coverage engine: runs manual-memo + compiler plugins, captures per-function events
171
+ ├── manual-memo-plugin.ts — Babel plugin detecting useMemo/useCallback/React.memo usage per function
172
+ ├── coverage-fixer.ts — Applies 'use memo' annotations to migration candidates
173
+ ├── reporter.ts — Directive report generation (grouped by package, then by status)
174
+ ├── coverage-reporter.ts — Coverage report generation (summary tables + migration candidates + per-function details)
175
+ ├── compiler-utils.ts — Shared utilities for processing compiler events
176
+ ├── fixer.ts — Source file modifications (remove redundant, annotate active)
177
+ ├── types.ts — Shared TypeScript interfaces
178
+ └── index.ts — Public API exports
179
+ ```
180
+
181
+ Key dependencies:
182
+
183
+ - `@babel/core` — runs `transformAsync` for each file
184
+ - `@babel/preset-typescript` — parses `.ts`/`.tsx` without SWC
185
+ - `babel-plugin-react-compiler` — the React Compiler itself, configured with `noEmit: true` and a custom `Logger`
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+
3
+ // @ts-check
4
+
5
+ const { cli } = require('../dist/src/cli');
6
+
7
+ cli().catch(err => {
8
+ console.error(err);
9
+ process.exit(1);
10
+ });
package/dist/README.md ADDED
@@ -0,0 +1,185 @@
1
+ # @fluentui/react-compiler-analyzer
2
+
3
+ Analyzes React Compiler behavior on TypeScript source files. Two commands:
4
+
5
+ - **`directives`** — Detects redundant `'use no memo'` directives by checking whether the compiler actually needs to bail out.
6
+ - **`coverage`** — Reports which functions the React Compiler will memoize, skip, or bail out on. Also detects manual memoization (`useMemo`, `useCallback`, `React.memo`) and identifies migration candidates.
7
+
8
+ ## `directives`
9
+
10
+ Detects redundant `'use no memo'` directives that were added conservatively during the React Compiler migration. Most are redundant — the compiler bails out on its own for patterns it can't safely optimize.
11
+
12
+ ```bash
13
+ react-compiler-analyzer directives <path> [options]
14
+ ```
15
+
16
+ ### How it works
17
+
18
+ For each source file containing `'use no memo'`:
19
+
20
+ 1. **Parse** — finds all directive locations and checks for `// justified: <reason>` comments
21
+ 2. **Strip** — creates an in-memory copy with non-justified directives removed (no files written)
22
+ 3. **Analyze** — runs `babel-plugin-react-compiler` with `noEmit: true` and a custom `Logger`
23
+ 4. **Classify** each directive:
24
+
25
+ | Status | Meaning | `--fix` action |
26
+ | ------------- | --------------------------------------------------------------------- | --------------------------------------- |
27
+ | **Redundant** | Compiler emits `CompileError` / `PipelineError` — it bails out anyway | Removes the directive |
28
+ | **Active** | Compiler emits `CompileSuccess` — the directive prevents optimization | Annotates with `// justified: <reason>` |
29
+ | **Skipped** | Directive already has a `// justified:` comment | No change |
30
+
31
+ ### Options
32
+
33
+ | Flag | Type | Default | Description |
34
+ | ------- | --------- | ------- | --------------------------------------------------------- |
35
+ | `--fix` | `boolean` | `false` | Auto-remove redundant directives and annotate active ones |
36
+
37
+ When `--fix` annotates an active directive it uses:
38
+
39
+ ```ts
40
+ 'use no memo'; // justified: compiler would optimize useFoo — manual opt-out to preserve runtime behavior
41
+ ```
42
+
43
+ This format satisfies the `@nx/workspace-no-unjustified-use-no-memo` ESLint rule (in `tools/eslint-rules/`), which enforces that every `'use no memo'` carries a justification comment.
44
+
45
+ Exit code `1` when redundant directives exist and `--fix` is not applied (useful for CI gating).
46
+
47
+ ### Examples
48
+
49
+ ```bash
50
+ # Detect redundant directives
51
+ react-compiler-analyzer directives ./packages/react-components/react-tree/library/src
52
+
53
+ # Auto-fix: remove redundant + annotate active
54
+ react-compiler-analyzer directives ./library/src --fix
55
+
56
+ # Show full compiler error reasons
57
+ react-compiler-analyzer directives ./src --full-reasons
58
+ ```
59
+
60
+ ## `coverage`
61
+
62
+ Reports which functions the React Compiler will memoize, skip, or bail out on. Detects manual memoization and identifies migration candidates.
63
+
64
+ ```bash
65
+ react-compiler-analyzer coverage <path> [options]
66
+ ```
67
+
68
+ ### Options
69
+
70
+ | Flag | Type | Default | Description |
71
+ | ------------ | --------- | --------- | ------------------------------------------------------------------------- |
72
+ | `--mode` | `string` | `"infer"` | React Compiler compilation mode. Choices: `infer`, `annotation`, `all` |
73
+ | `--annotate` | `boolean` | `false` | Insert `'use memo'` into compilable functions that use manual memoization |
74
+
75
+ ### `--annotate`
76
+
77
+ Supports a gradual migration workflow. A function is a **migration candidate** when:
78
+
79
+ 1. The React Compiler reports `CompileSuccess` (it can fully optimize the function)
80
+ 2. The function contains manual memoization (`useMemo`, `useCallback`, `React.memo`)
81
+
82
+ The flag inserts `'use memo';` at the top of each candidate's function body:
83
+
84
+ **Before:**
85
+
86
+ ```tsx
87
+ export function useTree_unstable(props: TreeProps) {
88
+ const sorted = useMemo(() => sortItems(props.items), [props.items]);
89
+ }
90
+ ```
91
+
92
+ **After:**
93
+
94
+ ```tsx
95
+ export function useTree_unstable(props: TreeProps) {
96
+ 'use memo';
97
+ const sorted = useMemo(() => sortItems(props.items), [props.items]);
98
+ }
99
+ ```
100
+
101
+ It does **not** remove `useMemo`/`useCallback`/`React.memo` calls, does not modify functions the compiler cannot compile, and is idempotent (running twice is safe).
102
+
103
+ **Recommended workflow:**
104
+
105
+ 1. **Audit** — Run `coverage` without `--annotate` to review migration candidates
106
+ 2. **Annotate** — Run with `--annotate` to opt-in candidates to compiler optimization
107
+ 3. **Verify** — Run tests, check bundle size
108
+ 4. **Clean up** (optional) — Remove now-redundant manual memoization calls
109
+
110
+ ### Examples
111
+
112
+ ```bash
113
+ # Report which functions will be memoized
114
+ react-compiler-analyzer coverage ./packages/react-components/react-button/library/src
115
+
116
+ # Per-function detail tables
117
+ react-compiler-analyzer coverage ./library/src --verbose
118
+
119
+ # Use annotation compilation mode
120
+ react-compiler-analyzer coverage ./library/src --mode annotation
121
+
122
+ # Auto-annotate migration candidates
123
+ react-compiler-analyzer coverage ./library/src --annotate
124
+
125
+ # Save report to a file
126
+ react-compiler-analyzer coverage ./src > report.md
127
+ ```
128
+
129
+ ## Shared options
130
+
131
+ | Argument / Flag | Type | Default | Description |
132
+ | ---------------- | ---------- | ------- | ---------------------------------------------------------------- |
133
+ | `<path>` | `string` | — | **Required.** Directory to scan for `.ts`/`.tsx` files |
134
+ | `--verbose` | `boolean` | `false` | Print per-function detail tables |
135
+ | `--full-reasons` | `boolean` | `false` | Show full compiler error messages instead of truncated summaries |
136
+ | `--concurrency` | `number` | `10` | Max parallel file processing |
137
+ | `--exclude` | `string[]` | _(1)_ | Glob patterns to exclude (tests, stories, mocks) |
138
+
139
+ _(1)_ Default excludes: `**/__tests__/**`, `**/testing/**`, `**/__mocks__/**`, `**/*.spec.*`, `**/*.test.*`, `**/*.stories.*`, `**/*.cy.*`
140
+
141
+ The package name shown in the report is derived from the nearest `package.json` found by walking up from `<path>`.
142
+
143
+ ## Nx integration
144
+
145
+ ```jsonc
146
+ // project.json
147
+ {
148
+ "targets": {
149
+ "analyze-compiler": {
150
+ "command": "react-compiler-analyzer directives ./library/src"
151
+ },
152
+ "compiler-coverage": {
153
+ "command": "react-compiler-analyzer coverage ./library/src"
154
+ }
155
+ }
156
+ }
157
+ ```
158
+
159
+ ## Architecture
160
+
161
+ ```
162
+ src/
163
+ ├── cli.ts — CLI entry: yargs setup and command registration
164
+ ├── commands/
165
+ │ ├── shared.ts — Shared options builder, path/concurrency validation, defaults
166
+ │ ├── directives.ts — CommandModule for 'directives' (builder + handler)
167
+ │ └── coverage.ts — CommandModule for 'coverage' (builder + handler, --annotate)
168
+ ├── discovery.ts — File discovery utilities (findPackageName, glob helpers)
169
+ ├── analyzer.ts — Directive engine: parsing, source stripping, babel transforms, event correlation
170
+ ├── coverage-analyzer.ts — Coverage engine: runs manual-memo + compiler plugins, captures per-function events
171
+ ├── manual-memo-plugin.ts — Babel plugin detecting useMemo/useCallback/React.memo usage per function
172
+ ├── coverage-fixer.ts — Applies 'use memo' annotations to migration candidates
173
+ ├── reporter.ts — Directive report generation (grouped by package, then by status)
174
+ ├── coverage-reporter.ts — Coverage report generation (summary tables + migration candidates + per-function details)
175
+ ├── compiler-utils.ts — Shared utilities for processing compiler events
176
+ ├── fixer.ts — Source file modifications (remove redundant, annotate active)
177
+ ├── types.ts — Shared TypeScript interfaces
178
+ └── index.ts — Public API exports
179
+ ```
180
+
181
+ Key dependencies:
182
+
183
+ - `@babel/core` — runs `transformAsync` for each file
184
+ - `@babel/preset-typescript` — parses `.ts`/`.tsx` without SWC
185
+ - `babel-plugin-react-compiler` — the React Compiler itself, configured with `noEmit: true` and a custom `Logger`
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "@fluentui/react-compiler-analyzer",
3
+ "version": "0.0.0-experimental.rc-analyzer.20260430-fc3bb2e193",
4
+ "type": "commonjs",
5
+ "main": "./dist/src/index.js",
6
+ "types": "./dist/src/index.d.ts",
7
+ "files": [
8
+ "bin",
9
+ "*.md",
10
+ "dist",
11
+ "lib",
12
+ "lib-commonjs"
13
+ ],
14
+ "bin": {
15
+ "react-compiler-analyzer": "./bin/react-compiler-analyzer.js"
16
+ },
17
+ "dependencies": {
18
+ "@swc/helpers": "~0.5.1",
19
+ "yargs": "^17.7.2",
20
+ "@babel/core": "^7.28.5",
21
+ "@babel/preset-typescript": "^7.28.5",
22
+ "babel-plugin-react-compiler": "^1.0.0"
23
+ }
24
+ }
@@ -0,0 +1,9 @@
1
+ import type { DirectiveAnalysis, FileEntry, AnalyzerOptions } from './types';
2
+ /**
3
+ * Analyze a single file for redundant 'use no memo' directives.
4
+ */
5
+ export declare function analyzeFile(filePath: string, packageName: string, verbose: boolean): Promise<DirectiveAnalysis[]>;
6
+ /**
7
+ * Analyze multiple files with concurrency-limited parallelism.
8
+ */
9
+ export declare function analyzeFiles(files: FileEntry[], options: AnalyzerOptions): Promise<DirectiveAnalysis[]>;