Skip to content

Commit a58276c

Browse files
committed
[playground] Allow (Arrow)FunctionExpressions
This was a pet peeve where our playground could only compile top level FunctionDeclarations. Just synthesize a fake identifier if it doesn't have one. ghstack-source-id: 882483c Pull Request resolved: #30729
1 parent 34edf3b commit a58276c

File tree

1 file changed

+34
-29
lines changed

1 file changed

+34
-29
lines changed

compiler/apps/playground/components/Editor/EditorImpl.tsx

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,14 @@ function parseFunctions(
6666
source: string,
6767
language: 'flow' | 'typescript',
6868
): Array<
69-
NodePath<
70-
t.FunctionDeclaration | t.ArrowFunctionExpression | t.FunctionExpression
71-
>
69+
| NodePath<t.FunctionDeclaration>
70+
| NodePath<t.ArrowFunctionExpression>
71+
| NodePath<t.FunctionExpression>
7272
> {
7373
const items: Array<
74-
NodePath<
75-
t.FunctionDeclaration | t.ArrowFunctionExpression | t.FunctionExpression
76-
>
74+
| NodePath<t.FunctionDeclaration>
75+
| NodePath<t.ArrowFunctionExpression>
76+
| NodePath<t.FunctionExpression>
7777
> = [];
7878
try {
7979
const ast = parseInput(source, language);
@@ -155,22 +155,33 @@ function isHookName(s: string): boolean {
155155
return /^use[A-Z0-9]/.test(s);
156156
}
157157

158-
function getReactFunctionType(
159-
id: NodePath<t.Identifier | null | undefined>,
160-
): ReactFunctionType {
161-
if (id && id.node && id.isIdentifier()) {
162-
if (isHookName(id.node.name)) {
158+
function getReactFunctionType(id: t.Identifier | null): ReactFunctionType {
159+
if (id != null) {
160+
if (isHookName(id.name)) {
163161
return 'Hook';
164162
}
165163

166164
const isPascalCaseNameSpace = /^[A-Z].*/;
167-
if (isPascalCaseNameSpace.test(id.node.name)) {
165+
if (isPascalCaseNameSpace.test(id.name)) {
168166
return 'Component';
169167
}
170168
}
171169
return 'Other';
172170
}
173171

172+
function getFunctionIdentifier(
173+
fn:
174+
| NodePath<t.FunctionDeclaration>
175+
| NodePath<t.ArrowFunctionExpression>
176+
| NodePath<t.FunctionExpression>,
177+
): t.Identifier | null {
178+
if (fn.isArrowFunctionExpression()) {
179+
return null;
180+
}
181+
const id = fn.get('id');
182+
return Array.isArray(id) === false && id.isIdentifier() ? id.node : null;
183+
}
184+
174185
function compile(source: string): [CompilerOutput, 'flow' | 'typescript'] {
175186
const results = new Map<string, PrintedCompilerPipelineValue[]>();
176187
const error = new CompilerError();
@@ -188,27 +199,21 @@ function compile(source: string): [CompilerOutput, 'flow' | 'typescript'] {
188199
} else {
189200
language = 'typescript';
190201
}
202+
let count = 0;
203+
const withIdentifier = (id: t.Identifier | null): t.Identifier => {
204+
if (id != null && id.name != null) {
205+
return id;
206+
} else {
207+
return t.identifier(`anonymous_${count++}`);
208+
}
209+
};
191210
try {
192211
// Extract the first line to quickly check for custom test directives
193212
const pragma = source.substring(0, source.indexOf('\n'));
194213
const config = parseConfigPragma(pragma);
195214

196215
for (const fn of parseFunctions(source, language)) {
197-
if (!fn.isFunctionDeclaration()) {
198-
error.pushErrorDetail(
199-
new CompilerErrorDetail({
200-
reason: `Unexpected function type ${fn.node.type}`,
201-
description:
202-
'Playground only supports parsing function declarations',
203-
severity: ErrorSeverity.Todo,
204-
loc: fn.node.loc ?? null,
205-
suggestions: null,
206-
}),
207-
);
208-
continue;
209-
}
210-
211-
const id = fn.get('id');
216+
const id = withIdentifier(getFunctionIdentifier(fn));
212217
for (const result of run(
213218
fn,
214219
{
@@ -221,7 +226,7 @@ function compile(source: string): [CompilerOutput, 'flow' | 'typescript'] {
221226
null,
222227
null,
223228
)) {
224-
const fnName = fn.node.id?.name ?? null;
229+
const fnName = id.name;
225230
switch (result.kind) {
226231
case 'ast': {
227232
upsert({
@@ -230,7 +235,7 @@ function compile(source: string): [CompilerOutput, 'flow' | 'typescript'] {
230235
name: result.name,
231236
value: {
232237
type: 'FunctionDeclaration',
233-
id: result.value.id,
238+
id,
234239
async: result.value.async,
235240
generator: result.value.generator,
236241
body: result.value.body,

0 commit comments

Comments
 (0)