Skip to content

Commit

Permalink
[playground] Allow (Arrow)FunctionExpressions
Browse files Browse the repository at this point in the history
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: 88342efbc594a430206383a66cdc47f8aa1efa06
Pull Request resolved: #30729
  • Loading branch information
poteto committed Aug 16, 2024
1 parent 4d088d9 commit d3992ee
Showing 1 changed file with 35 additions and 29 deletions.
64 changes: 35 additions & 29 deletions compiler/apps/playground/components/Editor/EditorImpl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,14 @@ function parseFunctions(
source: string,
language: 'flow' | 'typescript',
): Array<
NodePath<
t.FunctionDeclaration | t.ArrowFunctionExpression | t.FunctionExpression
>
| NodePath<t.FunctionDeclaration>
| NodePath<t.ArrowFunctionExpression>
| NodePath<t.FunctionExpression>
> {
const items: Array<
NodePath<
t.FunctionDeclaration | t.ArrowFunctionExpression | t.FunctionExpression
>
| NodePath<t.FunctionDeclaration>
| NodePath<t.ArrowFunctionExpression>
| NodePath<t.FunctionExpression>
> = [];
try {
const ast = parseInput(source, language);
Expand Down Expand Up @@ -155,22 +155,42 @@ function isHookName(s: string): boolean {
return /^use[A-Z0-9]/.test(s);
}

function getReactFunctionType(
id: NodePath<t.Identifier | null | undefined>,
): ReactFunctionType {
if (id && id.node && id.isIdentifier()) {
if (isHookName(id.node.name)) {
function getReactFunctionType(id: t.Identifier | null): ReactFunctionType {
if (id != null) {
if (isHookName(id.name)) {
return 'Hook';
}

const isPascalCaseNameSpace = /^[A-Z].*/;
if (isPascalCaseNameSpace.test(id.node.name)) {
if (isPascalCaseNameSpace.test(id.name)) {
return 'Component';
}
}
return 'Other';
}

function getFunctionName(
fn:
| NodePath<t.FunctionDeclaration>
| NodePath<t.ArrowFunctionExpression>
| NodePath<t.FunctionExpression>,
): t.Identifier | null {
if (fn.isArrowFunctionExpression()) {
return null;
}
const id = fn.get('id');
return Array.isArray(id) === false && id.isIdentifier() ? id.node : null;
}

let count = 0;
function makeIdentifier(id: t.Identifier | null): t.Identifier {
if (id != null && id.name != null) {
return id;
} else {
return t.identifier(`anonymous_${count++}`);
}
}

function compile(source: string): [CompilerOutput, 'flow' | 'typescript'] {
const results = new Map<string, PrintedCompilerPipelineValue[]>();
const error = new CompilerError();
Expand All @@ -194,21 +214,7 @@ function compile(source: string): [CompilerOutput, 'flow' | 'typescript'] {
const config = parseConfigPragma(pragma);

for (const fn of parseFunctions(source, language)) {
if (!fn.isFunctionDeclaration()) {
error.pushErrorDetail(
new CompilerErrorDetail({
reason: `Unexpected function type ${fn.node.type}`,
description:
'Playground only supports parsing function declarations',
severity: ErrorSeverity.Todo,
loc: fn.node.loc ?? null,
suggestions: null,
}),
);
continue;
}

const id = fn.get('id');
const id = getFunctionName(fn);
for (const result of run(
fn,
{
Expand All @@ -221,7 +227,7 @@ function compile(source: string): [CompilerOutput, 'flow' | 'typescript'] {
null,
null,
)) {
const fnName = fn.node.id?.name ?? null;
const fnName = id?.name ?? '(anonymous)';
switch (result.kind) {
case 'ast': {
upsert({
Expand All @@ -230,7 +236,7 @@ function compile(source: string): [CompilerOutput, 'flow' | 'typescript'] {
name: result.name,
value: {
type: 'FunctionDeclaration',
id: result.value.id,
id: makeIdentifier(result.value.id),
async: result.value.async,
generator: result.value.generator,
body: result.value.body,
Expand Down

0 comments on commit d3992ee

Please sign in to comment.