mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
[mcp] Refine passes returned (#32930)
Adds some new options to request the HIR, ReactiveFunction passes --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/32930). * #32932 * #32931 * __->__ #32930 * #32929 * #32928
This commit is contained in:
@@ -14,6 +14,16 @@ import * as prettier from 'prettier';
|
||||
|
||||
export let lastResult: BabelCore.BabelFileResult | null = null;
|
||||
|
||||
export type PrintedCompilerPipelineValue =
|
||||
| {
|
||||
kind: 'hir';
|
||||
name: string;
|
||||
fnName: string | null;
|
||||
value: string;
|
||||
}
|
||||
| {kind: 'reactive'; name: string; fnName: string | null; value: string}
|
||||
| {kind: 'debug'; name: string; fnName: string | null; value: string};
|
||||
|
||||
type CompileOptions = {
|
||||
text: string;
|
||||
file: string;
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
} from '@modelcontextprotocol/sdk/server/mcp.js';
|
||||
import {StdioServerTransport} from '@modelcontextprotocol/sdk/server/stdio.js';
|
||||
import {z} from 'zod';
|
||||
import {compile} from './compiler';
|
||||
import {compile, type PrintedCompilerPipelineValue} from './compiler';
|
||||
import {
|
||||
CompilerPipelineValue,
|
||||
printReactiveFunctionWithOutlined,
|
||||
@@ -22,19 +22,9 @@ import {
|
||||
import * as cheerio from 'cheerio';
|
||||
import TurndownService from 'turndown';
|
||||
import {queryAlgolia} from './utils/algolia';
|
||||
import assertExhaustive from './utils/assertExhaustive';
|
||||
|
||||
const turndownService = new TurndownService();
|
||||
|
||||
export type PrintedCompilerPipelineValue =
|
||||
| {
|
||||
kind: 'hir';
|
||||
name: string;
|
||||
fnName: string | null;
|
||||
value: string;
|
||||
}
|
||||
| {kind: 'reactive'; name: string; fnName: string | null; value: string}
|
||||
| {kind: 'debug'; name: string; fnName: string | null; value: string};
|
||||
|
||||
const server = new McpServer({
|
||||
name: 'React',
|
||||
version: '0.0.0',
|
||||
@@ -114,7 +104,7 @@ server.tool(
|
||||
'Compile code with React Compiler. Optionally, for debugging provide a pass name like "HIR" to see more information.',
|
||||
{
|
||||
text: z.string(),
|
||||
passName: z.string().optional(),
|
||||
passName: z.enum(['HIR', 'ReactiveFunction', 'All', '@DEBUG']).optional(),
|
||||
},
|
||||
async ({text, passName}) => {
|
||||
const pipelinePasses = new Map<
|
||||
@@ -164,8 +154,7 @@ server.tool(
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
const _: never = result;
|
||||
throw new Error(`Unhandled result ${result}`);
|
||||
assertExhaustive(result, `Unhandled result ${result}`);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -205,6 +194,78 @@ server.tool(
|
||||
}
|
||||
const requestedPasses: Array<{type: 'text'; text: string}> = [];
|
||||
if (passName != null) {
|
||||
switch (passName) {
|
||||
case 'All': {
|
||||
const hir = pipelinePasses.get('PropagateScopeDependenciesHIR');
|
||||
if (hir !== undefined) {
|
||||
for (const pipelineValue of hir) {
|
||||
requestedPasses.push({
|
||||
type: 'text' as const,
|
||||
text: pipelineValue.value,
|
||||
});
|
||||
}
|
||||
}
|
||||
const reactiveFunc = pipelinePasses.get('PruneHoistedContexts');
|
||||
if (reactiveFunc !== undefined) {
|
||||
for (const pipelineValue of reactiveFunc) {
|
||||
requestedPasses.push({
|
||||
type: 'text' as const,
|
||||
text: pipelineValue.value,
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'HIR': {
|
||||
// Last pass before HIR -> ReactiveFunction
|
||||
const requestedPass = pipelinePasses.get(
|
||||
'PropagateScopeDependenciesHIR',
|
||||
);
|
||||
if (requestedPass !== undefined) {
|
||||
for (const pipelineValue of requestedPass) {
|
||||
requestedPasses.push({
|
||||
type: 'text' as const,
|
||||
text: pipelineValue.value,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
console.error(`Could not find requested pass ${passName}`);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'ReactiveFunction': {
|
||||
// Last pass
|
||||
const requestedPass = pipelinePasses.get('PruneHoistedContexts');
|
||||
if (requestedPass !== undefined) {
|
||||
for (const pipelineValue of requestedPass) {
|
||||
requestedPasses.push({
|
||||
type: 'text' as const,
|
||||
text: pipelineValue.value,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
console.error(`Could not find requested pass ${passName}`);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '@DEBUG': {
|
||||
for (const [, pipelinePass] of pipelinePasses) {
|
||||
for (const pass of pipelinePass) {
|
||||
requestedPasses.push({
|
||||
type: 'text' as const,
|
||||
text: `${pass.name}\n\n${pass.value}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assertExhaustive(
|
||||
passName,
|
||||
`Unhandled passName option: ${passName}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
const requestedPass = pipelinePasses.get(passName);
|
||||
if (requestedPass !== undefined) {
|
||||
for (const pipelineValue of requestedPass) {
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Trigger an exhaustiveness check in TypeScript and throw at runtime.
|
||||
*/
|
||||
export default function assertExhaustive(_: never, errorMsg: string): never {
|
||||
throw new Error(errorMsg);
|
||||
}
|
||||
Reference in New Issue
Block a user