From a04a661dece7a322ee2dbba7072385c1ad875a01 Mon Sep 17 00:00:00 2001 From: Dmitrii Tikhomirov Date: Thu, 28 Nov 2024 01:04:54 -0800 Subject: [PATCH 1/3] elemental2 updated to 1.2.3, j2cl updated to v20241110-1 --- annotations/pom.xml | 2 +- common/pom.xml | 2 +- pom.xml | 25 +- processor/pom.xml | 14 +- .../generator/GWT3EntryPointGenerator.java | 4 +- .../generator/GWT3ExportGenerator.java | 10 +- tests/commons/pom.xml | 23 +- tests/entrypoint/jstype/pom.xml | 21 +- tests/entrypoint/pojo/pom.xml | 22 +- tests/entrypoint/pom.xml | 2 +- tests/es6shim/pom.xml | 22 +- tests/exports/javaenv/pom-advanced.xml | 21 +- tests/exports/javaenv/pom.xml | 21 +- tests/exports/jsenv/bundle_jar_pom.xml | 19 +- tests/exports/jsenv/pom.xml | 19 +- tests/exports/pom.xml | 2 +- tests/pom.xml | 23 +- tests/resources/pom.xml | 2 +- tests/translation/default/pom.xml | 22 +- tests/translation/fr/pom.xml | 22 +- tests/translation/fr_nr/pom.xml | 22 +- tests/translation/no_bundle/pom.xml | 22 +- tests/translation/pom.xml | 2 +- utils/pom.xml | 6 +- .../utils/HackedJavaEnvironment.java | 1006 +++++++++++++++ .../j2cl/processors/utils/J2CLUtils.java | 1078 +---------------- 26 files changed, 1149 insertions(+), 1285 deletions(-) create mode 100644 utils/src/main/java/org/treblereel/j2cl/processors/utils/HackedJavaEnvironment.java diff --git a/annotations/pom.xml b/annotations/pom.xml index 6ff9876..d8baaf8 100644 --- a/annotations/pom.xml +++ b/annotations/pom.xml @@ -4,7 +4,7 @@ org.treblereel.j2cl.processors parent - 0.7 + 0.8 annotations diff --git a/common/pom.xml b/common/pom.xml index 7251b70..364e06a 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -6,7 +6,7 @@ org.treblereel.j2cl.processors parent - 0.7 + 0.8 common diff --git a/pom.xml b/pom.xml index 6b2cf06..0810f4b 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.treblereel.j2cl.processors parent - 0.7 + 0.8 pom GWT3 processors parent @@ -57,18 +57,19 @@ 3.2.4 3.0 - 1.2.1 + 1.2.3 2.0.0 - v20240622-2 - 0.11 - 1.0-rc7 - 4.8.141 + v20241110-1 + 9.7.1 + 1.2.2 + 1.1.1 + 4.8.179 2.3.30 - 2.8.0 - 1.2 + 2.17.0 + 1.12.0 3.3.9 1.9.20 - 4.11 + 4.13.1 @@ -98,6 +99,12 @@ ${j2cl.version} + + org.ow2.asm + asm + ${ow2.asm.version} + + org.apache.maven.resolver maven-resolver-api diff --git a/processor/pom.xml b/processor/pom.xml index c0aa280..eea4291 100644 --- a/processor/pom.xml +++ b/processor/pom.xml @@ -5,7 +5,7 @@ org.treblereel.j2cl.processors parent - 0.7 + 0.8 processors @@ -110,6 +110,18 @@ + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + true + + --add-exports + jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED + + + org.apache.maven.plugins maven-shade-plugin diff --git a/processor/src/main/java/org/treblereel/j2cl/processors/generator/GWT3EntryPointGenerator.java b/processor/src/main/java/org/treblereel/j2cl/processors/generator/GWT3EntryPointGenerator.java index 12b5bea..a5615d8 100644 --- a/processor/src/main/java/org/treblereel/j2cl/processors/generator/GWT3EntryPointGenerator.java +++ b/processor/src/main/java/org/treblereel/j2cl/processors/generator/GWT3EntryPointGenerator.java @@ -100,8 +100,8 @@ private ExecutableElement checkMethod(Element target) { private void generate(ExecutableElement methodInfo) { TypeElement clazz = (TypeElement) methodInfo.getEnclosingElement(); - boolean isJsType = utils.createTypeDescriptor(clazz.asType()).isJsType(); - String methodName = utils.createDeclarationMethodDescriptor(methodInfo).getMangledName(); + boolean isJsType = utils.createTypeDescriptor(clazz).isJsType(); + String methodName = utils.getMethodMangledName(methodInfo); String className = clazz.getSimpleName().toString(); String classPkg = MoreElements.getPackage(clazz).getQualifiedName().toString(); diff --git a/processor/src/main/java/org/treblereel/j2cl/processors/generator/GWT3ExportGenerator.java b/processor/src/main/java/org/treblereel/j2cl/processors/generator/GWT3ExportGenerator.java index 35739cb..d5bf46f 100644 --- a/processor/src/main/java/org/treblereel/j2cl/processors/generator/GWT3ExportGenerator.java +++ b/processor/src/main/java/org/treblereel/j2cl/processors/generator/GWT3ExportGenerator.java @@ -18,7 +18,6 @@ import com.google.auto.common.MoreElements; import com.google.auto.common.MoreTypes; -import com.google.j2cl.transpiler.ast.DeclaredTypeDescriptor; import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateException; @@ -40,7 +39,6 @@ import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; -import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.ElementFilter; import jsinterop.annotations.JsType; @@ -164,18 +162,14 @@ private ExportDTO getExportDTO(TypeElement parent) { private MethodDTO getMethodDTO(TypeElement parent, Element m) { ExecutableElement method = checkMethod(m); String methodName = getSimpleName(method); - DeclaredType declaredType = MoreTypes.asDeclared(parent.asType()); - DeclaredTypeDescriptor enclosingTypeDescriptor = - utils.createDeclaredTypeDescriptor(declaredType); - String mangleName = - utils.createDeclarationMethodDescriptor(method, enclosingTypeDescriptor).getMangledName(); + String mangleName = utils.getMethodMangledName(method); return new MethodDTO(methodName, mangleName, m.getModifiers().contains(Modifier.STATIC)); } private PropertyDTO getPropertyDTO(Element method) { VariableElement variableElement = checkProperty(method); String name = getSimpleName(variableElement); - String mangleName = utils.createFieldDescriptor(variableElement).getMangledName(); + String mangleName = utils.getVariableMangledName(variableElement); return new PropertyDTO(name, mangleName); } diff --git a/tests/commons/pom.xml b/tests/commons/pom.xml index 53dde33..9f1d4b7 100644 --- a/tests/commons/pom.xml +++ b/tests/commons/pom.xml @@ -5,7 +5,7 @@ org.treblereel.j2cl common-tests - 0.7 + 0.8 Common test cases Common test cases @@ -24,13 +24,11 @@ 3.1.0 3.0.1 3.0 - 0.23.1 - v20240622-2 + 0.23.2 + v20241110-1 3.0-beta-02 - 2.0.0 - 1.0.0 - 1.2.1 + 1.2.3 @@ -39,17 +37,6 @@ annotations ${project.version} - - com.google.jsinterop - jsinterop-annotations - ${jsinterop.annotations.version} - - - com.google.jsinterop - base - ${jsinterop.base.version} - - com.google.elemental2 elemental2-dom @@ -85,7 +72,7 @@ org.treblereel.j2cl.processors common - 0.7 + 0.8 test diff --git a/tests/entrypoint/jstype/pom.xml b/tests/entrypoint/jstype/pom.xml index c2fa6f0..14e3976 100644 --- a/tests/entrypoint/jstype/pom.xml +++ b/tests/entrypoint/jstype/pom.xml @@ -5,7 +5,7 @@ org.treblereel.j2cl entrypoint-jstype-tests - 0.7 + 0.8 GWT3 Entry Point Tests for @JsType class Test cases for the GWT3 Entry Point for @JsType class @@ -24,14 +24,12 @@ 3.1.0 3.0.1 3.0 - 0.23.1 - v20240622-2 + 0.23.2 + v20241110-1 4.12.1 4.13.1 - 2.0.0 - 1.0.0 - 1.2.1 + 1.2.3 @@ -41,17 +39,6 @@ ${project.version} - - com.google.jsinterop - jsinterop-annotations - ${jsinterop.annotations.version} - - - com.google.jsinterop - base - ${jsinterop.base.version} - - com.google.elemental2 elemental2-dom diff --git a/tests/entrypoint/pojo/pom.xml b/tests/entrypoint/pojo/pom.xml index 7f3b301..cb90b48 100644 --- a/tests/entrypoint/pojo/pom.xml +++ b/tests/entrypoint/pojo/pom.xml @@ -5,7 +5,7 @@ org.treblereel.j2cl entrypoint-pojo-tests - 0.7 + 0.8 GWT3 Entry Point Tests for Pojo class Test cases for the GWT3 Entry Point for Pojo class @@ -24,14 +24,12 @@ 3.1.0 3.0.1 3.0 - 0.23.1 - v20240622-2 + 0.23.2 + v20241110-1 4.12.1 4.13.1 - 2.0.0 - 1.0.0 - 1.2.1 + 1.2.3 @@ -41,18 +39,6 @@ ${project.version} - - com.google.jsinterop - jsinterop-annotations - ${jsinterop.annotations.version} - test - - - com.google.jsinterop - base - ${jsinterop.base.version} - - com.google.elemental2 elemental2-dom diff --git a/tests/entrypoint/pom.xml b/tests/entrypoint/pom.xml index 432f763..85796de 100644 --- a/tests/entrypoint/pom.xml +++ b/tests/entrypoint/pom.xml @@ -5,7 +5,7 @@ org.treblereel.j2cl entrypoint-tests - 0.7 + 0.8 pom GWT3 Entry Point Tests diff --git a/tests/es6shim/pom.xml b/tests/es6shim/pom.xml index 0dd8b5b..8ca72a3 100644 --- a/tests/es6shim/pom.xml +++ b/tests/es6shim/pom.xml @@ -5,7 +5,7 @@ es6shim-tests org.treblereel.j2cl - 0.7 + 0.8 jar ES6SHIM Tests @@ -25,13 +25,11 @@ 3.1.0 3.0.1 3.0 - 0.23.1 - v20240622-2 + 0.23.2 + v20241110-1 3.0-beta-02 - 2.0.0 - 1.0.0 - 1.2.1 + 1.2.3 @@ -41,18 +39,6 @@ ${project.version} - - com.google.jsinterop - jsinterop-annotations - ${jsinterop.annotations.version} - test - - - com.google.jsinterop - base - ${jsinterop.base.version} - - com.google.elemental2 elemental2-dom diff --git a/tests/exports/javaenv/pom-advanced.xml b/tests/exports/javaenv/pom-advanced.xml index bddff2f..71710e6 100644 --- a/tests/exports/javaenv/pom-advanced.xml +++ b/tests/exports/javaenv/pom-advanced.xml @@ -5,7 +5,7 @@ org.treblereel.j2cl javaenv-advanced - 0.7 + 0.8 jar GWTExports java env Tests ADVANCED mode @@ -26,15 +26,13 @@ 3.1.0 3.0.1 3.0 - 0.23.1 + 0.23.2 - v20240622-2 + v20241110-1 4.12.1 4.13.1 - 2.0.0 - 1.0.0 - 1.1.0 + 1.2.3 @@ -44,17 +42,6 @@ ${project.version} - - com.google.jsinterop - jsinterop-annotations - ${jsinterop.annotations.version} - - - com.google.jsinterop - base - ${jsinterop.base.version} - - com.google.elemental2 elemental2-core diff --git a/tests/exports/javaenv/pom.xml b/tests/exports/javaenv/pom.xml index ac1f420..3d177d8 100644 --- a/tests/exports/javaenv/pom.xml +++ b/tests/exports/javaenv/pom.xml @@ -5,7 +5,7 @@ org.treblereel.j2cl javaenv - 0.7 + 0.8 jar GWTExports java env Tests BUNDLE_JAR mode @@ -26,15 +26,13 @@ 3.1.0 3.0.1 3.0 - 0.23.1 + 0.23.2 - v20240622-2 + v20241110-1 4.12.1 4.13.1 - 2.0.0 - 1.0.0 - 1.2.1 + 1.2.3 @@ -44,17 +42,6 @@ ${project.version} - - com.google.jsinterop - jsinterop-annotations - ${jsinterop.annotations.version} - - - com.google.jsinterop - base - ${jsinterop.base.version} - - com.google.elemental2 elemental2-core diff --git a/tests/exports/jsenv/bundle_jar_pom.xml b/tests/exports/jsenv/bundle_jar_pom.xml index 13aff21..064805b 100644 --- a/tests/exports/jsenv/bundle_jar_pom.xml +++ b/tests/exports/jsenv/bundle_jar_pom.xml @@ -5,7 +5,7 @@ org.treblereel.j2cl exports-bundle_jar - 0.7 + 0.8 jar GWTExports Tests BUNDLE_JAR mode @@ -25,14 +25,12 @@ 3.1.0 3.0.1 3.0 - 0.23.1 + 0.23.2 4.12.1 4.13.1 - 2.0.0 - 1.0.0 - 1.1.0 + 1.2.3 @@ -42,17 +40,6 @@ ${project.version} - - com.google.jsinterop - jsinterop-annotations - ${jsinterop.annotations.version} - - - com.google.jsinterop - base - ${jsinterop.base.version} - - com.google.elemental2 elemental2-dom diff --git a/tests/exports/jsenv/pom.xml b/tests/exports/jsenv/pom.xml index 2ea6be0..88d56b5 100644 --- a/tests/exports/jsenv/pom.xml +++ b/tests/exports/jsenv/pom.xml @@ -5,7 +5,7 @@ org.treblereel.j2cl jsenv - 0.7 + 0.8 jar GWTExports Tests ADVANCED mode @@ -25,14 +25,12 @@ 3.1.0 3.0.1 3.0 - 0.23.1 + 0.23.2 4.12.1 4.13.1 - 2.0.0 - 1.0.0 - 1.2.1 + 1.2.3 @@ -42,17 +40,6 @@ ${project.version} - - com.google.jsinterop - jsinterop-annotations - ${jsinterop.annotations.version} - - - com.google.jsinterop - base - ${jsinterop.base.version} - - com.google.elemental2 elemental2-dom diff --git a/tests/exports/pom.xml b/tests/exports/pom.xml index a2414dd..88f86bb 100644 --- a/tests/exports/pom.xml +++ b/tests/exports/pom.xml @@ -6,7 +6,7 @@ org.treblereel.j2cl tests-parent - 0.7 + 0.8 pom diff --git a/tests/pom.xml b/tests/pom.xml index 379670c..adcae9f 100644 --- a/tests/pom.xml +++ b/tests/pom.xml @@ -5,7 +5,7 @@ org.treblereel.j2cl tests-parent - 0.7 + 0.8 pom GWT3 processors Tests @@ -19,17 +19,16 @@ 11 11 - 0.23.1 + 0.23.2 2.17 2.8.2 3.8.0 2.0.0 - 1.0.0 - 1.2.1 + 1.2.3 - v20240622-2 - 4.11 + v20241110-1 + 4.13.2 4.12.1 @@ -56,24 +55,12 @@ ${project.version} - - com.google.jsinterop - jsinterop-annotations - ${jsinterop.annotations.version} - - - com.google.jsinterop - base - ${jsinterop.base.version} - - com.google.elemental2 elemental2-dom ${elemental2.version} - org.kie.j2cl.tools diff --git a/tests/resources/pom.xml b/tests/resources/pom.xml index b0572e0..d4e6bf9 100644 --- a/tests/resources/pom.xml +++ b/tests/resources/pom.xml @@ -6,7 +6,7 @@ org.treblereel.j2cl tests-parent - 0.7 + 0.8 resources diff --git a/tests/translation/default/pom.xml b/tests/translation/default/pom.xml index 4c36471..1b731dd 100644 --- a/tests/translation/default/pom.xml +++ b/tests/translation/default/pom.xml @@ -5,7 +5,7 @@ org.treblereel.j2cl translation-default - 0.7 + 0.8 jar Translation Tests en @@ -25,13 +25,11 @@ 3.1.0 3.0.1 3.0 - 0.23.1 - v20240622-2 + 0.23.2 + v20241110-1 3.0-beta-02 - 2.0.0 - 1.0.0 - 1.2.1 + 1.2.3 @@ -41,18 +39,6 @@ ${project.version} - - com.google.jsinterop - jsinterop-annotations - ${jsinterop.annotations.version} - test - - - com.google.jsinterop - base - ${jsinterop.base.version} - - com.google.elemental2 elemental2-dom diff --git a/tests/translation/fr/pom.xml b/tests/translation/fr/pom.xml index 69b77d5..17f4f95 100644 --- a/tests/translation/fr/pom.xml +++ b/tests/translation/fr/pom.xml @@ -5,7 +5,7 @@ org.treblereel.j2cl translation-fr - 0.7 + 0.8 jar Translation Tests fr @@ -25,13 +25,11 @@ 3.1.0 3.0.1 3.0 - 0.23.1 - v20240622-2 + 0.23.2 + v20241110-1 3.0-beta-02 - 2.0.0 - 1.0.0 - 1.2.1 + 1.2.3 @@ -41,18 +39,6 @@ ${project.version} - - com.google.jsinterop - jsinterop-annotations - ${jsinterop.annotations.version} - test - - - com.google.jsinterop - base - ${jsinterop.base.version} - - com.google.elemental2 elemental2-dom diff --git a/tests/translation/fr_nr/pom.xml b/tests/translation/fr_nr/pom.xml index 78344d6..80871ec 100644 --- a/tests/translation/fr_nr/pom.xml +++ b/tests/translation/fr_nr/pom.xml @@ -5,7 +5,7 @@ org.treblereel.j2cl translation-fr-nr - 0.7 + 0.8 jar Translation Tests fr-nr @@ -25,13 +25,11 @@ 3.1.0 3.0.1 3.0 - 0.23.1 - v20240622-2 + 0.23.2 + v20241110-1 3.0-beta-02 - 2.0.0 - 1.0.0 - 1.2.1 + 1.2.3 @@ -41,18 +39,6 @@ ${project.version} - - com.google.jsinterop - jsinterop-annotations - ${jsinterop.annotations.version} - test - - - com.google.jsinterop - base - ${jsinterop.base.version} - - com.google.elemental2 elemental2-dom diff --git a/tests/translation/no_bundle/pom.xml b/tests/translation/no_bundle/pom.xml index 7e08cb4..55f0b0c 100644 --- a/tests/translation/no_bundle/pom.xml +++ b/tests/translation/no_bundle/pom.xml @@ -6,7 +6,7 @@ org.treblereel.j2cl translation-tests - 0.7 + 0.8 translation-no_bundle @@ -29,13 +29,11 @@ 3.1.0 3.0.1 3.0 - 0.23.1 - v20240622-2 + 0.23.2 + v20241110-1 3.0-beta-02 - 2.0.0 - 1.0.0 - 1.2.1 + 1.2.3 @@ -45,18 +43,6 @@ ${project.version} - - com.google.jsinterop - jsinterop-annotations - ${jsinterop.annotations.version} - test - - - com.google.jsinterop - base - ${jsinterop.base.version} - - com.google.elemental2 elemental2-dom diff --git a/tests/translation/pom.xml b/tests/translation/pom.xml index 5c106d6..a5b19e1 100644 --- a/tests/translation/pom.xml +++ b/tests/translation/pom.xml @@ -5,7 +5,7 @@ org.treblereel.j2cl translation-tests - 0.7 + 0.8 pom GWT3 Entry Point Tests diff --git a/utils/pom.xml b/utils/pom.xml index ea96aa5..670c16c 100644 --- a/utils/pom.xml +++ b/utils/pom.xml @@ -5,7 +5,7 @@ parent org.treblereel.j2cl.processors - 0.7 + 0.8 4.0.0 @@ -51,6 +51,10 @@ org.kie.j2cl.tools frontend-javac + + org.ow2.asm + asm + diff --git a/utils/src/main/java/org/treblereel/j2cl/processors/utils/HackedJavaEnvironment.java b/utils/src/main/java/org/treblereel/j2cl/processors/utils/HackedJavaEnvironment.java new file mode 100644 index 0000000..a9c5486 --- /dev/null +++ b/utils/src/main/java/org/treblereel/j2cl/processors/utils/HackedJavaEnvironment.java @@ -0,0 +1,1006 @@ +/* + * Copyright 2015 Google Inc. + * + * 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 org.treblereel.j2cl.processors.utils; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.collect.ImmutableList.toImmutableList; +import static com.google.j2cl.transpiler.ast.TypeDeclaration.newBuilder; +import static com.google.j2cl.transpiler.frontend.common.FrontendConstants.WASM_ANNOTATION_NAME; + +import com.google.auto.common.MoreTypes; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; +import com.google.common.collect.Streams; +import com.google.j2cl.common.InternalCompilerError; +import com.google.j2cl.transpiler.ast.*; +import com.google.j2cl.transpiler.frontend.javac.AnnotationUtils; +import com.google.j2cl.transpiler.frontend.javac.JsInteropAnnotationUtils; +import com.google.j2cl.transpiler.frontend.javac.JsInteropUtils; +import java.util.*; +import java.util.function.Supplier; +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.AnnotatedConstruct; +import javax.lang.model.element.*; +import javax.lang.model.type.ArrayType; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.ElementFilter; +import javax.lang.model.util.Elements; +import javax.lang.model.util.Types; + +class HackedJavaEnvironment { + + private final Types javacTypes; + private final Elements elements; + + private final ProcessingEnvironment processingEnv; + private final Map + cachedDeclaredTypeDescriptorByDeclaredTypeInNullMarkedScope = new HashMap<>(); + private final Map + cachedDeclaredTypeDescriptorByDeclaredTypeOutOfNullMarkedScope = new HashMap<>(); + + HackedJavaEnvironment(ProcessingEnvironment processingEnv) { + this.javacTypes = processingEnv.getTypeUtils(); + this.elements = processingEnv.getElementUtils(); + this.processingEnv = processingEnv; + initWellKnownTypes(TypeDescriptors.getWellKnownTypeNames()); + } + + private boolean isNonNullAnnotation(AnnotationMirror annotation) { + DeclaredType annotationType = annotation.getAnnotationType(); + String name = annotationType.asElement().getSimpleName().toString(); + return name.equals("NonNull") || name.equals("JsNonNull"); + } + + private boolean isNullableAnnotation(AnnotationMirror annotation) { + DeclaredType annotationType = annotation.getAnnotationType(); + return annotationType.asElement().getSimpleName().toString().equals("Nullable"); + } + + private DeclaredTypeDescriptor withNullability( + DeclaredTypeDescriptor typeDescriptor, boolean nullable) { + return nullable ? typeDescriptor.toNullable() : typeDescriptor.toNonNullable(); + } + + /** + * In case the given type element is nested, return the outermost possible enclosing type element. + */ + private TypeElement toTopLevelTypeBinding(Element element) { + if (element.getEnclosingElement().getKind() == ElementKind.PACKAGE) { + return (TypeElement) element; + } + return toTopLevelTypeBinding(element.getEnclosingElement()); + } + + private boolean isValuesMethod(ExecutableElement methodElement) { + return methodElement.getSimpleName().contentEquals("values") + && methodElement.getParameters().isEmpty(); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Utility methods to process nullability annotations on classes that are compiled separately. + // Javac does not present TYPE_USE annotation in the returned type instances. + private TypeDescriptor applyParameterNullabilityAnnotations( + TypeDescriptor typeDescriptor, ExecutableElement declarationMethodElement, int index) { + return typeDescriptor; + } + + private int getInnerDepth(DeclaredTypeDescriptor innerType) { + if (innerType.getTypeDeclaration().isCapturingEnclosingInstance()) { + return getInnerDepth(innerType.getEnclosingTypeDescriptor()) + 1; + } + return 0; + } + + /** Returns true if the element is annotated with @UncheckedCast. */ + private boolean hasUncheckedCastAnnotation(Element element) { + return false; + } + + /** Returns true if the element is annotated with @HasNoSideEffects. */ + private boolean isAnnotatedWithHasNoSideEffects(Element element) { + return true; + } + + private List getTypeArguments(DeclaredType declaredType) { + List typeArguments = new ArrayList<>(); + DeclaredType currentType = declaredType; + do { + typeArguments.addAll(currentType.getTypeArguments()); + Element enclosingElement = currentType.asElement().getEnclosingElement(); + if (enclosingElement.getKind() == ElementKind.METHOD + || enclosingElement.getKind() == ElementKind.CONSTRUCTOR) { + typeArguments.addAll( + ((Parameterizable) enclosingElement) + .getTypeParameters().stream().map(Element::asType).collect(toImmutableList())); + } + currentType = + currentType.getEnclosingType() instanceof DeclaredType + ? (DeclaredType) currentType.getEnclosingType() + : null; + } while (currentType != null); + return typeArguments; + } + + private TypeDeclaration.Kind getKindFromTypeBinding(TypeElement typeElement) { + if (isEnum(typeElement) && !isAnonymous(typeElement)) { + // Do not consider the anonymous classes that constitute enum values as Enums, only the + // enum "class" itself is considered Kind.ENUM. + return TypeDeclaration.Kind.ENUM; + } else if (isClass(typeElement) || (isEnum(typeElement) && isAnonymous(typeElement))) { + return TypeDeclaration.Kind.CLASS; + } else if (isInterface(typeElement)) { + return TypeDeclaration.Kind.INTERFACE; + } + throw new InternalCompilerError("Type binding %s not handled.", typeElement); + } + + private String getJsName(final TypeElement classSymbol) { + return JsInteropAnnotationUtils.getJsName(classSymbol); + } + + private boolean hasNullMarkedAnnotation(TypeElement classSymbol) { + return false; + } + + private List getTypeParameters(TypeElement typeElement) { + List typeParameterElements = + new ArrayList<>(typeElement.getTypeParameters()); + Element currentElement = typeElement; + Element enclosingElement = typeElement.getEnclosingElement(); + while (enclosingElement != null) { + if (isStatic(currentElement)) { + break; + } + + if (enclosingElement.getKind() != ElementKind.STATIC_INIT + && enclosingElement.getKind() != ElementKind.INSTANCE_INIT + && enclosingElement instanceof Parameterizable) { + // Add the enclosing element type variables, skip STATIC_INIT and INSTANCE_INIT since they + // never define type variables, and throw NPE if getTypeParameters is called on them. + typeParameterElements.addAll(((Parameterizable) enclosingElement).getTypeParameters()); + } + currentElement = enclosingElement; + enclosingElement = enclosingElement.getEnclosingElement(); + } + return typeParameterElements; + } + + TypeElement getEnclosingType(Element typeElement) { + Element enclosing = typeElement.getEnclosingElement(); + while (enclosing != null && !(enclosing instanceof TypeElement)) { + enclosing = enclosing.getEnclosingElement(); + } + return (TypeElement) enclosing; + } + + private TypeElement getEnclosingType(TypeElement typeElement) { + Element enclosing = typeElement.getEnclosingElement(); + while (enclosing != null && !(enclosing instanceof TypeElement)) { + enclosing = enclosing.getEnclosingElement(); + } + return (TypeElement) enclosing; + } + + private boolean isEnum(TypeElement typeElement) { + return typeElement.getKind() == ElementKind.ENUM; + } + + private boolean isAnnotation(TypeElement typeElement) { + return typeElement.getKind() == ElementKind.ANNOTATION_TYPE; + } + + private boolean isAnonymous(TypeElement typeElement) { + return typeElement.getNestingKind() == NestingKind.ANONYMOUS; + } + + private boolean isClass(TypeElement typeElement) { + return typeElement.getKind() == ElementKind.CLASS; + } + + private boolean isInterface(TypeElement typeElement) { + return typeElement.getKind() == ElementKind.INTERFACE + || typeElement.getKind() == ElementKind.ANNOTATION_TYPE; + } + + private boolean isLocal(TypeElement typeElement) { + return typeElement.getNestingKind() == NestingKind.LOCAL; + } + + Visibility getVisibility(Element element) { + if (element.getModifiers().contains(Modifier.PUBLIC)) { + return Visibility.PUBLIC; + } else if (element.getModifiers().contains(Modifier.PROTECTED)) { + return Visibility.PROTECTED; + } else if (element.getModifiers().contains(Modifier.PRIVATE)) { + return Visibility.PRIVATE; + } else { + return Visibility.PACKAGE_PRIVATE; + } + } + + private boolean isDeprecated(AnnotatedConstruct binding) { + return binding.getAnnotation(Deprecated.class) != null; + } + + private boolean isDefaultMethod(Element element) { + return element.getModifiers().contains(Modifier.DEFAULT); + } + + private boolean isAbstract(Element element) { + return element.getModifiers().contains(Modifier.ABSTRACT); + } + + private boolean isFinal(Element element) { + return element.getModifiers().contains(Modifier.FINAL); + } + + boolean isStatic(Element element) { + return element.getModifiers().contains(Modifier.STATIC); + } + + private boolean isNative(Element element) { + return element.getModifiers().contains(Modifier.NATIVE); + } + + private boolean isSynthetic(Element element) { + return false; + // return element instanceof Symbol && (((Symbol) element).flags() & Flags.SYNTHETIC) != 0; + } + + private MethodDescriptor ctorMethodDescriptorFromJavaConstructor(MethodDescriptor constructor) { + return constructor.transform( + builder -> + builder + .setReturnTypeDescriptor(PrimitiveTypes.VOID) + .setName(getCtorName(constructor)) + .setConstructor(false) + .setStatic(false) + .setOriginalJsInfo(JsInfo.NONE) + .removeParameterOptionality() + .setOrigin(MethodDescriptor.MethodOrigin.SYNTHETIC_CTOR_FOR_CONSTRUCTOR) + .setVisibility(Visibility.PUBLIC)); + } + + private String getCtorName(MethodDescriptor methodDescriptor) { + // Synthesize a name that is unique per class to avoid property clashes in JS. + return MethodDescriptor.CTOR_METHOD_PREFIX + + "__" + + methodDescriptor.getEnclosingTypeDescriptor().getMangledName(); + } + + private void initWellKnownTypes(Collection wellKnownQualifiedBinaryNames) { + if (TypeDescriptors.isInitialized()) { + return; + } + TypeDescriptors.SingletonBuilder builder = new TypeDescriptors.SingletonBuilder(); + // Add well-known, non-primitive types. + wellKnownQualifiedBinaryNames.forEach( + binaryName -> { + String qualifiedSourceName = binaryName.replace('$', '.'); + TypeElement element = getTypeElement(qualifiedSourceName); + if (element != null) { + builder.addReferenceType(createDeclaredTypeDescriptor(element.asType())); + } + }); + + builder.addReferenceType(createSyntheticJavaEmulInternalExceptionsTypeDescriptor()); + + builder.buildSingleton(); + } + + private DeclaredTypeDescriptor createSyntheticJavaEmulInternalExceptionsTypeDescriptor() { + TypeDeclaration typeDeclaration = + TypeDeclaration.newBuilder() + .setClassComponents(ImmutableList.of("Exceptions")) + .setNative(false) + .setCustomizedJsNamespace("javaemul.internal") + .setPackage(PackageDeclaration.newBuilder().setName("javaemul.internal").build()) + .setTypeParameterDescriptors(ImmutableList.of()) + .setVisibility(Visibility.PUBLIC) + .setNullMarked(false) + .setKind(TypeDeclaration.Kind.CLASS) + .build(); + + return DeclaredTypeDescriptor.newBuilder() + .setTypeDeclaration(typeDeclaration) + .setNullable(false) + .setTypeArgumentDescriptors(Collections.EMPTY_LIST) + .build(); + } + + DeclaredTypeDescriptor createDeclaredTypeDescriptor(TypeMirror typeMirror) { + return createDeclaredTypeDescriptor(typeMirror, /* inNullMarkedScope= */ false); + } + + private DeclaredTypeDescriptor createDeclaredTypeDescriptor( + TypeMirror typeMirror, boolean inNullMarkedScope) { + return createTypeDescriptor(typeMirror, inNullMarkedScope, DeclaredTypeDescriptor.class); + } + + /** Creates a specific subclass of TypeDescriptor from a TypeMirror. */ + T createTypeDescriptor(TypeMirror typeMirror, Class clazz) { + return createTypeDescriptor(typeMirror, /* inNullMarkedScope= */ false, clazz); + } + + /** Creates a specific subclass of TypeDescriptor from a TypeMirror. */ + private T createTypeDescriptor( + TypeMirror typeMirror, boolean inNullMarkedScope, Class clazz) { + return clazz.cast(createTypeDescriptor(typeMirror, inNullMarkedScope)); + } + + /** Creates a TypeDescriptor from a TypeMirror. */ + TypeDescriptor createTypeDescriptor(TypeMirror typeMirror) { + return createTypeDescriptor(typeMirror, /* inNullMarkedScope= */ false); + } + + /** Creates a TypeDescriptor from a TypeMirror. */ + private TypeDescriptor createTypeDescriptor(TypeMirror typeMirror, boolean inNullMarkedScope) { + return createTypeDescriptorWithNullability(typeMirror, ImmutableList.of(), inNullMarkedScope); + } + + /** Creates a type descriptor for the given TypeMirror, taking into account nullability. */ + private TypeDescriptor createTypeDescriptorWithNullability( + TypeMirror typeMirror, + List elementAnnotations, + boolean inNullMarkedScope) { + if (typeMirror == null || typeMirror.getKind() == TypeKind.NONE) { + return null; + } + + if (typeMirror.getKind().isPrimitive()) { + return PrimitiveTypes.get(MoreTypes.asPrimitiveType(typeMirror).toString()); + } + + if (typeMirror.getKind() == TypeKind.VOID) { + return PrimitiveTypes.VOID; + } + + if (typeMirror.getKind() == TypeKind.INTERSECTION) { + throw new InternalCompilerError("Intersection types are not supported."); + // return createIntersectionType((IntersectionClassType) typeMirror); + } + + if (typeMirror.getKind() == TypeKind.UNION) { + throw new InternalCompilerError("Union types are not supported."); + // return createUnionType((UnionClassType) typeMirror); + } + + if (typeMirror.getKind() == TypeKind.NULL) { + return TypeDescriptors.get().javaLangObject; + } + + if (typeMirror.getKind() == TypeKind.TYPEVAR) { + return createTypeVariable((javax.lang.model.type.TypeVariable) typeMirror); + } + + if (typeMirror.getKind() == TypeKind.WILDCARD) { + return createWildcardTypeVariable( + ((javax.lang.model.type.WildcardType) typeMirror).getExtendsBound()); + } + + boolean isNullable = isNullable(typeMirror, elementAnnotations, inNullMarkedScope); + if (typeMirror.getKind() == TypeKind.ARRAY) { + ArrayType arrayType = (ArrayType) typeMirror; + TypeDescriptor componentTypeDescriptor = + createTypeDescriptor(arrayType.getComponentType(), inNullMarkedScope); + return ArrayTypeDescriptor.newBuilder() + .setComponentTypeDescriptor(componentTypeDescriptor) + .setNullable(isNullable) + .build(); + } + + return withNullability( + createDeclaredType(MoreTypes.asDeclared(typeMirror), inNullMarkedScope), isNullable); + } + + /** + * Returns whether the given type binding should be nullable, according to the annotations on it + * and if nullability is enabled for the package containing the binding. + */ + private boolean isNullable( + TypeMirror typeMirror, + List elementAnnotations, + boolean inNullMarkedScope) { + if (typeMirror.getKind().isPrimitive()) { + return true; + } + + checkArgument(!typeMirror.getKind().isPrimitive()); + + if (typeMirror.getKind() == TypeKind.VOID) { + return true; + } + + Iterable allAnnotations = + Iterables.concat(elementAnnotations, typeMirror.getAnnotationMirrors()); + + for (AnnotationMirror annotationMirror : allAnnotations) { + if (isNonNullAnnotation(annotationMirror)) { + return false; + } + if (isNullableAnnotation(annotationMirror)) { + return true; + } + } + + return !inNullMarkedScope; + } + + private TypeVariable createTypeVariable(javax.lang.model.type.TypeVariable typeVariable) { + if (typeVariable.getUpperBound().getKind() == TypeKind.WILDCARD) { + return createWildcardTypeVariable(typeVariable.getUpperBound()); + } + + Supplier boundTypeDescriptorFactory = + () -> createTypeDescriptor(typeVariable.getUpperBound()); + + List classComponents = getClassComponents(typeVariable); + return TypeVariable.newBuilder() + .setUpperBoundTypeDescriptorFactory(boundTypeDescriptorFactory) + .setUniqueKey( + String.join("::", classComponents) + + (typeVariable.getUpperBound() != null + ? typeVariable.getUpperBound().toString() + : "")) + .setName(typeVariable.asElement().getSimpleName().toString()) + .build(); + } + + private TypeVariable createWildcardTypeVariable(TypeMirror bound) { + return TypeVariable.newBuilder() + .setUpperBoundTypeDescriptorFactory(() -> createTypeDescriptor(bound)) + .setWildcard(true) + .setName("?") + .setUniqueKey("::?::" + (bound != null ? bound.toString() : "")) + .build(); + } + + private ImmutableList getClassComponents( + javax.lang.model.type.TypeVariable typeVariable) { + Element enclosingElement = typeVariable.asElement().getEnclosingElement(); + if (enclosingElement.getKind() == ElementKind.CLASS + || enclosingElement.getKind() == ElementKind.INTERFACE + || enclosingElement.getKind() == ElementKind.ENUM) { + return ImmutableList.builder() + .addAll(getClassComponents(enclosingElement)) + .add( + // If it is a class-level type variable, use the simple name (with prefix "C_") as the + // current name component. + "C_" + typeVariable.asElement().getSimpleName()) + .build(); + } else { + return ImmutableList.builder() + .addAll(getClassComponents(enclosingElement.getEnclosingElement())) + .add( + "M_" + + enclosingElement.getSimpleName() + + "_" + + typeVariable.asElement().getSimpleName()) + .build(); + } + } + + private ImmutableList getClassComponents(Element element) { + if (!(element instanceof TypeElement)) { + return ImmutableList.of(); + } + TypeElement typeElement = (TypeElement) element; + List classComponents = new ArrayList<>(); + TypeElement currentType = typeElement; + while (currentType != null) { + String simpleName; + if (currentType.getNestingKind() == NestingKind.LOCAL + || currentType.getNestingKind() == NestingKind.ANONYMOUS) { + // JavaC binary name for local class is like package.components.EnclosingClass$1SimpleName + // Extract the generated name by taking the part after the binary name of the declaring + // class. + String binaryName = getBinaryNameFromTypeBinding(currentType); + String declaringClassPrefix = + getBinaryNameFromTypeBinding(getEnclosingType(currentType)) + "$"; + simpleName = binaryName.substring(declaringClassPrefix.length()); + } else { + simpleName = asElement(erasure(currentType.asType())).getSimpleName().toString(); + } + classComponents.add(0, simpleName); + Element enclosingElement = currentType.getEnclosingElement(); + while (enclosingElement != null + && enclosingElement.getKind() != ElementKind.CLASS + && enclosingElement.getKind() != ElementKind.INTERFACE + && enclosingElement.getKind() != ElementKind.ENUM) { + enclosingElement = enclosingElement.getEnclosingElement(); + } + currentType = (TypeElement) enclosingElement; + } + return ImmutableList.copyOf(classComponents); + } + + /** Returns the binary name for a type element. */ + private String getBinaryNameFromTypeBinding(TypeElement typeElement) { + return elements.getBinaryName(typeElement).toString(); + } + + private boolean isEnumSyntheticMethod(ExecutableElement methodElement) { + // Enum synthetic methods are not marked as such because per JLS 13.1 these methods are + // implicitly declared but are not marked as synthetic. + return getEnclosingType(methodElement).getKind() == ElementKind.ENUM + && (isValuesMethod(methodElement) || isValueOfMethod(methodElement)); + } + + private boolean isValueOfMethod(ExecutableElement methodElement) { + return methodElement.getSimpleName().contentEquals("valueOf") + && methodElement.getParameters().size() == 1 + && asTypeElement(methodElement.getParameters().get(0).asType()) + .getQualifiedName() + .contentEquals("java.lang.String"); + } + + /** + * Returns true if instances of this type capture its outer instances; i.e. if it is an non member + * class, or an anonymous or local class defined in an instance context. + */ + private boolean capturesEnclosingInstance(TypeElement typeElement) { + if (isAnonymous(typeElement)) { + return hasOuterInstance(typeElement) || !isStatic(typeElement.getEnclosingElement()); + } + return hasOuterInstance(typeElement); + } + + boolean hasOuterInstance(TypeElement typeElement) { + return typeElement.getEnclosingElement().getKind().isClass() + && !isInterface((TypeElement) typeElement.getEnclosingElement()); + } + + FieldDescriptor createFieldDescriptor(VariableElement variableElement) { + return createFieldDescriptor(variableElement, variableElement.asType()); + } + + FieldDescriptor createFieldDescriptor(VariableElement variableElement, TypeMirror type) { + + boolean isStatic = isStatic(variableElement); + Visibility visibility = getVisibility(variableElement); + DeclaredTypeDescriptor enclosingTypeDescriptor = + createDeclaredTypeDescriptor(getEnclosingType(variableElement).asType()); + String fieldName = variableElement.getSimpleName().toString(); + + TypeDescriptor thisTypeDescriptor = + createTypeDescriptorWithNullability( + type, + variableElement.getAnnotationMirrors(), + enclosingTypeDescriptor.getTypeDeclaration().isNullMarked()); + + boolean isEnumConstant = variableElement.getKind().equals(ElementKind.ENUM_CONSTANT); + if (isEnumConstant) { + // Enum fields are always non-nullable. + thisTypeDescriptor = thisTypeDescriptor.toNonNullable(); + } + + FieldDescriptor declarationFieldDescriptor = null; + if (!javacTypes.isSameType(variableElement.asType(), type)) { + // Field references might be parameterized, and when they are we set the declaration + // descriptor to the unparameterized declaration. + declarationFieldDescriptor = createFieldDescriptor(variableElement, variableElement.asType()); + } + + JsInfo jsInfo = JsInteropUtils.getJsInfo(variableElement); + Object constantValue = variableElement.getConstantValue(); + boolean isCompileTimeConstant = constantValue != null; + if (isCompileTimeConstant) { + thisTypeDescriptor = thisTypeDescriptor.toNonNullable(); + } + boolean isFinal = isFinal(variableElement); + return FieldDescriptor.newBuilder() + .setEnclosingTypeDescriptor(enclosingTypeDescriptor) + .setName(fieldName) + .setTypeDescriptor(thisTypeDescriptor) + .setStatic(isStatic) + .setVisibility(visibility) + .setOriginalJsInfo(jsInfo) + .setFinal(isFinal) + .setCompileTimeConstant(isCompileTimeConstant) + .setConstantValue( + constantValue != null ? Literal.fromValue(constantValue, thisTypeDescriptor) : null) + .setDeclarationDescriptor(declarationFieldDescriptor) + .setEnumConstant(isEnumConstant) + .setUnusableByJsSuppressed( + JsInteropAnnotationUtils.isUnusableByJsSuppressed(variableElement)) + .setDeprecated(isDeprecated(variableElement)) + .build(); + } + + /** Create a MethodDescriptor directly based on the given JavaC ExecutableElement. */ + MethodDescriptor createMethodDescriptor( + DeclaredTypeDescriptor enclosingTypeDescriptor, + ExecutableElement methodElement, + ExecutableElement declarationMethodElement) { + + MethodDescriptor declarationMethodDescriptor = null; + + ImmutableList parameters = + methodElement.getParameters().stream() + .map(VariableElement::asType) + .collect(toImmutableList()); + + TypeMirror returnType = methodElement.getReturnType(); + if (isSpecialized(declarationMethodElement, parameters, returnType)) { + declarationMethodDescriptor = + createDeclarationMethodDescriptor( + declarationMethodElement, enclosingTypeDescriptor.getDeclarationDescriptor()); + } + + TypeDescriptor returnTypeDescriptor = + createTypeDescriptorWithNullability( + returnType, + declarationMethodElement.getAnnotationMirrors(), + enclosingTypeDescriptor.getTypeDeclaration().isNullMarked()); + + ImmutableList.Builder parametersBuilder = ImmutableList.builder(); + for (int i = 0; i < parameters.size(); i++) { + parametersBuilder.add( + applyParameterNullabilityAnnotations( + createTypeDescriptorWithNullability( + parameters.get(i), + declarationMethodElement.getParameters().get(i).getAnnotationMirrors(), + enclosingTypeDescriptor.getTypeDeclaration().isNullMarked()), + declarationMethodElement, + i)); + } + + return createDeclaredMethodDescriptor( + enclosingTypeDescriptor.toNullable(), + declarationMethodElement, + declarationMethodDescriptor, + parametersBuilder.build(), + returnTypeDescriptor); + } + + /** Create a MethodDescriptor directly based on the given JavaC ExecutableElement. */ + MethodDescriptor createDeclarationMethodDescriptor(ExecutableElement methodElement) { + DeclaredTypeDescriptor enclosingTypeDescriptor = + createDeclaredTypeDescriptor(methodElement.getEnclosingElement().asType()); + return createDeclarationMethodDescriptor(methodElement, enclosingTypeDescriptor); + } + + /** Create a MethodDescriptor directly based on the given JavaC ExecutableElement. */ + MethodDescriptor createDeclarationMethodDescriptor( + ExecutableElement methodElement, DeclaredTypeDescriptor enclosingTypeDescriptor) { + return createMethodDescriptor(enclosingTypeDescriptor, methodElement, methodElement); + } + + /** + * Returns true if any of the type parameters has been specialized. + * + *

For example the type {@code List} specialized the type variable {@code T} from the + * class declaration. + */ + private boolean isSpecialized( + ExecutableElement declarationMethodElement, + List parameters, + TypeMirror returnType) { + return !isSameType(returnType, declarationMethodElement.getReturnType()) + || !Streams.zip( + parameters.stream(), + declarationMethodElement.getParameters().stream(), + (thisType, thatType) -> isSameType(thisType, thatType.asType())) + .allMatch(equals -> equals); + } + + private boolean isSameType(TypeMirror thisType, TypeMirror thatType) { + return javacTypes.isSameType(thisType, thatType); + } + + private MethodDescriptor createDeclaredMethodDescriptor( + DeclaredTypeDescriptor enclosingTypeDescriptor, + ExecutableElement declarationMethodElement, + MethodDescriptor declarationMethodDescriptor, + List parameters, + TypeDescriptor returnTypeDescriptor) { + ImmutableList typeParameterTypeDescriptors = + declarationMethodElement.getTypeParameters().stream() + .map(Element::asType) + .map(this::createTypeDescriptor) + .map(TypeVariable.class::cast) + .collect(toImmutableList()); + + boolean isStatic = isStatic(declarationMethodElement); + Visibility visibility = getVisibility(declarationMethodElement); + boolean isDefault = isDefaultMethod(declarationMethodElement); + JsInfo jsInfo = JsInteropUtils.getJsInfo(declarationMethodElement); + + boolean isNative = + isNative(declarationMethodElement) + || (!jsInfo.isJsOverlay() + && enclosingTypeDescriptor.isNative() + && isAbstract(declarationMethodElement)); + + boolean isConstructor = declarationMethodElement.getKind() == ElementKind.CONSTRUCTOR; + String methodName = declarationMethodElement.getSimpleName().toString(); + + ImmutableList.Builder parameterDescriptorBuilder = + ImmutableList.builder(); + for (int i = 0; i < parameters.size(); i++) { + parameterDescriptorBuilder.add( + MethodDescriptor.ParameterDescriptor.newBuilder() + .setTypeDescriptor(parameters.get(i)) + .setJsOptional(JsInteropUtils.isJsOptional(declarationMethodElement, i)) + .setVarargs(i == parameters.size() - 1 && declarationMethodElement.isVarArgs()) + .setDoNotAutobox(JsInteropUtils.isDoNotAutobox(declarationMethodElement, i)) + .build()); + } + + boolean hasUncheckedCast = hasUncheckedCastAnnotation(declarationMethodElement); + return MethodDescriptor.newBuilder() + .setEnclosingTypeDescriptor(enclosingTypeDescriptor) + .setName(isConstructor ? null : methodName) + .setParameterDescriptors(parameterDescriptorBuilder.build()) + .setDeclarationDescriptor(declarationMethodDescriptor) + .setReturnTypeDescriptor(isConstructor ? enclosingTypeDescriptor : returnTypeDescriptor) + .setTypeParameterTypeDescriptors(typeParameterTypeDescriptors) + .setOriginalJsInfo(jsInfo) + .setVisibility(visibility) + .setStatic(isStatic) + .setConstructor(isConstructor) + .setNative(isNative) + .setWasmInfo(getWasmInfo(declarationMethodElement)) + .setFinal(isFinal(declarationMethodElement)) + .setDefaultMethod(isDefault) + .setAbstract(isAbstract(declarationMethodElement)) + .setSynthetic(isSynthetic(declarationMethodElement)) + .setEnumSyntheticMethod(isEnumSyntheticMethod(declarationMethodElement)) + .setSideEffectFree(isAnnotatedWithHasNoSideEffects(declarationMethodElement)) + .setUnusableByJsSuppressed( + JsInteropAnnotationUtils.isUnusableByJsSuppressed(declarationMethodElement)) + .setDeprecated(isDeprecated(declarationMethodElement)) + .setUncheckedCast(hasUncheckedCast) + .build(); + } + + ImmutableList createTypeDescriptors( + List typeMirrors, boolean inNullMarkedScope) { + return typeMirrors.stream() + .map(typeMirror -> createTypeDescriptor(typeMirror, inNullMarkedScope)) + .collect(toImmutableList()); + } + + ImmutableList createTypeDescriptors( + List typeMirrors, + boolean inNullMarkedScope, + Class clazz, + Element declarationElement) { + ImmutableList.Builder typeDescriptorsBuilder = ImmutableList.builder(); + for (int i = 0; i < typeMirrors.size(); i++) { + final int index = i; + TypeDescriptor typeDescriptor = + createTypeDescriptor(typeMirrors.get(i), inNullMarkedScope, clazz); + /* typeDescriptorsBuilder.add(typeDescriptor); + + typeDescriptorsBuilder.add( + clazz.cast( + applyNullabilityAnnotations( + createTypeDescriptor(typeMirrors.get(i), inNullMarkedScope, clazz), + declarationElement, + position -> + position.type == TargetType.CLASS_EXTENDS && position.type_index == index)));*/ + } + return typeDescriptorsBuilder.build(); + } + + ImmutableList createTypeDescriptors( + List typeMirrors, boolean inNullMarkedScope, Class clazz) { + return typeMirrors.stream() + .map(typeMirror -> createTypeDescriptor(typeMirror, inNullMarkedScope, clazz)) + .collect(toImmutableList()); + } + + private TypeElement getTypeElement(String qualifiedSourceName) { + return elements.getTypeElement(qualifiedSourceName); + } + + private Element asElement(TypeMirror typeMirror) { + if (typeMirror.getKind().isPrimitive()) { + return MoreTypes.asElement(typeMirror); + } + if (typeMirror.getKind().equals(TypeKind.DECLARED)) { + return MoreTypes.asDeclared(typeMirror).asElement(); + } + return javacTypes.asElement(typeMirror); + } + + private TypeElement asTypeElement(TypeMirror typeMirror) { + return (TypeElement) asElement(typeMirror); + } + + private TypeMirror erasure(TypeMirror typeMirror) { + return javacTypes.erasure(typeMirror); + } + + private PackageElement getPackageOf(TypeElement typeElement) { + return elements.getPackageOf(typeElement); + } + + private DeclaredTypeDescriptor createDeclaredType( + final DeclaredType classType, boolean inNullMarkedScope) { + + DeclaredTypeDescriptor cachedTypeDescriptor = + getCachedTypeDescriptor(classType, inNullMarkedScope); + if (cachedTypeDescriptor != null) { + return cachedTypeDescriptor; + } + + DeclaredTypeDescriptor typeDescriptor = + createDeclarationForType((TypeElement) classType.asElement()) + .toDescriptor(createTypeDescriptors(getTypeArguments(classType), inNullMarkedScope)); + putTypeDescriptorInCache(inNullMarkedScope, classType, typeDescriptor); + return typeDescriptor; + } + + private DeclaredTypeDescriptor getCachedTypeDescriptor( + DeclaredType classType, boolean inNullMarkedScope) { + Map cache = + inNullMarkedScope + ? cachedDeclaredTypeDescriptorByDeclaredTypeInNullMarkedScope + : cachedDeclaredTypeDescriptorByDeclaredTypeOutOfNullMarkedScope; + return cache.get(classType); + } + + private void putTypeDescriptorInCache( + boolean inNullMarkedScope, DeclaredType classType, DeclaredTypeDescriptor typeDescriptor) { + Map cache = + inNullMarkedScope + ? cachedDeclaredTypeDescriptorByDeclaredTypeInNullMarkedScope + : cachedDeclaredTypeDescriptorByDeclaredTypeOutOfNullMarkedScope; + cache.put(classType, typeDescriptor); + } + + private ImmutableList getDeclaredMethods(DeclaredType classType) { + return ElementFilter.methodsIn(classType.asElement().getEnclosedElements()).stream() + .collect(toImmutableList()); + } + + private String getJsNamespace(TypeElement classSymbol) { + String jsNamespace = JsInteropAnnotationUtils.getJsNamespace(classSymbol); + if (jsNamespace != null) { + return jsNamespace; + } + + // Maybe namespace is set via package-info file? + boolean isTopLevelType = classSymbol.getEnclosingElement().getKind() == ElementKind.PACKAGE; + if (isTopLevelType) { + return getBinaryNameFromTypeBinding(classSymbol); + } + return null; + } + + TypeDeclaration createDeclarationForType(final TypeElement typeElement) { + if (typeElement == null) { + return null; + } + + // Compute these first since they're reused in other calculations. + String packageName = getPackageOf(typeElement).getQualifiedName().toString(); + boolean isAbstract = isAbstract(typeElement) && !isInterface(typeElement); + TypeDeclaration.Kind kind = getKindFromTypeBinding(typeElement); + // TODO(b/341721484): Even though enums can not have the final modifier, turbine make them final + // in the header jars. + boolean isFinal = isFinal(typeElement) && kind != TypeDeclaration.Kind.ENUM; + + Supplier> declaredMethods = + () -> { + ImmutableList.Builder listBuilder = ImmutableList.builder(); + for (ExecutableElement methodElement : + ElementFilter.methodsIn(typeElement.getEnclosedElements())) { + MethodDescriptor methodDescriptor = createDeclarationMethodDescriptor(methodElement); + listBuilder.add(methodDescriptor); + } + return listBuilder.build(); + }; + + Supplier> declaredFields = + () -> + typeElement.getEnclosedElements().stream() + .filter( + element -> + element.getKind() == ElementKind.FIELD + || element.getKind() == ElementKind.ENUM_CONSTANT) + .map(VariableElement.class::cast) + .map(this::createFieldDescriptor) + .collect(toImmutableList()); + + JsEnumInfo jsEnumInfo = JsInteropUtils.getJsEnumInfo(typeElement); + + List typeParameterElements = getTypeParameters(typeElement); + + // boolean isNullMarked = isNullMarked(typeElement, packageInfoCache); + boolean isNullMarked = false; + return newBuilder() + .setClassComponents(getClassComponents(typeElement)) + .setEnclosingTypeDeclaration(createDeclarationForType(getEnclosingType(typeElement))) + .setInterfaceTypeDescriptorsFactory( + () -> + createTypeDescriptors( + typeElement.getInterfaces(), + isNullMarked, + DeclaredTypeDescriptor.class, + typeElement)) + .setHasAbstractModifier(isAbstract) + .setKind(kind) + .setAnnotation(isAnnotation(typeElement)) + .setCapturingEnclosingInstance(capturesEnclosingInstance(typeElement)) + .setFinal(isFinal) + .setFunctionalInterface(isFunctionalInterface(typeElement.asType())) + .setJsFunctionInterface(JsInteropUtils.isJsFunction(typeElement)) + .setJsType(JsInteropUtils.isJsType(typeElement)) + .setJsEnumInfo(jsEnumInfo) + .setNative(JsInteropUtils.isJsNativeType(typeElement)) + .setAnonymous(isAnonymous(typeElement)) + .setLocal(isLocal(typeElement)) + .setSimpleJsName(getJsName(typeElement)) + .setCustomizedJsNamespace(getJsNamespace(typeElement)) + .setNullMarked(isNullMarked) + /* .setOriginalSimpleSourceName( + typeElement.getSimpleName() != null ? typeElement.getSimpleName().toString() : null)*/ + .setPackage(PackageDeclaration.newBuilder().setName(packageName).build()) + /* .setSuperTypeDescriptorFactory( + () -> + (DeclaredTypeDescriptor) + applyNullabilityAnnotations( + createDeclaredTypeDescriptor(typeElement.getSuperclass(), isNullMarked), + typeElement, + position -> + position.type == TargetType.CLASS_EXTENDS && position.type_index == -1))*/ + .setTypeParameterDescriptors( + typeParameterElements.stream() + .map(TypeParameterElement::asType) + .map(javax.lang.model.type.TypeVariable.class::cast) + .map(this::createTypeVariable) + .collect(toImmutableList())) + .setVisibility(getVisibility(typeElement)) + .setDeclaredMethodDescriptorsFactory(declaredMethods) + .setDeclaredFieldDescriptorsFactory(declaredFields) + .setUnusableByJsSuppressed(JsInteropAnnotationUtils.isUnusableByJsSuppressed(typeElement)) + .setDeprecated(isDeprecated(typeElement)) + .build(); + } + + private boolean isFunctionalInterface(TypeMirror type) { + return type.getAnnotationsByType(FunctionalInterface.class).length > 0; + } + + MemberDescriptor getDefaultConstructor(TypeElement clazz) { + DeclaredTypeDescriptor typeDeclaration = + (DeclaredTypeDescriptor) createTypeDescriptor(clazz.asType()); + + MethodDescriptor ctor = + createDeclarationForType(clazz).getDeclaredMethodDescriptors().stream() + .filter(MemberDescriptor::isJsConstructor) + .filter(m -> m.getParameterDescriptors().isEmpty()) + .findFirst() + .orElseGet(() -> AstUtils.createImplicitConstructorDescriptor(typeDeclaration)); + return ctorMethodDescriptorFromJavaConstructor(ctor); + } + + private static String getWasmInfo(Element element) { + AnnotationMirror wasmAnnotation = + AnnotationUtils.findAnnotationBindingByName( + element.getAnnotationMirrors(), WASM_ANNOTATION_NAME); + if (wasmAnnotation == null) { + return null; + } + return AnnotationUtils.getAnnotationParameterString(wasmAnnotation, "value"); + } +} diff --git a/utils/src/main/java/org/treblereel/j2cl/processors/utils/J2CLUtils.java b/utils/src/main/java/org/treblereel/j2cl/processors/utils/J2CLUtils.java index bc3f9b2..9391e27 100644 --- a/utils/src/main/java/org/treblereel/j2cl/processors/utils/J2CLUtils.java +++ b/utils/src/main/java/org/treblereel/j2cl/processors/utils/J2CLUtils.java @@ -1,75 +1,30 @@ /* * Copyright 2015 Google Inc. * - * 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 + * 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 + * 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. + * 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 org.treblereel.j2cl.processors.utils; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.collect.ImmutableList.toImmutableList; -import static com.google.j2cl.transpiler.ast.TypeDeclaration.Kind; -import static com.google.j2cl.transpiler.ast.TypeDeclaration.newBuilder; - -import com.google.auto.common.MoreTypes; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Iterables; -import com.google.common.collect.Streams; -import com.google.j2cl.common.InternalCompilerError; -import com.google.j2cl.transpiler.ast.ArrayTypeDescriptor; -import com.google.j2cl.transpiler.ast.AstUtils; -import com.google.j2cl.transpiler.ast.DeclaredTypeDescriptor; -import com.google.j2cl.transpiler.ast.FieldDescriptor; -import com.google.j2cl.transpiler.ast.JsEnumInfo; -import com.google.j2cl.transpiler.ast.JsInfo; -import com.google.j2cl.transpiler.ast.Literal; -import com.google.j2cl.transpiler.ast.MemberDescriptor; -import com.google.j2cl.transpiler.ast.MethodDescriptor; -import com.google.j2cl.transpiler.ast.MethodDescriptor.ParameterDescriptor; -import com.google.j2cl.transpiler.ast.PrimitiveTypes; -import com.google.j2cl.transpiler.ast.TypeDeclaration; -import com.google.j2cl.transpiler.ast.TypeDescriptor; -import com.google.j2cl.transpiler.ast.TypeDescriptors; -import com.google.j2cl.transpiler.ast.TypeVariable; -import com.google.j2cl.transpiler.ast.Visibility; -import com.google.j2cl.transpiler.frontend.javac.JsInteropAnnotationUtils; -import com.google.j2cl.transpiler.frontend.javac.JsInteropUtils; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Supplier; +import com.google.auto.common.MoreElements; +import com.google.j2cl.transpiler.ast.*; import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.AnnotatedConstruct; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.NestingKind; -import javax.lang.model.element.PackageElement; -import javax.lang.model.element.Parameterizable; import javax.lang.model.element.TypeElement; -import javax.lang.model.element.TypeParameterElement; import javax.lang.model.element.VariableElement; -import javax.lang.model.type.ArrayType; import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.ElementFilter; -import javax.lang.model.util.Elements; -import javax.lang.model.util.Types; +import jsinterop.annotations.JsProperty; +import jsinterop.annotations.JsType; /** * Utility functions to interact with JavaC internal representations. @@ -77,1008 +32,69 @@ *

it's taken from J2CL project */ public class J2CLUtils { - private final Types javacTypes; - private final Elements elements; - private final ProcessingEnvironment processingEnv; - private final Map - cachedDeclaredTypeDescriptorByDeclaredTypeInNullMarkedScope = new HashMap<>(); - private final Map - cachedDeclaredTypeDescriptorByDeclaredTypeOutOfNullMarkedScope = new HashMap<>(); + private final HackedJavaEnvironment javaEnvironment; public J2CLUtils(ProcessingEnvironment processingEnv) { - this.javacTypes = processingEnv.getTypeUtils(); - this.elements = processingEnv.getElementUtils(); - this.processingEnv = processingEnv; - initWellKnownTypes(TypeDescriptors.getWellKnownTypeNames()); - } - - private boolean isNonNullAnnotation(AnnotationMirror annotation) { - DeclaredType annotationType = annotation.getAnnotationType(); - String name = annotationType.asElement().getSimpleName().toString(); - return name.equals("NonNull") || name.equals("JsNonNull"); - } - - private boolean isNullableAnnotation(AnnotationMirror annotation) { - DeclaredType annotationType = annotation.getAnnotationType(); - return annotationType.asElement().getSimpleName().toString().equals("Nullable"); - } - - private DeclaredTypeDescriptor withNullability( - DeclaredTypeDescriptor typeDescriptor, boolean nullable) { - return nullable ? typeDescriptor.toNullable() : typeDescriptor.toNonNullable(); - } - - /** - * In case the given type element is nested, return the outermost possible enclosing type element. - */ - private TypeElement toTopLevelTypeBinding(Element element) { - if (element.getEnclosingElement().getKind() == ElementKind.PACKAGE) { - return (TypeElement) element; - } - return toTopLevelTypeBinding(element.getEnclosingElement()); - } - - private boolean isValuesMethod(ExecutableElement methodElement) { - return methodElement.getSimpleName().contentEquals("values") - && methodElement.getParameters().isEmpty(); - } - - ///////////////////////////////////////////////////////////////////////////////////////////////// - // Utility methods to process nullability annotations on classes that are compiled separately. - // Javac does not present TYPE_USE annotation in the returned type instances. - private TypeDescriptor applyParameterNullabilityAnnotations( - TypeDescriptor typeDescriptor, ExecutableElement declarationMethodElement, int index) { - return typeDescriptor; - } - - private int getInnerDepth(DeclaredTypeDescriptor innerType) { - if (innerType.getTypeDeclaration().isCapturingEnclosingInstance()) { - return getInnerDepth(innerType.getEnclosingTypeDescriptor()) + 1; - } - return 0; - } - - /** Returns true if the element is annotated with @UncheckedCast. */ - private boolean hasUncheckedCastAnnotation(Element element) { - return false; - } - - /** Returns true if the element is annotated with @HasNoSideEffects. */ - private boolean isAnnotatedWithHasNoSideEffects(Element element) { - return true; - } - - private List getTypeArguments(DeclaredType declaredType) { - List typeArguments = new ArrayList<>(); - DeclaredType currentType = declaredType; - do { - typeArguments.addAll(currentType.getTypeArguments()); - Element enclosingElement = currentType.asElement().getEnclosingElement(); - if (enclosingElement.getKind() == ElementKind.METHOD - || enclosingElement.getKind() == ElementKind.CONSTRUCTOR) { - typeArguments.addAll( - ((Parameterizable) enclosingElement) - .getTypeParameters().stream().map(Element::asType).collect(toImmutableList())); - } - currentType = - currentType.getEnclosingType() instanceof DeclaredType - ? (DeclaredType) currentType.getEnclosingType() - : null; - } while (currentType != null); - return typeArguments; - } - - private Kind getKindFromTypeBinding(TypeElement typeElement) { - if (isEnum(typeElement) && !isAnonymous(typeElement)) { - // Do not consider the anonymous classes that constitute enum values as Enums, only the - // enum "class" itself is considered Kind.ENUM. - return Kind.ENUM; - } else if (isClass(typeElement) || (isEnum(typeElement) && isAnonymous(typeElement))) { - return Kind.CLASS; - } else if (isInterface(typeElement)) { - return Kind.INTERFACE; - } - throw new InternalCompilerError("Type binding %s not handled.", typeElement); - } - - private String getJsName(final TypeElement classSymbol) { - return JsInteropAnnotationUtils.getJsName(classSymbol); - } - - private boolean hasNullMarkedAnnotation(TypeElement classSymbol) { - return false; - } - - private List getTypeParameters(TypeElement typeElement) { - List typeParameterElements = - new ArrayList<>(typeElement.getTypeParameters()); - Element currentElement = typeElement; - Element enclosingElement = typeElement.getEnclosingElement(); - while (enclosingElement != null) { - if (isStatic(currentElement)) { - break; - } - - if (enclosingElement.getKind() != ElementKind.STATIC_INIT - && enclosingElement.getKind() != ElementKind.INSTANCE_INIT - && enclosingElement instanceof Parameterizable) { - // Add the enclosing element type variables, skip STATIC_INIT and INSTANCE_INIT since they - // never define type variables, and throw NPE if getTypeParameters is called on them. - typeParameterElements.addAll(((Parameterizable) enclosingElement).getTypeParameters()); - } - currentElement = enclosingElement; - enclosingElement = enclosingElement.getEnclosingElement(); - } - return typeParameterElements; - } - - public TypeElement getEnclosingType(Element typeElement) { - Element enclosing = typeElement.getEnclosingElement(); - while (enclosing != null && !(enclosing instanceof TypeElement)) { - enclosing = enclosing.getEnclosingElement(); - } - return (TypeElement) enclosing; - } - - private TypeElement getEnclosingType(TypeElement typeElement) { - Element enclosing = typeElement.getEnclosingElement(); - while (enclosing != null && !(enclosing instanceof TypeElement)) { - enclosing = enclosing.getEnclosingElement(); - } - return (TypeElement) enclosing; - } - - private boolean isEnum(TypeElement typeElement) { - return typeElement.getKind() == ElementKind.ENUM; - } - - private boolean isAnnotation(TypeElement typeElement) { - return typeElement.getKind() == ElementKind.ANNOTATION_TYPE; - } - - private boolean isAnonymous(TypeElement typeElement) { - return typeElement.getNestingKind() == NestingKind.ANONYMOUS; - } - - private boolean isClass(TypeElement typeElement) { - return typeElement.getKind() == ElementKind.CLASS; - } - - private boolean isInterface(TypeElement typeElement) { - return typeElement.getKind() == ElementKind.INTERFACE - || typeElement.getKind() == ElementKind.ANNOTATION_TYPE; - } - - private boolean isLocal(TypeElement typeElement) { - return typeElement.getNestingKind() == NestingKind.LOCAL; - } - - public Visibility getVisibility(Element element) { - if (element.getModifiers().contains(Modifier.PUBLIC)) { - return Visibility.PUBLIC; - } else if (element.getModifiers().contains(Modifier.PROTECTED)) { - return Visibility.PROTECTED; - } else if (element.getModifiers().contains(Modifier.PRIVATE)) { - return Visibility.PRIVATE; - } else { - return Visibility.PACKAGE_PRIVATE; - } - } - - private boolean isDeprecated(AnnotatedConstruct binding) { - return binding.getAnnotation(Deprecated.class) != null; - } - - private boolean isDefaultMethod(Element element) { - return element.getModifiers().contains(Modifier.DEFAULT); - } - - private boolean isAbstract(Element element) { - return element.getModifiers().contains(Modifier.ABSTRACT); - } - - private boolean isFinal(Element element) { - return element.getModifiers().contains(Modifier.FINAL); - } - - public boolean isStatic(Element element) { - return element.getModifiers().contains(Modifier.STATIC); - } - - private boolean isNative(Element element) { - return element.getModifiers().contains(Modifier.NATIVE); - } - - private boolean isSynthetic(Element element) { - return false; - // return element instanceof Symbol && (((Symbol) element).flags() & Flags.SYNTHETIC) != 0; - } - - private MethodDescriptor ctorMethodDescriptorFromJavaConstructor(MethodDescriptor constructor) { - return constructor.transform( - builder -> - builder - .setReturnTypeDescriptor(PrimitiveTypes.VOID) - .setName(getCtorName(constructor)) - .setConstructor(false) - .setStatic(false) - .setOriginalJsInfo(JsInfo.NONE) - .removeParameterOptionality() - .setOrigin(MethodDescriptor.MethodOrigin.SYNTHETIC_CTOR_FOR_CONSTRUCTOR) - .setVisibility(Visibility.PUBLIC)); - } - - private String getCtorName(MethodDescriptor methodDescriptor) { - // Synthesize a name that is unique per class to avoid property clashes in JS. - return MethodDescriptor.CTOR_METHOD_PREFIX - + "__" - + methodDescriptor.getEnclosingTypeDescriptor().getMangledName(); - } - - private void initWellKnownTypes(Collection wellKnownQualifiedBinaryNames) { - if (TypeDescriptors.isInitialized()) { - return; - } - TypeDescriptors.SingletonBuilder builder = new TypeDescriptors.SingletonBuilder(); - // Add well-known, non-primitive types. - wellKnownQualifiedBinaryNames.forEach( - binaryName -> { - String qualifiedSourceName = binaryName.replace('$', '.'); - TypeElement element = getTypeElement(qualifiedSourceName); - if (element != null) { - builder.addReferenceType(createDeclaredTypeDescriptor(element.asType())); - } - }); - - DeclaredTypeDescriptor typeDescriptor = - createSyntheticJavaEmulInternalExceptionsTypeDescriptor(); - builder.addReferenceType(typeDescriptor); - builder.buildSingleton(); - } - - private DeclaredTypeDescriptor createSyntheticJavaEmulInternalExceptionsTypeDescriptor() { - TypeDeclaration typeDeclaration = - TypeDeclaration.newBuilder() - .setClassComponents(ImmutableList.of("Exceptions")) - .setNative(false) - .setCustomizedJsNamespace("javaemul.internal") - .setPackageName("javaemul.internal") - .setTypeParameterDescriptors(ImmutableList.of()) - .setVisibility(Visibility.PUBLIC) - .setKind(Kind.CLASS) - .build(); - - return DeclaredTypeDescriptor.newBuilder() - .setTypeDeclaration(typeDeclaration) - .setTypeArgumentDescriptors(Collections.EMPTY_LIST) - .build(); - } - - public DeclaredTypeDescriptor createDeclaredTypeDescriptor(TypeMirror typeMirror) { - return createDeclaredTypeDescriptor(typeMirror, /* inNullMarkedScope= */ false); - } - - private DeclaredTypeDescriptor createDeclaredTypeDescriptor( - TypeMirror typeMirror, boolean inNullMarkedScope) { - return createTypeDescriptor(typeMirror, inNullMarkedScope, DeclaredTypeDescriptor.class); - } - - /** Creates a specific subclass of TypeDescriptor from a TypeMirror. */ - public T createTypeDescriptor(TypeMirror typeMirror, Class clazz) { - return createTypeDescriptor(typeMirror, /* inNullMarkedScope= */ false, clazz); - } - - /** Creates a specific subclass of TypeDescriptor from a TypeMirror. */ - private T createTypeDescriptor( - TypeMirror typeMirror, boolean inNullMarkedScope, Class clazz) { - return clazz.cast(createTypeDescriptor(typeMirror, inNullMarkedScope)); - } - - /** Creates a TypeDescriptor from a TypeMirror. */ - public TypeDescriptor createTypeDescriptor(TypeMirror typeMirror) { - return createTypeDescriptor(typeMirror, /* inNullMarkedScope= */ false); - } - - /** Creates a TypeDescriptor from a TypeMirror. */ - private TypeDescriptor createTypeDescriptor(TypeMirror typeMirror, boolean inNullMarkedScope) { - return createTypeDescriptorWithNullability(typeMirror, ImmutableList.of(), inNullMarkedScope); - } - - /** Creates a type descriptor for the given TypeMirror, taking into account nullability. */ - private TypeDescriptor createTypeDescriptorWithNullability( - TypeMirror typeMirror, - List elementAnnotations, - boolean inNullMarkedScope) { - if (typeMirror == null || typeMirror.getKind() == TypeKind.NONE) { - return null; - } - if (typeMirror.getKind().isPrimitive()) { - return PrimitiveTypes.get(typeMirror.toString()); - } - - if (typeMirror.getKind() == TypeKind.VOID) { - return PrimitiveTypes.VOID; - } - - if (typeMirror.getKind() == TypeKind.INTERSECTION) { - throw new InternalCompilerError("Intersection types are not supported."); - // return createIntersectionType((IntersectionClassType) typeMirror); - } - - if (typeMirror.getKind() == TypeKind.UNION) { - throw new InternalCompilerError("Union types are not supported."); - // return createUnionType((UnionClassType) typeMirror); - } - - if (typeMirror.getKind() == TypeKind.NULL) { - return TypeDescriptors.get().javaLangObject; - } - - if (typeMirror.getKind() == TypeKind.TYPEVAR) { - return createTypeVariable((javax.lang.model.type.TypeVariable) typeMirror); - } - - if (typeMirror.getKind() == TypeKind.WILDCARD) { - return createWildcardTypeVariable( - ((javax.lang.model.type.WildcardType) typeMirror).getExtendsBound()); - } - - boolean isNullable = isNullable(typeMirror, elementAnnotations, inNullMarkedScope); - if (typeMirror.getKind() == TypeKind.ARRAY) { - ArrayType arrayType = (ArrayType) typeMirror; - TypeDescriptor componentTypeDescriptor = - createTypeDescriptor(arrayType.getComponentType(), inNullMarkedScope); - return ArrayTypeDescriptor.newBuilder() - .setComponentTypeDescriptor(componentTypeDescriptor) - .setNullable(isNullable) - .build(); - } - - return withNullability( - createDeclaredType(MoreTypes.asDeclared(typeMirror), inNullMarkedScope), isNullable); + javaEnvironment = new HackedJavaEnvironment(processingEnv); } - /** - * Returns whether the given type binding should be nullable, according to the annotations on it - * and if nullability is enabled for the package containing the binding. - */ - private boolean isNullable( - TypeMirror typeMirror, - List elementAnnotations, - boolean inNullMarkedScope) { - checkArgument(!typeMirror.getKind().isPrimitive()); - - if (typeMirror.getKind() == TypeKind.VOID) { - return true; - } - - Iterable allAnnotations = - Iterables.concat(elementAnnotations, typeMirror.getAnnotationMirrors()); - - for (AnnotationMirror annotationMirror : allAnnotations) { - if (isNonNullAnnotation(annotationMirror)) { - return false; - } - if (isNullableAnnotation(annotationMirror)) { - return true; - } - } - - return !inNullMarkedScope; + public MemberDescriptor getDefaultConstructor(TypeElement parent) { + return javaEnvironment.getDefaultConstructor(parent); } - private TypeVariable createTypeVariable(javax.lang.model.type.TypeVariable typeVariable) { - /* if (typeVariable instanceof CapturedType) { - return createWildcardTypeVariable(typeVariable.getUpperBound()); - }*/ - - Supplier boundTypeDescriptorFactory = - () -> createTypeDescriptor(typeVariable.getUpperBound()); - - List classComponents = getClassComponents(typeVariable); - return TypeVariable.newBuilder() - .setUpperBoundTypeDescriptorSupplier(boundTypeDescriptorFactory) - .setUniqueKey( - String.join("::", classComponents) - + (typeVariable.getUpperBound() != null - ? typeVariable.getUpperBound().toString() - : "")) - .setName(typeVariable.asElement().getSimpleName().toString()) - .build(); - } - - private TypeVariable createWildcardTypeVariable(TypeMirror bound) { - return TypeVariable.newBuilder() - .setUpperBoundTypeDescriptorSupplier(() -> createTypeDescriptor(bound)) - .setWildcard(true) - .setName("?") - .setUniqueKey("::?::" + (bound != null ? bound.toString() : "")) - .build(); - } - - private ImmutableList getClassComponents( - javax.lang.model.type.TypeVariable typeVariable) { - Element enclosingElement = typeVariable.asElement().getEnclosingElement(); - if (enclosingElement.getKind() == ElementKind.CLASS - || enclosingElement.getKind() == ElementKind.INTERFACE - || enclosingElement.getKind() == ElementKind.ENUM) { - return ImmutableList.builder() - .addAll(getClassComponents(enclosingElement)) - .add( - // If it is a class-level type variable, use the simple name (with prefix "C_") as the - // current name component. - "C_" + typeVariable.asElement().getSimpleName()) - .build(); - } else { - return ImmutableList.builder() - .addAll(getClassComponents(enclosingElement.getEnclosingElement())) - .add( - "M_" - + enclosingElement.getSimpleName() - + "_" - + typeVariable.asElement().getSimpleName()) - .build(); - } - } - - private ImmutableList getClassComponents(Element element) { - if (!(element instanceof TypeElement)) { - return ImmutableList.of(); - } - TypeElement typeElement = (TypeElement) element; - List classComponents = new ArrayList<>(); - TypeElement currentType = typeElement; - while (currentType != null) { - String simpleName; - if (currentType.getNestingKind() == NestingKind.LOCAL - || currentType.getNestingKind() == NestingKind.ANONYMOUS) { - // JavaC binary name for local class is like package.components.EnclosingClass$1SimpleName - // Extract the generated name by taking the part after the binary name of the declaring - // class. - String binaryName = getBinaryNameFromTypeBinding(currentType); - String declaringClassPrefix = - getBinaryNameFromTypeBinding(getEnclosingType(currentType)) + "$"; - simpleName = binaryName.substring(declaringClassPrefix.length()); - } else { - simpleName = asElement(erasure(currentType.asType())).getSimpleName().toString(); - } - classComponents.add(0, simpleName); - Element enclosingElement = currentType.getEnclosingElement(); - while (enclosingElement != null - && enclosingElement.getKind() != ElementKind.CLASS - && enclosingElement.getKind() != ElementKind.INTERFACE - && enclosingElement.getKind() != ElementKind.ENUM) { - enclosingElement = enclosingElement.getEnclosingElement(); - } - currentType = (TypeElement) enclosingElement; - } - return ImmutableList.copyOf(classComponents); - } - - /** Returns the binary name for a type element. */ - private String getBinaryNameFromTypeBinding(TypeElement typeElement) { - return elements.getBinaryName(typeElement).toString(); - } - - private boolean isEnumSyntheticMethod(ExecutableElement methodElement) { - // Enum synthetic methods are not marked as such because per JLS 13.1 these methods are - // implicitly declared but are not marked as synthetic. - return getEnclosingType(methodElement).getKind() == ElementKind.ENUM - && (isValuesMethod(methodElement) || isValueOfMethod(methodElement)); - } - - private boolean isValueOfMethod(ExecutableElement methodElement) { - return methodElement.getSimpleName().contentEquals("valueOf") - && methodElement.getParameters().size() == 1 - && asTypeElement(methodElement.getParameters().get(0).asType()) - .getQualifiedName() - .contentEquals("java.lang.String"); - } - - /** - * Returns true if instances of this type capture its outer instances; i.e. if it is an non member - * class, or an anonymous or local class defined in an instance context. - */ - private boolean capturesEnclosingInstance(TypeElement typeElement) { - if (isAnonymous(typeElement)) { - return hasOuterInstance(typeElement) || !isStatic(typeElement.getEnclosingElement()); - } - return hasOuterInstance(typeElement); - } - - public boolean hasOuterInstance(TypeElement typeElement) { - return typeElement.getEnclosingElement().getKind().isClass() - && !isInterface((TypeElement) typeElement.getEnclosingElement()); - } - - public FieldDescriptor createFieldDescriptor(VariableElement variableElement) { - return createFieldDescriptor(variableElement, variableElement.asType()); - } - - public FieldDescriptor createFieldDescriptor(VariableElement variableElement, TypeMirror type) { - - boolean isStatic = isStatic(variableElement); - Visibility visibility = getVisibility(variableElement); - DeclaredTypeDescriptor enclosingTypeDescriptor = - createDeclaredTypeDescriptor(getEnclosingType(variableElement).asType()); - String fieldName = variableElement.getSimpleName().toString(); - - TypeDescriptor thisTypeDescriptor = - createTypeDescriptorWithNullability( - type, - variableElement.getAnnotationMirrors(), - enclosingTypeDescriptor.getTypeDeclaration().isNullMarked()); - - boolean isEnumConstant = variableElement.getKind().equals(ElementKind.ENUM_CONSTANT); - if (isEnumConstant) { - // Enum fields are always non-nullable. - thisTypeDescriptor = thisTypeDescriptor.toNonNullable(); - } - - FieldDescriptor declarationFieldDescriptor = null; - if (!javacTypes.isSameType(variableElement.asType(), type)) { - // Field references might be parameterized, and when they are we set the declaration - // descriptor to the unparameterized declaration. - declarationFieldDescriptor = createFieldDescriptor(variableElement, variableElement.asType()); - } - - JsInfo jsInfo = JsInteropUtils.getJsInfo(variableElement); - Object constantValue = variableElement.getConstantValue(); - boolean isCompileTimeConstant = constantValue != null; - if (isCompileTimeConstant) { - thisTypeDescriptor = thisTypeDescriptor.toNonNullable(); - } - boolean isFinal = isFinal(variableElement); - return FieldDescriptor.newBuilder() - .setEnclosingTypeDescriptor(enclosingTypeDescriptor) - .setName(fieldName) - .setTypeDescriptor(thisTypeDescriptor) - .setStatic(isStatic) - .setVisibility(visibility) - .setOriginalJsInfo(jsInfo) - .setFinal(isFinal) - .setCompileTimeConstant(isCompileTimeConstant) - .setConstantValue( - constantValue != null ? Literal.fromValue(constantValue, thisTypeDescriptor) : null) - .setDeclarationDescriptor(declarationFieldDescriptor) - .setEnumConstant(isEnumConstant) - .setUnusableByJsSuppressed( - JsInteropAnnotationUtils.isUnusableByJsSuppressed(variableElement)) - .setDeprecated(isDeprecated(variableElement)) - .build(); - } - - /** Create a MethodDescriptor directly based on the given JavaC ExecutableElement. */ - MethodDescriptor createMethodDescriptor( - DeclaredTypeDescriptor enclosingTypeDescriptor, - ExecutableElement methodElement, - ExecutableElement declarationMethodElement) { - - MethodDescriptor declarationMethodDescriptor = null; - - ImmutableList parameters = - methodElement.getParameters().stream() - .map(VariableElement::asType) - .collect(toImmutableList()); - - TypeMirror returnType = methodElement.getReturnType(); - if (isSpecialized(declarationMethodElement, parameters, returnType)) { - declarationMethodDescriptor = - createDeclarationMethodDescriptor( - declarationMethodElement, enclosingTypeDescriptor.toUnparameterizedTypeDescriptor()); - } - - TypeDescriptor returnTypeDescriptor = - createTypeDescriptorWithNullability( - returnType, - declarationMethodElement.getAnnotationMirrors(), - enclosingTypeDescriptor.getTypeDeclaration().isNullMarked()); - - ImmutableList.Builder parametersBuilder = ImmutableList.builder(); - for (int i = 0; i < parameters.size(); i++) { - parametersBuilder.add( - applyParameterNullabilityAnnotations( - createTypeDescriptorWithNullability( - parameters.get(i), - declarationMethodElement.getParameters().get(i).getAnnotationMirrors(), - enclosingTypeDescriptor.getTypeDeclaration().isNullMarked()), - declarationMethodElement, - i)); - } - - return createDeclaredMethodDescriptor( - enclosingTypeDescriptor.toNullable(), - declarationMethodElement, - declarationMethodDescriptor, - parametersBuilder.build(), - returnTypeDescriptor); + public DeclaredTypeDescriptor createDeclaredTypeDescriptor(DeclaredType declaredType) { + return javaEnvironment.createDeclaredTypeDescriptor(declaredType); } - /** Create a MethodDescriptor directly based on the given JavaC ExecutableElement. */ - public MethodDescriptor createDeclarationMethodDescriptor(ExecutableElement methodElement) { - DeclaredTypeDescriptor enclosingTypeDescriptor = - createDeclaredTypeDescriptor(methodElement.getEnclosingElement().asType()); - return createDeclarationMethodDescriptor(methodElement, enclosingTypeDescriptor); + public MethodDescriptor createDeclarationMethodDescriptor(ExecutableElement method) { + return javaEnvironment.createDeclarationMethodDescriptor(method); } - /** Create a MethodDescriptor directly based on the given JavaC ExecutableElement. */ public MethodDescriptor createDeclarationMethodDescriptor( ExecutableElement methodElement, DeclaredTypeDescriptor enclosingTypeDescriptor) { - return createMethodDescriptor(enclosingTypeDescriptor, methodElement, methodElement); - } - - /** - * Returns true if any of the type parameters has been specialized. - * - *

For example the type {@code List} specialized the type variable {@code T} from the - * class declaration. - */ - private boolean isSpecialized( - ExecutableElement declarationMethodElement, - List parameters, - TypeMirror returnType) { - return !isSameType(returnType, declarationMethodElement.getReturnType()) - || !Streams.zip( - parameters.stream(), - declarationMethodElement.getParameters().stream(), - (thisType, thatType) -> isSameType(thisType, thatType.asType())) - .allMatch(equals -> equals); - } - - private boolean isSameType(TypeMirror thisType, TypeMirror thatType) { - return javacTypes.isSameType(thisType, thatType); + return javaEnvironment.createDeclarationMethodDescriptor( + methodElement, enclosingTypeDescriptor); } - private MethodDescriptor createDeclaredMethodDescriptor( - DeclaredTypeDescriptor enclosingTypeDescriptor, - ExecutableElement declarationMethodElement, - MethodDescriptor declarationMethodDescriptor, - List parameters, - TypeDescriptor returnTypeDescriptor) { - ImmutableList typeParameterTypeDescriptors = - declarationMethodElement.getTypeParameters().stream() - .map(Element::asType) - .map(this::createTypeDescriptor) - .map(TypeVariable.class::cast) - .collect(toImmutableList()); - - boolean isStatic = isStatic(declarationMethodElement); - Visibility visibility = getVisibility(declarationMethodElement); - boolean isDefault = isDefaultMethod(declarationMethodElement); - JsInfo jsInfo = JsInteropUtils.getJsInfo(declarationMethodElement); - - boolean isNative = - isNative(declarationMethodElement) - || (!jsInfo.isJsOverlay() - && enclosingTypeDescriptor.isNative() - && isAbstract(declarationMethodElement)); - - boolean isConstructor = declarationMethodElement.getKind() == ElementKind.CONSTRUCTOR; - String methodName = declarationMethodElement.getSimpleName().toString(); - - ImmutableList.Builder parameterDescriptorBuilder = ImmutableList.builder(); - for (int i = 0; i < parameters.size(); i++) { - parameterDescriptorBuilder.add( - ParameterDescriptor.newBuilder() - .setTypeDescriptor(parameters.get(i)) - .setJsOptional(JsInteropUtils.isJsOptional(declarationMethodElement, i)) - .setVarargs(i == parameters.size() - 1 && declarationMethodElement.isVarArgs()) - .setDoNotAutobox(JsInteropUtils.isDoNotAutobox(declarationMethodElement, i)) - .build()); - } - - boolean hasUncheckedCast = hasUncheckedCastAnnotation(declarationMethodElement); - return MethodDescriptor.newBuilder() - .setEnclosingTypeDescriptor(enclosingTypeDescriptor) - .setName(isConstructor ? null : methodName) - .setParameterDescriptors(parameterDescriptorBuilder.build()) - .setDeclarationDescriptor(declarationMethodDescriptor) - .setReturnTypeDescriptor(isConstructor ? enclosingTypeDescriptor : returnTypeDescriptor) - .setTypeParameterTypeDescriptors(typeParameterTypeDescriptors) - .setOriginalJsInfo(jsInfo) - .setVisibility(visibility) - .setStatic(isStatic) - .setConstructor(isConstructor) - .setNative(isNative) - .setFinal(isFinal(declarationMethodElement)) - .setDefaultMethod(isDefault) - .setAbstract(isAbstract(declarationMethodElement)) - .setSynthetic(isSynthetic(declarationMethodElement)) - .setEnumSyntheticMethod(isEnumSyntheticMethod(declarationMethodElement)) - .setSideEffectFree(isAnnotatedWithHasNoSideEffects(declarationMethodElement)) - .setUnusableByJsSuppressed( - JsInteropAnnotationUtils.isUnusableByJsSuppressed(declarationMethodElement)) - .setDeprecated(isDeprecated(declarationMethodElement)) - .setUncheckedCast(hasUncheckedCast) - .build(); - } - - public ImmutableList createTypeDescriptors( - List typeMirrors, boolean inNullMarkedScope) { - return typeMirrors.stream() - .map(typeMirror -> createTypeDescriptor(typeMirror, inNullMarkedScope)) - .collect(toImmutableList()); - } - - public ImmutableList createTypeDescriptors( - List typeMirrors, - boolean inNullMarkedScope, - Class clazz, - Element declarationElement) { - ImmutableList.Builder typeDescriptorsBuilder = ImmutableList.builder(); - for (int i = 0; i < typeMirrors.size(); i++) { - final int index = i; - TypeDescriptor typeDescriptor = - createTypeDescriptor(typeMirrors.get(i), inNullMarkedScope, clazz); - /* typeDescriptorsBuilder.add(typeDescriptor); - - typeDescriptorsBuilder.add( - clazz.cast( - applyNullabilityAnnotations( - createTypeDescriptor(typeMirrors.get(i), inNullMarkedScope, clazz), - declarationElement, - position -> - position.type == TargetType.CLASS_EXTENDS && position.type_index == index)));*/ - } - return typeDescriptorsBuilder.build(); - } - - public ImmutableList createTypeDescriptors( - List typeMirrors, boolean inNullMarkedScope, Class clazz) { - return typeMirrors.stream() - .map(typeMirror -> createTypeDescriptor(typeMirror, inNullMarkedScope, clazz)) - .collect(toImmutableList()); - } - - private TypeElement getTypeElement(String qualifiedSourceName) { - return elements.getTypeElement(qualifiedSourceName); - } - - private Element asElement(TypeMirror typeMirror) { - if (typeMirror.getKind().isPrimitive()) { - return MoreTypes.asElement(typeMirror); - } - if (typeMirror.getKind().equals(TypeKind.DECLARED)) { - return MoreTypes.asDeclared(typeMirror).asElement(); - } - return javacTypes.asElement(typeMirror); - } - - private TypeElement asTypeElement(TypeMirror typeMirror) { - return (TypeElement) asElement(typeMirror); - } - - private TypeMirror erasure(TypeMirror typeMirror) { - return javacTypes.erasure(typeMirror); - } - - private PackageElement getPackageOf(TypeElement typeElement) { - return elements.getPackageOf(typeElement); - } - - private DeclaredTypeDescriptor createDeclaredType( - final DeclaredType classType, boolean inNullMarkedScope) { - - DeclaredTypeDescriptor cachedTypeDescriptor = - getCachedTypeDescriptor(classType, inNullMarkedScope); - if (cachedTypeDescriptor != null) { - return cachedTypeDescriptor; - } - - Supplier> declaredMethods = - () -> - getDeclaredMethods(classType).stream() - .map( - methodDeclarationPair -> - createMethodDescriptor( - createDeclaredTypeDescriptor(classType, inNullMarkedScope), - methodDeclarationPair, - methodDeclarationPair)) - .collect(toImmutableList()); - - Supplier> declaredFields = - () -> - ((TypeElement) classType.asElement()) - .getEnclosedElements().stream() - .filter( - element -> - element.getKind() == ElementKind.FIELD - || element.getKind() == ElementKind.ENUM_CONSTANT) - .map(VariableElement.class::cast) - .map(this::createFieldDescriptor) - .collect(toImmutableList()); - - TypeDeclaration typeDeclaration = createDeclarationForType((TypeElement) classType.asElement()); - - // Compute these even later - DeclaredTypeDescriptor typeDescriptor = - DeclaredTypeDescriptor.newBuilder() - .setTypeDeclaration(typeDeclaration) - .setEnclosingTypeDescriptor(createDeclaredTypeDescriptor(classType.getEnclosingType())) - .setSuperTypeDescriptorFactory( - td -> - td.isInterface() - ? null - : createDeclaredTypeDescriptor( - javacTypes.directSupertypes(classType).stream() - .filter(type -> !asTypeElement(type).getKind().isInterface()) - .findFirst() - .orElse(null), - inNullMarkedScope)) - .setInterfaceTypeDescriptorsFactory( - td -> - createTypeDescriptors( - javacTypes.directSupertypes(classType).stream() - .filter(type -> !asTypeElement(type).getKind().isInterface()) - .collect(toImmutableList()), - inNullMarkedScope, - DeclaredTypeDescriptor.class)) - .setSingleAbstractMethodDescriptorFactory( - td -> { - // MethodSymbol functionalInterfaceMethod = - // getFunctionalInterfaceMethod(classType); - throw new UnsupportedOperationException("Not implemented yet"); - /* return createMethodDescriptor( - td, - (MethodSymbol) - functionalInterfaceMethod.asMemberOf( - ((ClassSymbol) classType.asElement()).asType(), internalTypes), - getFunctionalInterfaceMethodDecl(classType));*/ - }) - .setTypeArgumentDescriptors( - createTypeDescriptors(getTypeArguments(classType), inNullMarkedScope)) - .setDeclaredFieldDescriptorsFactory(declaredFields) - .setDeclaredMethodDescriptorsFactory(declaredMethods) - .build(); - putTypeDescriptorInCache(inNullMarkedScope, classType, typeDescriptor); - return typeDescriptor; - } - - private DeclaredTypeDescriptor getCachedTypeDescriptor( - DeclaredType classType, boolean inNullMarkedScope) { - Map cache = - inNullMarkedScope - ? cachedDeclaredTypeDescriptorByDeclaredTypeInNullMarkedScope - : cachedDeclaredTypeDescriptorByDeclaredTypeOutOfNullMarkedScope; - return cache.get(classType); + public FieldDescriptor createFieldDescriptor(VariableElement variableElement) { + return javaEnvironment.createFieldDescriptor(variableElement); } - private void putTypeDescriptorInCache( - boolean inNullMarkedScope, DeclaredType classType, DeclaredTypeDescriptor typeDescriptor) { - Map cache = - inNullMarkedScope - ? cachedDeclaredTypeDescriptorByDeclaredTypeInNullMarkedScope - : cachedDeclaredTypeDescriptorByDeclaredTypeOutOfNullMarkedScope; - cache.put(classType, typeDescriptor); + public TypeDescriptor createTypeDescriptor(TypeElement element) { + return createTypeDescriptor(element.asType()); } - private ImmutableList getDeclaredMethods(DeclaredType classType) { - return ElementFilter.methodsIn(classType.asElement().getEnclosedElements()).stream() - .collect(toImmutableList()); + public TypeDescriptor createTypeDescriptor(TypeMirror type) { + return javaEnvironment.createTypeDescriptor(type); } - private String getJsNamespace(TypeElement classSymbol) { - String jsNamespace = JsInteropAnnotationUtils.getJsNamespace(classSymbol); - if (jsNamespace != null) { - return jsNamespace; + public String getMethodMangledName(ExecutableElement method) { + if (method.getAnnotation(JsProperty.class) != null) { + JsProperty jsProperty = method.getAnnotation(JsProperty.class); + return jsProperty.name().equals("") + ? method.getSimpleName().toString() + : jsProperty.name(); } - // Maybe namespace is set via package-info file? - boolean isTopLevelType = classSymbol.getEnclosingElement().getKind() == ElementKind.PACKAGE; - if (isTopLevelType) { - return getBinaryNameFromTypeBinding(classSymbol); + if (isJsType(MoreElements.asType(method.getEnclosingElement()))) { + return method.getSimpleName().toString(); } - return null; + return javaEnvironment.createDeclarationMethodDescriptor(method).getMangledName(); } - TypeDeclaration createDeclarationForType(final TypeElement typeElement) { - if (typeElement == null) { - return null; + public String getVariableMangledName(VariableElement variableElement) { + if (variableElement.getAnnotation(JsProperty.class) != null) { + JsProperty jsProperty = variableElement.getAnnotation(JsProperty.class); + return jsProperty.name().equals("") + ? variableElement.getSimpleName().toString() + : jsProperty.name(); } - - // Compute these first since they're reused in other calculations. - String packageName = getPackageOf(typeElement).getQualifiedName().toString(); - boolean isAbstract = isAbstract(typeElement) && !isInterface(typeElement); - Kind kind = getKindFromTypeBinding(typeElement); - // TODO(b/341721484): Even though enums can not have the final modifier, turbine make them final - // in the header jars. - boolean isFinal = isFinal(typeElement) && kind != Kind.ENUM; - - Supplier> declaredMethods = - () -> { - ImmutableList.Builder listBuilder = ImmutableList.builder(); - for (ExecutableElement methodElement : - ElementFilter.methodsIn(typeElement.getEnclosedElements())) { - MethodDescriptor methodDescriptor = createDeclarationMethodDescriptor(methodElement); - listBuilder.add(methodDescriptor); - } - return listBuilder.build(); - }; - - Supplier> declaredFields = - () -> - typeElement.getEnclosedElements().stream() - .filter( - element -> - element.getKind() == ElementKind.FIELD - || element.getKind() == ElementKind.ENUM_CONSTANT) - .map(VariableElement.class::cast) - .map(this::createFieldDescriptor) - .collect(toImmutableList()); - - JsEnumInfo jsEnumInfo = JsInteropUtils.getJsEnumInfo(typeElement); - - List typeParameterElements = getTypeParameters(typeElement); - - // boolean isNullMarked = isNullMarked(typeElement, packageInfoCache); - boolean isNullMarked = false; - return newBuilder() - .setClassComponents(getClassComponents(typeElement)) - .setEnclosingTypeDeclaration(createDeclarationForType(getEnclosingType(typeElement))) - .setInterfaceTypeDescriptorsFactory( - () -> - createTypeDescriptors( - typeElement.getInterfaces(), - isNullMarked, - DeclaredTypeDescriptor.class, - typeElement)) - .setUnparameterizedTypeDescriptorFactory( - () -> createDeclaredTypeDescriptor(typeElement.asType())) - .setHasAbstractModifier(isAbstract) - .setKind(kind) - // .setAnnotation(isAnnotation(typeElement)) - .setCapturingEnclosingInstance(capturesEnclosingInstance(typeElement)) - .setFinal(isFinal) - .setFunctionalInterface(isFunctionalInterface(typeElement.asType())) - .setJsFunctionInterface(JsInteropUtils.isJsFunction(typeElement)) - .setJsType(JsInteropUtils.isJsType(typeElement)) - .setJsEnumInfo(jsEnumInfo) - .setNative(JsInteropUtils.isJsNativeType(typeElement)) - .setAnonymous(isAnonymous(typeElement)) - .setLocal(isLocal(typeElement)) - .setSimpleJsName(getJsName(typeElement)) - .setCustomizedJsNamespace(getJsNamespace(typeElement)) - .setNullMarked(isNullMarked) - /* .setOriginalSimpleSourceName( - typeElement.getSimpleName() != null ? typeElement.getSimpleName().toString() : null)*/ - .setPackageName(packageName) - /* .setSuperTypeDescriptorFactory( - () -> - (DeclaredTypeDescriptor) - applyNullabilityAnnotations( - createDeclaredTypeDescriptor(typeElement.getSuperclass(), isNullMarked), - typeElement, - position -> - position.type == TargetType.CLASS_EXTENDS && position.type_index == -1))*/ - .setTypeParameterDescriptors( - typeParameterElements.stream() - .map(TypeParameterElement::asType) - .map(javax.lang.model.type.TypeVariable.class::cast) - .map(this::createTypeVariable) - .collect(toImmutableList())) - .setVisibility(getVisibility(typeElement)) - .setDeclaredMethodDescriptorsFactory(declaredMethods) - .setDeclaredFieldDescriptorsFactory(declaredFields) - .setUnusableByJsSuppressed(JsInteropAnnotationUtils.isUnusableByJsSuppressed(typeElement)) - .setDeprecated(isDeprecated(typeElement)) - .build(); + return javaEnvironment.createFieldDescriptor(variableElement).getMangledName(); } - private boolean isFunctionalInterface(TypeMirror type) { - return type.getAnnotationsByType(FunctionalInterface.class).length > 0; - } - - public MemberDescriptor getDefaultConstructor(TypeElement clazz) { - DeclaredTypeDescriptor typeDeclaration = - (DeclaredTypeDescriptor) createTypeDescriptor(clazz.asType()); - - MethodDescriptor ctor = - createDeclarationForType(clazz).getDeclaredMethodDescriptors().stream() - .filter(MemberDescriptor::isJsConstructor) - .filter(m -> m.getParameterDescriptors().isEmpty()) - .findFirst() - .orElseGet(() -> AstUtils.createImplicitConstructorDescriptor(typeDeclaration)); - return ctorMethodDescriptorFromJavaConstructor(ctor); + public boolean isJsType(TypeElement element) { + return element.getAnnotation(JsType.class) != null + && !element.getAnnotation(JsType.class).isNative(); } } From 5803751aa2c9852497004e7e3f4615e08b97b62c Mon Sep 17 00:00:00 2001 From: Dmitrii Tikhomirov Date: Thu, 28 Nov 2024 01:09:04 -0800 Subject: [PATCH 2/3] bump gh action --- .github/workflows/maven.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 1cae877..7046547 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -14,7 +14,7 @@ jobs: os: [ubuntu-latest, windows-latest, macos-latest] steps: - name: Setup Chrome - uses: browser-actions/setup-chrome@v1.7.1 + uses: browser-actions/setup-chrome@v1.7.2 - name: Checkout uses: actions/checkout@v2 - name: Set up Java 11 @@ -26,7 +26,7 @@ jobs: run: | mvn -B package --file pom.xml - name: Upload test results for review - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 if: always() with: name: test-results-${{ matrix.os }} @@ -55,7 +55,7 @@ jobs: run: | mvn -B package --file pom.xml - name: Upload test results for review - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 if: always() with: name: test-results-mvn-v${{ matrix.mvn }}-jvm${{ matrix.java }} From 7b08ca2688be7def914f4ac6752eef0ab164045a Mon Sep 17 00:00:00 2001 From: Dmitrii Tikhomirov Date: Thu, 28 Nov 2024 11:33:07 -0800 Subject: [PATCH 3/3] bump java to 17 --- .github/workflows/maven.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 7046547..d767af9 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -17,10 +17,10 @@ jobs: uses: browser-actions/setup-chrome@v1.7.2 - name: Checkout uses: actions/checkout@v2 - - name: Set up Java 11 + - name: Set up Java 17 uses: actions/setup-java@v2 with: - java-version: '11' + java-version: '17' distribution: 'temurin' - name: Build and test run: | @@ -39,7 +39,7 @@ jobs: strategy: matrix: mvn: ['3.8.6', '3.6.3'] - java: ['11'] + java: ['17'] steps: - name: Checkout uses: actions/checkout@v2