Skip to content

Commit

Permalink
use jsxs when passing an array of children
Browse files Browse the repository at this point in the history
  • Loading branch information
mmews committed Feb 20, 2024
1 parent 8e6eab1 commit 7651225
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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]));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)}. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down

0 comments on commit 7651225

Please sign in to comment.