Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GH-2608: Fix jsx transpiler wrt jsxs #2609

Merged
merged 3 commits into from
Feb 20, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
use jsxs when passing an array of children
mmews committed Feb 20, 2024
commit 76512252ab8b3d1f606d3a2c4ae94135e8296e12
Original file line number Diff line number Diff line change
@@ -12,10 +12,12 @@

import static org.eclipse.n4js.tooling.react.ReactHelper.REACT_ELEMENT_PROPERTY_CHILDREN_NAME;
import static org.eclipse.n4js.tooling.react.ReactHelper.REACT_ELEMENT_PROPERTY_KEY_NAME;
import static org.eclipse.n4js.tooling.react.ReactHelper.REACT_JSXS_TRANSFORM_NAME;
import static org.eclipse.n4js.tooling.react.ReactHelper.REACT_JSX_RUNTIME_NAME;
import static org.eclipse.n4js.tooling.react.ReactHelper.REACT_JSX_TRANSFORM_NAME;
import static org.eclipse.n4js.transpiler.TranspilerBuilderBlocks._ArrLit;
import static org.eclipse.n4js.transpiler.TranspilerBuilderBlocks._CallExpr;
import static org.eclipse.n4js.transpiler.TranspilerBuilderBlocks._NamedImportSpecifier;
import static org.eclipse.n4js.transpiler.TranspilerBuilderBlocks._ObjLit;
import static org.eclipse.n4js.transpiler.TranspilerBuilderBlocks._PropertyAccessExpr;
import static org.eclipse.n4js.transpiler.TranspilerBuilderBlocks._PropertyNameValuePair;
@@ -28,7 +30,10 @@

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.emf.common.util.EList;
import org.eclipse.n4js.n4JS.Expression;
@@ -41,6 +46,7 @@
import org.eclipse.n4js.n4JS.JSXFragment;
import org.eclipse.n4js.n4JS.JSXPropertyAttribute;
import org.eclipse.n4js.n4JS.JSXSpreadAttribute;
import org.eclipse.n4js.n4JS.NamedImportSpecifier;
import org.eclipse.n4js.n4JS.NamespaceImportSpecifier;
import org.eclipse.n4js.n4JS.ParameterizedCallExpression;
import org.eclipse.n4js.n4JS.PropertyAssignment;
@@ -71,13 +77,15 @@
* will be transformed to
*
* <pre>
* React.createElement('div', Object.assign({attr: "value"}));
* $jsv('div', {attr: "value"});
* </pre>
*/
public class JSXTransformation extends Transformation {
/** Alias for React transform */
public static final String JSX_ALIAS = "$" + REACT_JSX_TRANSFORM_NAME;
static final Map<String, String> ALIAS_MAP = Map.of(
REACT_JSX_TRANSFORM_NAME, "$" + REACT_JSX_TRANSFORM_NAME,
REACT_JSXS_TRANSFORM_NAME, "$" + REACT_JSXS_TRANSFORM_NAME);

private final Set<String> necessaryImports = new LinkedHashSet<>();
private SymbolTableEntryOriginal steForJsxBackendNamespace;
private SymbolTableEntryOriginal steForJsxBackendFragmentComponent;

@@ -138,19 +146,25 @@ public void transform() {
return;
}

createImportOfJsx();
steForJsxBackendNamespace = createImportOfJsxBackend(); // will be removed if obsolete
steForJsxBackendFragmentComponent = prepareFragmentComponent();

// Transform JSXFragments and JSXElements
for (JSXAbstractElement jsxElem : jsxAbstractElements) {
transformJSXAbstractElement(jsxElem);
}
createNecessaryImportsOfJsx();
}

private void createImportOfJsx() {
ImportDeclaration impDecl = addNamedImport(REACT_JSX_TRANSFORM_NAME, JSX_ALIAS, REACT_JSX_RUNTIME_NAME);
impDecl.getImportSpecifiers().forEach(is -> is.setFlaggedUsedInCode(true));
private void createNecessaryImportsOfJsx() {
List<String> importSpecifierNames = new ArrayList<>(necessaryImports);
NamedImportSpecifier[] importSpecs = new NamedImportSpecifier[importSpecifierNames.size()];
for (int i = 0; i < importSpecifierNames.size(); i++) {
String isn = importSpecifierNames.get(i);
String alias = ALIAS_MAP.get(isn);
importSpecs[i] = _NamedImportSpecifier(isn, alias, true);
}
addNamedImport(REACT_JSX_RUNTIME_NAME, importSpecs);
}

private SymbolTableEntryOriginal createImportOfJsxBackend() {
@@ -216,7 +230,10 @@ private ParameterizedCallExpression convertJSXAbstractElement(JSXAbstractElement
}

IdentifierRef_IM idRef = ImFactory.eINSTANCE.createIdentifierRef_IM();
idRef.setIdAsText(JSX_ALIAS);
String isn = elem.getJsxChildren().size() > 1 ? REACT_JSXS_TRANSFORM_NAME : REACT_JSX_TRANSFORM_NAME;
necessaryImports.add(isn);
String jsxAlias = ALIAS_MAP.get(isn);
idRef.setIdAsText(jsxAlias);
SymbolTableEntryInternal ste = getSymbolTableEntryInternal(idRef.getIdAsText(), true);
idRef.setId_IM(ste);
return _CallExpr(idRef, args.toArray(new Expression[0]));
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@
*/
package org.eclipse.n4js.transpiler.es.transform;

import static org.eclipse.n4js.tooling.react.ReactHelper.REACT_JSX_RUNTIME_NAME;
import static org.eclipse.xtext.xbase.lib.IterableExtensions.exists;
import static org.eclipse.xtext.xbase.lib.IterableExtensions.filter;
import static org.eclipse.xtext.xbase.lib.IterableExtensions.toList;
@@ -158,8 +159,9 @@ private boolean isUsed(ImportSpecifier importSpec) {
// add new usages of an existing import)
// -> therefore simply return false (i.e. unused)
return false;
} else if (importSpec instanceof NamedImportSpecifier
&& JSXTransformation.JSX_ALIAS.equals(((NamedImportSpecifier) importSpec).getAlias())) {
} else if (importSpec.eContainer() instanceof ImportDeclaration
&& REACT_JSX_RUNTIME_NAME
.equals(((ImportDeclaration) importSpec.eContainer()).getModuleSpecifierAsText())) {
// special case for import that is added in JSXTransformation
return true;
} else {
Original file line number Diff line number Diff line change
@@ -109,10 +109,9 @@ public void addNamedImport(SymbolTableEntryOriginal steOfElementToImport, String
TranspilerStateOperations.addNamedImport(state, steOfElementToImport, aliasOrNull);
}

/** See {@link TranspilerStateOperations#addNamedImport(TranspilerState, String, String, String)}. */
public ImportDeclaration addNamedImport(String elementNameToImport, String aliasOrNull,
String moduleSpecifierName) {
return TranspilerStateOperations.addNamedImport(state, elementNameToImport, aliasOrNull, moduleSpecifierName);
/** See {@link TranspilerStateOperations#addNamedImport(TranspilerState, String, NamedImportSpecifier...)}. */
public ImportDeclaration addNamedImport(String moduleSpecifierName, NamedImportSpecifier... importSpecifiers) {
return TranspilerStateOperations.addNamedImport(state, moduleSpecifierName, importSpecifiers);
}

/** See {@link TranspilerStateOperations#addEmptyImport(TranspilerState, String)}. */
Original file line number Diff line number Diff line change
@@ -187,18 +187,17 @@ public static void addNamedImport(TranspilerState state, SymbolTableEntryOrigina
}

/**
* Creates a new named import for the given STE and adds it to the intermediate model of the given transpiler state.
* Note that this method does not perform a binding to an existing target module.
* Creates a new named import for the given names. It does not add it to the intermediate model of the given
* transpiler state. Note that this method does not perform a binding to an existing target module.
* <p>
* IMPORTANT: this method does not check if the given element name or alias is unique (i.e. does not avoid name
* clashes!).
*/
public static ImportDeclaration addNamedImport(TranspilerState state, String elementNameToImport,
String aliasOrNull, String moduleSpecifierName) {
public static ImportDeclaration addNamedImport(TranspilerState state, String moduleSpecifierName,
NamedImportSpecifier... importSpecifiers) {

// 1) create import declaration & specifier
NamedImportSpecifier importSpec = _NamedImportSpecifier(elementNameToImport, aliasOrNull, true);
ImportDeclaration importDecl = _ImportDecl(importSpec);
ImportDeclaration importDecl = _ImportDecl(importSpecifiers);
importDecl.setModuleSpecifierAsText(moduleSpecifierName);

// 2) add import to intermediate model
Original file line number Diff line number Diff line change
@@ -62,6 +62,7 @@ class ReactHelper {

public final static String REACT_NAMESPACE_NAME = REACT_PROJECT_ID.toFirstUpper;
public final static String REACT_JSX_TRANSFORM_NAME = "jsx";
public final static String REACT_JSXS_TRANSFORM_NAME = "jsxs";
public final static String REACT_ELEMENT_FACTORY_FUNCTION_NAME = "createElement";
public final static String REACT_ELEMENT_PROPERTY_KEY_NAME = "key";
public final static String REACT_ELEMENT_PROPERTY_CHILDREN_NAME = "children";