Merge branch 'pbtura-issue-427'

This commit is contained in:
Louis Grignon 2018-05-13 19:30:20 +02:00
commit 71d1e6f226
12 changed files with 403 additions and 192 deletions

View File

@ -0,0 +1,33 @@
/*
* JSweet - http://www.jsweet.org
* Copyright (C) 2015 CINCHEO SAS <renaud.pawlak@cincheo.fr>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jsweet.lang;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Use this annotation to indicate a method that should have it's parameters
* wrapped in a parameter object.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.CONSTRUCTOR })
@Documented
public @interface WrapParameters {
}

View File

@ -0,0 +1,33 @@
/*
* JSweet - http://www.jsweet.org
* Copyright (C) 2015 CINCHEO SAS <renaud.pawlak@cincheo.fr>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jsweet.lang;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Use this annotation to indicate a method that should have it's parameters
* wrapped in a parameter object.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.CONSTRUCTOR })
@Documented
public @interface WrapParameters {
}

View File

@ -157,6 +157,11 @@
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>

View File

@ -313,6 +313,10 @@ public abstract class JSweetConfig {
* Fully-qualified name for the JSweet <code>@SNoDebug</code> annotation (see JSweet core API).
*/
public static final String ANNOTATION_NO_DEBUG = JSweetConfig.LANG_PACKAGE + ".NoDebug";
/**
* Fully-qualified name for the JSweet <code>@WrapParameters</code> annotation (see JSweet core API).
*/
public static final String ANNOTATION_WRAP_PARAMETERS = JSweetConfig.LANG_PACKAGE + ".WrapParameters";
/**
* Fully-qualified name for the built-in Java {@link FunctionalInterface} annotation.
*/

View File

@ -130,7 +130,7 @@ public class JSweetContext extends Context {
public Map<String, TypeMirror> getJdkSubclasses() {
return jdkSubclasses;
}
/**
* Gets the JDK type extended by the given subclass, if any.
*/
@ -174,9 +174,9 @@ public class JSweetContext extends Context {
*
* @param fullyQualifiedName
* fully qualified owning type name + "." + method name
* @return an array containing the class and method AST objects of any
* matching method (in theory several methods could match because of
* overloading but we ignore it here)
* @return an array containing the class and method AST objects of any matching
* method (in theory several methods could match because of overloading
* but we ignore it here)
* @see #registerGlobalMethod(JCMethodDecl)
*/
public JCTree[] lookupGlobalMethod(String fullyQualifiedName) {
@ -203,17 +203,15 @@ public class JSweetContext extends Context {
* @param sourceTypeName
* the fully qualified name of the source type
* @param targetTypeName
* the fully Qualified name of the type the source type is mapped
* to
* the fully Qualified name of the type the source type is mapped to
*/
public final void addTypeMapping(String sourceTypeName, String targetTypeName) {
typesMapping.put(sourceTypeName, targetTypeName);
}
/**
* Adds a set of name-based type mappings. This method is equivalent to
* calling {@link #addTypeMapping(String, String)} for each entry of the
* given map.
* Adds a set of name-based type mappings. This method is equivalent to calling
* {@link #addTypeMapping(String, String)} for each entry of the given map.
*/
public final void addTypeMappings(Map<String, String> nameMappings) {
typesMapping.putAll(nameMappings);
@ -241,9 +239,9 @@ public class JSweetContext extends Context {
* Adds a functional type mapping.
*
* @param mappingFunction
* a function that takes the type tree, the type name, and
* returns a mapped type (either under the form of a string, or
* of a string, or of another type tree).
* a function that takes the type tree, the type name, and returns a
* mapped type (either under the form of a string, or of a string, or
* of another type tree).
*/
public final void addTypeMapping(BiFunction<ExtendedElement, String, Object> mappingFunction) {
complexTypesMapping.add(mappingFunction);
@ -257,8 +255,8 @@ public class JSweetContext extends Context {
}
/**
* Adds an annotation manager that will tune (add or remove) annotations on
* the AST. Lastly added managers have precedence over firstly added ones.
* Adds an annotation manager that will tune (add or remove) annotations on the
* AST. Lastly added managers have precedence over firstly added ones.
*/
public final void addAnnotationManager(AnnotationManager annotationManager) {
annotationManagers.add(annotationManager);
@ -373,16 +371,15 @@ public class JSweetContext extends Context {
* </pre>
*
* <p>
* Filters are simplified regular expressions matching on the Java AST.
* Special characters are the following:
* Filters are simplified regular expressions matching on the Java AST. Special
* characters are the following:
*
* <ul>
* <li>*: matches any token/identifier in the signature of the AST element
* </li>
* <li>**: matches any list of tokens in signature of the AST element (same
* as ..)</li>
* <li>..: matches any list of tokens in signature of the AST element (same
* as **)</li>
* <li>*: matches any token/identifier in the signature of the AST element</li>
* <li>**: matches any list of tokens in signature of the AST element (same as
* ..)</li>
* <li>..: matches any list of tokens in signature of the AST element (same as
* **)</li>
* <li>!: negates the filter (first character only)</li>
* </ul>
*
@ -412,9 +409,9 @@ public class JSweetContext extends Context {
/**
* Adds an annotation on the AST through global filters.
*
* The annotation to be added is described by its type and by a value, which
* is passed as is to the annotation's value. If the annotation type does
* not accept a value parameter, no annotations will be added.
* The annotation to be added is described by its type and by a value, which is
* passed as is to the annotation's value. If the annotation type does not
* accept a value parameter, no annotations will be added.
*
* @see #addAnnotation(String, String...)
*/
@ -435,8 +432,8 @@ public class JSweetContext extends Context {
* </pre>
*
* <p>
* Filters are simplified regular expressions matching on the Java AST.
* Special characters are the following:
* Filters are simplified regular expressions matching on the Java AST. Special
* characters are the following:
*
* <ul>
* <li>*: matches any character in the signature of the AST element</li>
@ -445,8 +442,8 @@ public class JSweetContext extends Context {
*
* @param annotationDescriptor
* the annotation type name, optionally preceded with a @, and
* optionally defining a value (fully qualified name is not
* necessary for JSweet annotations)
* optionally defining a value (fully qualified name is not necessary
* for JSweet annotations)
* @param filters
* the annotation is activated if one of the filters match and no
* negative filter matches
@ -638,8 +635,7 @@ public class JSweetContext extends Context {
}
/**
* Tells if that method is part of an invalid overload in its declaring
* class.
* Tells if that method is part of an invalid overload in its declaring class.
*/
public boolean isInvalidOverload(MethodSymbol method) {
Overload overload = getOverload((ClassSymbol) method.getEnclosingElement(), method);
@ -674,9 +670,9 @@ public class JSweetContext extends Context {
public boolean useModules = false;
/**
* A flag to tell if the transpiler should transpiler modules to old
* fashioned require instructions rather than the ES2015 flavored syntax.
* import foo = require("foo"); instead of import * as foo from 'foo';
* A flag to tell if the transpiler should transpiler modules to old fashioned
* require instructions rather than the ES2015 flavored syntax. import foo =
* require("foo"); instead of import * as foo from 'foo';
*/
public boolean useRequireForModules = true;
@ -793,8 +789,7 @@ public class JSweetContext extends Context {
}
/**
* The list of package names imported by the given m of the transpiled
* program.
* The list of package names imported by the given m of the transpiled program.
*/
public Map<Symbol, String> getImportedElements(String moduleName) {
Map<Symbol, String> importedElements = importedElementsInModules.get(moduleName);
@ -867,22 +862,21 @@ public class JSweetContext extends Context {
public DirectedGraph<PackageSymbol> packageDependencies = new DirectedGraph<>();
/**
* Stores the root package names (i.e. packages contained in the default
* package or in a package annotated with the {@link jsweet.lang.Root}
* annotation).
* Stores the root package names (i.e. packages contained in the default package
* or in a package annotated with the {@link jsweet.lang.Root} annotation).
*/
public Set<String> topLevelPackageNames = new HashSet<>();
/**
* Store root packages (i.e. packages contained in the default package or in
* a package annotated with the {@link jsweet.lang.Root} annotation,
* including null, i.e. default package).
* Store root packages (i.e. packages contained in the default package or in a
* package annotated with the {@link jsweet.lang.Root} annotation, including
* null, i.e. default package).
*/
public HashSet<PackageSymbol> rootPackages = new HashSet<>();
/**
* A flag to keep track of wether a multiple root packages problem was
* already reported (shall report only once).
* A flag to keep track of wether a multiple root packages problem was already
* reported (shall report only once).
*/
public boolean reportedMultipleRootPackages = false;
@ -892,20 +886,20 @@ public class JSweetContext extends Context {
public Set<String> globalImports = new HashSet<>();
/**
* Imported top packages (used to avoid clashes with local variables when
* bundle is on).
* Imported top packages (used to avoid clashes with local variables when bundle
* is on).
*/
public Set<String> importedTopPackages = new HashSet<>();
/**
* A flag that indicates if the transpilation is in "strict" mode, which
* means that the <code>jsweet-core-strict</code> jar is in the classpath.
* A flag that indicates if the transpilation is in "strict" mode, which means
* that the <code>jsweet-core-strict</code> jar is in the classpath.
*/
public boolean strictMode = false;
/**
* A flag that indicates if the transpiler should transform old-fashionned
* apply method to lambda or use the new convention ($apply)
* A flag that indicates if the transpiler should transform old-fashionned apply
* method to lambda or use the new convention ($apply)
*/
public boolean deprecatedApply = false;
@ -917,7 +911,7 @@ public class JSweetContext extends Context {
public void clearFooterStatements() {
footerStatements.clear();
}
/**
* Gets the footer statements.
*/
@ -953,7 +947,7 @@ public class JSweetContext extends Context {
public void clearHeaders() {
headers.clear();
}
/**
* Gets the headers.
*/
@ -1153,8 +1147,8 @@ public class JSweetContext extends Context {
private static Pattern libPackagePattern = Pattern.compile(JSweetConfig.LIBS_PACKAGE + "\\.[^.]*");
/**
* Returns true if the given symbol is a root package (annotated with @Root
* or a definition package).
* Returns true if the given symbol is a root package (annotated with @Root or a
* definition package).
*/
public boolean isRootPackage(Element element) {
Symbol symbol = (Symbol) element;
@ -1268,10 +1262,9 @@ public class JSweetContext extends Context {
}
/**
* Gets the top-level package enclosing the given symbol. The top-level
* package is the one that is enclosed within a root package (see
* <code>jsweet.lang.Root</code>) or the one in the default (unnamed)
* package.
* Gets the top-level package enclosing the given symbol. The top-level package
* is the one that is enclosed within a root package (see
* <code>jsweet.lang.Root</code>) or the one in the default (unnamed) package.
*/
public PackageSymbol getTopLevelPackage(Symbol symbol) {
if ((symbol instanceof PackageSymbol) && isRootPackage(symbol)) {
@ -1299,8 +1292,7 @@ public class JSweetContext extends Context {
}
/**
* Finds the first (including itself) enclosing package annotated
* with @Root.
* Finds the first (including itself) enclosing package annotated with @Root.
*/
public PackageSymbol getFirstEnclosingRootPackage(PackageSymbol packageSymbol) {
if (packageSymbol == null) {
@ -1375,8 +1367,8 @@ public class JSweetContext extends Context {
}
/**
* Gets the first value of the 'value' property for the given annotation
* type if found on the given symbol.
* Gets the first value of the 'value' property for the given annotation type if
* found on the given symbol.
*/
public final <T> T getAnnotationValue(Symbol symbol, String annotationType, Class<T> propertyClass,
T defaultValue) {
@ -1384,9 +1376,10 @@ public class JSweetContext extends Context {
}
/**
* Gets the first value of the given property for the given annotation type
* if found on the given symbol.
* Gets the first value of the given property for the given annotation type if
* found on the given symbol.
*/
@SuppressWarnings("unchecked")
public <T> T getAnnotationValue(Symbol symbol, String annotationType, String propertyName, Class<T> propertyClass,
T defaultValue) {
for (AnnotationManager annotationIntrospector : annotationManagers) {
@ -1574,8 +1567,8 @@ public class JSweetContext extends Context {
}
/**
* Tells if the given symbol is annotated with one of the given annotation
* type names.
* Tells if the given symbol is annotated with one of the given annotation type
* names.
*/
private static boolean hasActualAnnotationType(Symbol symbol, String... annotationTypes) {
for (Compound a : symbol.getAnnotationMirrors()) {
@ -1714,8 +1707,8 @@ public class JSweetContext extends Context {
}
/**
* Returns true if the given type symbol corresponds to a functional type
* (in the TypeScript way).
* Returns true if the given type symbol corresponds to a functional type (in
* the TypeScript way).
*/
public boolean isFunctionalType(TypeSymbol type) {
String name = type.getQualifiedName().toString();
@ -1727,8 +1720,7 @@ public class JSweetContext extends Context {
}
/**
* Returns true if the given type symbol corresponds to a core functional
* type.
* Returns true if the given type symbol corresponds to a core functional type.
*/
public boolean isCoreFunctionalType(TypeSymbol type) {
String name = type.getQualifiedName().toString();
@ -1739,8 +1731,8 @@ public class JSweetContext extends Context {
}
/**
* Tells if the given type has a anonymous function (instances can be used
* as lambdas).
* Tells if the given type has a anonymous function (instances can be used as
* lambdas).
*/
public boolean hasAnonymousFunction(TypeSymbol type) {
for (Symbol s : type.getEnclosedElements()) {
@ -1756,8 +1748,7 @@ public class JSweetContext extends Context {
}
/**
* Returns true if this class declaration is not to be output by the
* transpiler.
* Returns true if this class declaration is not to be output by the transpiler.
*/
public boolean isIgnored(JCClassDecl classdecl) {
if (hasAnnotationType(classdecl.type.tsym, JSweetConfig.ANNOTATION_OBJECT_TYPE)) {
@ -1792,9 +1783,8 @@ public class JSweetContext extends Context {
}
/**
* Tells if the transpiler is using J4TS Java runtime. If yes, it will use
* the adapter that tries to delegate to the Java emulation layer for the
* Java API.
* Tells if the transpiler is using J4TS Java runtime. If yes, it will use the
* adapter that tries to delegate to the Java emulation layer for the Java API.
*/
public boolean isUsingJavaRuntime() {
return usingJavaRuntime;
@ -1833,8 +1823,8 @@ public class JSweetContext extends Context {
}
/**
* Tells if the given symbol is ambient (part of a def.* package or within
* an <code>@Ambient</code>-annotated scope).
* Tells if the given symbol is ambient (part of a def.* package or within an
* <code>@Ambient</code>-annotated scope).
*/
public boolean isAmbientDeclaration(Symbol symbol) {
if (symbol instanceof TypeSymbol

View File

@ -55,8 +55,8 @@ import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringEscapeUtils;
import org.apache.log4j.Logger;
import org.jsweet.JSweetConfig;
import org.jsweet.transpiler.OverloadScanner.Overload;
@ -289,7 +289,7 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
}
}
private static class ClassScope {
public static class ClassScope {
private String name;
private JCMethodDecl mainMethod;
@ -347,6 +347,122 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
private boolean decoratorScope = false;
public String getName() {
return name;
}
protected JCMethodDecl getMainMethod() {
return mainMethod;
}
protected boolean isInterfaceScope() {
return interfaceScope;
}
protected boolean isEnumScope() {
return enumScope;
}
protected boolean isComplexEnum() {
return isComplexEnum;
}
public boolean isEnumWrapperClassScope() {
return enumWrapperClassScope;
}
protected boolean isRemovedSuperclass() {
return removedSuperclass;
}
protected boolean isDeclareClassScope() {
return declareClassScope;
}
protected boolean isSkipTypeAnnotations() {
return skipTypeAnnotations;
}
protected boolean isDefaultMethodScope() {
return defaultMethodScope;
}
protected boolean isEraseVariableTypes() {
return eraseVariableTypes;
}
public void setEraseVariableTypes(boolean eraseVariableTypes) {
this.eraseVariableTypes = eraseVariableTypes;
}
protected boolean isHasDeclaredConstructor() {
return hasDeclaredConstructor;
}
protected boolean getInnerClass() {
return innerClass;
}
public boolean isInnerClassNotStatic() {
return innerClassNotStatic;
}
protected boolean isHasInnerClass() {
return hasInnerClass;
}
protected List<JCClassDecl> getAnonymousClasses() {
return anonymousClasses;
}
protected List<JCNewClass> getAnonymousClassesConstructors() {
return anonymousClassesConstructors;
}
protected List<LinkedHashSet<VarSymbol>> getFinalVariables() {
return finalVariables;
}
protected boolean isHasConstructorOverloadWithSuperClass() {
return hasConstructorOverloadWithSuperClass;
}
protected List<JCVariableDecl> getFieldsWithInitializers() {
return fieldsWithInitializers;
}
protected List<String> getInlinedConstructorArgs() {
return inlinedConstructorArgs;
}
protected List<JCClassDecl> getLocalClasses() {
return localClasses;
}
protected List<String> getGeneratedMethodNames() {
return generatedMethodNames;
}
protected boolean isAnonymousClass() {
return isAnonymousClass;
}
protected boolean isInnerClass() {
return isInnerClass;
}
protected boolean isLocalClass() {
return isLocalClass;
}
public boolean isConstructor() {
return constructor;
}
protected boolean isDecoratorScope() {
return decoratorScope;
}
}
private Stack<ClassScope> scope = new Stack<>();
@ -674,33 +790,11 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
}
}
Stack<Overload> overloadStack = new Stack<>();
@Override
public void scan(JCTree t) {
if (t instanceof JCImport) {
return;
}
// grab the types in overloaded method because they may use
// other types necessary for the instanceof implementation
// (see #342)
// if (t instanceof JCMethodDecl) {
// JCMethodDecl method = (JCMethodDecl) t;
// if (context.isInvalidOverload(method.sym)) {
// Overload overload = context.getOverload((ClassSymbol)
// method.sym.getEnclosingElement(),
// method.sym);
// System.out.println("overload: "+overload +" /
// "+overloadStack.size());
// if (!overloadStack.contains(overload)) {
// overloadStack.push(overload);
// for (JCMethodDecl overloadedMethod : overload.methods) {
// this.scan(overloadedMethod);
// }
// overloadStack.pop();
// }
// }
// }
if (t != null && t.type != null && t.type.tsym instanceof ClassSymbol) {
if (!(t instanceof JCTypeApply)) {
checkType(t.type.tsym);
@ -715,7 +809,7 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
// require root modules when using fully qualified names or reserved
// keywords
TreeScanner inlinedModuleScanner = new TreeScanner() {
new TreeScanner() {
Stack<JCTree> stack = new Stack<>();
public void scan(JCTree t) {
@ -950,7 +1044,7 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
}
}
private boolean isAnonymousClass() {
protected boolean isAnonymousClass() {
return scope.size() > 1 && getScope(1).isAnonymousClass;
}
@ -993,6 +1087,7 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
return this;
}
@SuppressWarnings("unlikely-arg-type")
private AbstractTreePrinter substituteAndPrintType(JCTree typeTree, boolean arrayComponent,
boolean inTypeParameters, boolean completeRawTypes, boolean disableSubstitution) {
if (typeTree.type.tsym instanceof TypeVariableSymbol) {
@ -1165,7 +1260,7 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
}
}
for (BiFunction<ExtendedElement, String, Object> mapping : context.getFunctionalTypeMappings()) {
Object mapped = mapping.apply(new ExtendedElementSupport(typeTree), typeFullName);
Object mapped = mapping.apply(new ExtendedElementSupport<JCTree>(typeTree), typeFullName);
if (mapped instanceof String) {
print((String) mapped);
return this;
@ -1335,6 +1430,7 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
print("/** @ignore */").println().printIndent();
}
print(classdecl.mods);
if (!isTopLevelScope() || context.useModules || isAnonymousClass() || isInnerClass() || isLocalClass()) {
print("export ");
}
@ -2212,35 +2308,7 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
inTypeParameters = false;
}
print("(");
if (inCoreWrongOverload) {
getScope().eraseVariableTypes = true;
}
boolean paramPrinted = false;
if (getScope().innerClassNotStatic && methodDecl.sym.isConstructor() && !getScope().enumWrapperClassScope) {
print(PARENT_CLASS_FIELD_NAME + ": any, ");
paramPrinted = true;
}
if (getScope().constructor && getScope().enumWrapperClassScope) {
print((isAnonymousClass() ? "" : "protected ") + ENUM_WRAPPER_CLASS_ORDINAL + " : number, ");
print((isAnonymousClass() ? "" : "protected ") + ENUM_WRAPPER_CLASS_NAME + " : string, ");
paramPrinted = true;
}
int i = 0;
for (JCVariableDecl param : methodDecl.getParameters()) {
print(param);
if (inOverload && overload.isValid && overload.defaultValues.get(i) != null) {
print(" = ").print(overload.defaultValues.get(i));
}
print(", ");
i++;
paramPrinted = true;
}
if (inCoreWrongOverload) {
getScope().eraseVariableTypes = false;
}
if (paramPrinted) {
removeLastChars(2);
}
printMethodArgs(methodDecl, overload, inOverload, inCoreWrongOverload, getScope());
print(")");
if (inCoreWrongOverload && !methodDecl.sym.isConstructor()) {
print(" : any");
@ -2284,7 +2352,7 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
print(" {").println().startIndent().printIndent();
boolean wasPrinted = false;
for (i = 0; i < overload.methods.size(); i++) {
for (int i = 0; i < overload.methods.size(); i++) {
JCMethodDecl method = overload.methods.get(i);
if (context.isInterface((ClassSymbol) method.sym.getEnclosingElement())
&& !method.getModifiers().getFlags().contains(Modifier.DEFAULT)
@ -2309,25 +2377,20 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
method.sym).coreMethod == method) {
print("{").println().startIndent().printIndent();
if ((method.getBody() == null
|| (method.mods.getFlags().contains(Modifier.DEFAULT) && !getScope().defaultMethodScope))
&& !getScope().interfaceScope && method.getModifiers().getFlags().contains(Modifier.ABSTRACT))
{
if ((method.getBody() == null || (method.mods.getFlags().contains(Modifier.DEFAULT)
&& !getScope().defaultMethodScope)) && !getScope().interfaceScope
&& method.getModifiers().getFlags().contains(Modifier.ABSTRACT)) {
print(" throw new Error('cannot invoke abstract overloaded method... check your argument(s) type(s)'); ");
}
else
{
} else {
String tsMethodAccess = getTSMemberAccess(getTSMethodName(methodDecl), true);
print("super" + tsMethodAccess);
print("(");
for (int j = 0; j < method.getParameters().size(); j++)
{
print(
avoidJSKeyword(overload.coreMethod.getParameters().get(j).name.toString()))
.print(", ");
for (int j = 0; j < method.getParameters().size(); j++) {
print(avoidJSKeyword(
overload.coreMethod.getParameters().get(j).name.toString()))
.print(", ");
}
if (!method.getParameters().isEmpty())
{
if (!method.getParameters().isEmpty()) {
removeLastChars(2);
}
print(");");
@ -2408,6 +2471,59 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
}
}
protected void printMethodArgs(JCMethodDecl methodDecl, Overload overload, boolean inOverload,
boolean inCoreWrongOverload, ClassScope scope) {
boolean isWrapped = false;
if (this.context.hasAnnotationType(methodDecl.sym, JSweetConfig.ANNOTATION_WRAP_PARAMETERS)) {
isWrapped = true;
}
if (isWrapped) {
print("{");
}
if (inCoreWrongOverload) {
scope.setEraseVariableTypes(true);
}
boolean paramPrinted = false;
if (scope.isInnerClassNotStatic() && methodDecl.sym.isConstructor() && !scope.isEnumWrapperClassScope()) {
print(PARENT_CLASS_FIELD_NAME + ": any, ");
paramPrinted = true;
}
if (scope.isConstructor() && scope.isEnumWrapperClassScope()) {
print((isAnonymousClass() ? "" : "protected ") + ENUM_WRAPPER_CLASS_ORDINAL + " : number, ");
print((isAnonymousClass() ? "" : "protected ") + ENUM_WRAPPER_CLASS_NAME + " : string, ");
paramPrinted = true;
}
int i = 0;
for (JCVariableDecl param : methodDecl.getParameters()) {
if (isWrapped) {
print(param.getName().toString());
} else {
print(param);
}
if (inOverload && overload.isValid && overload.defaultValues.get(i) != null) {
print(" = ").print(overload.defaultValues.get(i));
}
print(", ");
i++;
paramPrinted = true;
}
if (inCoreWrongOverload) {
scope.setEraseVariableTypes(false);
}
if (paramPrinted) {
removeLastChars(2);
}
if (isWrapped) {
print("}: {");
for (JCVariableDecl param : methodDecl.getParameters()) {
print(param).println(";");
}
print("}");
}
}
protected void printMethodModifiers(JCMethodDecl methodDecl, JCClassDecl parent, boolean constructor,
boolean inOverload, Overload overload) {
if (methodDecl.mods.getFlags().contains(Modifier.PUBLIC)
@ -2995,7 +3111,7 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
print(name);
}
if (!Util.isVarargs(varDecl) && (getScope().eraseVariableTypes || (getScope().interfaceScope
if (!Util.isVarargs(varDecl) && (getScope().isEraseVariableTypes() || (getScope().interfaceScope
&& context.hasAnnotationType(varDecl.sym, JSweetConfig.ANNOTATION_OPTIONAL)))) {
print("?");
}
@ -3005,7 +3121,7 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
if (confictInDefinitionScope) {
print("any");
} else {
if (getScope().eraseVariableTypes) {
if (getScope().isEraseVariableTypes()) {
print("any");
if (Util.isVarargs(varDecl)) {
print("[]");
@ -4580,7 +4696,7 @@ public class Java2TypeScriptTranslator extends AbstractTreePrinter {
}
return;
}
print(" " + op + "= ");
if (context.types.isSameType(context.symtab.charType, context.types.unboxedTypeOrType(assignOp.rhs.type))) {
substituteAndPrintAssignedExpression(context.symtab.intType, assignOp.rhs);

View File

@ -25,7 +25,6 @@ import java.util.Map;
import javax.lang.model.element.Modifier;
import org.apache.commons.lang3.StringUtils;
import org.jsweet.JSweetConfig;
import org.jsweet.transpiler.util.AbstractTreeScanner;
import org.jsweet.transpiler.util.Util;
@ -133,34 +132,6 @@ public class OverloadScanner extends AbstractTreeScanner {
return parameterNames.get(index);
}
private void initParameterNames() {
if (isValid) {
for (int index = 0; index < coreMethod.getParameters().length(); index++) {
parameterNames.add(coreMethod.getParameters().get(index).name.toString());
}
} else {
for (int index = 0; index < coreMethod.getParameters().length(); index++) {
List<String> names = new ArrayList<>();
for (JCMethodDecl method : methods) {
if (method.getParameters().length() > index) {
if (!names.contains(method.getParameters().get(index).name.toString())) {
names.add(method.getParameters().get(index).name.toString());
}
}
}
String parameterName = names.get(0);
for (int i = 1; i < names.size(); i++) {
parameterName += "Or" + StringUtils.capitalize(names.get(i));
}
int count = 2;
while (parameterNames.contains(parameterName)) {
parameterName = parameterName + (count++);
}
parameterNames.add(parameterName);
}
}
}
/**
* Checks the validity of the overload and calculates the default
* values.

View File

@ -220,6 +220,7 @@ public abstract class AbstractTreeScanner extends TreeScanner {
/**
* Generically scan an extended element.
*/
@SuppressWarnings("rawtypes")
public void scan(ExtendedElement element) {
scan(((ExtendedElementSupport) element).getTree());
}

View File

@ -96,7 +96,7 @@ public class JSDoc {
boolean isMapped = false;
if (typeTree != null) {
for (BiFunction<ExtendedElement, String, Object> mapping : context.getFunctionalTypeMappings()) {
Object mapped = mapping.apply(new ExtendedElementSupport(typeTree), qualifiedName);
Object mapped = mapping.apply(new ExtendedElementSupport<JCTree>(typeTree), qualifiedName);
if (mapped instanceof String) {
isMapped = true;
qualifiedName = (String) mapped;

View File

@ -282,8 +282,7 @@ public class ExtensionTests extends AbstractTest {
eval((logHandler, result) -> {
logHandler.assertNoProblems();
try {
String generatedCode = FileUtils
.readFileToString(transpiler.getContext().sourceFiles[1].getTsFile());
String generatedCode = FileUtils.readFileToString(transpiler.getContext().sourceFiles[1].getTsFile());
Assert.assertFalse(generatedCode.contains("A2"));
} catch (Exception e) {
throw new RuntimeException(e);

View File

@ -66,6 +66,7 @@ import source.structural.ReplaceAnnotation;
import source.structural.StaticMembersInInterfaces;
import source.structural.SubAbstract;
import source.structural.TwoClassesInSameFile;
import source.structural.WrappedParametersOwner;
import source.structural.WrongConstructsInInterfaces;
import source.structural.WrongThisAccessOnStatic;
import source.structural.globalclasses.Globals;
@ -91,6 +92,13 @@ public class StructuralTests extends AbstractTest {
}, getSourceFile(NoNameClashesWithFields.class));
}
@Test
public void testParametersDtoDestructuring() {
eval((logHandler, r) -> {
logHandler.assertNoProblems();
}, getSourceFile(WrappedParametersOwner.class));
}
@Test
public void testVariableMethodNameClashes() {
transpile(logHandler -> {
@ -179,13 +187,13 @@ public class StructuralTests extends AbstractTest {
public void testInheritance() {
eval((logHandler, r) -> {
assertEquals("There should be no errors", 0, logHandler.reportedProblems.size());
assertEquals(true, r.<Boolean> get("X"));
assertEquals(true, r.<Boolean> get("Y"));
assertEquals("s1", r.<Boolean> get("s1b"));
assertEquals("s2", r.<Boolean> get("s2b"));
assertEquals(false, r.<Boolean> get("itfo"));
assertEquals("s1", r.<Boolean> get("s1o"));
assertEquals("s2", r.<Boolean> get("s2o"));
assertEquals(true, r.<Boolean>get("X"));
assertEquals(true, r.<Boolean>get("Y"));
assertEquals("s1", r.<Boolean>get("s1b"));
assertEquals("s2", r.<Boolean>get("s2b"));
assertEquals(false, r.<Boolean>get("itfo"));
assertEquals("s1", r.<Boolean>get("s1o"));
assertEquals("s2", r.<Boolean>get("s2o"));
}, getSourceFile(Inheritance.class));
}

View File

@ -0,0 +1,51 @@
package source.structural;
import java.util.Date;
import java.util.List;
import jsweet.lang.WrapParameters;
public class WrappedParametersOwner {
public String msg;
private Date date;
protected Integer quantity;
public String[] items;
@WrapParameters
public WrappedParametersOwner(String msg, Date date, Integer quantity, String[] items) {
super();
this.msg = msg;
this.date = date;
this.quantity = quantity;
this.items = items;
System.out.println("ctor_params: " + this.msg + ";" + this.date + ";" + this.quantity + ";" + this.items);
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
/**
* Gets the date.
*/
public Date getDate() {
return date;
}
/**
* Sets the date.
*/
public void setDate(Date date) {
this.date = date;
}
@WrapParameters
public void action(boolean p1, def.js.Object p2, List<Date> p3) {
System.out.println("action_params" + p1 + ";" + p2 + ";" + p3);
}
}