diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-04-08 16:02:01 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-04-08 16:02:01 +0000 |
commit | d19a57accd743e731795db0eeb93a380cc81344f (patch) | |
tree | e9d1e379e3b445f390a78473334159b3dbc7b518 | |
parent | 0fce418f12c96a635404c1b558cc14ac8ee249d4 (diff) | |
parent | c6fb3b925e3e7c9dbf8324105097988c75b69c2b (diff) | |
download | turbine-aml_tz2_305400100.tar.gz |
Snap for 8426163 from c6fb3b925e3e7c9dbf8324105097988c75b69c2b to mainline-tzdata2-releaseandroid-mainline-12.0.0_r112aml_tz2_305400500aml_tz2_305400300aml_tz2_305400100aml_tz2_304500300aml_tz2_303900110aml_tz2_303900102aml_tz2_303800002aml_tz2_303800001aml_tz2_303200001android12-mainline-tzdata2-releaseaml_tz2_305400100
Change-Id: Ied7a36ed72c7436a60480fe376562c97aeb72b56
138 files changed, 1334 insertions, 13825 deletions
diff --git a/.travis.yml b/.travis.yml index 8113f5f..3ea8885 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,8 @@ language: java jdk: - - openjdk8 - - openjdk9 + - oraclejdk8 + - oraclejdk9 - openjdk10 - openjdk11 - openjdk-ea @@ -14,30 +14,12 @@ // limitations under the License. // -package { - default_applicable_licenses: ["external_turbine_license"], -} - -// Added automatically by a large-scale-change -// See: http://go/android-license-faq -license { - name: "external_turbine_license", - visibility: [":__subpackages__"], - license_kinds: [ - "SPDX-license-identifier-Apache-2.0", - ], - license_text: [ - "LICENSE", - ], -} - java_library_host { name: "turbine", srcs: [ "java/**/*.java", "proto/**/*.proto", - "android-annotation-stubs/src/**/*.java", ], manifest: "manifest.txt", @@ -46,11 +28,8 @@ java_library_host { "guava", ], - plugins: ["auto_value_plugin"], - libs: [ - "auto_value_annotations", - "auto_value_memoized_extension_annotations", - ], + plugins: ["dagger2-auto-value"], + libs: ["dagger2-auto-value"], proto: { type: "full", diff --git a/METADATA b/METADATA deleted file mode 100644 index e166a49..0000000 --- a/METADATA +++ /dev/null @@ -1,17 +0,0 @@ -name: "turbine" -description: - "Turbine is a header compiler for Java." - -third_party { - url { - type: HOMEPAGE - value: "https://github.com/google/turbine" - } - url { - type: GIT - value: "https://github.com/google/turbine" - } - version: "a963d859dc98108c37a701c1f76c4494fc480198" - last_upgrade_date { year: 2020 month: 3 day: 27 } - license_type: NOTICE -} @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/android-annotation-stubs/gen_annotations.sh b/android-annotation-stubs/gen_annotations.sh deleted file mode 100755 index 1965324..0000000 --- a/android-annotation-stubs/gen_annotations.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash - -declare -A INNER -declare -A PARAMETER -declare -A IMPORT - -ANNOTATIONS=( - org.checkerframework.checker.nullness.qual.Nullable - org.checkerframework.checker.nullness.compatqual.NullableDecl -) - -for a in ${ANNOTATIONS[@]}; do - package=${a%.*} - class=${a##*.} - dir=$(dirname $0)/src/${package//.//} - file=${class}.java - inner=${INNER[$a]} - parameter=${PARAMETER[$a]} - import= - - if [ -n "${parameter}" ]; then - parameter="${parameter} value();" - fi - - for i in ${IMPORT[$a]}; do - import="${import}import ${i};" - done - - mkdir -p ${dir} - sed -e"s/__PACKAGE__/${package}/" \ - -e"s/__CLASS__/${class}/" \ - -e"s/__INNER__/${inner}/" \ - -e"s/__PARAMETER__/${parameter}/" \ - -e"s/__IMPORT__/${import}/" \ - $(dirname $0)/tmpl.java > ${dir}/${file} - google-java-format -i ${dir}/${file} -done diff --git a/android-annotation-stubs/src/org/checkerframework/checker/nullness/compatqual/NullableDecl.java b/android-annotation-stubs/src/org/checkerframework/checker/nullness/compatqual/NullableDecl.java deleted file mode 100644 index 2d39b0f..0000000 --- a/android-annotation-stubs/src/org/checkerframework/checker/nullness/compatqual/NullableDecl.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * 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.checkerframework.checker.nullness.compatqual; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/* This is an annotation stub to avoid dependencies on annotations that aren't - * in the Android platform source tree. */ - -@Target({ - ElementType.ANNOTATION_TYPE, - ElementType.CONSTRUCTOR, - ElementType.FIELD, - ElementType.LOCAL_VARIABLE, - ElementType.METHOD, - ElementType.PACKAGE, - ElementType.PARAMETER, - ElementType.TYPE, - ElementType.TYPE_PARAMETER, - ElementType.TYPE_USE -}) -@Retention(RetentionPolicy.SOURCE) -public @interface NullableDecl {} diff --git a/android-annotation-stubs/src/org/checkerframework/checker/nullness/qual/Nullable.java b/android-annotation-stubs/src/org/checkerframework/checker/nullness/qual/Nullable.java deleted file mode 100644 index 276d64c..0000000 --- a/android-annotation-stubs/src/org/checkerframework/checker/nullness/qual/Nullable.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * 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.checkerframework.checker.nullness.qual; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/* This is an annotation stub to avoid dependencies on annotations that aren't - * in the Android platform source tree. */ - -@Target({ - ElementType.ANNOTATION_TYPE, - ElementType.CONSTRUCTOR, - ElementType.FIELD, - ElementType.LOCAL_VARIABLE, - ElementType.METHOD, - ElementType.PACKAGE, - ElementType.PARAMETER, - ElementType.TYPE, - ElementType.TYPE_PARAMETER, - ElementType.TYPE_USE -}) -@Retention(RetentionPolicy.SOURCE) -public @interface Nullable {} diff --git a/android-annotation-stubs/tmpl.java b/android-annotation-stubs/tmpl.java deleted file mode 100644 index c4df609..0000000 --- a/android-annotation-stubs/tmpl.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * 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 __PACKAGE__; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -__IMPORT__ - -/* This is an annotation stub to avoid dependencies on annotations that aren't - * in the Android platform source tree. */ - -@Target({ - ElementType.ANNOTATION_TYPE, - ElementType.CONSTRUCTOR, - ElementType.FIELD, - ElementType.LOCAL_VARIABLE, - ElementType.METHOD, - ElementType.PACKAGE, - ElementType.PARAMETER, - ElementType.TYPE, - ElementType.TYPE_PARAMETER, - ElementType.TYPE_USE}) -@Retention(RetentionPolicy.SOURCE) -public @interface __CLASS__ { - __INNER__ - __PARAMETER__ -} diff --git a/java/com/google/turbine/binder/Binder.java b/java/com/google/turbine/binder/Binder.java index 0e3f41f..cffe291 100644 --- a/java/com/google/turbine/binder/Binder.java +++ b/java/com/google/turbine/binder/Binder.java @@ -16,13 +16,11 @@ package com.google.turbine.binder; -import com.google.auto.value.AutoValue; import com.google.common.base.Splitter; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.turbine.binder.CompUnitPreprocessor.PreprocessedCompUnit; -import com.google.turbine.binder.Processing.ProcessorInfo; import com.google.turbine.binder.Resolve.CanonicalResolver; import com.google.turbine.binder.bound.BoundClass; import com.google.turbine.binder.bound.HeaderBoundClass; @@ -53,7 +51,6 @@ import com.google.turbine.binder.lookup.WildImportIndex; import com.google.turbine.binder.sym.ClassSymbol; import com.google.turbine.binder.sym.FieldSymbol; import com.google.turbine.binder.sym.ModuleSymbol; -import com.google.turbine.diag.SourceFile; import com.google.turbine.diag.TurbineError; import com.google.turbine.diag.TurbineError.ErrorKind; import com.google.turbine.diag.TurbineLog; @@ -63,56 +60,19 @@ import com.google.turbine.tree.Tree; import com.google.turbine.tree.Tree.CompUnit; import com.google.turbine.tree.Tree.ModDecl; import com.google.turbine.type.Type; -import java.time.Duration; +import java.util.List; import java.util.Optional; -import javax.annotation.processing.Processor; /** The entry point for analysis. */ public class Binder { /** Binds symbols and types to the given compilation units. */ public static BindingResult bind( - ImmutableList<CompUnit> units, + List<CompUnit> units, ClassPath classpath, ClassPath bootclasspath, Optional<String> moduleVersion) { - return bind(units, classpath, Processing.ProcessorInfo.empty(), bootclasspath, moduleVersion); - } - /** Binds symbols and types to the given compilation units. */ - public static BindingResult bind( - ImmutableList<CompUnit> units, - ClassPath classpath, - ProcessorInfo processorInfo, - ClassPath bootclasspath, - Optional<String> moduleVersion) { - TurbineLog log = new TurbineLog(); - BindingResult br = - bind( - log, - units, - /* generatedSources= */ ImmutableMap.of(), - /* generatedClasses= */ ImmutableMap.of(), - classpath, - bootclasspath, - moduleVersion); - if (!processorInfo.processors().isEmpty() && !units.isEmpty()) { - br = - Processing.process( - log, units, classpath, processorInfo, bootclasspath, br, moduleVersion); - } - log.maybeThrow(); - return br; - } - - static BindingResult bind( - TurbineLog log, - ImmutableList<CompUnit> units, - ImmutableMap<String, SourceFile> generatedSources, - ImmutableMap<String, byte[]> generatedClasses, - ClassPath classpath, - ClassPath bootclasspath, - Optional<String> moduleVersion) { ImmutableList<PreprocessedCompUnit> preProcessedUnits = CompUnitPreprocessor.preprocess(units); SimpleEnv<ClassSymbol, SourceBoundClass> ienv = bindSourceBoundClasses(preProcessedUnits); @@ -131,6 +91,8 @@ public class Binder { CompoundEnv<ModuleSymbol, ModuleInfo> classPathModuleEnv = CompoundEnv.of(classpath.moduleEnv()).append(bootclasspath.moduleEnv()); + TurbineLog log = new TurbineLog(); + BindPackagesResult bindPackagesResult = bindPackages(log, ienv, tli, preProcessedUnits, classPathEnv); @@ -146,12 +108,11 @@ public class Binder { henv, CompoundEnv.<ClassSymbol, HeaderBoundClass>of(classPathEnv).append(henv)); + log.maybeThrow(); + tenv = constants( - syms, - tenv, - CompoundEnv.<ClassSymbol, TypeBoundClass>of(classPathEnv).append(tenv), - log); + syms, tenv, CompoundEnv.<ClassSymbol, TypeBoundClass>of(classPathEnv).append(tenv)); tenv = disambiguateTypeAnnotations( syms, tenv, CompoundEnv.<ClassSymbol, TypeBoundClass>of(classPathEnv).append(tenv)); @@ -164,22 +125,13 @@ public class Binder { modules, CompoundEnv.<ClassSymbol, TypeBoundClass>of(classPathEnv).append(tenv), classPathModuleEnv, - moduleVersion, - log); + moduleVersion); ImmutableMap.Builder<ClassSymbol, SourceTypeBoundClass> result = ImmutableMap.builder(); for (ClassSymbol sym : syms) { result.put(sym, tenv.get(sym)); } - - return new BindingResult( - result.build(), - boundModules, - classPathEnv, - tli, - generatedSources, - generatedClasses, - Statistics.empty()); + return new BindingResult(result.build(), boundModules, classPathEnv); } /** Records enclosing declarations of member classes, and group classes by compilation unit. */ @@ -310,8 +262,7 @@ public class Binder { SimpleEnv<ModuleSymbol, PackageSourceBoundModule> modules, CompoundEnv<ClassSymbol, TypeBoundClass> env, CompoundEnv<ModuleSymbol, ModuleInfo> moduleEnv, - Optional<String> moduleVersion, - TurbineLog log) { + Optional<String> moduleVersion) { // Allow resolution of modules in the current compilation. Currently this is only needed for // version strings in requires directives. moduleEnv = @@ -337,9 +288,7 @@ public class Binder { }); ImmutableList.Builder<SourceModuleInfo> bound = ImmutableList.builder(); for (PackageSourceBoundModule module : modules.asMap().values()) { - bound.add( - ModuleBinder.bind( - module, env, moduleEnv, moduleVersion, log.withSource(module.source()))); + bound.add(ModuleBinder.bind(module, env, moduleEnv, moduleVersion)); } return bound.build(); } @@ -347,8 +296,7 @@ public class Binder { private static Env<ClassSymbol, SourceTypeBoundClass> constants( ImmutableSet<ClassSymbol> syms, Env<ClassSymbol, SourceTypeBoundClass> env, - CompoundEnv<ClassSymbol, TypeBoundClass> baseEnv, - TurbineLog log) { + CompoundEnv<ClassSymbol, TypeBoundClass> baseEnv) { // Prepare to lazily evaluate constant fields in each compilation unit. // The laziness is necessary since constant fields can reference other @@ -374,8 +322,7 @@ public class Binder { info.source(), info.scope(), env1, - baseEnv, - log.withSource(info.source())) + baseEnv) .evalFieldInitializer(field.decl().init().get(), field.type()); } catch (LazyEnv.LazyBindingError e) { // fields initializers are allowed to reference the field being initialized, @@ -395,9 +342,7 @@ public class Binder { SimpleEnv.Builder<ClassSymbol, SourceTypeBoundClass> builder = SimpleEnv.builder(); for (ClassSymbol sym : syms) { - SourceTypeBoundClass base = env.get(sym); - builder.put( - sym, new ConstBinder(constenv, sym, baseEnv, base, log.withSource(base.source())).bind()); + builder.put(sym, new ConstBinder(constenv, sym, baseEnv, env.get(sym)).bind()); } return builder.build(); } @@ -442,57 +387,19 @@ public class Binder { return builder.build(); } - /** Statistics about annotation processing. */ - @AutoValue - public abstract static class Statistics { - - /** - * The total elapsed time spent in {@link Processor#init} and {@link Processor#process} across - * all rounds for each annotation processor. - */ - public abstract ImmutableMap<String, Duration> processingTime(); - - /** - * Serialized protos containing processor-specific metrics. Currently only supported for Dagger. - */ - public abstract ImmutableMap<String, byte[]> processorMetrics(); - - public static Statistics create( - ImmutableMap<String, Duration> processingTime, - ImmutableMap<String, byte[]> processorMetrics) { - return new AutoValue_Binder_Statistics(processingTime, processorMetrics); - } - - public static Statistics empty() { - return create(ImmutableMap.of(), ImmutableMap.of()); - } - } - /** The result of binding: bound nodes for sources in the compilation, and the classpath. */ public static class BindingResult { private final ImmutableMap<ClassSymbol, SourceTypeBoundClass> units; private final ImmutableList<SourceModuleInfo> modules; private final CompoundEnv<ClassSymbol, BytecodeBoundClass> classPathEnv; - private final TopLevelIndex tli; - private final ImmutableMap<String, SourceFile> generatedSources; - private final ImmutableMap<String, byte[]> generatedClasses; - private final Statistics statistics; public BindingResult( ImmutableMap<ClassSymbol, SourceTypeBoundClass> units, ImmutableList<SourceModuleInfo> modules, - CompoundEnv<ClassSymbol, BytecodeBoundClass> classPathEnv, - TopLevelIndex tli, - ImmutableMap<String, SourceFile> generatedSources, - ImmutableMap<String, byte[]> generatedClasses, - Statistics statistics) { + CompoundEnv<ClassSymbol, BytecodeBoundClass> classPathEnv) { this.units = units; this.modules = modules; this.classPathEnv = classPathEnv; - this.tli = tli; - this.generatedSources = generatedSources; - this.generatedClasses = generatedClasses; - this.statistics = statistics; } /** Bound nodes for sources in the compilation. */ @@ -508,36 +415,5 @@ public class Binder { public CompoundEnv<ClassSymbol, BytecodeBoundClass> classPathEnv() { return classPathEnv; } - - public TopLevelIndex tli() { - return tli; - } - - public ImmutableMap<String, SourceFile> generatedSources() { - return generatedSources; - } - - public ImmutableMap<String, byte[]> generatedClasses() { - return generatedClasses; - } - - public Statistics statistics() { - return statistics; - } - - public BindingResult withGeneratedClasses(ImmutableMap<String, byte[]> generatedClasses) { - return new BindingResult( - units, modules, classPathEnv, tli, generatedSources, generatedClasses, statistics); - } - - public BindingResult withGeneratedSources(ImmutableMap<String, SourceFile> generatedSources) { - return new BindingResult( - units, modules, classPathEnv, tli, generatedSources, generatedClasses, statistics); - } - - public BindingResult withStatistics(Statistics statistics) { - return new BindingResult( - units, modules, classPathEnv, tli, generatedSources, generatedClasses, statistics); - } } } diff --git a/java/com/google/turbine/binder/CanonicalTypeBinder.java b/java/com/google/turbine/binder/CanonicalTypeBinder.java index a2f045a..934ec54 100644 --- a/java/com/google/turbine/binder/CanonicalTypeBinder.java +++ b/java/com/google/turbine/binder/CanonicalTypeBinder.java @@ -147,8 +147,8 @@ public class CanonicalTypeBinder { ClassSymbol sym, ParamInfo base) { return new ParamInfo( - base.sym(), Canonicalize.canonicalize(source, position, env, sym, base.type()), + base.name(), base.annotations(), base.access()); } @@ -162,9 +162,8 @@ public class CanonicalTypeBinder { ImmutableMap.Builder<TyVarSymbol, TyVarInfo> result = ImmutableMap.builder(); for (Map.Entry<TyVarSymbol, TyVarInfo> e : tps.entrySet()) { TyVarInfo info = e.getValue(); - IntersectionTy upperBound = - (IntersectionTy) Canonicalize.canonicalize(source, position, env, sym, info.upperBound()); - result.put(e.getKey(), new TyVarInfo(upperBound, /* lowerBound= */ null, info.annotations())); + Type bound = Canonicalize.canonicalize(source, position, env, sym, info.bound()); + result.put(e.getKey(), new TyVarInfo((IntersectionTy) bound, info.annotations())); } return result.build(); } diff --git a/java/com/google/turbine/binder/ClassPath.java b/java/com/google/turbine/binder/ClassPath.java index eeea7c5..d3461bf 100644 --- a/java/com/google/turbine/binder/ClassPath.java +++ b/java/com/google/turbine/binder/ClassPath.java @@ -16,7 +16,6 @@ package com.google.turbine.binder; -import com.google.common.base.Supplier; import com.google.turbine.binder.bound.ModuleInfo; import com.google.turbine.binder.bytecode.BytecodeBoundClass; import com.google.turbine.binder.env.Env; @@ -25,7 +24,7 @@ import com.google.turbine.binder.sym.ClassSymbol; import com.google.turbine.binder.sym.ModuleSymbol; /** - * A compilation classpath, e.g. the user or platform class path. May be backed by a search path of + * A compilation classpath, e.g. the user or platform class path. Maybe backed by a search path of * jar files, or a jrtfs filesystem. */ public interface ClassPath { @@ -37,6 +36,4 @@ public interface ClassPath { /** The classpath's top level index. */ TopLevelIndex index(); - - Supplier<byte[]> resource(String path); } diff --git a/java/com/google/turbine/binder/ClassPathBinder.java b/java/com/google/turbine/binder/ClassPathBinder.java index 8aead80..5d8db86 100644 --- a/java/com/google/turbine/binder/ClassPathBinder.java +++ b/java/com/google/turbine/binder/ClassPathBinder.java @@ -53,7 +53,6 @@ public class ClassPathBinder { Map<ClassSymbol, BytecodeBoundClass> transitive = new LinkedHashMap<>(); Map<ClassSymbol, BytecodeBoundClass> map = new HashMap<>(); Map<ModuleSymbol, ModuleInfo> modules = new HashMap<>(); - Map<String, Supplier<byte[]>> resources = new HashMap<>(); Env<ClassSymbol, BytecodeBoundClass> benv = new Env<ClassSymbol, BytecodeBoundClass>() { @Override @@ -63,7 +62,7 @@ public class ClassPathBinder { }; for (Path path : paths) { try { - bindJar(path, map, modules, benv, transitive, resources); + bindJar(path, map, modules, benv, transitive); } catch (IOException e) { throw new IOException("error reading " + path, e); } @@ -90,11 +89,6 @@ public class ClassPathBinder { public TopLevelIndex index() { return index; } - - @Override - public Supplier<byte[]> resource(String path) { - return resources.get(path); - } }; } @@ -103,14 +97,12 @@ public class ClassPathBinder { Map<ClassSymbol, BytecodeBoundClass> env, Map<ModuleSymbol, ModuleInfo> modules, Env<ClassSymbol, BytecodeBoundClass> benv, - Map<ClassSymbol, BytecodeBoundClass> transitive, - Map<String, Supplier<byte[]>> resources) + Map<ClassSymbol, BytecodeBoundClass> transitive) throws IOException { // TODO(cushon): don't leak file descriptors for (Zip.Entry ze : new Zip.ZipIterable(path)) { String name = ze.name(); if (!name.endsWith(".class")) { - resources.put(name, toByteArrayOrDie(ze)); continue; } if (name.startsWith(TRANSITIVE_PREFIX)) { diff --git a/java/com/google/turbine/binder/CompUnitPreprocessor.java b/java/com/google/turbine/binder/CompUnitPreprocessor.java index ed70e88..85ff1c0 100644 --- a/java/com/google/turbine/binder/CompUnitPreprocessor.java +++ b/java/com/google/turbine/binder/CompUnitPreprocessor.java @@ -219,7 +219,6 @@ public class CompUnitPreprocessor { Optional.empty(), ImmutableList.of(), ImmutableList.of(), - TurbineTyKind.INTERFACE, - /* javadoc= */ null); + TurbineTyKind.INTERFACE); } } diff --git a/java/com/google/turbine/binder/ConstBinder.java b/java/com/google/turbine/binder/ConstBinder.java index 3a41e94..0f989dd 100644 --- a/java/com/google/turbine/binder/ConstBinder.java +++ b/java/com/google/turbine/binder/ConstBinder.java @@ -33,7 +33,6 @@ import com.google.turbine.binder.env.Env; import com.google.turbine.binder.sym.ClassSymbol; import com.google.turbine.binder.sym.FieldSymbol; import com.google.turbine.binder.sym.TyVarSymbol; -import com.google.turbine.diag.TurbineLog.TurbineLogWithSource; import com.google.turbine.model.Const; import com.google.turbine.model.Const.ArrayInitValue; import com.google.turbine.model.Const.Kind; @@ -64,29 +63,19 @@ public class ConstBinder { private final SourceTypeBoundClass base; private final CompoundEnv<ClassSymbol, TypeBoundClass> env; private final ConstEvaluator constEvaluator; - private final TurbineLogWithSource log; public ConstBinder( Env<FieldSymbol, Value> constantEnv, ClassSymbol origin, CompoundEnv<ClassSymbol, TypeBoundClass> env, - SourceTypeBoundClass base, - TurbineLogWithSource log) { + SourceTypeBoundClass base) { this.constantEnv = constantEnv; this.origin = origin; this.base = base; this.env = env; - this.log = log; this.constEvaluator = new ConstEvaluator( - origin, - origin, - base.memberImports(), - base.source(), - base.scope(), - constantEnv, - env, - log); + origin, origin, base.memberImports(), base.source(), base.scope(), constantEnv, env); } public SourceTypeBoundClass bind() { @@ -98,8 +87,7 @@ public class ConstBinder { base.source(), base.enclosingScope(), constantEnv, - env, - log) + env) .evaluateAnnotations(base.annotations()); ImmutableList<TypeBoundClass.FieldInfo> fields = fields(base.fields()); ImmutableList<MethodInfo> methods = bindMethods(base.methods()); @@ -161,7 +149,7 @@ public class ConstBinder { private ParamInfo bindParameter(ParamInfo base) { ImmutableList<AnnoInfo> annos = constEvaluator.evaluateAnnotations(base.annotations()); - return new ParamInfo(base.sym(), bindType(base.type()), annos, base.access()); + return new ParamInfo(bindType(base.type()), base.name(), annos, base.access()); } static AnnotationMetadata bindAnnotationMetadata( @@ -173,11 +161,7 @@ public class ConstBinder { ImmutableSet<TurbineElementType> target = null; ClassSymbol repeatable = null; for (AnnoInfo annotation : annotations) { - ClassSymbol sym = annotation.sym(); - if (sym == null) { - continue; - } - switch (sym.binaryName()) { + switch (annotation.sym().binaryName()) { case "java/lang/annotation/Retention": retention = bindRetention(annotation); break; @@ -302,8 +286,7 @@ public class ConstBinder { result.put( entry.getKey(), new TyVarInfo( - (IntersectionTy) bindType(info.upperBound()), - /* lowerBound= */ null, + (IntersectionTy) bindType(info.bound()), constEvaluator.evaluateAnnotations(info.annotations()))); } return result.build(); @@ -335,12 +318,12 @@ public class ConstBinder { return WildLowerBoundedTy.create( bindType(wildTy.bound()), constEvaluator.evaluateAnnotations(wildTy.annotations())); + default: + throw new AssertionError(wildTy.boundKind()); } - throw new AssertionError(wildTy.boundKind()); } case PRIM_TY: case VOID_TY: - case ERROR_TY: return type; case INTERSECTION_TY: return IntersectionTy.create(bindTypes(((IntersectionTy) type).bounds())); diff --git a/java/com/google/turbine/binder/ConstEvaluator.java b/java/com/google/turbine/binder/ConstEvaluator.java index 9d5f042..0e837a4 100644 --- a/java/com/google/turbine/binder/ConstEvaluator.java +++ b/java/com/google/turbine/binder/ConstEvaluator.java @@ -22,8 +22,8 @@ import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; +import com.google.turbine.binder.bound.AnnotationValue; import com.google.turbine.binder.bound.EnumConstantValue; -import com.google.turbine.binder.bound.TurbineAnnotationValue; import com.google.turbine.binder.bound.TurbineClassValue; import com.google.turbine.binder.bound.TypeBoundClass; import com.google.turbine.binder.bound.TypeBoundClass.FieldInfo; @@ -38,10 +38,8 @@ import com.google.turbine.binder.sym.ClassSymbol; import com.google.turbine.binder.sym.FieldSymbol; import com.google.turbine.binder.sym.Symbol; import com.google.turbine.diag.SourceFile; -import com.google.turbine.diag.TurbineDiagnostic; import com.google.turbine.diag.TurbineError; import com.google.turbine.diag.TurbineError.ErrorKind; -import com.google.turbine.diag.TurbineLog.TurbineLogWithSource; import com.google.turbine.model.Const; import com.google.turbine.model.Const.ConstCastError; import com.google.turbine.model.Const.Value; @@ -93,17 +91,14 @@ public strictfp class ConstEvaluator { private final Scope scope; - private final TurbineLogWithSource log; - public ConstEvaluator( ClassSymbol origin, ClassSymbol owner, MemberImportIndex memberImports, SourceFile source, Scope scope, - Env<FieldSymbol, Value> values, - CompoundEnv<ClassSymbol, TypeBoundClass> env, - TurbineLogWithSource log) { + Env<FieldSymbol, Const.Value> values, + CompoundEnv<ClassSymbol, TypeBoundClass> env) { this.origin = origin; this.owner = owner; @@ -112,7 +107,6 @@ public strictfp class ConstEvaluator { this.values = values; this.env = env; this.scope = scope; - this.log = log; } /** Evaluates the given expression's value. */ @@ -145,8 +139,9 @@ public strictfp class ConstEvaluator { case SHORT: case BYTE: case NULL: + default: + throw new AssertionError(a.constantTypeKind()); } - throw new AssertionError(a.constantTypeKind()); } case VOID_TY: throw new AssertionError(t.kind()); @@ -167,7 +162,7 @@ public strictfp class ConstEvaluator { case ANNO_EXPR: return evalAnno(((Tree.AnnoExpr) t).value()); default: - throw error(t.position(), ErrorKind.EXPRESSION_ERROR); + throw new AssertionError(t.kind()); } } @@ -183,7 +178,7 @@ public strictfp class ConstEvaluator { case VOID_TY: return Type.VOID; case CLASS_TY: - return resolveClass((ClassTy) type); + return Type.ClassTy.asNonParametricClassTy(resolveClass((ClassTy) type)); case ARR_TY: return Type.ArrayTy.create( evalClassLiteralType(((Tree.ArrTy) type).elem()), ImmutableList.of()); @@ -196,20 +191,19 @@ public strictfp class ConstEvaluator { * Resolves the {@link ClassSymbol} for the given {@link Tree.ClassTy}, with handling for * non-canonical qualified type names. * - * <p>Similar to {@code HierarchyBinder#resolveClass}, except we can't unconditionally consider + * <p>Similar to {@link HierarchyBinder#resolveClass}, except we can't unconditionally consider * members of the current class (e.g. when binding constants inside annotations on that class), * and when we do want to consider members we can rely on them being in the current scope (it * isn't completed during the hierarchy phase). */ - private Type resolveClass(ClassTy classTy) { + private ClassSymbol resolveClass(ClassTy classTy) { ArrayDeque<Ident> flat = new ArrayDeque<>(); for (ClassTy curr = classTy; curr != null; curr = curr.base().orElse(null)) { flat.addFirst(curr.name()); } LookupResult result = scope.lookup(new LookupKey(ImmutableList.copyOf(flat))); if (result == null) { - log.error(classTy.position(), ErrorKind.CANNOT_RESOLVE, flat.peekFirst()); - return Type.ErrorTy.create(flat); + throw error(classTy.position(), ErrorKind.CANNOT_RESOLVE, flat.peekFirst()); } if (result.sym().symKind() != Symbol.Kind.CLASS) { throw error(classTy.position(), ErrorKind.UNEXPECTED_TYPE_PARAMETER, flat.peekFirst()); @@ -218,7 +212,7 @@ public strictfp class ConstEvaluator { for (Ident bit : result.remaining()) { classSym = resolveNext(classTy.position(), classSym, bit); } - return Type.ClassTy.asNonParametricClassTy(classSym); + return classSym; } private ClassSymbol resolveNext(int position, ClassSymbol sym, Ident bit) { @@ -378,41 +372,41 @@ public strictfp class ConstEvaluator { } switch (t.op()) { case NOT: - return unaryNegate(t.position(), expr); + return unaryNegate(expr); case BITWISE_COMP: - return bitwiseComp(t.position(), expr); + return bitwiseComp(expr); case UNARY_PLUS: - return unaryPlus(t.position(), expr); + return unaryPlus(expr); case NEG: - return unaryMinus(t.position(), expr); + return unaryMinus(expr); default: throw new AssertionError(t.op()); } } - private Value unaryNegate(int position, Value expr) { + private Value unaryNegate(Value expr) { switch (expr.constantTypeKind()) { case BOOLEAN: return new Const.BooleanValue(!expr.asBoolean().value()); default: - throw error(position, ErrorKind.OPERAND_TYPE, expr.constantTypeKind()); + throw new AssertionError(expr.constantTypeKind()); } } - private Value bitwiseComp(int position, Value expr) { - expr = promoteUnary(position, expr); + private Value bitwiseComp(Value expr) { + expr = promoteUnary(expr); switch (expr.constantTypeKind()) { case INT: return new Const.IntValue(~expr.asInteger().value()); case LONG: return new Const.LongValue(~expr.asLong().value()); default: - throw error(position, ErrorKind.OPERAND_TYPE, expr.constantTypeKind()); + throw new AssertionError(expr.constantTypeKind()); } } - private Value unaryPlus(int position, Value expr) { - expr = promoteUnary(position, expr); + private Value unaryPlus(Value expr) { + expr = promoteUnary(expr); switch (expr.constantTypeKind()) { case INT: return new Const.IntValue(+expr.asInteger().value()); @@ -423,12 +417,12 @@ public strictfp class ConstEvaluator { case DOUBLE: return new Const.DoubleValue(+expr.asDouble().value()); default: - throw error(position, ErrorKind.OPERAND_TYPE, expr.constantTypeKind()); + throw new AssertionError(expr.constantTypeKind()); } } - private Value unaryMinus(int position, Value expr) { - expr = promoteUnary(position, expr); + private Value unaryMinus(Value expr) { + expr = promoteUnary(expr); switch (expr.constantTypeKind()) { case INT: return new Const.IntValue(-expr.asInteger().value()); @@ -439,7 +433,7 @@ public strictfp class ConstEvaluator { case DOUBLE: return new Const.DoubleValue(-expr.asDouble().value()); default: - throw error(position, ErrorKind.OPERAND_TYPE, expr.constantTypeKind()); + throw new AssertionError(expr.constantTypeKind()); } } @@ -466,12 +460,12 @@ public strictfp class ConstEvaluator { } } - private Const.Value add(int position, Const.Value a, Const.Value b) { + static Const.Value add(Const.Value a, Const.Value b) { if (a.constantTypeKind() == TurbineConstantTypeKind.STRING || b.constantTypeKind() == TurbineConstantTypeKind.STRING) { return new Const.StringValue(a.asString().value() + b.asString().value()); } - TurbineConstantTypeKind type = promoteBinary(position, a, b); + TurbineConstantTypeKind type = promoteBinary(a, b); a = coerce(a, type); b = coerce(b, type); switch (type) { @@ -484,12 +478,12 @@ public strictfp class ConstEvaluator { case DOUBLE: return new Const.DoubleValue(a.asDouble().value() + b.asDouble().value()); default: - throw error(position, ErrorKind.OPERAND_TYPE, type); + throw new AssertionError(type); } } - private Const.Value subtract(int position, Const.Value a, Const.Value b) { - TurbineConstantTypeKind type = promoteBinary(position, a, b); + static Const.Value subtract(Const.Value a, Const.Value b) { + TurbineConstantTypeKind type = promoteBinary(a, b); a = coerce(a, type); b = coerce(b, type); switch (type) { @@ -502,12 +496,12 @@ public strictfp class ConstEvaluator { case DOUBLE: return new Const.DoubleValue(a.asDouble().value() - b.asDouble().value()); default: - throw error(position, ErrorKind.OPERAND_TYPE, type); + throw new AssertionError(type); } } - private Const.Value mult(int position, Const.Value a, Const.Value b) { - TurbineConstantTypeKind type = promoteBinary(position, a, b); + static Const.Value mult(Const.Value a, Const.Value b) { + TurbineConstantTypeKind type = promoteBinary(a, b); a = coerce(a, type); b = coerce(b, type); switch (type) { @@ -520,12 +514,12 @@ public strictfp class ConstEvaluator { case DOUBLE: return new Const.DoubleValue(a.asDouble().value() * b.asDouble().value()); default: - throw error(position, ErrorKind.OPERAND_TYPE, type); + throw new AssertionError(type); } } - private Const.Value divide(int position, Const.Value a, Const.Value b) { - TurbineConstantTypeKind type = promoteBinary(position, a, b); + static Const.Value divide(Const.Value a, Const.Value b) { + TurbineConstantTypeKind type = promoteBinary(a, b); a = coerce(a, type); b = coerce(b, type); switch (type) { @@ -538,12 +532,12 @@ public strictfp class ConstEvaluator { case DOUBLE: return new Const.DoubleValue(a.asDouble().value() / b.asDouble().value()); default: - throw error(position, ErrorKind.OPERAND_TYPE, type); + throw new AssertionError(type); } } - private Const.Value mod(int position, Const.Value a, Const.Value b) { - TurbineConstantTypeKind type = promoteBinary(position, a, b); + static Const.Value mod(Const.Value a, Const.Value b) { + TurbineConstantTypeKind type = promoteBinary(a, b); a = coerce(a, type); b = coerce(b, type); switch (type) { @@ -556,17 +550,17 @@ public strictfp class ConstEvaluator { case DOUBLE: return new Const.DoubleValue(a.asDouble().value() % b.asDouble().value()); default: - throw error(position, ErrorKind.OPERAND_TYPE, type); + throw new AssertionError(type); } } - private static final int INT_SHIFT_MASK = 0b11111; + static final int INT_SHIFT_MASK = 0b11111; - private static final int LONG_SHIFT_MASK = 0b111111; + static final int LONG_SHIFT_MASK = 0b111111; - private Const.Value shiftLeft(int position, Const.Value a, Const.Value b) { - a = promoteUnary(position, a); - b = promoteUnary(position, b); + static Const.Value shiftLeft(Const.Value a, Const.Value b) { + a = promoteUnary(a); + b = promoteUnary(b); switch (a.constantTypeKind()) { case INT: return new Const.IntValue( @@ -574,13 +568,13 @@ public strictfp class ConstEvaluator { case LONG: return new Const.LongValue(a.asLong().value() << (b.asInteger().value() & LONG_SHIFT_MASK)); default: - throw error(position, ErrorKind.OPERAND_TYPE, a.constantTypeKind()); + throw new AssertionError(a.constantTypeKind()); } } - private Const.Value shiftRight(int position, Const.Value a, Const.Value b) { - a = promoteUnary(position, a); - b = promoteUnary(position, b); + static Const.Value shiftRight(Const.Value a, Const.Value b) { + a = promoteUnary(a); + b = promoteUnary(b); switch (a.constantTypeKind()) { case INT: return new Const.IntValue( @@ -588,13 +582,13 @@ public strictfp class ConstEvaluator { case LONG: return new Const.LongValue(a.asLong().value() >> (b.asInteger().value() & LONG_SHIFT_MASK)); default: - throw error(position, ErrorKind.OPERAND_TYPE, a.constantTypeKind()); + throw new AssertionError(a.constantTypeKind()); } } - private Const.Value unsignedShiftRight(int position, Const.Value a, Const.Value b) { - a = promoteUnary(position, a); - b = promoteUnary(position, b); + static Const.Value unsignedShiftRight(Const.Value a, Const.Value b) { + a = promoteUnary(a); + b = promoteUnary(b); switch (a.constantTypeKind()) { case INT: return new Const.IntValue( @@ -603,12 +597,12 @@ public strictfp class ConstEvaluator { return new Const.LongValue( a.asLong().value() >>> (b.asInteger().value() & LONG_SHIFT_MASK)); default: - throw error(position, ErrorKind.OPERAND_TYPE, a.constantTypeKind()); + throw new AssertionError(a.constantTypeKind()); } } - private Const.Value lessThan(int position, Const.Value a, Const.Value b) { - TurbineConstantTypeKind type = promoteBinary(position, a, b); + static Const.Value lessThan(Const.Value a, Const.Value b) { + TurbineConstantTypeKind type = promoteBinary(a, b); a = coerce(a, type); b = coerce(b, type); switch (type) { @@ -621,12 +615,12 @@ public strictfp class ConstEvaluator { case DOUBLE: return new Const.BooleanValue(a.asDouble().value() < b.asDouble().value()); default: - throw error(position, ErrorKind.OPERAND_TYPE, type); + throw new AssertionError(type); } } - private Const.Value lessThanEqual(int position, Const.Value a, Const.Value b) { - TurbineConstantTypeKind type = promoteBinary(position, a, b); + static Const.Value lessThanEqual(Const.Value a, Const.Value b) { + TurbineConstantTypeKind type = promoteBinary(a, b); a = coerce(a, type); b = coerce(b, type); switch (type) { @@ -639,12 +633,12 @@ public strictfp class ConstEvaluator { case DOUBLE: return new Const.BooleanValue(a.asDouble().value() <= b.asDouble().value()); default: - throw error(position, ErrorKind.OPERAND_TYPE, type); + throw new AssertionError(type); } } - private Const.Value greaterThan(int position, Const.Value a, Const.Value b) { - TurbineConstantTypeKind type = promoteBinary(position, a, b); + static Const.Value greaterThan(Const.Value a, Const.Value b) { + TurbineConstantTypeKind type = promoteBinary(a, b); a = coerce(a, type); b = coerce(b, type); switch (type) { @@ -657,12 +651,12 @@ public strictfp class ConstEvaluator { case DOUBLE: return new Const.BooleanValue(a.asDouble().value() > b.asDouble().value()); default: - throw error(position, ErrorKind.OPERAND_TYPE, type); + throw new AssertionError(type); } } - private Const.Value greaterThanEqual(int position, Const.Value a, Const.Value b) { - TurbineConstantTypeKind type = promoteBinary(position, a, b); + static Const.Value greaterThanEqual(Const.Value a, Const.Value b) { + TurbineConstantTypeKind type = promoteBinary(a, b); a = coerce(a, type); b = coerce(b, type); switch (type) { @@ -675,11 +669,11 @@ public strictfp class ConstEvaluator { case DOUBLE: return new Const.BooleanValue(a.asDouble().value() >= b.asDouble().value()); default: - throw error(position, ErrorKind.OPERAND_TYPE, type); + throw new AssertionError(type); } } - private Const.Value equal(int position, Const.Value a, Const.Value b) { + static Const.Value equal(Const.Value a, Const.Value b) { switch (a.constantTypeKind()) { case STRING: return new Const.BooleanValue(a.asString().value().equals(b.asString().value())); @@ -688,7 +682,7 @@ public strictfp class ConstEvaluator { default: break; } - TurbineConstantTypeKind type = promoteBinary(position, a, b); + TurbineConstantTypeKind type = promoteBinary(a, b); a = coerce(a, type); b = coerce(b, type); switch (type) { @@ -701,11 +695,11 @@ public strictfp class ConstEvaluator { case DOUBLE: return new Const.BooleanValue(a.asDouble().value() == b.asDouble().value()); default: - throw error(position, ErrorKind.OPERAND_TYPE, type); + throw new AssertionError(type); } } - private Const.Value notEqual(int position, Const.Value a, Const.Value b) { + static Const.Value notEqual(Const.Value a, Const.Value b) { switch (a.constantTypeKind()) { case STRING: return new Const.BooleanValue(!a.asString().value().equals(b.asString().value())); @@ -714,7 +708,7 @@ public strictfp class ConstEvaluator { default: break; } - TurbineConstantTypeKind type = promoteBinary(position, a, b); + TurbineConstantTypeKind type = promoteBinary(a, b); a = coerce(a, type); b = coerce(b, type); switch (type) { @@ -727,18 +721,18 @@ public strictfp class ConstEvaluator { case DOUBLE: return new Const.BooleanValue(a.asDouble().value() != b.asDouble().value()); default: - throw error(position, ErrorKind.OPERAND_TYPE, type); + throw new AssertionError(type); } } - private Const.Value bitwiseAnd(int position, Const.Value a, Const.Value b) { + static Const.Value bitwiseAnd(Const.Value a, Const.Value b) { switch (a.constantTypeKind()) { case BOOLEAN: return new Const.BooleanValue(a.asBoolean().value() & b.asBoolean().value()); default: break; } - TurbineConstantTypeKind type = promoteBinary(position, a, b); + TurbineConstantTypeKind type = promoteBinary(a, b); a = coerce(a, type); b = coerce(b, type); switch (type) { @@ -747,18 +741,18 @@ public strictfp class ConstEvaluator { case LONG: return new Const.LongValue(a.asLong().value() & b.asLong().value()); default: - throw error(position, ErrorKind.OPERAND_TYPE, type); + throw new AssertionError(type); } } - private Const.Value bitwiseOr(int position, Const.Value a, Const.Value b) { + static Const.Value bitwiseOr(Const.Value a, Const.Value b) { switch (a.constantTypeKind()) { case BOOLEAN: return new Const.BooleanValue(a.asBoolean().value() | b.asBoolean().value()); default: break; } - TurbineConstantTypeKind type = promoteBinary(position, a, b); + TurbineConstantTypeKind type = promoteBinary(a, b); a = coerce(a, type); b = coerce(b, type); switch (type) { @@ -767,18 +761,18 @@ public strictfp class ConstEvaluator { case LONG: return new Const.LongValue(a.asLong().value() | b.asLong().value()); default: - throw error(position, ErrorKind.OPERAND_TYPE, type); + throw new AssertionError(type); } } - private Const.Value bitwiseXor(int position, Const.Value a, Const.Value b) { + static Const.Value bitwiseXor(Const.Value a, Const.Value b) { switch (a.constantTypeKind()) { case BOOLEAN: return new Const.BooleanValue(a.asBoolean().value() ^ b.asBoolean().value()); default: break; } - TurbineConstantTypeKind type = promoteBinary(position, a, b); + TurbineConstantTypeKind type = promoteBinary(a, b); a = coerce(a, type); b = coerce(b, type); switch (type) { @@ -787,7 +781,7 @@ public strictfp class ConstEvaluator { case LONG: return new Const.LongValue(a.asLong().value() ^ b.asLong().value()); default: - throw error(position, ErrorKind.OPERAND_TYPE, type); + throw new AssertionError(type); } } @@ -799,49 +793,49 @@ public strictfp class ConstEvaluator { } switch (t.op()) { case PLUS: - return add(t.position(), lhs, rhs); + return add(lhs, rhs); case MINUS: - return subtract(t.position(), lhs, rhs); + return subtract(lhs, rhs); case MULT: - return mult(t.position(), lhs, rhs); + return mult(lhs, rhs); case DIVIDE: - return divide(t.position(), lhs, rhs); + return divide(lhs, rhs); case MODULO: - return mod(t.position(), lhs, rhs); + return mod(lhs, rhs); case SHIFT_LEFT: - return shiftLeft(t.position(), lhs, rhs); + return shiftLeft(lhs, rhs); case SHIFT_RIGHT: - return shiftRight(t.position(), lhs, rhs); + return shiftRight(lhs, rhs); case UNSIGNED_SHIFT_RIGHT: - return unsignedShiftRight(t.position(), lhs, rhs); + return unsignedShiftRight(lhs, rhs); case LESS_THAN: - return lessThan(t.position(), lhs, rhs); + return lessThan(lhs, rhs); case GREATER_THAN: - return greaterThan(t.position(), lhs, rhs); + return greaterThan(lhs, rhs); case LESS_THAN_EQ: - return lessThanEqual(t.position(), lhs, rhs); + return lessThanEqual(lhs, rhs); case GREATER_THAN_EQ: - return greaterThanEqual(t.position(), lhs, rhs); + return greaterThanEqual(lhs, rhs); case EQUAL: - return equal(t.position(), lhs, rhs); + return equal(lhs, rhs); case NOT_EQUAL: - return notEqual(t.position(), lhs, rhs); + return notEqual(lhs, rhs); case AND: return new Const.BooleanValue(lhs.asBoolean().value() && rhs.asBoolean().value()); case OR: return new Const.BooleanValue(lhs.asBoolean().value() || rhs.asBoolean().value()); case BITWISE_AND: - return bitwiseAnd(t.position(), lhs, rhs); + return bitwiseAnd(lhs, rhs); case BITWISE_XOR: - return bitwiseXor(t.position(), lhs, rhs); + return bitwiseXor(lhs, rhs); case BITWISE_OR: - return bitwiseOr(t.position(), lhs, rhs); + return bitwiseOr(lhs, rhs); default: throw new AssertionError(t.op()); } } - private Const.Value promoteUnary(int position, Value v) { + private static Const.Value promoteUnary(Const.Value v) { switch (v.constantTypeKind()) { case CHAR: case SHORT: @@ -853,13 +847,13 @@ public strictfp class ConstEvaluator { case DOUBLE: return v; default: - throw error(position, ErrorKind.OPERAND_TYPE, v.constantTypeKind()); + throw new AssertionError(v.constantTypeKind()); } } - private TurbineConstantTypeKind promoteBinary(int position, Const.Value a, Const.Value b) { - a = promoteUnary(position, a); - b = promoteUnary(position, b); + private static TurbineConstantTypeKind promoteBinary(Const.Value a, Const.Value b) { + a = promoteUnary(a); + b = promoteUnary(b); switch (a.constantTypeKind()) { case INT: switch (b.constantTypeKind()) { @@ -869,7 +863,7 @@ public strictfp class ConstEvaluator { case FLOAT: return b.constantTypeKind(); default: - throw error(position, ErrorKind.OPERAND_TYPE, b.constantTypeKind()); + throw new AssertionError(b.constantTypeKind()); } case LONG: switch (b.constantTypeKind()) { @@ -880,7 +874,7 @@ public strictfp class ConstEvaluator { case FLOAT: return b.constantTypeKind(); default: - throw error(position, ErrorKind.OPERAND_TYPE, b.constantTypeKind()); + throw new AssertionError(b.constantTypeKind()); } case FLOAT: switch (b.constantTypeKind()) { @@ -891,7 +885,7 @@ public strictfp class ConstEvaluator { case DOUBLE: return TurbineConstantTypeKind.DOUBLE; default: - throw error(position, ErrorKind.OPERAND_TYPE, b.constantTypeKind()); + throw new AssertionError(b.constantTypeKind()); } case DOUBLE: switch (b.constantTypeKind()) { @@ -901,10 +895,10 @@ public strictfp class ConstEvaluator { case DOUBLE: return TurbineConstantTypeKind.DOUBLE; default: - throw error(position, ErrorKind.OPERAND_TYPE, b.constantTypeKind()); + throw new AssertionError(b.constantTypeKind()); } default: - throw error(position, ErrorKind.OPERAND_TYPE, a.constantTypeKind()); + throw new AssertionError(a.constantTypeKind()); } } @@ -921,17 +915,9 @@ public strictfp class ConstEvaluator { * expression trees. */ AnnoInfo evaluateAnnotation(AnnoInfo info) { - // bail if annotation has not been resolved - if (info.sym() == null) { - return info; - } - Map<String, Type> template = new LinkedHashMap<>(); - TypeBoundClass annoClass = env.get(info.sym()); - if (annoClass != null) { - for (MethodInfo method : annoClass.methods()) { - template.put(method.name(), method.returnType()); - } + for (MethodInfo method : env.get(info.sym()).methods()) { + template.put(method.name(), method.returnType()); } Map<String, Const> values = new LinkedHashMap<>(); @@ -966,7 +952,7 @@ public strictfp class ConstEvaluator { return info.withValues(ImmutableMap.copyOf(values)); } - private TurbineAnnotationValue evalAnno(Tree.Anno t) { + private AnnotationValue evalAnno(Tree.Anno t) { LookupResult result = scope.lookup(new LookupKey(t.name())); if (result == null) { throw error( @@ -982,8 +968,8 @@ public strictfp class ConstEvaluator { if (sym == null) { return null; } - AnnoInfo annoInfo = evaluateAnnotation(new AnnoInfo(source, sym, t, ImmutableMap.of())); - return new TurbineAnnotationValue(annoInfo); + AnnoInfo annoInfo = evaluateAnnotation(new AnnoInfo(source, sym, t, null)); + return new AnnotationValue(annoInfo.sym(), annoInfo.values()); } private Const.ArrayInitValue evalArrayInit(ArrayInit t) { @@ -1008,9 +994,6 @@ public strictfp class ConstEvaluator { } switch (ty.tyKind()) { case PRIM_TY: - if (!(value instanceof Const.Value)) { - throw error(tree.position(), ErrorKind.EXPRESSION_ERROR); - } return coerce((Const.Value) value, ((Type.PrimTy) ty).primkind()); case CLASS_TY: case TY_VAR: @@ -1044,17 +1027,7 @@ public strictfp class ConstEvaluator { return null; } return (Const.Value) cast(type, value); - } catch (TurbineError error) { - for (TurbineDiagnostic diagnostic : error.diagnostics()) { - switch (diagnostic.kind()) { - case CANNOT_RESOLVE: - // assume this wasn't a constant - return null; - default: // fall out - } - } - throw error; - } catch (ConstCastError error) { + } catch (TurbineError | ConstCastError error) { return null; } } diff --git a/java/com/google/turbine/binder/CtSymClassBinder.java b/java/com/google/turbine/binder/CtSymClassBinder.java index a6f1b3d..84fa966 100644 --- a/java/com/google/turbine/binder/CtSymClassBinder.java +++ b/java/com/google/turbine/binder/CtSymClassBinder.java @@ -105,11 +105,6 @@ public class CtSymClassBinder { public TopLevelIndex index() { return index; } - - @Override - public Supplier<byte[]> resource(String input) { - return null; - } }; } diff --git a/java/com/google/turbine/binder/DisambiguateTypeAnnotations.java b/java/com/google/turbine/binder/DisambiguateTypeAnnotations.java index 7e3fbda..9ad20d2 100644 --- a/java/com/google/turbine/binder/DisambiguateTypeAnnotations.java +++ b/java/com/google/turbine/binder/DisambiguateTypeAnnotations.java @@ -18,14 +18,13 @@ package com.google.turbine.binder; import static com.google.common.collect.Iterables.getOnlyElement; +import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableList.Builder; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; import com.google.common.collect.Multimap; -import com.google.common.collect.MultimapBuilder; -import com.google.turbine.binder.bound.AnnotationMetadata; +import com.google.turbine.binder.bound.AnnotationValue; import com.google.turbine.binder.bound.SourceTypeBoundClass; -import com.google.turbine.binder.bound.TurbineAnnotationValue; import com.google.turbine.binder.bound.TypeBoundClass; import com.google.turbine.binder.bound.TypeBoundClass.FieldInfo; import com.google.turbine.binder.bound.TypeBoundClass.MethodInfo; @@ -45,6 +44,7 @@ import com.google.turbine.type.Type.PrimTy; import com.google.turbine.type.Type.TyVar; import java.util.Collection; import java.util.Map; +import java.util.Set; /** * Disambiguate annotations on field, parameter, and method return types that could be declaration @@ -139,7 +139,7 @@ public class DisambiguateTypeAnnotations { base.type(), base.annotations(), declarationAnnotations); - return new ParamInfo(base.sym(), type, declarationAnnotations.build(), base.access()); + return new ParamInfo(type, base.name(), declarationAnnotations.build(), base.access()); } /** @@ -151,13 +151,13 @@ public class DisambiguateTypeAnnotations { TurbineElementType declarationTarget, Type type, ImmutableList<AnnoInfo> annotations, - ImmutableList.Builder<AnnoInfo> declarationAnnotations) { + Builder<AnnoInfo> declarationAnnotations) { // desugar @Repeatable annotations before disambiguating: annotation containers may target // a subset of the types targeted by their element annotation annotations = groupRepeated(env, annotations); ImmutableList.Builder<AnnoInfo> typeAnnotations = ImmutableList.builder(); for (AnnoInfo anno : annotations) { - ImmutableSet<TurbineElementType> target = getTarget(env, anno); + Set<TurbineElementType> target = env.get(anno.sym()).annotationMetadata().target(); if (target.contains(TurbineElementType.TYPE_USE)) { typeAnnotations.add(anno); } @@ -168,23 +168,6 @@ public class DisambiguateTypeAnnotations { return addAnnotationsToType(type, typeAnnotations.build()); } - private static ImmutableSet<TurbineElementType> getTarget( - Env<ClassSymbol, TypeBoundClass> env, AnnoInfo anno) { - ClassSymbol sym = anno.sym(); - if (sym == null) { - return AnnotationMetadata.DEFAULT_TARGETS; - } - TypeBoundClass info = env.get(sym); - if (info == null) { - return AnnotationMetadata.DEFAULT_TARGETS; - } - AnnotationMetadata metadata = info.annotationMetadata(); - if (metadata == null) { - return AnnotationMetadata.DEFAULT_TARGETS; - } - return metadata.target(); - } - private static ImmutableList<FieldInfo> bindFields( Env<ClassSymbol, TypeBoundClass> env, ImmutableList<FieldInfo> fields) { ImmutableList.Builder<FieldInfo> result = ImmutableList.builder(); @@ -235,7 +218,6 @@ public class DisambiguateTypeAnnotations { TyVar tyVar = (TyVar) type; return Type.TyVar.create(tyVar.sym(), appendAnnotations(tyVar.annos(), extra)); case VOID_TY: - case ERROR_TY: return type; case WILD_TY: throw new AssertionError("unexpected wildcard type outside type argument context"); @@ -260,33 +242,21 @@ public class DisambiguateTypeAnnotations { */ public static ImmutableList<AnnoInfo> groupRepeated( Env<ClassSymbol, TypeBoundClass> env, ImmutableList<AnnoInfo> annotations) { - Multimap<ClassSymbol, AnnoInfo> repeated = - MultimapBuilder.linkedHashKeys().arrayListValues().build(); - ImmutableList.Builder<AnnoInfo> result = ImmutableList.builder(); + Multimap<ClassSymbol, AnnoInfo> repeated = ArrayListMultimap.create(); for (AnnoInfo anno : annotations) { - if (anno.sym() == null) { - result.add(anno); - continue; - } repeated.put(anno.sym(), anno); } + Builder<AnnoInfo> result = ImmutableList.builder(); for (Map.Entry<ClassSymbol, Collection<AnnoInfo>> entry : repeated.asMap().entrySet()) { ClassSymbol symbol = entry.getKey(); Collection<AnnoInfo> infos = entry.getValue(); if (infos.size() > 1) { - ImmutableList.Builder<Const> elements = ImmutableList.builder(); + Builder<Const> elements = ImmutableList.builder(); for (AnnoInfo element : infos) { - elements.add(new TurbineAnnotationValue(element)); + elements.add(new AnnotationValue(element.sym(), element.values())); } - TypeBoundClass info = env.get(symbol); - if (info == null || info.annotationMetadata() == null) { - continue; - } - ClassSymbol container = info.annotationMetadata().repeatable(); + ClassSymbol container = env.get(symbol).annotationMetadata().repeatable(); if (container == null) { - if (isKotlinRepeatable(info)) { - continue; - } AnnoInfo anno = infos.iterator().next(); throw TurbineError.format( anno.source(), anno.position(), ErrorKind.NONREPEATABLE_ANNOTATION, symbol); @@ -303,18 +273,4 @@ public class DisambiguateTypeAnnotations { } return result.build(); } - - // Work-around for https://youtrack.jetbrains.net/issue/KT-34189. - // Kotlin stubs include repeated annotations that are valid in Kotlin (i.e. meta-annotated with - // @kotlin.annotation.Repeatable), even though they are invalid Java. - // TODO(b/142002426): kill this with fire - static boolean isKotlinRepeatable(TypeBoundClass info) { - for (AnnoInfo metaAnno : info.annotations()) { - if (metaAnno.sym() != null - && metaAnno.sym().binaryName().equals("kotlin/annotation/Repeatable")) { - return true; - } - } - return false; - } } diff --git a/java/com/google/turbine/binder/HierarchyBinder.java b/java/com/google/turbine/binder/HierarchyBinder.java index 07d255c..8549d3a 100644 --- a/java/com/google/turbine/binder/HierarchyBinder.java +++ b/java/com/google/turbine/binder/HierarchyBinder.java @@ -16,7 +16,6 @@ package com.google.turbine.binder; -import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.turbine.binder.bound.HeaderBoundClass; @@ -69,9 +68,6 @@ public class HierarchyBinder { ClassSymbol superclass; if (decl.xtnds().isPresent()) { superclass = resolveClass(decl.xtnds().get()); - if (origin.equals(superclass)) { - log.error(decl.xtnds().get().position(), ErrorKind.CYCLIC_HIERARCHY, origin); - } } else { switch (decl.tykind()) { case ENUM: @@ -94,9 +90,6 @@ public class HierarchyBinder { if (result == null) { continue; } - if (origin.equals(result)) { - log.error(i.position(), ErrorKind.CYCLIC_HIERARCHY, origin); - } interfaces.add(result); } } else { @@ -127,7 +120,7 @@ public class HierarchyBinder { // Resolve the base symbol in the qualified name. LookupResult result = lookup(ty, new LookupKey(ImmutableList.copyOf(flat))); if (result == null) { - log.error(ty.position(), ErrorKind.CANNOT_RESOLVE, Joiner.on('.').join(flat)); + log.error(ty.position(), ErrorKind.CANNOT_RESOLVE, ty); return null; } // Resolve pieces in the qualified name referring to member types. diff --git a/java/com/google/turbine/binder/JimageClassBinder.java b/java/com/google/turbine/binder/JimageClassBinder.java index d11dda1..e3d0865 100644 --- a/java/com/google/turbine/binder/JimageClassBinder.java +++ b/java/com/google/turbine/binder/JimageClassBinder.java @@ -33,7 +33,6 @@ import com.google.turbine.binder.bytecode.BytecodeBoundClass; import com.google.turbine.binder.env.Env; import com.google.turbine.binder.lookup.LookupKey; import com.google.turbine.binder.lookup.LookupResult; -import com.google.turbine.binder.lookup.PackageScope; import com.google.turbine.binder.lookup.Scope; import com.google.turbine.binder.lookup.TopLevelIndex; import com.google.turbine.binder.sym.ClassSymbol; @@ -151,7 +150,7 @@ public class JimageClassBinder { String binaryName = modulePath.relativize(path).toString(); binaryName = binaryName.substring(0, binaryName.length() - ".class".length()); ClassSymbol sym = new ClassSymbol(binaryName); - packageClassesBySimpleName.put(packageName, sym.simpleName(), sym); + packageClassesBySimpleName.put(packageName, simpleName(sym), sym); JimageClassBinder.this.env.put( sym, new BytecodeBoundClass(sym, toByteArrayOrDie(path), env, path.toString())); } @@ -177,6 +176,16 @@ public class JimageClassBinder { }); } + private static String simpleName(ClassSymbol sym) { + int idx = sym.binaryName().lastIndexOf('/'); + return idx != -1 ? sym.binaryName().substring(idx + 1) : sym.binaryName(); + } + + private static String packageName(ClassSymbol sym) { + int idx = sym.binaryName().lastIndexOf('/'); + return idx != -1 ? sym.binaryName().substring(0, idx) : ""; + } + private class JimageTopLevelIndex implements TopLevelIndex { final Scope topLevelScope = @@ -213,23 +222,18 @@ public class JimageClassBinder { } @Override - public PackageScope lookupPackage(Iterable<String> name) { + public Scope lookupPackage(ImmutableList<String> name) { String packageName = Joiner.on('/').join(name); if (!initPackage(packageName)) { return null; } - return new PackageScope() { + return new Scope() { @Nullable @Override public LookupResult lookup(LookupKey lookupKey) { ClassSymbol sym = packageClassesBySimpleName.get(packageName, lookupKey.first().value()); return sym != null ? new LookupResult(sym, lookupKey) : null; } - - @Override - public Iterable<ClassSymbol> classes() { - return packageClassesBySimpleName.row(packageName).values(); - } }; } } @@ -243,7 +247,7 @@ public class JimageClassBinder { return new Env<ClassSymbol, BytecodeBoundClass>() { @Override public BytecodeBoundClass get(ClassSymbol sym) { - return initPackage(sym.packageName()) ? env.get(sym) : null; + return initPackage(packageName(sym)) ? env.get(sym) : null; } }; } @@ -262,10 +266,5 @@ public class JimageClassBinder { public TopLevelIndex index() { return index; } - - @Override - public Supplier<byte[]> resource(String input) { - return null; - } } } diff --git a/java/com/google/turbine/binder/ModuleBinder.java b/java/com/google/turbine/binder/ModuleBinder.java index 748ff39..afd8770 100644 --- a/java/com/google/turbine/binder/ModuleBinder.java +++ b/java/com/google/turbine/binder/ModuleBinder.java @@ -40,7 +40,6 @@ import com.google.turbine.binder.sym.ClassSymbol; import com.google.turbine.binder.sym.ModuleSymbol; import com.google.turbine.diag.TurbineError; import com.google.turbine.diag.TurbineError.ErrorKind; -import com.google.turbine.diag.TurbineLog.TurbineLogWithSource; import com.google.turbine.model.TurbineFlag; import com.google.turbine.tree.Tree; import com.google.turbine.tree.Tree.Ident; @@ -61,9 +60,8 @@ public class ModuleBinder { PackageSourceBoundModule module, CompoundEnv<ClassSymbol, TypeBoundClass> env, Env<ModuleSymbol, ModuleInfo> moduleEnv, - Optional<String> moduleVersion, - TurbineLogWithSource log) { - return new ModuleBinder(module, env, moduleEnv, moduleVersion, log).bind(); + Optional<String> moduleVersion) { + return new ModuleBinder(module, env, moduleEnv, moduleVersion).bind(); } private final PackageSourceBoundModule module; @@ -71,19 +69,16 @@ public class ModuleBinder { private final Env<ModuleSymbol, ModuleInfo> moduleEnv; private final Optional<String> moduleVersion; private final CompoundScope scope; - private final TurbineLogWithSource log; public ModuleBinder( PackageSourceBoundModule module, CompoundEnv<ClassSymbol, TypeBoundClass> env, Env<ModuleSymbol, ModuleInfo> moduleEnv, - Optional<String> moduleVersion, - TurbineLogWithSource log) { + Optional<String> moduleVersion) { this.module = module; this.env = env; this.moduleEnv = moduleEnv; this.moduleVersion = moduleVersion; - this.log = log; this.scope = module.scope().toScope(Resolve.resolveFunction(env, /* origin= */ null)); } @@ -97,12 +92,11 @@ public class ModuleBinder { module.source(), scope, /* values= */ new SimpleEnv<>(ImmutableMap.of()), - env, - log); + env); ImmutableList.Builder<AnnoInfo> annoInfos = ImmutableList.builder(); for (Tree.Anno annoTree : module.module().annos()) { ClassSymbol sym = resolve(annoTree.position(), annoTree.name()); - annoInfos.add(new AnnoInfo(module.source(), sym, annoTree, ImmutableMap.of())); + annoInfos.add(new AnnoInfo(module.source(), sym, annoTree, null)); } ImmutableList<AnnoInfo> annos = constEvaluator.evaluateAnnotations(annoInfos.build()); @@ -136,6 +130,8 @@ public class ModuleBinder { case PROVIDES: provides.add(bindProvides((ModProvides) directive)); break; + default: + throw new AssertionError(directive.kind()); } } if (!requiresJavaBase) { @@ -185,11 +181,11 @@ public class ModuleBinder { return new RequireInfo(moduleName, flags, requires != null ? requires.version() : null); } - private static ExportInfo bindExports(ModExports directive) { + private ExportInfo bindExports(ModExports directive) { return new ExportInfo(directive.packageName(), directive.moduleNames()); } - private static OpenInfo bindOpens(ModOpens directive) { + private OpenInfo bindOpens(ModOpens directive) { return new OpenInfo(directive.packageName(), directive.moduleNames()); } diff --git a/java/com/google/turbine/binder/Processing.java b/java/com/google/turbine/binder/Processing.java deleted file mode 100644 index ecdf195..0000000 --- a/java/com/google/turbine/binder/Processing.java +++ /dev/null @@ -1,556 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.binder; - -import com.google.auto.value.AutoValue; -import com.google.common.base.Function; -import com.google.common.base.Joiner; -import com.google.common.base.Stopwatch; -import com.google.common.base.Supplier; -import com.google.common.base.Throwables; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.ImmutableSetMultimap; -import com.google.common.collect.Sets; -import com.google.turbine.binder.Binder.BindingResult; -import com.google.turbine.binder.Binder.Statistics; -import com.google.turbine.binder.bound.SourceTypeBoundClass; -import com.google.turbine.binder.bound.TypeBoundClass; -import com.google.turbine.binder.bound.TypeBoundClass.FieldInfo; -import com.google.turbine.binder.env.CompoundEnv; -import com.google.turbine.binder.env.Env; -import com.google.turbine.binder.env.SimpleEnv; -import com.google.turbine.binder.sym.ClassSymbol; -import com.google.turbine.binder.sym.Symbol; -import com.google.turbine.diag.SourceFile; -import com.google.turbine.diag.TurbineLog; -import com.google.turbine.parse.Parser; -import com.google.turbine.processing.ModelFactory; -import com.google.turbine.processing.TurbineElements; -import com.google.turbine.processing.TurbineFiler; -import com.google.turbine.processing.TurbineMessager; -import com.google.turbine.processing.TurbineProcessingEnvironment; -import com.google.turbine.processing.TurbineRoundEnvironment; -import com.google.turbine.processing.TurbineTypes; -import com.google.turbine.tree.Tree.CompUnit; -import com.google.turbine.type.AnnoInfo; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLClassLoader; -import java.nio.file.Paths; -import java.time.Duration; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.regex.Pattern; -import javax.annotation.processing.Processor; -import javax.lang.model.SourceVersion; -import javax.lang.model.element.TypeElement; -import javax.tools.Diagnostic; -import org.checkerframework.checker.nullness.qual.Nullable; - -/** Top level annotation processing logic, see also {@link Binder}. */ -public class Processing { - - static BindingResult process( - TurbineLog log, - final ImmutableList<CompUnit> initialSources, - final ClassPath classpath, - ProcessorInfo processorInfo, - ClassPath bootclasspath, - BindingResult result, - Optional<String> moduleVersion) { - - Set<String> seen = new HashSet<>(); - for (CompUnit u : initialSources) { - if (u.source() != null) { - seen.add(u.source().path()); - } - } - - TurbineFiler filer = - new TurbineFiler( - seen, - new Function<String, Supplier<byte[]>>() { - @Nullable - @Override - public Supplier<byte[]> apply(@Nullable String input) { - // TODO(cushon): should annotation processors be allowed to generate code with - // dependencies between source and bytecode, or vice versa? - // Currently generated classes are not available on the classpath when compiling - // the compilation sources (including generated sources). - return classpath.resource(input); - } - }, - processorInfo.loader()); - - Env<ClassSymbol, SourceTypeBoundClass> tenv = new SimpleEnv<>(result.units()); - CompoundEnv<ClassSymbol, TypeBoundClass> env = - CompoundEnv.<ClassSymbol, TypeBoundClass>of(result.classPathEnv()).append(tenv); - ModelFactory factory = new ModelFactory(env, processorInfo.loader(), result.tli()); - - Map<String, byte[]> statistics = new LinkedHashMap<>(); - - TurbineTypes turbineTypes = new TurbineTypes(factory); - TurbineProcessingEnvironment processingEnv = - new TurbineProcessingEnvironment( - filer, - turbineTypes, - new TurbineElements(factory, turbineTypes), - new TurbineMessager(factory, log), - processorInfo.options(), - processorInfo.sourceVersion(), - processorInfo.loader(), - statistics); - Timers timers = new Timers(); - for (Processor processor : processorInfo.processors()) { - try (Timers.Timer unused = timers.start(processor)) { - processor.init(processingEnv); - } catch (Throwable t) { - reportProcessorCrash(log, processor, t); - } - } - - Map<Processor, Pattern> wanted = new HashMap<>(); - for (Processor processor : processorInfo.processors()) { - List<String> patterns = new ArrayList<>(); - for (String supportedAnnotationType : processor.getSupportedAnnotationTypes()) { - // TODO(b/139026291): this handling of getSupportedAnnotationTypes isn't correct - patterns.add(supportedAnnotationType.replace("*", ".*")); - } - wanted.put(processor, Pattern.compile(Joiner.on('|').join(patterns))); - } - - Set<ClassSymbol> allSymbols = new HashSet<>(); - - ImmutableList.Builder<CompUnit> units = - ImmutableList.<CompUnit>builder().addAll(initialSources); - - Set<Processor> toRun = new LinkedHashSet<>(); - - boolean errorRaised = false; - - while (true) { - ImmutableSet<ClassSymbol> syms = - Sets.difference(result.units().keySet(), allSymbols).immutableCopy(); - allSymbols.addAll(syms); - if (syms.isEmpty()) { - break; - } - ImmutableSetMultimap<ClassSymbol, Symbol> allAnnotations = getAllAnnotations(env, syms); - TurbineRoundEnvironment roundEnv = null; - for (Processor processor : processorInfo.processors()) { - Set<TypeElement> annotations = new HashSet<>(); - Pattern pattern = wanted.get(processor); - boolean run = toRun.contains(processor); - for (ClassSymbol a : allAnnotations.keys()) { - if (pattern.matcher(a.toString()).matches()) { - annotations.add(factory.typeElement(a)); - run = true; - } - } - if (run) { - toRun.add(processor); - if (roundEnv == null) { - roundEnv = - new TurbineRoundEnvironment(factory, syms, false, errorRaised, allAnnotations); - } - try (Timers.Timer unused = timers.start(processor)) { - // discard the result of Processor#process because 'claiming' annotations is a bad idea - // TODO(cushon): consider disallowing this, or reporting a diagnostic - processor.process(annotations, roundEnv); - } catch (Throwable t) { - reportProcessorCrash(log, processor, t); - } - } - } - Collection<SourceFile> files = filer.finishRound(); - if (files.isEmpty()) { - break; - } - for (SourceFile file : files) { - units.add(Parser.parse(file)); - } - errorRaised = log.errorRaised(); - if (errorRaised) { - log.maybeThrow(); - } - log.clear(); - result = - Binder.bind( - log, - units.build(), - filer.generatedSources(), - filer.generatedClasses(), - classpath, - bootclasspath, - moduleVersion); - tenv = new SimpleEnv<>(result.units()); - env = CompoundEnv.<ClassSymbol, TypeBoundClass>of(result.classPathEnv()).append(tenv); - factory.round(env, result.tli()); - } - - TurbineRoundEnvironment roundEnv = null; - for (Processor processor : toRun) { - if (roundEnv == null) { - roundEnv = - new TurbineRoundEnvironment( - factory, - ImmutableSet.of(), - /* processingOver= */ true, - errorRaised, - ImmutableSetMultimap.of()); - } - try (Timers.Timer unused = timers.start(processor)) { - processor.process(ImmutableSet.of(), roundEnv); - } catch (Throwable t) { - reportProcessorCrash(log, processor, t); - } - } - - Collection<SourceFile> files = filer.finishRound(); - if (!files.isEmpty()) { - // processors aren't supposed to generate sources on the final processing round, but javac - // tolerates it anyway - // TODO(cushon): consider disallowing this, or reporting a diagnostic - for (SourceFile file : files) { - units.add(Parser.parse(file)); - } - result = - Binder.bind( - log, - units.build(), - filer.generatedSources(), - filer.generatedClasses(), - classpath, - bootclasspath, - moduleVersion); - log.maybeThrow(); - } - - if (!filer.generatedClasses().isEmpty()) { - // add any generated class files to the output - // TODO(cushon): consider handling generated classes after each round - result = result.withGeneratedClasses(filer.generatedClasses()); - } - if (!filer.generatedSources().isEmpty()) { - result = result.withGeneratedSources(filer.generatedSources()); - } - - result = - result.withStatistics(Statistics.create(timers.build(), ImmutableMap.copyOf(statistics))); - - return result; - } - - private static void reportProcessorCrash(TurbineLog log, Processor processor, Throwable t) { - log.diagnostic( - Diagnostic.Kind.ERROR, - String.format( - "An exception occurred in %s:\n%s", - processor.getClass().getCanonicalName(), Throwables.getStackTraceAsString(t))); - log.maybeThrow(); - } - - /** Returns a map from annotations present in the compilation to the annotated elements. */ - private static ImmutableSetMultimap<ClassSymbol, Symbol> getAllAnnotations( - Env<ClassSymbol, TypeBoundClass> env, Iterable<ClassSymbol> syms) { - ImmutableSetMultimap.Builder<ClassSymbol, Symbol> result = ImmutableSetMultimap.builder(); - for (ClassSymbol sym : syms) { - TypeBoundClass info = env.get(sym); - for (AnnoInfo annoInfo : info.annotations()) { - if (sym.simpleName().equals("package-info")) { - addAnno(result, annoInfo, sym.owner()); - } else { - addAnno(result, annoInfo, sym); - } - } - for (ClassSymbol inheritedAnno : - inheritedAnnotations(new HashSet<>(), info.superclass(), env)) { - result.put(inheritedAnno, sym); - } - for (TypeBoundClass.MethodInfo method : info.methods()) { - for (AnnoInfo annoInfo : method.annotations()) { - addAnno(result, annoInfo, method.sym()); - } - for (TypeBoundClass.ParamInfo param : method.parameters()) { - for (AnnoInfo annoInfo : param.annotations()) { - addAnno(result, annoInfo, param.sym()); - } - } - } - for (FieldInfo field : info.fields()) { - for (AnnoInfo annoInfo : field.annotations()) { - addAnno(result, annoInfo, field.sym()); - } - } - } - return result.build(); - } - - // TODO(cushon): consider memoizing this (or isAnnotationInherited) if they show up in profiles - private static Set<ClassSymbol> inheritedAnnotations( - Set<ClassSymbol> seen, ClassSymbol sym, Env<ClassSymbol, TypeBoundClass> env) { - ImmutableSet.Builder<ClassSymbol> result = ImmutableSet.builder(); - ClassSymbol curr = sym; - while (curr != null && seen.add(curr)) { - TypeBoundClass info = env.get(curr); - if (info == null) { - break; - } - for (AnnoInfo anno : info.annotations()) { - ClassSymbol annoSym = anno.sym(); - if (annoSym == null) { - continue; - } - if (isAnnotationInherited(env, annoSym)) { - result.add(annoSym); - } - } - curr = info.superclass(); - } - return result.build(); - } - - private static boolean isAnnotationInherited( - Env<ClassSymbol, TypeBoundClass> env, ClassSymbol sym) { - TypeBoundClass annoInfo = env.get(sym); - if (annoInfo == null) { - return false; - } - for (AnnoInfo anno : annoInfo.annotations()) { - if (Objects.equals(anno.sym(), ClassSymbol.INHERITED)) { - return true; - } - } - return false; - } - - private static void addAnno( - ImmutableSetMultimap.Builder<ClassSymbol, Symbol> result, AnnoInfo annoInfo, Symbol owner) { - ClassSymbol sym = annoInfo.sym(); - if (sym != null) { - result.put(sym, owner); - } - } - - public static ProcessorInfo initializeProcessors( - ImmutableList<String> javacopts, - ImmutableList<String> processorPath, - ImmutableSet<String> processorNames, - ImmutableSet<String> builtinProcessors) - throws MalformedURLException { - ClassLoader processorLoader = null; - ImmutableList.Builder<Processor> processors = ImmutableList.builder(); - ImmutableMap<String, String> processorOptions; - if (!processorNames.isEmpty() && !javacopts.contains("-proc:none")) { - if (!processorPath.isEmpty()) { - processorLoader = - new URLClassLoader( - toUrls(processorPath), - new ClassLoader(getPlatformClassLoader()) { - @Override - protected Class<?> findClass(String name) throws ClassNotFoundException { - if (name.startsWith("com.sun.source.") - || name.startsWith("com.sun.tools.") - || name.startsWith("com.google.common.collect.") - || name.startsWith("com.google.common.base.") - || name.startsWith("com.google.common.graph.") - || name.startsWith("com.google.devtools.build.buildjar.javac.statistics.") - || name.startsWith("dagger.model.") - || name.startsWith("dagger.spi.") - || name.equals("com.google.turbine.processing.TurbineProcessingEnvironment") - || builtinProcessors.contains(name)) { - return Class.forName(name); - } - throw new ClassNotFoundException(name); - } - }); - } else { - processorLoader = Processing.class.getClassLoader(); - } - for (String processor : processorNames) { - try { - Class<? extends Processor> clazz = - Class.forName(processor, false, processorLoader).asSubclass(Processor.class); - processors.add(clazz.getConstructor().newInstance()); - } catch (ReflectiveOperationException e) { - throw new LinkageError(e.getMessage(), e); - } - } - processorOptions = processorOptions(javacopts); - } else { - processorOptions = ImmutableMap.of(); - } - SourceVersion sourceVersion = SourceVersion.latestSupported(); - Iterator<String> it = javacopts.iterator(); - while (it.hasNext()) { - String option = it.next(); - switch (option) { - case "-target": - if (it.hasNext()) { - String value = it.next(); - switch (value) { - case "5": - case "1.5": - sourceVersion = SourceVersion.RELEASE_5; - break; - case "6": - case "1.6": - sourceVersion = SourceVersion.RELEASE_6; - break; - case "7": - case "1.7": - sourceVersion = SourceVersion.RELEASE_7; - break; - case "8": - sourceVersion = SourceVersion.RELEASE_8; - break; - default: - break; - } - } - break; - default: - break; - } - } - return ProcessorInfo.create( - processors.build(), processorLoader, processorOptions, sourceVersion); - } - - private static URL[] toUrls(ImmutableList<String> processorPath) throws MalformedURLException { - URL[] urls = new URL[processorPath.size()]; - int i = 0; - for (String path : processorPath) { - urls[i++] = Paths.get(path).toUri().toURL(); - } - return urls; - } - - public static ClassLoader getPlatformClassLoader() { - try { - return (ClassLoader) ClassLoader.class.getMethod("getPlatformClassLoader").invoke(null); - } catch (ReflectiveOperationException e) { - // In earlier releases, set 'null' as the parent to delegate to the boot class loader. - return null; - } - } - - private static ImmutableMap<String, String> processorOptions(ImmutableList<String> javacopts) { - Map<String, String> result = new LinkedHashMap<>(); // ImmutableMap.Builder rejects duplicates - for (String javacopt : javacopts) { - if (javacopt.startsWith("-A")) { - javacopt = javacopt.substring("-A".length()); - int idx = javacopt.indexOf('='); - String key; - String value; - if (idx != -1) { - key = javacopt.substring(0, idx); - value = javacopt.substring(idx + 1); - } else { - key = javacopt; - value = javacopt; - } - result.put(key, value); - } - } - return ImmutableMap.copyOf(result); - } - - /** Information about any annotation processing performed by this compilation. */ - @AutoValue - public abstract static class ProcessorInfo { - - abstract ImmutableList<Processor> processors(); - - /** - * The classloader to use for annotation processor implementations, and any annotations they - * access reflectively. - */ - @Nullable - abstract ClassLoader loader(); - - /** Command line annotation processing options, passed to javac with {@code -Akey=value}. */ - abstract ImmutableMap<String, String> options(); - - public abstract SourceVersion sourceVersion(); - - public static ProcessorInfo create( - ImmutableList<Processor> processors, - @Nullable ClassLoader loader, - ImmutableMap<String, String> options, - SourceVersion sourceVersion) { - return new AutoValue_Processing_ProcessorInfo(processors, loader, options, sourceVersion); - } - - static ProcessorInfo empty() { - return create( - /* processors= */ ImmutableList.of(), - /* loader= */ null, - /* options= */ ImmutableMap.of(), - /* sourceVersion= */ SourceVersion.latest()); - } - } - - private static class Timers { - private final Map<Class<?>, Stopwatch> processorTimers = new LinkedHashMap<>(); - - Timer start(Processor processor) { - Class<? extends Processor> clazz = processor.getClass(); - Stopwatch sw = processorTimers.get(clazz); - if (sw == null) { - sw = Stopwatch.createUnstarted(); - processorTimers.put(clazz, sw); - } - sw.start(); - return new Timer(sw); - } - - private static class Timer implements AutoCloseable { - - private final Stopwatch sw; - - public Timer(Stopwatch sw) { - this.sw = sw; - } - - @Override - public void close() { - sw.stop(); - } - } - - ImmutableMap<String, Duration> build() { - ImmutableMap.Builder<String, Duration> result = ImmutableMap.builder(); - for (Map.Entry<Class<?>, Stopwatch> e : processorTimers.entrySet()) { - result.put(e.getKey().getCanonicalName(), e.getValue().elapsed()); - } - return result.build(); - } - } -} diff --git a/java/com/google/turbine/binder/Resolve.java b/java/com/google/turbine/binder/Resolve.java index 28a8be3..0a61844 100644 --- a/java/com/google/turbine/binder/Resolve.java +++ b/java/com/google/turbine/binder/Resolve.java @@ -136,11 +136,12 @@ public class Resolve { return true; case PROTECTED: case PACKAGE: - return Objects.equals(sym.packageName(), packagename); + return Objects.equals(packageName(sym), packagename); case PRIVATE: return false; + default: + throw new AssertionError(visibility); } - throw new AssertionError(visibility); } } @@ -205,12 +206,24 @@ public class Resolve { case PROTECTED: return true; case PACKAGE: - return Objects.equals(owner.packageName(), origin.packageName()); + return Objects.equals(packageName(owner), packageName(origin)); case PRIVATE: // Private members of lexically enclosing declarations are not handled, // since this visibility check is only used for inherited members. return owner.equals(origin); + default: + throw new AssertionError(visibility); } - throw new AssertionError(visibility); + } + + private static String packageName(ClassSymbol sym) { + if (sym == null) { + return null; + } + int idx = sym.binaryName().lastIndexOf('/'); + if (idx == -1) { + return null; + } + return sym.binaryName().substring(0, idx); } } diff --git a/java/com/google/turbine/binder/TypeBinder.java b/java/com/google/turbine/binder/TypeBinder.java index 7b01856..8cf71e1 100644 --- a/java/com/google/turbine/binder/TypeBinder.java +++ b/java/com/google/turbine/binder/TypeBinder.java @@ -34,7 +34,6 @@ import com.google.turbine.binder.lookup.Scope; import com.google.turbine.binder.sym.ClassSymbol; import com.google.turbine.binder.sym.FieldSymbol; import com.google.turbine.binder.sym.MethodSymbol; -import com.google.turbine.binder.sym.ParamSymbol; import com.google.turbine.binder.sym.Symbol; import com.google.turbine.binder.sym.TyVarSymbol; import com.google.turbine.diag.TurbineError.ErrorKind; @@ -267,23 +266,22 @@ public class TypeBinder { if (hasConstructor()) { return ImmutableList.of(); } - MethodSymbol symbol = new MethodSymbol(-1, owner, "<init>"); ImmutableList<ParamInfo> formals; if (hasEnclosingInstance(base)) { - formals = ImmutableList.of(enclosingInstanceParameter(symbol)); + formals = ImmutableList.of(enclosingInstanceParameter()); } else { formals = ImmutableList.of(); } return ImmutableList.of( - syntheticConstructor(symbol, formals, TurbineVisibility.fromAccess(base.access()))); + syntheticConstructor(formals, TurbineVisibility.fromAccess(base.access()))); } private MethodInfo syntheticConstructor( - MethodSymbol symbol, ImmutableList<ParamInfo> formals, TurbineVisibility visibility) { + ImmutableList<ParamInfo> formals, TurbineVisibility visibility) { int access = visibility.flag(); access |= (base.access() & TurbineFlag.ACC_STRICT); return new MethodInfo( - symbol, + new MethodSymbol(owner, "<init>"), ImmutableMap.of(), Type.VOID, formals, @@ -295,7 +293,7 @@ public class TypeBinder { null); } - private ParamInfo enclosingInstanceParameter(MethodSymbol owner) { + private ParamInfo enclosingInstanceParameter() { int access = TurbineFlag.ACC_FINAL; if ((base.access() & TurbineFlag.ACC_PRIVATE) == TurbineFlag.ACC_PRIVATE) { access |= TurbineFlag.ACC_SYNTHETIC; @@ -313,40 +311,37 @@ public class TypeBinder { sym = info.owner(); } return new ParamInfo( - new ParamSymbol(owner, "this$" + enclosingInstances), Type.ClassTy.asNonParametricClassTy(base.owner()), + "this$" + enclosingInstances, ImmutableList.of(), access); } - private static ImmutableList<ParamInfo> enumCtorParams(MethodSymbol owner) { - return ImmutableList.of( - new ParamInfo( - new ParamSymbol(owner, "$enum$name"), - Type.ClassTy.STRING, - ImmutableList.of(), - /*synthetic*/ - TurbineFlag.ACC_SYNTHETIC), - new ParamInfo( - new ParamSymbol(owner, "$enum$ordinal"), - Type.PrimTy.create(TurbineConstantTypeKind.INT, ImmutableList.of()), - ImmutableList.of(), - /*synthetic*/ - TurbineFlag.ACC_SYNTHETIC)); - } + private static final ImmutableList<ParamInfo> ENUM_CTOR_PARAMS = + ImmutableList.of( + new ParamInfo( + Type.ClassTy.STRING, + "$enum$name", + ImmutableList.of(), + /*synthetic*/ + TurbineFlag.ACC_SYNTHETIC), + new ParamInfo( + Type.PrimTy.create(TurbineConstantTypeKind.INT, ImmutableList.of()), + "$enum$ordinal", + ImmutableList.of(), + /*synthetic*/ + TurbineFlag.ACC_SYNTHETIC)); private ImmutableList<MethodInfo> syntheticEnumMethods() { ImmutableList.Builder<MethodInfo> methods = ImmutableList.builder(); int access = 0; access |= (base.access() & TurbineFlag.ACC_STRICT); if (!hasConstructor()) { - MethodSymbol symbol = new MethodSymbol(-1, owner, "<init>"); - methods.add(syntheticConstructor(symbol, enumCtorParams(symbol), TurbineVisibility.PRIVATE)); + methods.add(syntheticConstructor(ENUM_CTOR_PARAMS, TurbineVisibility.PRIVATE)); } - MethodSymbol valuesMethod = new MethodSymbol(-2, owner, "values"); methods.add( new MethodInfo( - valuesMethod, + new MethodSymbol(owner, "values"), ImmutableMap.of(), Type.ArrayTy.create(Type.ClassTy.asNonParametricClassTy(owner), ImmutableList.of()), ImmutableList.of(), @@ -356,18 +351,14 @@ public class TypeBinder { null, ImmutableList.of(), null)); - MethodSymbol valueOfMethod = new MethodSymbol(-3, owner, "valueOf"); methods.add( new MethodInfo( - valueOfMethod, + new MethodSymbol(owner, "valueOf"), ImmutableMap.of(), Type.ClassTy.asNonParametricClassTy(owner), ImmutableList.of( new ParamInfo( - new ParamSymbol(valueOfMethod, "name"), - Type.ClassTy.STRING, - ImmutableList.of(), - TurbineFlag.ACC_MANDATED)), + Type.ClassTy.STRING, "name", ImmutableList.of(), TurbineFlag.ACC_MANDATED)), ImmutableList.of(), access | TurbineFlag.ACC_PUBLIC | TurbineFlag.ACC_STATIC, null, @@ -396,38 +387,38 @@ public class TypeBinder { for (Tree.TyParam tree : trees) { TyVarSymbol sym = symbols.get(tree.name().value()); ImmutableList.Builder<Type> bounds = ImmutableList.builder(); - for (Tree bound : tree.bounds()) { - bounds.add(bindTy(scope, bound)); + if (tree.bounds().isEmpty()) { + bounds.add(Type.ClassTy.OBJECT); + } else { + for (Tree bound : tree.bounds()) { + bounds.add(bindTy(scope, bound)); + } } ImmutableList<AnnoInfo> annotations = bindAnnotations(scope, tree.annos()); - result.put( - sym, - new TyVarInfo( - IntersectionTy.create(bounds.build()), /* lowerBound= */ null, annotations)); + result.put(sym, new TyVarInfo(IntersectionTy.create(bounds.build()), annotations)); } return result.build(); } private List<MethodInfo> bindMethods(CompoundScope scope, ImmutableList<Tree> members) { List<MethodInfo> methods = new ArrayList<>(); - int idx = 0; for (Tree member : members) { if (member.kind() == Tree.Kind.METH_DECL) { - methods.add(bindMethod(idx++, scope, (Tree.MethDecl) member)); + methods.add(bindMethod(scope, (Tree.MethDecl) member)); } } return methods; } - private MethodInfo bindMethod(int idx, CompoundScope scope, Tree.MethDecl t) { + private MethodInfo bindMethod(CompoundScope scope, Tree.MethDecl t) { - MethodSymbol sym = new MethodSymbol(idx, owner, t.name().value()); + MethodSymbol sym = new MethodSymbol(owner, t.name().value()); ImmutableMap<String, TyVarSymbol> typeParameters; { ImmutableMap.Builder<String, TyVarSymbol> builder = ImmutableMap.builder(); for (Tree.TyParam pt : t.typarams()) { - builder.put(pt.name().value(), new TyVarSymbol(sym, pt.name().value())); + builder.put(pt.name().value(), new TyVarSymbol(owner, pt.name().value())); } typeParameters = builder.build(); } @@ -448,9 +439,9 @@ public class TypeBinder { String name = t.name().value(); if (name.equals("<init>")) { if (hasEnclosingInstance(base)) { - parameters.add(enclosingInstanceParameter(sym)); + parameters.add(enclosingInstanceParameter()); } else if (base.kind() == TurbineTyKind.ENUM && name.equals("<init>")) { - parameters.addAll(enumCtorParams(sym)); + parameters.addAll(ENUM_CTOR_PARAMS); } } ParamInfo receiver = null; @@ -461,8 +452,8 @@ public class TypeBinder { } ParamInfo param = new ParamInfo( - new ParamSymbol(sym, p.name().value()), bindTy(scope, p.ty()), + p.name().value(), bindAnnotations(scope, p.annos()), /*synthetic*/ access); if (p.name().value().equals("this")) { @@ -570,7 +561,7 @@ public class TypeBinder { ImmutableList<Ident> name = tree.name(); LookupResult lookupResult = scope.lookup(new LookupKey(name)); ClassSymbol sym = resolveAnnoSymbol(tree, name, lookupResult); - result.add(new AnnoInfo(base.source(), sym, tree, ImmutableMap.of())); + result.add(new AnnoInfo(base.source(), sym, tree, null)); } return result.build(); } @@ -657,7 +648,7 @@ public class TypeBinder { LookupResult result = scope.lookup(new LookupKey(names)); if (result == null || result.sym() == null) { log.error(names.get(0).position(), ErrorKind.CANNOT_RESOLVE, Joiner.on('.').join(names)); - return Type.ErrorTy.create(names); + return Type.ErrorTy.create(); } Symbol sym = result.sym(); int annoIdx = flat.size() - result.remaining().size() - 1; @@ -669,7 +660,7 @@ public class TypeBinder { case TY_PARAM: if (!result.remaining().isEmpty()) { log.error(t.position(), ErrorKind.TYPE_PARAMETER_QUALIFIER); - return Type.ErrorTy.create(names); + return Type.ErrorTy.create(); } return Type.TyVar.create((TyVarSymbol) sym, annos); default: @@ -693,7 +684,7 @@ public class TypeBinder { Tree.ClassTy curr = flat.get(idx); sym = resolveNext(sym, curr.name()); if (sym == null) { - return Type.ErrorTy.create(bits); + return Type.ErrorTy.create(); } annotations = bindAnnotations(scope, curr.annos()); diff --git a/java/com/google/turbine/binder/bound/AnnotationMetadata.java b/java/com/google/turbine/binder/bound/AnnotationMetadata.java index 31860b6..9c81a5f 100644 --- a/java/com/google/turbine/binder/bound/AnnotationMetadata.java +++ b/java/com/google/turbine/binder/bound/AnnotationMetadata.java @@ -30,7 +30,7 @@ import java.util.EnumSet; */ public class AnnotationMetadata { - public static final ImmutableSet<TurbineElementType> DEFAULT_TARGETS = getDefaultElements(); + private static final ImmutableSet<TurbineElementType> DEFAULT_TARGETS = getDefaultElements(); private static ImmutableSet<TurbineElementType> getDefaultElements() { EnumSet<TurbineElementType> values = EnumSet.allOf(TurbineElementType.class); diff --git a/java/com/google/turbine/binder/bound/TurbineAnnotationValue.java b/java/com/google/turbine/binder/bound/AnnotationValue.java index 808d603..fd4ffab 100644 --- a/java/com/google/turbine/binder/bound/TurbineAnnotationValue.java +++ b/java/com/google/turbine/binder/bound/AnnotationValue.java @@ -19,20 +19,22 @@ package com.google.turbine.binder.bound; import com.google.common.collect.ImmutableMap; import com.google.turbine.binder.sym.ClassSymbol; import com.google.turbine.model.Const; -import com.google.turbine.type.AnnoInfo; +import java.util.Objects; /** An annotation literal constant. */ -public class TurbineAnnotationValue extends Const { +public class AnnotationValue extends Const { - private final AnnoInfo info; + private final ClassSymbol sym; + private final ImmutableMap<String, Const> values; - public TurbineAnnotationValue(AnnoInfo info) { - this.info = info; + public AnnotationValue(ClassSymbol sym, ImmutableMap<String, Const> values) { + this.sym = sym; + this.values = values; } @Override public String toString() { - return info.toString(); + return String.format("@%s", sym); } @Override @@ -42,26 +44,25 @@ public class TurbineAnnotationValue extends Const { /** The annotation declaration. */ public ClassSymbol sym() { - return info.sym(); + return sym; } /** The annotation literal's element-value pairs. */ public ImmutableMap<String, Const> values() { - return info.values(); + return values; } @Override public int hashCode() { - return info.hashCode(); + return Objects.hash(sym, values); } @Override public boolean equals(Object obj) { - return obj instanceof TurbineAnnotationValue - && info().equals(((TurbineAnnotationValue) obj).info()); - } - - public AnnoInfo info() { - return info; + if (!(obj instanceof AnnotationValue)) { + return false; + } + AnnotationValue that = (AnnotationValue) obj; + return sym().equals(that.sym()) && values().equals(that.values()); } } diff --git a/java/com/google/turbine/binder/bound/EnumConstantValue.java b/java/com/google/turbine/binder/bound/EnumConstantValue.java index e99c6ed..4083ae3 100644 --- a/java/com/google/turbine/binder/bound/EnumConstantValue.java +++ b/java/com/google/turbine/binder/bound/EnumConstantValue.java @@ -46,9 +46,4 @@ public class EnumConstantValue extends Const { public boolean equals(Object obj) { return obj instanceof EnumConstantValue && sym().equals(((EnumConstantValue) obj).sym()); } - - @Override - public String toString() { - return sym.toString(); - } } diff --git a/java/com/google/turbine/binder/bound/TypeBoundClass.java b/java/com/google/turbine/binder/bound/TypeBoundClass.java index e8933ac..350d311 100644 --- a/java/com/google/turbine/binder/bound/TypeBoundClass.java +++ b/java/com/google/turbine/binder/bound/TypeBoundClass.java @@ -16,12 +16,10 @@ package com.google.turbine.binder.bound; - import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.turbine.binder.sym.FieldSymbol; import com.google.turbine.binder.sym.MethodSymbol; -import com.google.turbine.binder.sym.ParamSymbol; import com.google.turbine.binder.sym.TyVarSymbol; import com.google.turbine.model.Const; import com.google.turbine.model.TurbineFlag; @@ -30,8 +28,6 @@ import com.google.turbine.tree.Tree.MethDecl; import com.google.turbine.type.AnnoInfo; import com.google.turbine.type.Type; import com.google.turbine.type.Type.IntersectionTy; -import com.google.turbine.type.Type.MethodTy; -import org.checkerframework.checker.nullness.qual.Nullable; /** A bound node that augments {@link HeaderBoundClass} with type information. */ public interface TypeBoundClass extends HeaderBoundClass { @@ -61,29 +57,17 @@ public interface TypeBoundClass extends HeaderBoundClass { /** A type parameter declaration. */ class TyVarInfo { - private final IntersectionTy upperBound; - @Nullable private final Type lowerBound; + private final IntersectionTy bound; private final ImmutableList<AnnoInfo> annotations; - public TyVarInfo( - IntersectionTy upperBound, @Nullable Type lowerBound, ImmutableList<AnnoInfo> annotations) { - this.upperBound = upperBound; - if (lowerBound != null) { - throw new IllegalArgumentException("TODO(cushon): support lower bounds"); - } - this.lowerBound = lowerBound; + public TyVarInfo(IntersectionTy bound, ImmutableList<AnnoInfo> annotations) { + this.bound = bound; this.annotations = annotations; } - /** The upper bound. */ - public IntersectionTy upperBound() { - return upperBound; - } - - /** The lower bound. */ - @Nullable - public Type lowerBound() { - return lowerBound; + /** The bound. */ + public IntersectionTy bound() { + return bound; } /** Type parameter declaration annotations. */ @@ -164,7 +148,7 @@ public interface TypeBoundClass extends HeaderBoundClass { private final Const defaultValue; private final MethDecl decl; private final ImmutableList<AnnoInfo> annotations; - private final @Nullable ParamInfo receiver; + private final ParamInfo receiver; public MethodInfo( MethodSymbol sym, @@ -176,7 +160,7 @@ public interface TypeBoundClass extends HeaderBoundClass { Const defaultValue, MethDecl decl, ImmutableList<AnnoInfo> annotations, - @Nullable ParamInfo receiver) { + ParamInfo receiver) { this.sym = sym; this.tyParams = tyParams; this.returnType = returnType; @@ -239,50 +223,26 @@ public interface TypeBoundClass extends HeaderBoundClass { return annotations; } - /** Receiver parameter (see JLS 8.4.1), or {@code null}. */ - public @Nullable ParamInfo receiver() { + /** Receiver parameter. */ + public ParamInfo receiver() { return receiver; } - - public MethodTy asType() { - return MethodTy.create( - tyParams.keySet(), - returnType, - receiver != null ? receiver.type() : null, - asTypes(parameters), - exceptions); - } - - private static ImmutableList<Type> asTypes(ImmutableList<ParamInfo> parameters) { - ImmutableList.Builder<Type> result = ImmutableList.builder(); - for (ParamInfo param : parameters) { - if (!param.synthetic()) { - result.add(param.type()); - } - } - return result.build(); - } } /** A formal parameter declaration. */ class ParamInfo { - private final ParamSymbol sym; private final Type type; + private final String name; private final int access; private final ImmutableList<AnnoInfo> annotations; - public ParamInfo(ParamSymbol sym, Type type, ImmutableList<AnnoInfo> annotations, int access) { - this.sym = sym; + public ParamInfo(Type type, String name, ImmutableList<AnnoInfo> annotations, int access) { this.type = type; + this.name = name; this.access = access; this.annotations = annotations; } - /** The parameter's symbol. */ - public ParamSymbol sym() { - return sym; - } - /** The parameter type. */ public Type type() { return type; @@ -303,7 +263,7 @@ public interface TypeBoundClass extends HeaderBoundClass { /** The parameter's name. */ public String name() { - return sym.name(); + return name; } /** The parameter's modifiers. */ diff --git a/java/com/google/turbine/binder/bytecode/BytecodeBinder.java b/java/com/google/turbine/binder/bytecode/BytecodeBinder.java index 66d4cf0..1d2eecb 100644 --- a/java/com/google/turbine/binder/bytecode/BytecodeBinder.java +++ b/java/com/google/turbine/binder/bytecode/BytecodeBinder.java @@ -18,9 +18,9 @@ package com.google.turbine.binder.bytecode; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.turbine.binder.bound.AnnotationValue; import com.google.turbine.binder.bound.EnumConstantValue; import com.google.turbine.binder.bound.ModuleInfo; -import com.google.turbine.binder.bound.TurbineAnnotationValue; import com.google.turbine.binder.bound.TurbineClassValue; import com.google.turbine.binder.sym.ClassSymbol; import com.google.turbine.binder.sym.FieldSymbol; @@ -81,8 +81,9 @@ public class BytecodeBinder { case UPPER: return Type.WildUpperBoundedTy.create( bindTy(((UpperBoundTySig) sig).bound(), scope), ImmutableList.of()); + default: + throw new AssertionError(sig.boundKind()); } - throw new AssertionError(sig.boundKind()); } static Type bindTy(Sig.TySig sig, Function<String, TyVarSymbol> scope) { @@ -99,22 +100,23 @@ public class BytecodeBinder { return wildTy((WildTySig) sig, scope); case VOID_TY_SIG: return Type.VOID; + default: + throw new AssertionError(sig.kind()); } - throw new AssertionError(sig.kind()); } private static Type bindArrayTy(Sig.ArrayTySig arrayTySig, Function<String, TyVarSymbol> scope) { return Type.ArrayTy.create(bindTy(arrayTySig.elementType(), scope), ImmutableList.of()); } - public static Const bindValue(ElementValue value) { + public static Const bindValue(Type type, ElementValue value) { switch (value.kind()) { case ENUM: return bindEnumValue((EnumConstValue) value); case CONST: - return ((ConstValue) value).value(); + return bindConstValue(type, ((ConstValue) value).value()); case ARRAY: - return bindArrayValue((ArrayValue) value); + return bindArrayValue(type, (ArrayValue) value); case CLASS: return new TurbineClassValue( bindTy( @@ -123,45 +125,37 @@ public class BytecodeBinder { throw new IllegalStateException(x); })); case ANNOTATION: - return bindAnnotationValue(((ElementValue.ConstTurbineAnnotationValue) value).annotation()); + return bindAnnotationValue(type, ((ElementValue.AnnotationValue) value).annotation()); } throw new AssertionError(value.kind()); } - static TurbineAnnotationValue bindAnnotationValue(AnnotationInfo value) { + static AnnotationValue bindAnnotationValue(Type type, AnnotationInfo value) { ClassSymbol sym = asClassSymbol(value.typeName()); ImmutableMap.Builder<String, Const> values = ImmutableMap.builder(); for (Map.Entry<String, ElementValue> e : value.elementValuePairs().entrySet()) { - values.put(e.getKey(), bindValue(e.getValue())); + values.put(e.getKey(), bindValue(type, e.getValue())); } - return new TurbineAnnotationValue(new AnnoInfo(null, sym, null, values.build())); + return new AnnotationValue(sym, values.build()); } static ImmutableList<AnnoInfo> bindAnnotations(List<AnnotationInfo> input) { ImmutableList.Builder<AnnoInfo> result = ImmutableList.builder(); for (AnnotationInfo annotation : input) { - TurbineAnnotationValue anno = bindAnnotationValue(annotation); - if (!shouldSkip(anno)) { - result.add(anno.info()); - } + AnnotationValue anno = bindAnnotationValue(Type.VOID, annotation); + result.add(new AnnoInfo(null, anno.sym(), null, anno.values())); } return result.build(); } - private static boolean shouldSkip(TurbineAnnotationValue anno) { - // ct.sym contains fake annotations without corresponding class files. - return anno.sym().equals(ClassSymbol.PROFILE_ANNOTATION) - || anno.sym().equals(ClassSymbol.PROPRIETARY_ANNOTATION); - } - private static ClassSymbol asClassSymbol(String s) { return new ClassSymbol(s.substring(1, s.length() - 1)); } - private static Const bindArrayValue(ArrayValue value) { + private static Const bindArrayValue(Type type, ArrayValue value) { ImmutableList.Builder<Const> elements = ImmutableList.builder(); for (ElementValue element : value.elements()) { - elements.add(bindValue(element)); + elements.add(bindValue(type, element)); } return new ArrayInitValue(elements.build()); } @@ -170,22 +164,30 @@ public class BytecodeBinder { if (type.tyKind() != Type.TyKind.PRIM_TY) { return value; } - // Deficient numberic types and booleans are all stored as ints in the class file, - // coerce them to the target type. // TODO(b/32626659): this is not bug-compatible with javac switch (((Type.PrimTy) type).primkind()) { case CHAR: return new Const.CharValue(value.asChar().value()); case SHORT: return new Const.ShortValue(value.asShort().value()); + case INT: + return new Const.IntValue(value.asInteger().value()); + case LONG: + return new Const.LongValue(value.asLong().value()); + case FLOAT: + return new Const.FloatValue(value.asFloat().value()); + case DOUBLE: + return new Const.DoubleValue(value.asDouble().value()); case BOOLEAN: // boolean constants are encoded as integers return new Const.BooleanValue(value.asInteger().value() != 0); case BYTE: return new Const.ByteValue(value.asByte().value()); - default: + case STRING: + case NULL: return value; } + throw new AssertionError(type); } private static Const bindEnumValue(EnumConstValue value) { diff --git a/java/com/google/turbine/binder/bytecode/BytecodeBoundClass.java b/java/com/google/turbine/binder/bytecode/BytecodeBoundClass.java index b992643..6ff8cb4 100644 --- a/java/com/google/turbine/binder/bytecode/BytecodeBoundClass.java +++ b/java/com/google/turbine/binder/bytecode/BytecodeBoundClass.java @@ -32,7 +32,6 @@ import com.google.turbine.binder.env.Env; import com.google.turbine.binder.sym.ClassSymbol; import com.google.turbine.binder.sym.FieldSymbol; import com.google.turbine.binder.sym.MethodSymbol; -import com.google.turbine.binder.sym.ParamSymbol; import com.google.turbine.binder.sym.TyVarSymbol; import com.google.turbine.bytecode.ClassFile; import com.google.turbine.bytecode.ClassFile.AnnotationInfo; @@ -333,8 +332,7 @@ public class BytecodeBoundClass implements BoundClass, HeaderBoundClass, TypeBou for (Sig.TySig t : sig.interfaceBounds()) { bounds.add(BytecodeBinder.bindTy(t, scope)); } - return new TyVarInfo( - IntersectionTy.create(bounds.build()), /* lowerBound= */ null, ImmutableList.of()); + return new TyVarInfo(IntersectionTy.create(bounds.build()), ImmutableList.of()); } @Override @@ -352,17 +350,14 @@ public class BytecodeBoundClass implements BoundClass, HeaderBoundClass, TypeBou FieldSymbol fieldSym = new FieldSymbol(sym, cfi.name()); Type type = BytecodeBinder.bindTy( - new SigParser(firstNonNull(cfi.signature(), cfi.descriptor())).parseType(), + new SigParser(cfi.descriptor()).parseType(), makeScope(env, sym, ImmutableMap.of())); int access = cfi.access(); Const.Value value = cfi.value(); if (value != null) { value = BytecodeBinder.bindConstValue(type, value); } - ImmutableList<AnnoInfo> annotations = - BytecodeBinder.bindAnnotations(cfi.annotations()); - fields.add( - new FieldInfo(fieldSym, type, access, annotations, /* decl= */ null, value)); + fields.add(new FieldInfo(fieldSym, type, access, ImmutableList.of(), null, value)); } return fields.build(); } @@ -379,16 +374,15 @@ public class BytecodeBoundClass implements BoundClass, HeaderBoundClass, TypeBou @Override public ImmutableList<MethodInfo> get() { ImmutableList.Builder<MethodInfo> methods = ImmutableList.builder(); - int idx = 0; for (ClassFile.MethodInfo m : classFile.get().methods()) { - methods.add(bindMethod(idx++, m)); + methods.add(bindMethod(m)); } return methods.build(); } }); - private MethodInfo bindMethod(int methodIdx, ClassFile.MethodInfo m) { - MethodSymbol methodSymbol = new MethodSymbol(methodIdx, sym, m.name()); + private MethodInfo bindMethod(ClassFile.MethodInfo m) { + MethodSymbol methodSymbol = new MethodSymbol(sym, m.name()); Sig.MethodSig sig = new SigParser(firstNonNull(m.signature(), m.descriptor())).parseMethodSig(); ImmutableMap<String, TyVarSymbol> tyParams; @@ -420,43 +414,28 @@ public class BytecodeBoundClass implements BoundClass, HeaderBoundClass, TypeBou ImmutableList.Builder<ParamInfo> formals = ImmutableList.builder(); int idx = 0; for (Sig.TySig tySig : sig.params()) { - String name; + String name = null; int access = 0; if (idx < m.parameters().size()) { ParameterInfo paramInfo = m.parameters().get(idx); name = paramInfo.name(); - // ignore parameter modifiers for bug-parity with javac: - // https://bugs.openjdk.java.net/browse/JDK-8226216 - // access = paramInfo.access(); - } else { - name = "arg" + idx; + access = paramInfo.access(); } ImmutableList<AnnoInfo> annotations = (idx < m.parameterAnnotations().size()) ? BytecodeBinder.bindAnnotations(m.parameterAnnotations().get(idx)) : ImmutableList.of(); - formals.add( - new ParamInfo( - new ParamSymbol(methodSymbol, name), - BytecodeBinder.bindTy(tySig, scope), - annotations, - access)); + formals.add(new ParamInfo(BytecodeBinder.bindTy(tySig, scope), name, annotations, access)); idx++; } ImmutableList.Builder<Type> exceptions = ImmutableList.builder(); - if (!sig.exceptions().isEmpty()) { - for (TySig e : sig.exceptions()) { - exceptions.add(BytecodeBinder.bindTy(e, scope)); - } - } else { - for (String e : m.exceptions()) { - exceptions.add(ClassTy.asNonParametricClassTy(new ClassSymbol(e))); - } + for (TySig e : sig.exceptions()) { + exceptions.add(BytecodeBinder.bindTy(e, scope)); } Const defaultValue = - m.defaultValue() != null ? BytecodeBinder.bindValue(m.defaultValue()) : null; + m.defaultValue() != null ? BytecodeBinder.bindValue(ret, m.defaultValue()) : null; ImmutableList<AnnoInfo> annotations = BytecodeBinder.bindAnnotations(m.annotations()); @@ -508,7 +487,7 @@ public class BytecodeBoundClass implements BoundClass, HeaderBoundClass, TypeBou } }); - private static RetentionPolicy bindRetention(AnnotationInfo annotation) { + private RetentionPolicy bindRetention(AnnotationInfo annotation) { ElementValue val = annotation.elementValuePairs().get("value"); if (val.kind() != Kind.ENUM) { return null; diff --git a/java/com/google/turbine/binder/lookup/CompoundTopLevelIndex.java b/java/com/google/turbine/binder/lookup/CompoundTopLevelIndex.java index b41edb0..de50a2e 100644 --- a/java/com/google/turbine/binder/lookup/CompoundTopLevelIndex.java +++ b/java/com/google/turbine/binder/lookup/CompoundTopLevelIndex.java @@ -62,14 +62,14 @@ public class CompoundTopLevelIndex implements TopLevelIndex { } @Override - public PackageScope lookupPackage(Iterable<String> packagename) { + public Scope lookupPackage(ImmutableList<String> packagename) { // When returning package scopes, build up a compound scope containing entries from all // indices with matching packages. - PackageScope result = null; + CompoundScope result = null; for (TopLevelIndex index : indexes) { - PackageScope packageScope = index.lookupPackage(packagename); + Scope packageScope = index.lookupPackage(packagename); if (packageScope != null) { - result = result == null ? packageScope : result.append(packageScope); + result = result == null ? CompoundScope.base(packageScope) : result.append(packageScope); } } return result; diff --git a/java/com/google/turbine/binder/lookup/ImportIndex.java b/java/com/google/turbine/binder/lookup/ImportIndex.java index fd57223..afa985a 100644 --- a/java/com/google/turbine/binder/lookup/ImportIndex.java +++ b/java/com/google/turbine/binder/lookup/ImportIndex.java @@ -142,8 +142,7 @@ public class ImportIndex implements ImportScope { TurbineLogWithSource log, TopLevelIndex cpi, ImportDecl i) { LookupResult base = cpi.scope().lookup(new LookupKey(i.type())); if (base == null) { - log.error( - i.position(), ErrorKind.SYMBOL_NOT_FOUND, new ClassSymbol(Joiner.on("/").join(i.type()))); + log.error(i.position(), ErrorKind.SYMBOL_NOT_FOUND, Joiner.on(".").join(i.type())); return null; } return new ImportScope() { diff --git a/java/com/google/turbine/binder/lookup/PackageScope.java b/java/com/google/turbine/binder/lookup/PackageScope.java deleted file mode 100644 index 695e802..0000000 --- a/java/com/google/turbine/binder/lookup/PackageScope.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.binder.lookup; - -import com.google.common.collect.Iterables; -import com.google.turbine.binder.sym.ClassSymbol; -import org.checkerframework.checker.nullness.qual.Nullable; - -/** - * A scope that corresponds to a particular package, which supports iteration over its enclosed - * classes. - */ -public interface PackageScope extends Scope { - - /** Returns the top-level classes enclosed by this package. */ - Iterable<ClassSymbol> classes(); - - default PackageScope append(PackageScope next) { - return concat(this, next); - } - - static PackageScope concat(PackageScope base, PackageScope next) { - return new PackageScope() { - @Override - public Iterable<ClassSymbol> classes() { - return Iterables.concat(base.classes(), next.classes()); - } - - @Override - public @Nullable LookupResult lookup(LookupKey lookupKey) { - LookupResult result = base.lookup(lookupKey); - if (result != null) { - return result; - } - return next.lookup(lookupKey); - } - }; - } -} diff --git a/java/com/google/turbine/binder/lookup/SimpleTopLevelIndex.java b/java/com/google/turbine/binder/lookup/SimpleTopLevelIndex.java index 4ec05bc..2454319 100644 --- a/java/com/google/turbine/binder/lookup/SimpleTopLevelIndex.java +++ b/java/com/google/turbine/binder/lookup/SimpleTopLevelIndex.java @@ -16,8 +16,6 @@ package com.google.turbine.binder.lookup; -import com.google.common.base.Supplier; -import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableList; import com.google.turbine.binder.sym.ClassSymbol; import java.util.HashMap; @@ -159,7 +157,7 @@ public class SimpleTopLevelIndex implements TopLevelIndex { /** Returns a {@link Scope} that performs lookups in the given qualified package name. */ @Override - public PackageScope lookupPackage(Iterable<String> packagename) { + public Scope lookupPackage(ImmutableList<String> packagename) { Node curr = root; for (String bit : packagename) { curr = curr.lookup(bit); @@ -170,7 +168,7 @@ public class SimpleTopLevelIndex implements TopLevelIndex { return new PackageIndex(curr); } - static class PackageIndex implements PackageScope { + static class PackageIndex implements Scope { private final Node node; @@ -186,25 +184,5 @@ public class SimpleTopLevelIndex implements TopLevelIndex { } return null; } - - private final Supplier<ImmutableList<ClassSymbol>> classes = - Suppliers.memoize( - new Supplier<ImmutableList<ClassSymbol>>() { - @Override - public ImmutableList<ClassSymbol> get() { - ImmutableList.Builder<ClassSymbol> result = ImmutableList.builder(); - for (Node child : node.children.values()) { - if (child.sym != null) { - result.add(child.sym); - } - } - return result.build(); - } - }); - - @Override - public Iterable<ClassSymbol> classes() { - return classes.get(); - } } } diff --git a/java/com/google/turbine/binder/lookup/TopLevelIndex.java b/java/com/google/turbine/binder/lookup/TopLevelIndex.java index a364119..95782f5 100644 --- a/java/com/google/turbine/binder/lookup/TopLevelIndex.java +++ b/java/com/google/turbine/binder/lookup/TopLevelIndex.java @@ -16,6 +16,7 @@ package com.google.turbine.binder.lookup; +import com.google.common.collect.ImmutableList; /** * An index of canonical type names. @@ -35,5 +36,5 @@ public interface TopLevelIndex { Scope scope(); /** Returns a scope to look up members of the given package. */ - PackageScope lookupPackage(Iterable<String> packagename); + Scope lookupPackage(ImmutableList<String> packagename); } diff --git a/java/com/google/turbine/binder/sym/ClassSymbol.java b/java/com/google/turbine/binder/sym/ClassSymbol.java index 20513e7..2adf15f 100644 --- a/java/com/google/turbine/binder/sym/ClassSymbol.java +++ b/java/com/google/turbine/binder/sym/ClassSymbol.java @@ -33,23 +33,6 @@ public class ClassSymbol implements Symbol { public static final ClassSymbol STRING = new ClassSymbol("java/lang/String"); public static final ClassSymbol ENUM = new ClassSymbol("java/lang/Enum"); public static final ClassSymbol ANNOTATION = new ClassSymbol("java/lang/annotation/Annotation"); - public static final ClassSymbol INHERITED = new ClassSymbol("java/lang/annotation/Inherited"); - public static final ClassSymbol CLONEABLE = new ClassSymbol("java/lang/Cloneable"); - public static final ClassSymbol SERIALIZABLE = new ClassSymbol("java/io/Serializable"); - public static final ClassSymbol DEPRECATED = new ClassSymbol("java/lang/Deprecated"); - public static final ClassSymbol PROFILE_ANNOTATION = new ClassSymbol("jdk/Profile+Annotation"); - public static final ClassSymbol PROPRIETARY_ANNOTATION = - new ClassSymbol("sun/Proprietary+Annotation"); - public static final ClassSymbol ERROR = new ClassSymbol("<error>"); - - public static final ClassSymbol CHARACTER = new ClassSymbol("java/lang/Character"); - public static final ClassSymbol SHORT = new ClassSymbol("java/lang/Short"); - public static final ClassSymbol INTEGER = new ClassSymbol("java/lang/Integer"); - public static final ClassSymbol LONG = new ClassSymbol("java/lang/Long"); - public static final ClassSymbol FLOAT = new ClassSymbol("java/lang/Float"); - public static final ClassSymbol DOUBLE = new ClassSymbol("java/lang/Double"); - public static final ClassSymbol BOOLEAN = new ClassSymbol("java/lang/Boolean"); - public static final ClassSymbol BYTE = new ClassSymbol("java/lang/Byte"); private final String className; @@ -81,17 +64,4 @@ public class ClassSymbol implements Symbol { public Kind symKind() { return Kind.CLASS; } - - public String simpleName() { - return binaryName().substring(binaryName().lastIndexOf('/') + 1); - } - - public String packageName() { - int idx = binaryName().lastIndexOf('/'); - return idx != -1 ? binaryName().substring(0, idx) : ""; - } - - public PackageSymbol owner() { - return new PackageSymbol(packageName()); - } } diff --git a/java/com/google/turbine/binder/sym/FieldSymbol.java b/java/com/google/turbine/binder/sym/FieldSymbol.java index d6c3cbc..21304e7 100644 --- a/java/com/google/turbine/binder/sym/FieldSymbol.java +++ b/java/com/google/turbine/binder/sym/FieldSymbol.java @@ -61,6 +61,6 @@ public class FieldSymbol implements Symbol { @Override public String toString() { - return name; + return owner + "#" + name; } } diff --git a/java/com/google/turbine/binder/sym/MethodSymbol.java b/java/com/google/turbine/binder/sym/MethodSymbol.java index f4b211d..b2050f4 100644 --- a/java/com/google/turbine/binder/sym/MethodSymbol.java +++ b/java/com/google/turbine/binder/sym/MethodSymbol.java @@ -22,17 +22,10 @@ import java.util.Objects; /** A method symbol. */ @Immutable public class MethodSymbol implements Symbol { - /** - * The index of the method in its enclosing element. Used to implement equals and hashCode, since - * methods aren't uniquely identified by their name and owner. - */ - private final int idx; - private final ClassSymbol owner; private final String name; - public MethodSymbol(int idx, ClassSymbol owner, String name) { - this.idx = idx; + public MethodSymbol(ClassSymbol owner, String name) { this.owner = owner; this.name = name; } @@ -63,7 +56,7 @@ public class MethodSymbol implements Symbol { return false; } MethodSymbol other = (MethodSymbol) obj; - return name().equals(other.name()) && owner().equals(other.owner()) && idx == other.idx; + return name().equals(other.name()) && owner().equals(other.owner()); } @Override diff --git a/java/com/google/turbine/binder/sym/PackageSymbol.java b/java/com/google/turbine/binder/sym/PackageSymbol.java deleted file mode 100644 index 8354a34..0000000 --- a/java/com/google/turbine/binder/sym/PackageSymbol.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.binder.sym; - -import com.google.errorprone.annotations.Immutable; - -/** A package symbol. */ -@Immutable -public class PackageSymbol implements Symbol { - - final String binaryName; - - public PackageSymbol(String binaryName) { - this.binaryName = binaryName; - } - - @Override - public int hashCode() { - return binaryName.hashCode(); - } - - @Override - public boolean equals(Object obj) { - return obj instanceof PackageSymbol && binaryName.equals(((PackageSymbol) obj).binaryName); - } - - @Override - public String toString() { - return binaryName.replace('/', '.'); - } - - @Override - public Kind symKind() { - return Kind.PACKAGE; - } - - public String binaryName() { - return binaryName; - } -} diff --git a/java/com/google/turbine/binder/sym/ParamSymbol.java b/java/com/google/turbine/binder/sym/ParamSymbol.java deleted file mode 100644 index 328658e..0000000 --- a/java/com/google/turbine/binder/sym/ParamSymbol.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2016 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.binder.sym; - -import com.google.errorprone.annotations.Immutable; -import java.util.Objects; - -/** A parameter symbol. */ -@Immutable -public class ParamSymbol implements Symbol { - private final MethodSymbol owner; - private final String name; - - public ParamSymbol(MethodSymbol owner, String name) { - this.owner = owner; - this.name = name; - } - - /** The enclosing class. */ - public MethodSymbol owner() { - return owner; - } - - /** The parameter name. */ - public String name() { - return name; - } - - @Override - public Kind symKind() { - return Kind.PARAMETER; - } - - @Override - public int hashCode() { - return Objects.hash(name, owner); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof ParamSymbol)) { - return false; - } - ParamSymbol other = (ParamSymbol) obj; - return name().equals(other.name()) && owner().equals(other.owner()); - } - - @Override - public String toString() { - return name; - } -} diff --git a/java/com/google/turbine/binder/sym/Symbol.java b/java/com/google/turbine/binder/sym/Symbol.java index bc142cb..b2a7723 100644 --- a/java/com/google/turbine/binder/sym/Symbol.java +++ b/java/com/google/turbine/binder/sym/Symbol.java @@ -27,9 +27,7 @@ public interface Symbol { TY_PARAM, METHOD, FIELD, - PARAMETER, - MODULE, - PACKAGE + MODULE } /** The symbol kind. */ diff --git a/java/com/google/turbine/binder/sym/TyVarSymbol.java b/java/com/google/turbine/binder/sym/TyVarSymbol.java index 1ecec11..a73a79e 100644 --- a/java/com/google/turbine/binder/sym/TyVarSymbol.java +++ b/java/com/google/turbine/binder/sym/TyVarSymbol.java @@ -62,6 +62,6 @@ public class TyVarSymbol implements Symbol { @Override public String toString() { - return name; + return owner + "#" + name; } } diff --git a/java/com/google/turbine/bytecode/AnnotationWriter.java b/java/com/google/turbine/bytecode/AnnotationWriter.java index b547971..868b548 100644 --- a/java/com/google/turbine/bytecode/AnnotationWriter.java +++ b/java/com/google/turbine/bytecode/AnnotationWriter.java @@ -20,8 +20,8 @@ import com.google.common.collect.ImmutableList; import com.google.common.io.ByteArrayDataOutput; import com.google.turbine.bytecode.ClassFile.AnnotationInfo; import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue; +import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.AnnotationValue; import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.ArrayValue; -import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.ConstTurbineAnnotationValue; import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.ConstTurbineClassValue; import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.ConstValue; import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.EnumConstValue; @@ -71,8 +71,10 @@ public class AnnotationWriter { writeArrayElementValue((ArrayValue) value); break; case ANNOTATION: - writeAnnotationElementValue((ConstTurbineAnnotationValue) value); + writeAnnotationElementValue((AnnotationValue) value); break; + default: + throw new AssertionError(value.kind()); } } @@ -134,7 +136,7 @@ public class AnnotationWriter { } } - private void writeAnnotationElementValue(ConstTurbineAnnotationValue value) { + private void writeAnnotationElementValue(AnnotationValue value) { output.writeByte('@'); writeAnnotation(value.annotation()); } @@ -176,6 +178,8 @@ public class AnnotationWriter { output.writeByte(typeParameterBoundTarget.typeParameterIndex()); output.writeByte(typeParameterBoundTarget.boundIndex()); break; + default: + throw new AssertionError(target.kind()); } } } diff --git a/java/com/google/turbine/bytecode/AttributeWriter.java b/java/com/google/turbine/bytecode/AttributeWriter.java index c5ffd16..5e3ea95 100644 --- a/java/com/google/turbine/bytecode/AttributeWriter.java +++ b/java/com/google/turbine/bytecode/AttributeWriter.java @@ -87,6 +87,8 @@ public class AttributeWriter { case MODULE: writeModule((Attribute.Module) attribute); break; + default: + throw new AssertionError(attribute.kind()); } } diff --git a/java/com/google/turbine/bytecode/ClassFile.java b/java/com/google/turbine/bytecode/ClassFile.java index 8ee2aac..54b6983 100644 --- a/java/com/google/turbine/bytecode/ClassFile.java +++ b/java/com/google/turbine/bytecode/ClassFile.java @@ -368,7 +368,7 @@ public class ClassFile { public interface ElementValue { /** The value kind. */ - ElementValue.Kind kind(); + Kind kind(); /** Element value kinds. */ enum Kind { @@ -391,8 +391,8 @@ public class ClassFile { } @Override - public ElementValue.Kind kind() { - return ElementValue.Kind.ENUM; + public Kind kind() { + return Kind.ENUM; } /** The type of the enum. */ @@ -417,8 +417,8 @@ public class ClassFile { } @Override - public ElementValue.Kind kind() { - return ElementValue.Kind.CONST; + public Kind kind() { + return Kind.CONST; } /** The constant value. */ @@ -437,8 +437,8 @@ public class ClassFile { } @Override - public ElementValue.Kind kind() { - return ElementValue.Kind.ARRAY; + public Kind kind() { + return Kind.ARRAY; } /** The elements of the array. */ @@ -457,8 +457,8 @@ public class ClassFile { } @Override - public ElementValue.Kind kind() { - return ElementValue.Kind.CLASS; + public Kind kind() { + return Kind.CLASS; } /** The class name. */ @@ -468,17 +468,17 @@ public class ClassFile { } /** A nested annotation value. */ - class ConstTurbineAnnotationValue implements ElementValue { + class AnnotationValue implements ElementValue { private final AnnotationInfo annotation; - public ConstTurbineAnnotationValue(AnnotationInfo annotation) { + public AnnotationValue(AnnotationInfo annotation) { this.annotation = annotation; } @Override - public ElementValue.Kind kind() { - return ElementValue.Kind.ANNOTATION; + public Kind kind() { + return Kind.ANNOTATION; } /** The annotation. */ @@ -566,7 +566,7 @@ public class ClassFile { } /** Returns the target info kind. */ - public abstract Target.Kind kind(); + public abstract Kind kind(); } /** A JVMS 4.7.20.1 type_parameter_target. */ @@ -582,8 +582,8 @@ public class ClassFile { } @Override - public Target.Kind kind() { - return Target.Kind.TYPE_PARAMETER; + public Kind kind() { + return Kind.TYPE_PARAMETER; } } @@ -596,8 +596,8 @@ public class ClassFile { } @Override - public Target.Kind kind() { - return Target.Kind.SUPERTYPE; + public Kind kind() { + return Kind.SUPERTYPE; } public int index() { @@ -616,8 +616,8 @@ public class ClassFile { } @Override - public Target.Kind kind() { - return Target.Kind.TYPE_PARAMETER_BOUND; + public Kind kind() { + return Kind.TYPE_PARAMETER_BOUND; } public int typeParameterIndex() { @@ -633,8 +633,8 @@ public class ClassFile { public static final Target EMPTY_TARGET = new Target() { @Override - public Target.Kind kind() { - return Target.Kind.EMPTY; + public Kind kind() { + return Kind.EMPTY; } }; @@ -647,8 +647,8 @@ public class ClassFile { } @Override - public Target.Kind kind() { - return Target.Kind.FORMAL_PARAMETER; + public Kind kind() { + return Kind.FORMAL_PARAMETER; } public int index() { @@ -665,8 +665,8 @@ public class ClassFile { } @Override - public Target.Kind kind() { - return Target.Kind.THROWS; + public Kind kind() { + return Kind.THROWS; } public int index() { @@ -689,22 +689,22 @@ public class ClassFile { /** Adds an array type_path_kind entry. */ public TypePath array() { - return new TypePath(TypePath.Kind.ARRAY, this); + return new TypePath(Kind.ARRAY, this); } /** Adds a nested type type_path_kind entry. */ public TypePath nested() { - return new TypePath(TypePath.Kind.NESTED, this); + return new TypePath(Kind.NESTED, this); } /** Adds a wildcard bound type_path_kind entry. */ public TypePath wild() { - return new TypePath(TypePath.Kind.WILDCARD_BOUND, this); + return new TypePath(Kind.WILDCARD_BOUND, this); } /** Adds a type argument type_path_kind entry. */ public TypePath typeArgument(int idx) { - return new TypePath(idx, TypePath.Kind.TYPE_ARGUMENT, this); + return new TypePath(idx, Kind.TYPE_ARGUMENT, this); } /** A type_path_kind. */ @@ -722,15 +722,15 @@ public class ClassFile { } private final TypePath parent; - private final TypePath.Kind kind; + private final Kind kind; private final int index; - private TypePath(TypePath.Kind kind, TypePath parent) { + private TypePath(Kind kind, TypePath parent) { // JVMS 4.7.20.2: type_argument_index is 0 if the bound kind is not TYPE_ARGUMENT this(0, kind, parent); } - private TypePath(int index, TypePath.Kind kind, TypePath parent) { + private TypePath(int index, Kind kind, TypePath parent) { this.index = index; this.kind = kind; this.parent = parent; diff --git a/java/com/google/turbine/bytecode/ClassReader.java b/java/com/google/turbine/bytecode/ClassReader.java index 9c79b42..a894997 100644 --- a/java/com/google/turbine/bytecode/ClassReader.java +++ b/java/com/google/turbine/bytecode/ClassReader.java @@ -19,10 +19,9 @@ package com.google.turbine.bytecode; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.errorprone.annotations.CheckReturnValue; -import com.google.errorprone.annotations.FormatMethod; import com.google.turbine.bytecode.ClassFile.AnnotationInfo; import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue; -import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.ConstTurbineAnnotationValue; +import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.AnnotationValue; import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.ConstTurbineClassValue; import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.ConstValue; import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.EnumConstValue; @@ -34,7 +33,6 @@ import com.google.turbine.bytecode.ClassFile.ModuleInfo.ProvideInfo; import com.google.turbine.bytecode.ClassFile.ModuleInfo.RequireInfo; import com.google.turbine.bytecode.ClassFile.ModuleInfo.UseInfo; import com.google.turbine.model.Const; -import com.google.turbine.model.TurbineFlag; import java.util.ArrayList; import java.util.List; import org.checkerframework.checker.nullness.qual.Nullable; @@ -61,7 +59,6 @@ public class ClassReader { this.reader = new ByteReader(bytes, 0); } - @FormatMethod @CheckReturnValue Error error(String format, Object... args) { StringBuilder sb = new StringBuilder(); @@ -75,7 +72,7 @@ public class ClassReader { private ClassFile read() { int magic = reader.u4(); if (magic != 0xcafebabe) { - throw error("bad magic: 0x%x", magic); + throw error("bad magic: 0x%x", path, magic); } int minorVersion = reader.u2(); int majorVersion = reader.u2(); @@ -215,11 +212,6 @@ public class ClassReader { for (int i = 0; i < numParameters; i++) { String name = constantPool.utf8(reader.u2()); int access = reader.u2(); - if ((access & (TurbineFlag.ACC_SYNTHETIC | TurbineFlag.ACC_MANDATED)) != 0) { - // ExecutableElement#getParameters doesn't expect synthetic or mandated - // parameters - continue; - } parameters.add(new ParameterInfo(name, access)); } } @@ -329,22 +321,17 @@ public class ClassReader { int tag = reader.u1(); switch (tag) { case 'B': - return new ConstValue(readConst(constantPool).asByte()); case 'C': - return new ConstValue(readConst(constantPool).asChar()); - case 'S': - return new ConstValue(readConst(constantPool).asShort()); case 'D': case 'F': case 'I': case 'J': - case 's': - return new ConstValue(readConst(constantPool)); + case 'S': case 'Z': + case 's': { - Const.Value value = readConst(constantPool); - // boolean constants are encoded as integers - return new ConstValue(new Const.BooleanValue(value.asInteger().value() != 0)); + int constValueIndex = reader.u2(); + return new ConstValue(constantPool.constant(constValueIndex)); } case 'e': { @@ -361,7 +348,7 @@ public class ClassReader { return new ConstTurbineClassValue(className); } case '@': - return new ConstTurbineAnnotationValue(readAnnotation(constantPool)); + return new AnnotationValue(readAnnotation(constantPool)); case '[': { int numValues = reader.u2(); @@ -376,11 +363,6 @@ public class ClassReader { throw new AssertionError(String.format("bad tag value %c", tag)); } - private Const.Value readConst(ConstantPoolReader constantPool) { - int constValueIndex = reader.u2(); - return constantPool.constant(constValueIndex); - } - /** Reads JVMS 4.6 method_infos. */ private List<ClassFile.MethodInfo> readMethods(ConstantPoolReader constantPool) { int methodsCount = reader.u2(); @@ -433,10 +415,6 @@ public class ClassReader { for (ImmutableList.Builder<AnnotationInfo> x : parameterAnnotationsBuilder) { parameterAnnotations.add(x.build()); } - if ((accessFlags & (TurbineFlag.ACC_BRIDGE | TurbineFlag.ACC_SYNTHETIC)) != 0) { - // javac doesn't enter synthetic members for reasons 'lost to history', so we don't either - continue; - } methods.add( new ClassFile.MethodInfo( accessFlags, @@ -476,8 +454,6 @@ public class ClassReader { String desc = constantPool.utf8(descriptorIndex); int attributesCount = reader.u2(); Const.Value value = null; - ImmutableList.Builder<ClassFile.AnnotationInfo> annotations = ImmutableList.builder(); - String signature = null; for (int j = 0; j < attributesCount; j++) { String attributeName = constantPool.utf8(reader.u2()); switch (attributeName) { @@ -485,13 +461,6 @@ public class ClassReader { reader.u4(); // length value = constantPool.constant(reader.u2()); break; - case "RuntimeInvisibleAnnotations": - case "RuntimeVisibleAnnotations": - readAnnotations(annotations, constantPool); - break; - case "Signature": - signature = readSignature(constantPool); - break; default: reader.skip(reader.u4()); break; @@ -502,10 +471,10 @@ public class ClassReader { accessFlags, name, desc, - signature, + /*signature*/ null, value, - annotations.build(), - /* typeAnnotations= */ ImmutableList.of())); + ImmutableList.of(), + ImmutableList.of())); } return fields; } diff --git a/java/com/google/turbine/bytecode/ClassWriter.java b/java/com/google/turbine/bytecode/ClassWriter.java index c3490ca..4a89ec8 100644 --- a/java/com/google/turbine/bytecode/ClassWriter.java +++ b/java/com/google/turbine/bytecode/ClassWriter.java @@ -110,6 +110,8 @@ public class ClassWriter { case UTF8: output.writeUTF(((StringValue) value).value()); break; + default: + throw new AssertionError(e.kind()); } } } diff --git a/java/com/google/turbine/bytecode/ConstantPool.java b/java/com/google/turbine/bytecode/ConstantPool.java index 673102c..b423cfc 100644 --- a/java/com/google/turbine/bytecode/ConstantPool.java +++ b/java/com/google/turbine/bytecode/ConstantPool.java @@ -66,8 +66,9 @@ public class ConstantPool { // "In retrospect, making 8-byte constants take two constant pool entries // was a poor choice." -- JVMS 4.4.5 return 2; + default: + throw new AssertionError(kind); } - throw new AssertionError(kind); } /** A constant pool entry. */ diff --git a/java/com/google/turbine/bytecode/sig/SigWriter.java b/java/com/google/turbine/bytecode/sig/SigWriter.java index 3711186..dab4f47 100644 --- a/java/com/google/turbine/bytecode/sig/SigWriter.java +++ b/java/com/google/turbine/bytecode/sig/SigWriter.java @@ -113,6 +113,8 @@ public class SigWriter { sb.append('+'); writeTySig(((UpperBoundTySig) sig).bound()); break; + default: + throw new AssertionError(sig.kind()); } } @@ -196,6 +198,8 @@ public class SigWriter { case WILD_TY_SIG: wildTyArgSig((WildTySig) p); break; + default: + throw new AssertionError(p.kind()); } } diff --git a/java/com/google/turbine/deps/Dependencies.java b/java/com/google/turbine/deps/Dependencies.java index 92193e8..f76efe7 100644 --- a/java/com/google/turbine/deps/Dependencies.java +++ b/java/com/google/turbine/deps/Dependencies.java @@ -22,22 +22,14 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.turbine.binder.Binder.BindingResult; import com.google.turbine.binder.ClassPath; -import com.google.turbine.binder.bound.EnumConstantValue; -import com.google.turbine.binder.bound.TurbineAnnotationValue; -import com.google.turbine.binder.bound.TurbineClassValue; import com.google.turbine.binder.bound.TypeBoundClass; -import com.google.turbine.binder.bound.TypeBoundClass.FieldInfo; -import com.google.turbine.binder.bound.TypeBoundClass.MethodInfo; import com.google.turbine.binder.bytecode.BytecodeBoundClass; import com.google.turbine.binder.env.CompoundEnv; import com.google.turbine.binder.env.Env; import com.google.turbine.binder.env.SimpleEnv; import com.google.turbine.binder.sym.ClassSymbol; import com.google.turbine.lower.Lower.Lowered; -import com.google.turbine.model.Const; import com.google.turbine.proto.DepsProto; -import com.google.turbine.type.AnnoInfo; -import com.google.turbine.type.Type; import java.io.BufferedInputStream; import java.io.IOError; import java.io.IOException; @@ -90,59 +82,13 @@ public class Dependencies { Env<ClassSymbol, TypeBoundClass> env = CompoundEnv.<ClassSymbol, TypeBoundClass>of(new SimpleEnv<>(bound.units())) .append(bound.classPathEnv()); - Set<ClassSymbol> closure = new LinkedHashSet<>(lowered.symbols()); + Set<ClassSymbol> closure = new LinkedHashSet<>(); for (ClassSymbol sym : lowered.symbols()) { - TypeBoundClass info = env.get(sym); - addAnnotations(closure, info.annotations()); - for (MethodInfo method : info.methods()) { - addAnnotations(closure, method.annotations()); - } - for (FieldInfo field : info.fields()) { - addAnnotations(closure, field.annotations()); - } - addSuperTypes(closure, env, info); + addSuperTypes(closure, env, sym); } return closure; } - private static void addAnnotations( - Set<ClassSymbol> closure, ImmutableList<AnnoInfo> annotations) { - for (AnnoInfo annoInfo : annotations) { - addAnnotation(closure, annoInfo); - } - } - - private static void addAnnotation(Set<ClassSymbol> closure, AnnoInfo annoInfo) { - closure.add(annoInfo.sym()); - for (Const c : annoInfo.values().values()) { - addConst(closure, c); - } - } - - private static void addConst(Set<ClassSymbol> closure, Const c) { - switch (c.kind()) { - case ARRAY: - for (Const e : ((Const.ArrayInitValue) c).elements()) { - addConst(closure, e); - } - break; - case CLASS_LITERAL: - Type t = ((TurbineClassValue) c).type(); - if (t.tyKind() == Type.TyKind.CLASS_TY) { - closure.add(((Type.ClassTy) t).sym()); - } - break; - case ENUM_CONSTANT: - closure.add(((EnumConstantValue) c).sym().owner()); - break; - case ANNOTATION: - addAnnotation(closure, ((TurbineAnnotationValue) c).info()); - break; - case PRIMITIVE: - // continue below - } - } - private static void addSuperTypes( Set<ClassSymbol> closure, Env<ClassSymbol, TypeBoundClass> env, ClassSymbol sym) { if (!closure.add(sym)) { @@ -152,11 +98,6 @@ public class Dependencies { if (info == null) { return; } - addSuperTypes(closure, env, info); - } - - private static void addSuperTypes( - Set<ClassSymbol> closure, Env<ClassSymbol, TypeBoundClass> env, TypeBoundClass info) { if (info.superclass() != null) { addSuperTypes(closure, env, info.superclass()); } @@ -168,11 +109,11 @@ public class Dependencies { private static void addPackageInfos(Set<ClassSymbol> closure, BindingResult bound) { Set<ClassSymbol> packages = new LinkedHashSet<>(); for (ClassSymbol sym : closure) { - String packageName = sym.packageName(); - if (packageName.isEmpty()) { + int idx = sym.binaryName().lastIndexOf('/'); + if (idx == -1) { continue; } - packages.add(new ClassSymbol(packageName + "/package-info")); + packages.add(new ClassSymbol(sym.binaryName().substring(0, idx) + "/package-info")); } for (ClassSymbol pkg : packages) { if (bound.classPathEnv().get(pkg) != null) { @@ -193,7 +134,6 @@ public class Dependencies { ImmutableList<String> depsArtifacts) { if (directJars.isEmpty()) { // the compilation doesn't support strict deps (e.g. proto libraries) - // TODO(cushon): make this a usage error return transitiveClasspath; } Set<String> reduced = new HashSet<>(directJars); @@ -213,6 +153,8 @@ public class Dependencies { case INCOMPLETE: case UNUSED: break; + default: + throw new AssertionError(dep.getKind()); } } } diff --git a/java/com/google/turbine/deps/Transitive.java b/java/com/google/turbine/deps/Transitive.java index 8b0d44d..f9a29a1 100644 --- a/java/com/google/turbine/deps/Transitive.java +++ b/java/com/google/turbine/deps/Transitive.java @@ -17,6 +17,7 @@ package com.google.turbine.deps; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableList.Builder; import com.google.common.collect.ImmutableMap; import com.google.turbine.binder.Binder.BindingResult; import com.google.turbine.binder.ClassPath; @@ -64,7 +65,7 @@ public class Transitive { */ public static ClassFile trimClass(ClassFile cf) { // drop non-constant fields - ImmutableList.Builder<FieldInfo> fields = ImmutableList.builder(); + Builder<FieldInfo> fields = ImmutableList.builder(); for (FieldInfo f : cf.fields()) { if (f.value() != null) { fields.add(f); @@ -74,7 +75,7 @@ public class Transitive { // To do this for javac, we would have to scan all remaining signatures and preserve attributes // for reachable inner classes, but turbine only needs the attributes for the immediate // children or parent of the current class. - ImmutableList.Builder<InnerClass> innerClasses = ImmutableList.builder(); + Builder<InnerClass> innerClasses = ImmutableList.builder(); for (InnerClass i : cf.innerClasses()) { if (i.innerClass().equals(cf.name()) || i.outerClass().equals(cf.name())) { innerClasses.add(i); diff --git a/java/com/google/turbine/diag/SourceFile.java b/java/com/google/turbine/diag/SourceFile.java index 3868252..cb4133b 100644 --- a/java/com/google/turbine/diag/SourceFile.java +++ b/java/com/google/turbine/diag/SourceFile.java @@ -16,25 +16,12 @@ package com.google.turbine.diag; -import com.google.common.base.Supplier; -import com.google.common.base.Suppliers; -import java.util.Objects; - /** A source file. */ public class SourceFile { private final String path; private final String source; - private final Supplier<LineMap> lineMap = - Suppliers.memoize( - new Supplier<LineMap>() { - @Override - public LineMap get() { - return LineMap.create(source); - } - }); - public SourceFile(String path, String source) { this.path = path; this.source = source; @@ -49,22 +36,4 @@ public class SourceFile { public String source() { return source; } - - LineMap lineMap() { - return lineMap.get(); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof SourceFile)) { - return false; - } - SourceFile that = (SourceFile) obj; - return Objects.equals(path, that.path) && source.equals(that.source); - } - - @Override - public int hashCode() { - return path != null ? path.hashCode() : 0; - } } diff --git a/java/com/google/turbine/diag/TurbineDiagnostic.java b/java/com/google/turbine/diag/TurbineDiagnostic.java index ccbaa7f..0404a8e 100644 --- a/java/com/google/turbine/diag/TurbineDiagnostic.java +++ b/java/com/google/turbine/diag/TurbineDiagnostic.java @@ -16,6 +16,7 @@ package com.google.turbine.diag; +import static com.google.common.base.MoreObjects.firstNonNull; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.collect.Iterables.getOnlyElement; import static java.util.Objects.requireNonNull; @@ -26,29 +27,18 @@ import com.google.common.collect.ImmutableList; import com.google.turbine.binder.sym.ClassSymbol; import com.google.turbine.diag.TurbineError.ErrorKind; import java.util.Objects; -import javax.tools.Diagnostic; -import org.checkerframework.checker.nullness.qual.Nullable; /** A compilation error. */ public class TurbineDiagnostic { - private final Diagnostic.Kind severity; private final ErrorKind kind; + private final String diagnostic; private final ImmutableList<Object> args; - private final @Nullable SourceFile source; - private final int position; - private TurbineDiagnostic( - Diagnostic.Kind severity, - ErrorKind kind, - ImmutableList<Object> args, - @Nullable SourceFile source, - int position) { - this.severity = requireNonNull(severity); + private TurbineDiagnostic(ErrorKind kind, String diagnostic, ImmutableList<Object> args) { this.kind = requireNonNull(kind); + this.diagnostic = requireNonNull(diagnostic); this.args = requireNonNull(args); - this.source = source; - this.position = position; } /** The diagnostic kind. */ @@ -56,28 +46,9 @@ public class TurbineDiagnostic { return kind; } - /** - * The diagnostic severity (error, warning, ...). Turbine only produces errors, non-error - * diagnostics are only ever created by annotation processors. - */ - public Diagnostic.Kind severity() { - return severity; - } - /** The diagnostic message. */ public String diagnostic() { - StringBuilder sb = new StringBuilder(path()); - if (line() != -1) { - sb.append(':').append(line()); - } - sb.append(": error: "); - sb.append(message().trim()).append(System.lineSeparator()); - if (line() != -1 && column() != -1) { - sb.append(CharMatcher.breakingWhitespace().trimTrailingFrom(source.lineMap().line(position))) - .append(System.lineSeparator()); - sb.append(Strings.repeat(" ", column() - 1)).append('^'); - } - return sb.toString(); + return diagnostic; } /** The diagnostic arguments. */ @@ -86,28 +57,20 @@ public class TurbineDiagnostic { } private static TurbineDiagnostic create( - Diagnostic.Kind severity, - ErrorKind kind, - ImmutableList<Object> args, - SourceFile source, - int position) { + ErrorKind kind, String diagnostic, ImmutableList<Object> args) { switch (kind) { case SYMBOL_NOT_FOUND: { checkArgument( args.size() == 1 && getOnlyElement(args) instanceof ClassSymbol, - "diagnostic (%s) has invalid argument %s", - kind, + "diagnostic (%s) has invalid argument args %s", + diagnostic, args); break; } default: // fall out } - return new TurbineDiagnostic(severity, kind, args, source, position); - } - - public static TurbineDiagnostic format(Diagnostic.Kind severity, ErrorKind kind, String message) { - return create(severity, kind, ImmutableList.of(message), null, -1); + return new TurbineDiagnostic(kind, diagnostic, args); } /** @@ -118,7 +81,10 @@ public class TurbineDiagnostic { * @param args format args */ public static TurbineDiagnostic format(SourceFile source, ErrorKind kind, Object... args) { - return create(Diagnostic.Kind.ERROR, kind, ImmutableList.copyOf(args), source, -1); + String path = firstNonNull(source.path(), "<>"); + String message = kind.format(args); + String diagnostic = path + ": error: " + message.trim() + System.lineSeparator(); + return create(kind, diagnostic, ImmutableList.copyOf(args)); } /** @@ -129,13 +95,26 @@ public class TurbineDiagnostic { * @param args format args */ public static TurbineDiagnostic format( - Diagnostic.Kind severity, SourceFile source, int position, ErrorKind kind, Object... args) { - return create(severity, kind, ImmutableList.copyOf(args), source, position); + SourceFile source, int position, ErrorKind kind, Object... args) { + String path = firstNonNull(source.path(), "<>"); + LineMap lineMap = LineMap.create(source.source()); + int lineNumber = lineMap.lineNumber(position); + int column = lineMap.column(position); + String message = kind.format(args); + + StringBuilder sb = new StringBuilder(path).append(":"); + sb.append(lineNumber).append(": error: "); + sb.append(message.trim()).append(System.lineSeparator()); + sb.append(CharMatcher.breakingWhitespace().trimTrailingFrom(lineMap.line(position))) + .append(System.lineSeparator()); + sb.append(Strings.repeat(" ", column)).append('^'); + String diagnostic = sb.toString(); + return create(kind, diagnostic, ImmutableList.copyOf(args)); } @Override public int hashCode() { - return Objects.hash(kind, source, position); + return Objects.hash(diagnostic, kind); } @Override @@ -144,26 +123,6 @@ public class TurbineDiagnostic { return false; } TurbineDiagnostic that = (TurbineDiagnostic) obj; - return severity.equals(that.severity) - && kind.equals(that.kind) - && args.equals(that.args) - && Objects.equals(source, that.source) - && position == that.position; - } - - public String path() { - return source != null && source.path() != null ? source.path() : "<>"; - } - - public int line() { - return position != -1 ? source.lineMap().lineNumber(position) : -1; - } - - public int column() { - return position != -1 ? source.lineMap().column(position) + 1 : -1; - } - - public String message() { - return kind.format(args.toArray()); + return diagnostic.equals(that.diagnostic) && kind.equals(that.kind); } } diff --git a/java/com/google/turbine/diag/TurbineError.java b/java/com/google/turbine/diag/TurbineError.java index 39244b5..b8b2a54 100644 --- a/java/com/google/turbine/diag/TurbineError.java +++ b/java/com/google/turbine/diag/TurbineError.java @@ -19,7 +19,6 @@ package com.google.turbine.diag; import static java.util.stream.Collectors.joining; import com.google.common.collect.ImmutableList; -import javax.tools.Diagnostic; /** A compilation error. */ public class TurbineError extends Error { @@ -32,7 +31,6 @@ public class TurbineError extends Error { UNTERMINATED_STRING("unterminated string literal"), UNTERMINATED_CHARACTER_LITERAL("unterminated char literal"), UNTERMINATED_EXPRESSION("unterminated expression, expected ';' not found"), - INVALID_UNICODE("illegal unicode escape"), EMPTY_CHARACTER_LITERAL("empty char literal"), EXPECTED_TOKEN("expected token %s"), INVALID_LITERAL("invalid literal: %s"), @@ -44,14 +42,11 @@ public class TurbineError extends Error { INVALID_ANNOTATION_ARGUMENT("invalid annotation argument"), CANNOT_RESOLVE("could not resolve %s"), EXPRESSION_ERROR("could not evaluate constant expression"), - OPERAND_TYPE("bad operand type %s"), CYCLIC_HIERARCHY("cycle in class hierarchy: %s"), NOT_AN_ANNOTATION("%s is not an annotation"), NONREPEATABLE_ANNOTATION("%s is not @Repeatable"), DUPLICATE_DECLARATION("duplicate declaration of %s"), - BAD_MODULE_INFO("unexpected declaration found in module-info"), - UNCLOSED_COMMENT("unclosed comment"), - PROC("%s"); + BAD_MODULE_INFO("unexpected declaration found in module-info"); private final String message; @@ -85,21 +80,16 @@ public class TurbineError extends Error { public static TurbineError format( SourceFile source, int position, ErrorKind kind, Object... args) { return new TurbineError( - ImmutableList.of( - TurbineDiagnostic.format(Diagnostic.Kind.ERROR, source, position, kind, args))); + ImmutableList.of(TurbineDiagnostic.format(source, position, kind, args))); } private final ImmutableList<TurbineDiagnostic> diagnostics; public TurbineError(ImmutableList<TurbineDiagnostic> diagnostics) { + super(diagnostics.stream().map(d -> d.diagnostic()).collect(joining("\n"))); this.diagnostics = diagnostics; } - @Override - public String getMessage() { - return diagnostics.stream().map(d -> d.diagnostic()).collect(joining(System.lineSeparator())); - } - public ImmutableList<TurbineDiagnostic> diagnostics() { return diagnostics; } diff --git a/java/com/google/turbine/diag/TurbineLog.java b/java/com/google/turbine/diag/TurbineLog.java index b336e25..fd8fc38 100644 --- a/java/com/google/turbine/diag/TurbineLog.java +++ b/java/com/google/turbine/diag/TurbineLog.java @@ -18,10 +18,8 @@ package com.google.turbine.diag; import com.google.common.collect.ImmutableList; import com.google.turbine.diag.TurbineError.ErrorKind; -import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Set; -import javax.tools.Diagnostic; /** A log that collects diagnostics. */ public class TurbineLog { @@ -33,51 +31,11 @@ public class TurbineLog { } public void maybeThrow() { - if (anyErrors()) { + if (!errors.isEmpty()) { throw new TurbineError(ImmutableList.copyOf(errors)); } } - private boolean anyErrors() { - for (TurbineDiagnostic error : errors) { - if (error.severity().equals(Diagnostic.Kind.ERROR)) { - return true; - } - } - return false; - } - - /** - * Returns true if a non-deferrable error was raised during annotation processing, i.e. an error - * reported by an annotation processor. - * - * <p>Errors reported by turbine (e.g. missing symbols) are non-fatal, since they may be fixed by - * code generated in later processing rounds. - */ - public boolean errorRaised() { - for (TurbineDiagnostic error : errors) { - if (error.kind().equals(ErrorKind.PROC) && error.severity().equals(Diagnostic.Kind.ERROR)) { - return true; - } - } - return false; - } - - /** Reset the log between annotation processing rounds. */ - public void clear() { - Iterator<TurbineDiagnostic> it = errors.iterator(); - while (it.hasNext()) { - if (it.next().severity().equals(Diagnostic.Kind.ERROR)) { - it.remove(); - } - } - } - - /** Reports an annotation processing diagnostic with no position information. */ - public void diagnostic(Diagnostic.Kind severity, String message) { - errors.add(TurbineDiagnostic.format(severity, ErrorKind.PROC, message)); - } - /** A log for a specific source file. */ public class TurbineLogWithSource { @@ -87,12 +45,12 @@ public class TurbineLog { this.source = source; } - public void diagnostic(Diagnostic.Kind severity, int position, ErrorKind kind, Object... args) { - errors.add(TurbineDiagnostic.format(severity, source, position, kind, args)); + public void error(ErrorKind kind, Object... args) { + errors.add(TurbineDiagnostic.format(source, kind, args)); } public void error(int position, ErrorKind kind, Object... args) { - diagnostic(Diagnostic.Kind.ERROR, position, kind, args); + errors.add(TurbineDiagnostic.format(source, position, kind, args)); } } } diff --git a/java/com/google/turbine/lower/Lower.java b/java/com/google/turbine/lower/Lower.java index 0f7bb90..16447ab 100644 --- a/java/com/google/turbine/lower/Lower.java +++ b/java/com/google/turbine/lower/Lower.java @@ -21,8 +21,10 @@ import static com.google.turbine.binder.DisambiguateTypeAnnotations.groupRepeate import com.google.common.base.Function; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableList.Builder; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import com.google.turbine.binder.bound.AnnotationValue; import com.google.turbine.binder.bound.EnumConstantValue; import com.google.turbine.binder.bound.ModuleInfo.ExportInfo; import com.google.turbine.binder.bound.ModuleInfo.OpenInfo; @@ -31,7 +33,6 @@ import com.google.turbine.binder.bound.ModuleInfo.RequireInfo; import com.google.turbine.binder.bound.ModuleInfo.UseInfo; import com.google.turbine.binder.bound.SourceModuleInfo; import com.google.turbine.binder.bound.SourceTypeBoundClass; -import com.google.turbine.binder.bound.TurbineAnnotationValue; import com.google.turbine.binder.bound.TurbineClassValue; import com.google.turbine.binder.bound.TypeBoundClass; import com.google.turbine.binder.bound.TypeBoundClass.FieldInfo; @@ -263,10 +264,10 @@ public class Lower { ImmutableList<AnnotationInfo> annotations = lowerAnnotations(info.annotations()); - ImmutableList<TypeAnnotationInfo> typeAnnotations = classTypeAnnotations(info); - ImmutableList<ClassFile.InnerClass> inners = collectInnerClasses(info.source(), sym, info); + ImmutableList<TypeAnnotationInfo> typeAnnotations = classTypeAnnotations(info); + ClassFile classfile = new ClassFile( access, @@ -524,8 +525,9 @@ public class Lower { return true; case SOURCE: return null; + default: + throw new AssertionError(retention); } - throw new AssertionError(retention); } private ImmutableMap<String, ElementValue> annotationValues(ImmutableMap<String, Const> values) { @@ -561,12 +563,12 @@ public class Lower { } case ANNOTATION: { - TurbineAnnotationValue annotationValue = (TurbineAnnotationValue) value; + AnnotationValue annotationValue = (AnnotationValue) value; Boolean visible = isVisible(annotationValue.sym()); if (visible == null) { visible = true; } - return new ElementValue.ConstTurbineAnnotationValue( + return new ElementValue.AnnotationValue( new AnnotationInfo( sig.objectType(annotationValue.sym()), visible, @@ -574,8 +576,9 @@ public class Lower { } case PRIMITIVE: return new ElementValue.ConstValue((Const.Value) value); + default: + throw new AssertionError(value.kind()); } - throw new AssertionError(value.kind()); } /** Lower type annotations in a class declaration's signature. */ @@ -653,7 +656,7 @@ public class Lower { * or on bounds. */ private void typeParameterAnnotations( - ImmutableList.Builder<TypeAnnotationInfo> result, + Builder<TypeAnnotationInfo> result, Iterable<TyVarInfo> typeParameters, TargetType targetType, TargetType boundTargetType) { @@ -672,7 +675,7 @@ public class Lower { info)); } int boundIndex = 0; - for (Type i : p.upperBound().bounds()) { + for (Type i : p.bound().bounds()) { if (boundIndex == 0 && isInterface(i, env)) { // super class bound index is always 0; interface bounds start at 1 boundIndex++; @@ -693,10 +696,7 @@ public class Lower { } private void lowerTypeAnnotations( - ImmutableList.Builder<TypeAnnotationInfo> result, - Type type, - TargetType targetType, - Target target) { + Builder<TypeAnnotationInfo> result, Type type, TargetType targetType, Target target) { new LowerTypeAnnotations(result, targetType, target) .lowerTypeAnnotations(type, TypePath.root()); } @@ -707,7 +707,7 @@ public class Lower { private final Target target; public LowerTypeAnnotations( - ImmutableList.Builder<TypeAnnotationInfo> result, TargetType targetType, Target target) { + Builder<TypeAnnotationInfo> result, TargetType targetType, Target target) { this.result = result; this.targetType = targetType; this.target = target; @@ -764,6 +764,8 @@ public class Lower { lowerTypeAnnotations(type.annotations(), path); lowerTypeAnnotations(type.bound(), path.wild()); break; + default: + throw new AssertionError(type.boundKind()); } } diff --git a/java/com/google/turbine/lower/LowerSignature.java b/java/com/google/turbine/lower/LowerSignature.java index 13a7b9f..fe9b912 100644 --- a/java/com/google/turbine/lower/LowerSignature.java +++ b/java/com/google/turbine/lower/LowerSignature.java @@ -92,8 +92,17 @@ public class LowerSignature { while (curr.targs().isEmpty() && it.hasNext()) { curr = it.next(); } - String pkg = curr.sym().packageName(); - classes.add(new Sig.SimpleClassTySig(curr.sym().simpleName(), tyArgSigs(curr))); + String pkg; + String name; + int idx = curr.sym().binaryName().lastIndexOf('/'); + if (idx == -1) { + pkg = ""; + name = curr.sym().binaryName(); + } else { + pkg = curr.sym().binaryName().substring(0, idx); + name = curr.sym().binaryName().substring(idx + 1); + } + classes.add(new Sig.SimpleClassTySig(name, tyArgSigs(curr))); while (it.hasNext()) { SimpleClassTy outer = curr; curr = it.next(); @@ -119,8 +128,9 @@ public class LowerSignature { return new UpperBoundTySig(signature(((Type.WildUpperBoundedTy) ty).bound())); case LOWER: return new LowerBoundTySig(signature(((Type.WildLowerBoundedTy) ty).bound())); + default: + throw new AssertionError(ty.boundKind()); } - throw new AssertionError(ty.boundKind()); } /** @@ -274,13 +284,13 @@ public class LowerSignature { String identifier = sym.name(); Sig.TySig cbound = null; ImmutableList.Builder<Sig.TySig> ibounds = ImmutableList.builder(); - if (info.upperBound().bounds().isEmpty()) { + if (info.bound().bounds().isEmpty()) { cbound = new ClassTySig( "java/lang", ImmutableList.of(new SimpleClassTySig("Object", ImmutableList.of()))); } else { boolean first = true; - for (Type bound : info.upperBound().bounds()) { + for (Type bound : info.bound().bounds()) { TySig sig = signature(bound); if (first) { if (!isInterface(bound, env)) { diff --git a/java/com/google/turbine/main/Main.java b/java/com/google/turbine/main/Main.java index 1e60ae6..34421e1 100644 --- a/java/com/google/turbine/main/Main.java +++ b/java/com/google/turbine/main/Main.java @@ -19,21 +19,15 @@ package com.google.turbine.main; import static com.google.common.base.StandardSystemProperty.JAVA_SPECIFICATION_VERSION; import static java.nio.charset.StandardCharsets.UTF_8; -import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; import com.google.common.hash.Hashing; import com.google.common.io.MoreFiles; import com.google.turbine.binder.Binder; import com.google.turbine.binder.Binder.BindingResult; -import com.google.turbine.binder.Binder.Statistics; import com.google.turbine.binder.ClassPath; import com.google.turbine.binder.ClassPathBinder; import com.google.turbine.binder.CtSymClassBinder; import com.google.turbine.binder.JimageClassBinder; -import com.google.turbine.binder.Processing; -import com.google.turbine.binder.bound.SourceTypeBoundClass; -import com.google.turbine.binder.sym.ClassSymbol; import com.google.turbine.deps.Dependencies; import com.google.turbine.deps.Transitive; import com.google.turbine.diag.SourceFile; @@ -41,12 +35,9 @@ import com.google.turbine.diag.TurbineError; import com.google.turbine.lower.Lower; import com.google.turbine.lower.Lower.Lowered; import com.google.turbine.options.TurbineOptions; -import com.google.turbine.options.TurbineOptions.ReducedClasspathMode; import com.google.turbine.options.TurbineOptionsParser; import com.google.turbine.parse.Parser; import com.google.turbine.proto.DepsProto; -import com.google.turbine.proto.ManifestProto; -import com.google.turbine.proto.ManifestProto.CompilationUnit; import com.google.turbine.tree.Tree.CompUnit; import com.google.turbine.zip.Zip; import java.io.BufferedOutputStream; @@ -84,8 +75,7 @@ public class Main { public static void main(String[] args) throws IOException { boolean ok; try { - compile(args); - ok = true; + ok = compile(args); } catch (TurbineError | UsageException e) { System.err.println(e.getMessage()); ok = false; @@ -96,182 +86,56 @@ public class Main { System.exit(ok ? 0 : 1); } - /** The result of a turbine invocation. */ - @AutoValue - public abstract static class Result { - /** Returns {@code true} if transitive classpath fallback occurred. */ - public abstract boolean transitiveClasspathFallback(); - - /** The length of the transitive classpath. */ - public abstract int transitiveClasspathLength(); - - /** - * The length of the reduced classpath, or {@link #transitiveClasspathLength} if classpath - * reduction is not supported. - */ - public abstract int reducedClasspathLength(); - - public abstract Statistics processorStatistics(); - - static Result create( - boolean transitiveClasspathFallback, - int transitiveClasspathLength, - int reducedClasspathLength, - Statistics processorStatistics) { - return new AutoValue_Main_Result( - transitiveClasspathFallback, - transitiveClasspathLength, - reducedClasspathLength, - processorStatistics); - } - } - - public static void compile(String[] args) throws IOException { - compile(TurbineOptionsParser.parse(Arrays.asList(args))); + public static boolean compile(String[] args) throws IOException { + TurbineOptions options = TurbineOptionsParser.parse(Arrays.asList(args)); + return compile(options); } - public static Result compile(TurbineOptions options) throws IOException { + public static boolean compile(TurbineOptions options) throws IOException { usage(options); ImmutableList<CompUnit> units = parseAll(options); ClassPath bootclasspath = bootclasspath(options); - BindingResult bound; - ReducedClasspathMode reducedClasspathMode = options.reducedClasspathMode(); - if (reducedClasspathMode == ReducedClasspathMode.JAVABUILDER_REDUCED - && options.directJars().isEmpty()) { - // the compilation doesn't support reduced classpaths - // TODO(cushon): make this a usage error, see TODO in Dependencies.reduceClasspath - reducedClasspathMode = ReducedClasspathMode.NONE; - } - boolean transitiveClasspathFallback = false; - ImmutableList<String> classPath = options.classPath(); - int transitiveClasspathLength = classPath.size(); - int reducedClasspathLength = classPath.size(); - switch (reducedClasspathMode) { - case NONE: - bound = bind(options, units, bootclasspath, classPath); - break; - case BAZEL_FALLBACK: - reducedClasspathLength = options.reducedClasspathLength(); - bound = bind(options, units, bootclasspath, classPath); - transitiveClasspathFallback = true; - break; - case JAVABUILDER_REDUCED: - Collection<String> reducedClasspath = - Dependencies.reduceClasspath(classPath, options.directJars(), options.depsArtifacts()); - reducedClasspathLength = reducedClasspath.size(); - try { - bound = bind(options, units, bootclasspath, reducedClasspath); - } catch (TurbineError e) { - bound = fallback(options, units, bootclasspath, classPath); - transitiveClasspathFallback = true; - } - break; - case BAZEL_REDUCED: - transitiveClasspathLength = options.fullClasspathLength(); - try { - bound = bind(options, units, bootclasspath, classPath); - } catch (TurbineError e) { - writeJdepsForFallback(options); - return Result.create( - /* transitiveClasspathFallback= */ true, - /* transitiveClasspathLength= */ transitiveClasspathLength, - /* reducedClasspathLength= */ reducedClasspathLength, - Statistics.empty()); - } - break; - default: - throw new AssertionError(reducedClasspathMode); - } + Collection<String> reducedClasspath = + Dependencies.reduceClasspath( + options.classPath(), options.directJars(), options.depsArtifacts()); + ClassPath classpath = ClassPathBinder.bindClasspath(toPaths(reducedClasspath)); - if (options.outputDeps().isPresent() - || options.output().isPresent() - || options.outputManifest().isPresent()) { - // TODO(cushon): parallelize - Lowered lowered = Lower.lowerAll(bound.units(), bound.modules(), bound.classPathEnv()); + BindingResult bound = + Binder.bind(units, classpath, bootclasspath, /* moduleVersion=*/ Optional.empty()); - if (options.outputDeps().isPresent()) { - DepsProto.Dependencies deps = - Dependencies.collectDeps(options.targetLabel(), bootclasspath, bound, lowered); - try (OutputStream os = - new BufferedOutputStream( - Files.newOutputStream(Paths.get(options.outputDeps().get())))) { - deps.writeTo(os); - } - } - if (options.output().isPresent()) { - Map<String, byte[]> transitive = Transitive.collectDeps(bootclasspath, bound); - writeOutput(options, bound.generatedClasses(), lowered.bytes(), transitive); - } - if (options.outputManifest().isPresent()) { - writeManifestProto(options, bound.units(), bound.generatedSources()); - } - } + // TODO(cushon): parallelize + Lowered lowered = Lower.lowerAll(bound.units(), bound.modules(), bound.classPathEnv()); - writeSources(options, bound.generatedSources()); - writeResources(options, bound.generatedClasses()); - return Result.create( - /* transitiveClasspathFallback= */ transitiveClasspathFallback, - /* transitiveClasspathLength= */ transitiveClasspathLength, - /* reducedClasspathLength= */ reducedClasspathLength, - bound.statistics()); - } + Map<String, byte[]> transitive = Transitive.collectDeps(bootclasspath, bound); - // don't inline this; we want it to show up in profiles - private static BindingResult fallback( - TurbineOptions options, - ImmutableList<CompUnit> units, - ClassPath bootclasspath, - ImmutableList<String> classPath) - throws IOException { - return bind(options, units, bootclasspath, classPath); - } - - /** - * Writes a jdeps proto that indiciates to Blaze that the transitive classpath compilation failed, - * and it should fall back to the transitive classpath. Used only when {@link - * ReducedClasspathMode#BAZEL_REDUCED}. - */ - public static void writeJdepsForFallback(TurbineOptions options) throws IOException { - try (OutputStream os = - new BufferedOutputStream(Files.newOutputStream(Paths.get(options.outputDeps().get())))) { - DepsProto.Dependencies.newBuilder() - .setRuleLabel(options.targetLabel().get()) - .setRequiresReducedClasspathFallback(true) - .build() - .writeTo(os); + if (options.outputDeps().isPresent()) { + DepsProto.Dependencies deps = + Dependencies.collectDeps(options.targetLabel(), bootclasspath, bound, lowered); + try (OutputStream os = + new BufferedOutputStream(Files.newOutputStream(Paths.get(options.outputDeps().get())))) { + deps.writeTo(os); + } } - } - private static BindingResult bind( - TurbineOptions options, - ImmutableList<CompUnit> units, - ClassPath bootclasspath, - Collection<String> classpath) - throws IOException { - return Binder.bind( - units, - ClassPathBinder.bindClasspath(toPaths(classpath)), - Processing.initializeProcessors( - /* javacopts= */ options.javacOpts(), - /* processorPath= */ options.processorPath(), - /* processorNames= */ options.processors(), - /* builtinProcessors= */ options.builtinProcessors()), - bootclasspath, - /* moduleVersion=*/ Optional.empty()); + writeOutput(options, lowered.bytes(), transitive); + return true; } private static void usage(TurbineOptions options) { + if (!options.processors().isEmpty()) { + throw new UsageException("--processors is not supported"); + } + if (options.sources().isEmpty() && options.sourceJars().isEmpty()) { + throw new UsageException("no sources were provided"); + } if (options.help()) { throw new UsageException(); } - if (!options.output().isPresent() - && !options.gensrcOutput().isPresent() - && !options.resourceOutput().isPresent()) { - throw new UsageException( - "at least one of --output, --gensrc_output, or --resource_output is required"); + if (!options.output().isPresent()) { + throw new UsageException("--output is required"); } } @@ -324,46 +188,9 @@ public class Main { return units.build(); } - /** Writes source files generated by annotation processors. */ - private static void writeSources( - TurbineOptions options, ImmutableMap<String, SourceFile> generatedSources) - throws IOException { - if (!options.gensrcOutput().isPresent()) { - return; - } - Path path = Paths.get(options.gensrcOutput().get()); - try (OutputStream os = Files.newOutputStream(path); - BufferedOutputStream bos = new BufferedOutputStream(os, BUFFER_SIZE); - JarOutputStream jos = new JarOutputStream(bos)) { - for (SourceFile source : generatedSources.values()) { - addEntry(jos, source.path(), source.source().getBytes(UTF_8)); - } - writeManifest(jos, manifest()); - } - } - - /** Writes resource files generated by annotation processors. */ - private static void writeResources( - TurbineOptions options, ImmutableMap<String, byte[]> generatedResources) throws IOException { - if (!options.resourceOutput().isPresent()) { - return; - } - Path path = Paths.get(options.resourceOutput().get()); - try (OutputStream os = Files.newOutputStream(path); - BufferedOutputStream bos = new BufferedOutputStream(os, BUFFER_SIZE); - JarOutputStream jos = new JarOutputStream(bos)) { - for (Map.Entry<String, byte[]> resource : generatedResources.entrySet()) { - addEntry(jos, resource.getKey(), resource.getValue()); - } - } - } - - /** Writes bytecode to the output jar. */ + /** Write bytecode to the output jar. */ private static void writeOutput( - TurbineOptions options, - Map<String, byte[]> generated, - Map<String, byte[]> lowered, - Map<String, byte[]> transitive) + TurbineOptions options, Map<String, byte[]> lowered, Map<String, byte[]> transitive) throws IOException { Path path = Paths.get(options.output().get()); try (OutputStream os = Files.newOutputStream(path); @@ -372,42 +199,17 @@ public class Main { for (Map.Entry<String, byte[]> entry : lowered.entrySet()) { addEntry(jos, entry.getKey() + ".class", entry.getValue()); } - for (Map.Entry<String, byte[]> entry : generated.entrySet()) { - addEntry(jos, entry.getKey(), entry.getValue()); - } for (Map.Entry<String, byte[]> entry : transitive.entrySet()) { addEntry( jos, ClassPathBinder.TRANSITIVE_PREFIX + entry.getKey() + ".class", entry.getValue()); } if (options.targetLabel().isPresent()) { - writeManifest(jos, manifest(options)); + addEntry(jos, MANIFEST_DIR, new byte[] {}); + addEntry(jos, MANIFEST_NAME, manifestContent(options)); } } } - private static void writeManifestProto( - TurbineOptions options, - ImmutableMap<ClassSymbol, SourceTypeBoundClass> units, - ImmutableMap<String, SourceFile> generatedSources) - throws IOException { - ManifestProto.Manifest.Builder manifest = ManifestProto.Manifest.newBuilder(); - for (Map.Entry<ClassSymbol, SourceTypeBoundClass> e : units.entrySet()) { - manifest.addCompilationUnit( - CompilationUnit.newBuilder() - .setPath(e.getValue().source().path()) - .setPkg(e.getKey().packageName()) - .addTopLevel(e.getKey().simpleName()) - .setGeneratedByAnnotationProcessor( - generatedSources.containsKey(e.getValue().source().path())) - .build()); - } - try (OutputStream os = - new BufferedOutputStream( - Files.newOutputStream(Paths.get(options.outputManifest().get())))) { - manifest.build().writeTo(os); - } - } - /** Normalize timestamps. */ static final long DEFAULT_TIMESTAMP = LocalDateTime.of(2010, 1, 1, 0, 0, 0) @@ -426,15 +228,7 @@ public class Main { jos.write(bytes); } - private static void writeManifest(JarOutputStream jos, Manifest manifest) throws IOException { - addEntry(jos, MANIFEST_DIR, new byte[] {}); - ByteArrayOutputStream out = new ByteArrayOutputStream(); - manifest.write(out); - addEntry(jos, MANIFEST_NAME, out.toByteArray()); - } - - /** Creates a default {@link Manifest}. */ - private static Manifest manifest() { + private static byte[] manifestContent(TurbineOptions turbineOptions) throws IOException { Manifest manifest = new Manifest(); Attributes attributes = manifest.getMainAttributes(); attributes.put(Attributes.Name.MANIFEST_VERSION, "1.0"); @@ -442,20 +236,15 @@ public class Main { if (attributes.getValue(createdBy) == null) { attributes.put(createdBy, "bazel"); } - return manifest; - } - - /** Creates a {@link Manifest} that includes the target label and injecting rule kind. */ - private static Manifest manifest(TurbineOptions turbineOptions) { - Manifest manifest = manifest(); - Attributes attributes = manifest.getMainAttributes(); if (turbineOptions.targetLabel().isPresent()) { attributes.put(TARGET_LABEL, turbineOptions.targetLabel().get()); } if (turbineOptions.injectingRuleKind().isPresent()) { attributes.put(INJECTING_RULE_KIND, turbineOptions.injectingRuleKind().get()); } - return manifest; + ByteArrayOutputStream out = new ByteArrayOutputStream(); + manifest.write(out); + return out.toByteArray(); } private static ImmutableList<Path> toPaths(Iterable<String> paths) { diff --git a/java/com/google/turbine/model/Const.java b/java/com/google/turbine/model/Const.java index ed4b072..6e41bd2 100644 --- a/java/com/google/turbine/model/Const.java +++ b/java/com/google/turbine/model/Const.java @@ -18,9 +18,6 @@ package com.google.turbine.model; import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; -import com.google.common.escape.SourceCodeEscapers; -import javax.lang.model.element.AnnotationValue; -import javax.lang.model.element.AnnotationValueVisitor; /** * Compile-time constant expressions, including literals of primitive or String type, class @@ -34,9 +31,6 @@ public abstract class Const { @Override public abstract boolean equals(Object obj); - @Override - public abstract String toString(); - /** The constant kind. */ public abstract Kind kind(); @@ -57,7 +51,7 @@ public abstract class Const { } /** Subtypes of {@link Const} for primitive and String literals. */ - public abstract static class Value extends Const implements AnnotationValue { + public abstract static class Value extends Const { public abstract TurbineConstantTypeKind constantTypeKind(); @Override @@ -116,11 +110,6 @@ public abstract class Const { } @Override - public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) { - return v.visitBoolean(value, p); - } - - @Override public TurbineConstantTypeKind constantTypeKind() { return TurbineConstantTypeKind.BOOLEAN; } @@ -130,11 +119,6 @@ public abstract class Const { } @Override - public Object getValue() { - return value; - } - - @Override public BooleanValue asBoolean() { return this; } @@ -170,11 +154,6 @@ public abstract class Const { } @Override - public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) { - return v.visitInt(value, p); - } - - @Override public TurbineConstantTypeKind constantTypeKind() { return TurbineConstantTypeKind.INT; } @@ -184,11 +163,6 @@ public abstract class Const { } @Override - public Object getValue() { - return value; - } - - @Override public IntValue asInteger() { return this; } @@ -253,11 +227,6 @@ public abstract class Const { } @Override - public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) { - return v.visitLong(value, p); - } - - @Override public TurbineConstantTypeKind constantTypeKind() { return TurbineConstantTypeKind.LONG; } @@ -267,11 +236,6 @@ public abstract class Const { } @Override - public Object getValue() { - return value; - } - - @Override public IntValue asInteger() { return new IntValue((int) value); } @@ -332,12 +296,7 @@ public abstract class Const { @Override public String toString() { - return "'" + SourceCodeEscapers.javaCharEscaper().escape(String.valueOf(value)) + "'"; - } - - @Override - public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) { - return v.visitChar(value, p); + return "'" + value + "'"; } @Override @@ -350,11 +309,6 @@ public abstract class Const { } @Override - public Object getValue() { - return value; - } - - @Override public IntValue asInteger() { return new IntValue((int) value); } @@ -415,18 +369,10 @@ public abstract class Const { @Override public String toString() { - if (Float.isNaN(value)) { - return "0.0f/0.0f"; - } return value + "f"; } @Override - public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) { - return v.visitFloat(value, p); - } - - @Override public TurbineConstantTypeKind constantTypeKind() { return TurbineConstantTypeKind.FLOAT; } @@ -436,11 +382,6 @@ public abstract class Const { } @Override - public Object getValue() { - return value; - } - - @Override public IntValue asInteger() { return new IntValue((int) value); } @@ -501,24 +442,10 @@ public abstract class Const { @Override public String toString() { - if (Double.isNaN(value)) { - return "0.0/0.0"; - } - if (value == Double.POSITIVE_INFINITY) { - return "1.0/0.0"; - } - if (value == Double.NEGATIVE_INFINITY) { - return "-1.0/0.0"; - } return String.valueOf(value); } @Override - public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) { - return v.visitDouble(value, p); - } - - @Override public TurbineConstantTypeKind constantTypeKind() { return TurbineConstantTypeKind.DOUBLE; } @@ -528,11 +455,6 @@ public abstract class Const { } @Override - public Object getValue() { - return value; - } - - @Override public IntValue asInteger() { return new IntValue((int) value); } @@ -593,12 +515,7 @@ public abstract class Const { @Override public String toString() { - return '"' + SourceCodeEscapers.javaCharEscaper().escape(value) + '"'; - } - - @Override - public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) { - return v.visitString(value, p); + return String.format("\"%s\"", value); } @Override @@ -611,11 +528,6 @@ public abstract class Const { } @Override - public Object getValue() { - return value; - } - - @Override public StringValue asString() { return this; } @@ -645,11 +557,6 @@ public abstract class Const { } @Override - public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) { - return v.visitShort(value, p); - } - - @Override public TurbineConstantTypeKind constantTypeKind() { return TurbineConstantTypeKind.SHORT; } @@ -659,11 +566,6 @@ public abstract class Const { } @Override - public Object getValue() { - return value; - } - - @Override public IntValue asInteger() { return new IntValue((int) value); } @@ -733,11 +635,6 @@ public abstract class Const { } @Override - public Object getValue() { - return value; - } - - @Override public IntValue asInteger() { return new IntValue((int) value); } @@ -789,12 +686,7 @@ public abstract class Const { @Override public String toString() { - return String.format("(byte)0x%02x", value); - } - - @Override - public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) { - return v.visitByte(value, p); + return String.valueOf(value); } } diff --git a/java/com/google/turbine/options/TurbineOptions.java b/java/com/google/turbine/options/TurbineOptions.java index 4dcc408..0ce0c13 100644 --- a/java/com/google/turbine/options/TurbineOptions.java +++ b/java/com/google/turbine/options/TurbineOptions.java @@ -16,59 +16,104 @@ package com.google.turbine.options; -import com.google.auto.value.AutoValue; +import static com.google.common.base.Preconditions.checkNotNull; + import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import java.util.Optional; import org.checkerframework.checker.nullness.qual.Nullable; /** Header compilation options. */ -@AutoValue -public abstract class TurbineOptions { - - /** - * This modes controls how a probablistic Java classpath reduction is used. For each mode except - * {@code NONE} a speculative compilation is performed against a subset of the original classpath. - * If it fails due to a missing symbol, it is retried with the original transitive classpath. - */ - public enum ReducedClasspathMode { - /** - * Bazel performs classpath reduction, and invokes turbine passing only the reduced classpath. - * If the compilation fails and requires fallback, turbine finishes with exit code 0 but records - * that the reduced classpath compilation failed in the jdeps proto. - */ - BAZEL_REDUCED, - /** - * Indicates that the reduced classpath compilation failed when Bazel previously invoked - * turbine, and that we are retrying with a transitive classpath. - */ - BAZEL_FALLBACK, - /** - * Turbine implements reduced classpaths locally, with in-process fallback if the compilation - * fails. - */ - JAVABUILDER_REDUCED, - /** Reduced classpaths are disabled, and a full transitive classpath is used. */ - NONE +public class TurbineOptions { + + private final Optional<String> output; + private final ImmutableList<String> classPath; + private final ImmutableSet<String> bootClassPath; + private final Optional<String> release; + private final Optional<String> system; + private final ImmutableList<String> sources; + private final ImmutableList<String> processorPath; + private final ImmutableSet<String> processors; + private final ImmutableList<String> sourceJars; + private final Optional<String> outputDeps; + private final ImmutableSet<String> directJars; + private final Optional<String> targetLabel; + private final Optional<String> injectingRuleKind; + private final ImmutableList<String> depsArtifacts; + private final boolean javacFallback; + private final boolean help; + private final ImmutableList<String> javacOpts; + private final boolean shouldReduceClassPath; + + private TurbineOptions( + @Nullable String output, + ImmutableList<String> classPath, + ImmutableSet<String> bootClassPath, + @Nullable String release, + @Nullable String system, + ImmutableList<String> sources, + ImmutableList<String> processorPath, + ImmutableSet<String> processors, + ImmutableList<String> sourceJars, + @Nullable String outputDeps, + ImmutableSet<String> directJars, + @Nullable String targetLabel, + @Nullable String injectingRuleKind, + ImmutableList<String> depsArtifacts, + boolean javacFallback, + boolean help, + ImmutableList<String> javacOpts, + boolean shouldReduceClassPath) { + this.output = Optional.ofNullable(output); + this.classPath = checkNotNull(classPath, "classPath must not be null"); + this.bootClassPath = checkNotNull(bootClassPath, "bootClassPath must not be null"); + this.release = Optional.ofNullable(release); + this.system = Optional.ofNullable(system); + this.sources = checkNotNull(sources, "sources must not be null"); + this.processorPath = checkNotNull(processorPath, "processorPath must not be null"); + this.processors = checkNotNull(processors, "processors must not be null"); + this.sourceJars = checkNotNull(sourceJars, "sourceJars must not be null"); + this.outputDeps = Optional.ofNullable(outputDeps); + this.directJars = checkNotNull(directJars, "directJars must not be null"); + this.targetLabel = Optional.ofNullable(targetLabel); + this.injectingRuleKind = Optional.ofNullable(injectingRuleKind); + this.depsArtifacts = checkNotNull(depsArtifacts, "depsArtifacts must not be null"); + this.javacFallback = javacFallback; + this.help = help; + this.javacOpts = checkNotNull(javacOpts, "javacOpts must not be null"); + this.shouldReduceClassPath = shouldReduceClassPath; } /** Paths to the Java source files to compile. */ - public abstract ImmutableList<String> sources(); + public ImmutableList<String> sources() { + return sources; + } /** Paths to classpath artifacts. */ - public abstract ImmutableList<String> classPath(); + public ImmutableList<String> classPath() { + return classPath; + } /** Paths to compilation bootclasspath artifacts. */ - public abstract ImmutableSet<String> bootClassPath(); + public ImmutableSet<String> bootClassPath() { + return bootClassPath; + } /** The target platform version. */ - public abstract Optional<String> release(); + public Optional<String> release() { + return release; + } /** The target platform's system modules. */ - public abstract Optional<String> system(); + public Optional<String> system() { + return system; + } /** The output jar. */ - public abstract Optional<String> output(); + @Nullable + public Optional<String> output() { + return output; + } /** * The output jar. @@ -78,187 +123,214 @@ public abstract class TurbineOptions { @Deprecated @Nullable public String outputFile() { - return output().orElse(null); + return output.orElse(null); } /** Paths to annotation processor artifacts. */ - public abstract ImmutableList<String> processorPath(); + public ImmutableList<String> processorPath() { + return processorPath; + } /** Annotation processor class names. */ - public abstract ImmutableSet<String> processors(); - - /** Class names of annotation processor that are built in. */ - public abstract ImmutableSet<String> builtinProcessors(); + public ImmutableSet<String> processors() { + return processors; + } /** Source jars for compilation. */ - public abstract ImmutableList<String> sourceJars(); + public ImmutableList<String> sourceJars() { + return sourceJars; + } /** Output jdeps file. */ - public abstract Optional<String> outputDeps(); - - /** Output manifest file. */ - public abstract Optional<String> outputManifest(); + public Optional<String> outputDeps() { + return outputDeps; + } /** The direct dependencies. */ - public abstract ImmutableSet<String> directJars(); + public ImmutableSet<String> directJars() { + return directJars; + } /** The label of the target being compiled. */ - public abstract Optional<String> targetLabel(); + public Optional<String> targetLabel() { + return targetLabel; + } /** * If present, the name of the rule that injected an aspect that compiles this target. * * <p>Note that this rule will have a completely different label to {@link #targetLabel} above. */ - public abstract Optional<String> injectingRuleKind(); + public Optional<String> injectingRuleKind() { + return injectingRuleKind; + } /** The .jdeps artifacts for direct dependencies. */ - public abstract ImmutableList<String> depsArtifacts(); + public ImmutableList<String> depsArtifacts() { + return depsArtifacts; + } + + /** Fall back to javac-turbine for error reporting. */ + public boolean javacFallback() { + return javacFallback; + } /** Print usage information. */ - public abstract boolean help(); + public boolean help() { + return help; + } /** Additional Java compiler flags. */ - public abstract ImmutableList<String> javacOpts(); - - /** The reduced classpath optimization mode. */ - public abstract ReducedClasspathMode reducedClasspathMode(); - - /** An optional path for profiling output. */ - public abstract Optional<String> profile(); - - /** An optional path for generated source output. */ - public abstract Optional<String> gensrcOutput(); - - /** An optional path for generated resource output. */ - public abstract Optional<String> resourceOutput(); - - public abstract int fullClasspathLength(); + public ImmutableList<String> javacOpts() { + return javacOpts; + } - public abstract int reducedClasspathLength(); + /** Returns true if the reduced classpath optimization is enabled. */ + public boolean shouldReduceClassPath() { + return shouldReduceClassPath; + } public static Builder builder() { - return new AutoValue_TurbineOptions.Builder() - .setSources(ImmutableList.of()) - .setClassPath(ImmutableList.of()) - .setBootClassPath(ImmutableList.of()) - .setProcessorPath(ImmutableList.of()) - .setProcessors(ImmutableList.of()) - .setBuiltinProcessors(ImmutableList.of()) - .setSourceJars(ImmutableList.of()) - .setDirectJars(ImmutableList.of()) - .setDepsArtifacts(ImmutableList.of()) - .addAllJavacOpts(ImmutableList.of()) - .setReducedClasspathMode(ReducedClasspathMode.NONE) - .setHelp(false) - .setFullClasspathLength(0) - .setReducedClasspathLength(0); + return new Builder(); } /** A {@link Builder} for {@link TurbineOptions}. */ - @AutoValue.Builder - public abstract static class Builder { - public abstract Builder setOutput(String output); - - /** @deprecated use {@link #setClassPath(ImmutableList)} instead. */ - @Deprecated - public Builder addClassPathEntries(Iterable<String> sources) { - return setClassPath(ImmutableList.copyOf(sources)); + public static class Builder { + + private String output; + private final ImmutableList.Builder<String> classPath = ImmutableList.builder(); + private final ImmutableList.Builder<String> sources = ImmutableList.builder(); + private final ImmutableList.Builder<String> processorPath = ImmutableList.builder(); + private final ImmutableSet.Builder<String> processors = ImmutableSet.builder(); + private final ImmutableList.Builder<String> sourceJars = ImmutableList.builder(); + private final ImmutableSet.Builder<String> bootClassPath = ImmutableSet.builder(); + @Nullable private String release; + @Nullable private String system; + private String outputDeps; + private final ImmutableSet.Builder<String> directJars = ImmutableSet.builder(); + @Nullable private String targetLabel; + @Nullable private String injectingRuleKind; + private final ImmutableList.Builder<String> depsArtifacts = ImmutableList.builder(); + private boolean javacFallback = true; + private boolean help = false; + private final ImmutableList.Builder<String> javacOpts = ImmutableList.builder(); + private boolean shouldReduceClassPath = true; + + public TurbineOptions build() { + return new TurbineOptions( + output, + classPath.build(), + bootClassPath.build(), + release, + system, + sources.build(), + processorPath.build(), + processors.build(), + sourceJars.build(), + outputDeps, + directJars.build(), + targetLabel, + injectingRuleKind, + depsArtifacts.build(), + javacFallback, + help, + javacOpts.build(), + shouldReduceClassPath); } - public abstract Builder setClassPath(ImmutableList<String> classPath); - - public abstract Builder setBootClassPath(ImmutableList<String> bootClassPath); + public Builder setOutput(String output) { + this.output = output; + return this; + } - /** @deprecated use {@link #setBootClassPath(ImmutableList)} instead. */ - @Deprecated - public Builder addBootClassPathEntries(Iterable<String> sources) { - return setBootClassPath(ImmutableList.copyOf(sources)); + public Builder addClassPathEntries(Iterable<String> classPath) { + this.classPath.addAll(classPath); + return this; } - public abstract Builder setRelease(String release); + public Builder addBootClassPathEntries(Iterable<String> bootClassPath) { + this.bootClassPath.addAll(bootClassPath); + return this; + } - public abstract Builder setSystem(String system); + public Builder setRelease(String release) { + this.release = release; + return this; + } - public abstract Builder setSources(ImmutableList<String> sources); + public Builder setSystem(String system) { + this.system = system; + return this; + } - /** @deprecated use {@link #setSources(ImmutableList)} instead. */ - @Deprecated public Builder addSources(Iterable<String> sources) { - return setSources(ImmutableList.copyOf(sources)); + this.sources.addAll(sources); + return this; } - /** @deprecated use {@link #setProcessorPath(ImmutableList)} instead. */ - @Deprecated public Builder addProcessorPathEntries(Iterable<String> processorPath) { - return setProcessorPath(ImmutableList.copyOf(processorPath)); + this.processorPath.addAll(processorPath); + return this; } - public abstract Builder setProcessorPath(ImmutableList<String> processorPath); - - /** @deprecated use {@link #setProcessors(ImmutableList)} instead. */ - @Deprecated public Builder addProcessors(Iterable<String> processors) { - return setProcessors(ImmutableList.copyOf(processors)); + this.processors.addAll(processors); + return this; } - public abstract Builder setProcessors(ImmutableList<String> processors); - - /** @deprecated use {@link #setBuiltinProcessors(ImmutableList)} instead. */ - @Deprecated - public Builder addBuiltinProcessors(Iterable<String> builtinProcessors) { - return setBuiltinProcessors(ImmutableList.copyOf(builtinProcessors)); + // TODO(cushon): remove this when turbine dependency is updated + public Builder setTempDir(String tempDir) { + return this; } - public abstract Builder setBuiltinProcessors(ImmutableList<String> builtinProcessors); - - public abstract Builder setSourceJars(ImmutableList<String> sourceJars); - - public abstract Builder setOutputDeps(String outputDeps); + public Builder setSourceJars(Iterable<String> sourceJars) { + this.sourceJars.addAll(sourceJars); + return this; + } - public abstract Builder setOutputManifest(String outputManifest); + public Builder setOutputDeps(String outputDeps) { + this.outputDeps = outputDeps; + return this; + } - public abstract Builder setTargetLabel(String targetLabel); + public Builder setTargetLabel(String targetLabel) { + this.targetLabel = targetLabel; + return this; + } - public abstract Builder setInjectingRuleKind(String injectingRuleKind); + public Builder setInjectingRuleKind(String injectingRuleKind) { + this.injectingRuleKind = injectingRuleKind; + return this; + } - /** @deprecated use {@link #setDepsArtifacts(ImmutableList)} instead. */ - @Deprecated public Builder addAllDepsArtifacts(Iterable<String> depsArtifacts) { - return setDepsArtifacts(ImmutableList.copyOf(depsArtifacts)); + this.depsArtifacts.addAll(depsArtifacts); + return this; } - public abstract Builder setDepsArtifacts(ImmutableList<String> depsArtifacts); - - public abstract Builder setHelp(boolean help); + public Builder setJavacFallback(boolean javacFallback) { + this.javacFallback = javacFallback; + return this; + } - abstract ImmutableList.Builder<String> javacOptsBuilder(); + public Builder setHelp(boolean help) { + this.help = help; + return this; + } public Builder addAllJavacOpts(Iterable<String> javacOpts) { - javacOptsBuilder().addAll(javacOpts); + this.javacOpts.addAll(javacOpts); return this; } - public abstract Builder setReducedClasspathMode(ReducedClasspathMode reducedClasspathMode); - - /** @deprecated use {@link #setDirectJars(ImmutableList)} instead. */ - @Deprecated - public Builder addDirectJars(Iterable<String> directJars) { - return setDirectJars(ImmutableList.copyOf(directJars)); + public Builder setShouldReduceClassPath(boolean shouldReduceClassPath) { + this.shouldReduceClassPath = shouldReduceClassPath; + return this; } - public abstract Builder setDirectJars(ImmutableList<String> jars); - - public abstract Builder setProfile(String profile); - - public abstract Builder setGensrcOutput(String gensrcOutput); - - public abstract Builder setResourceOutput(String resourceOutput); - - public abstract Builder setFullClasspathLength(int fullClasspathLength); - - public abstract Builder setReducedClasspathLength(int reducedClasspathLength); - - public abstract TurbineOptions build(); + public Builder addDirectJars(ImmutableList<String> jars) { + this.directJars.addAll(jars); + return this; + } } } diff --git a/java/com/google/turbine/options/TurbineOptionsParser.java b/java/com/google/turbine/options/TurbineOptionsParser.java index 17d4bf6..55697ca 100644 --- a/java/com/google/turbine/options/TurbineOptionsParser.java +++ b/java/com/google/turbine/options/TurbineOptionsParser.java @@ -22,7 +22,6 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.base.CharMatcher; import com.google.common.base.Splitter; import com.google.common.collect.ImmutableList; -import com.google.turbine.options.TurbineOptions.ReducedClasspathMode; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -70,19 +69,16 @@ public class TurbineOptionsParser { readOne(argumentDeque); break; case "--processors": - builder.setProcessors(readList(argumentDeque)); - break; - case "--builtin_processors": - builder.setBuiltinProcessors(readList(argumentDeque)); + builder.addProcessors(readList(argumentDeque)); break; case "--processorpath": - builder.setProcessorPath(readList(argumentDeque)); + builder.addProcessorPathEntries(readList(argumentDeque)); break; case "--classpath": - builder.setClassPath(readList(argumentDeque)); + builder.addClassPathEntries(readList(argumentDeque)); break; case "--bootclasspath": - builder.setBootClassPath(readList(argumentDeque)); + builder.addBootClassPathEntries(readList(argumentDeque)); break; case "--release": builder.setRelease(readOne(argumentDeque)); @@ -98,19 +94,16 @@ public class TurbineOptionsParser { break; } case "--sources": - builder.setSources(readList(argumentDeque)); + builder.addSources(readList(argumentDeque)); break; case "--output_deps": builder.setOutputDeps(readOne(argumentDeque)); break; - case "--output_manifest_proto": - builder.setOutputManifest(readOne(argumentDeque)); - break; case "--direct_dependencies": - builder.setDirectJars(readList(argumentDeque)); + builder.addDirectJars(readList(argumentDeque)); break; case "--deps_artifacts": - builder.setDepsArtifacts(readList(argumentDeque)); + builder.addAllDepsArtifacts(readList(argumentDeque)); break; case "--target_label": builder.setTargetLabel(readOne(argumentDeque)); @@ -119,32 +112,16 @@ public class TurbineOptionsParser { builder.setInjectingRuleKind(readOne(argumentDeque)); break; case "--javac_fallback": + builder.setJavacFallback(true); + break; case "--nojavac_fallback": - // TODO(cushon): remove this case once blaze stops passing the flag + builder.setJavacFallback(false); break; case "--reduce_classpath": - builder.setReducedClasspathMode(ReducedClasspathMode.JAVABUILDER_REDUCED); + builder.setShouldReduceClassPath(true); break; case "--noreduce_classpath": - builder.setReducedClasspathMode(ReducedClasspathMode.NONE); - break; - case "--reduce_classpath_mode": - builder.setReducedClasspathMode(ReducedClasspathMode.valueOf(readOne(argumentDeque))); - break; - case "--full_classpath_length": - builder.setFullClasspathLength(Integer.parseInt(readOne(argumentDeque))); - break; - case "--reduced_classpath_length": - builder.setReducedClasspathLength(Integer.parseInt(readOne(argumentDeque))); - break; - case "--profile": - builder.setProfile(readOne(argumentDeque)); - break; - case "--gensrc_output": - builder.setGensrcOutput(readOne(argumentDeque)); - break; - case "--resource_output": - builder.setResourceOutput(readOne(argumentDeque)); + builder.setShouldReduceClassPath(false); break; case "--help": builder.setHelp(true); diff --git a/java/com/google/turbine/parse/ConstExpressionParser.java b/java/com/google/turbine/parse/ConstExpressionParser.java index e49d51c..b3666a4 100644 --- a/java/com/google/turbine/parse/ConstExpressionParser.java +++ b/java/com/google/turbine/parse/ConstExpressionParser.java @@ -96,7 +96,7 @@ public class ConstExpressionParser { } } - private Tree.@Nullable Expression primary(boolean negate) { + private Tree.Expression primary(boolean negate) { switch (token) { case INT_LITERAL: return finishLiteral(TurbineConstantTypeKind.INT, negate); @@ -133,9 +133,8 @@ public class ConstExpressionParser { case LPAREN: return maybeCast(); case LBRACE: - int pos = position; eat(); - return arrayInitializer(pos); + return arrayInitializer(); case IDENT: return qualIdent(); case BYTE: @@ -245,10 +244,10 @@ public class ConstExpressionParser { position = lexer.position(); } - private Tree.Expression arrayInitializer(int pos) { + private Tree.Expression arrayInitializer() { if (token == Token.RBRACE) { eat(); - return new Tree.ArrayInit(pos, ImmutableList.<Tree.Expression>of()); + return new Tree.ArrayInit(position, ImmutableList.<Tree.Expression>of()); } ImmutableList.Builder<Tree.Expression> exprs = ImmutableList.builder(); @@ -274,12 +273,11 @@ public class ConstExpressionParser { return null; } } - return new Tree.ArrayInit(pos, exprs.build()); + return new Tree.ArrayInit(position, exprs.build()); } /** Finish hex, decimal, octal, and binary integer literals (see JLS 3.10.1). */ private Tree.Expression finishLiteral(TurbineConstantTypeKind kind, boolean negate) { - int pos = position; String text = ident().value(); Const.Value value; switch (kind) { @@ -356,7 +354,7 @@ public class ConstExpressionParser { throw new AssertionError(kind); } eat(); - return new Tree.Literal(pos, kind, value); + return new Tree.Literal(position, kind, value); } static boolean isOctal(String text) { @@ -563,16 +561,12 @@ public class ConstExpressionParser { return new Tree.TypeCast(position, new Tree.PrimTy(position, ImmutableList.of(), ty), rhs); } - private Tree.@Nullable AnnoExpr annotation() { + private Tree.AnnoExpr annotation() { if (token != Token.AT) { throw new AssertionError(); } eat(); - Tree.ConstVarName constVarName = (Tree.ConstVarName) qualIdent(); - if (constVarName == null) { - return null; - } - ImmutableList<Ident> name = constVarName.name(); + ImmutableList<Ident> name = ((Tree.ConstVarName) qualIdent()).name(); ImmutableList.Builder<Tree.Expression> args = ImmutableList.builder(); if (token == Token.LPAREN) { eat(); diff --git a/java/com/google/turbine/parse/IteratorLexer.java b/java/com/google/turbine/parse/IteratorLexer.java index 1b7a9d0..823f9bb 100644 --- a/java/com/google/turbine/parse/IteratorLexer.java +++ b/java/com/google/turbine/parse/IteratorLexer.java @@ -56,11 +56,7 @@ public class IteratorLexer implements Lexer { @Override public int position() { - return curr.position; - } - - @Override - public String javadoc() { - return null; + // TODO(cushon): test expression position EOF handling + return curr != null ? curr.position : -1; } } diff --git a/java/com/google/turbine/parse/Lexer.java b/java/com/google/turbine/parse/Lexer.java index 992bef1..2d8422a 100644 --- a/java/com/google/turbine/parse/Lexer.java +++ b/java/com/google/turbine/parse/Lexer.java @@ -31,7 +31,4 @@ public interface Lexer { /** Returns the source file for diagnostics. */ SourceFile source(); - - /** Returns a saved javadoc comment. */ - String javadoc(); } diff --git a/java/com/google/turbine/parse/Parser.java b/java/com/google/turbine/parse/Parser.java index 4a090b3..ff3cc3e 100644 --- a/java/com/google/turbine/parse/Parser.java +++ b/java/com/google/turbine/parse/Parser.java @@ -23,7 +23,6 @@ import static com.google.turbine.parse.Token.RPAREN; import static com.google.turbine.parse.Token.SEMI; import static com.google.turbine.tree.TurbineModifier.PROTECTED; import static com.google.turbine.tree.TurbineModifier.PUBLIC; -import static com.google.turbine.tree.TurbineModifier.VARARGS; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; @@ -150,14 +149,13 @@ public class Parser { break; case AT: { - int pos = position; next(); if (token == INTERFACE) { decls.add(annotationDeclaration(access, annos.build())); access = EnumSet.noneOf(TurbineModifier.class); annos = ImmutableList.builder(); } else { - annos.add(annotation(pos)); + annos.add(annotation()); } break; } @@ -215,7 +213,6 @@ public class Parser { } private TyDecl interfaceDeclaration(EnumSet<TurbineModifier> access, ImmutableList<Anno> annos) { - String javadoc = lexer.javadoc(); eat(Token.INTERFACE); int pos = position; Ident name = eatIdent(); @@ -244,12 +241,10 @@ public class Parser { Optional.<ClassTy>empty(), interfaces.build(), members, - TurbineTyKind.INTERFACE, - javadoc); + TurbineTyKind.INTERFACE); } private TyDecl annotationDeclaration(EnumSet<TurbineModifier> access, ImmutableList<Anno> annos) { - String javadoc = lexer.javadoc(); eat(Token.INTERFACE); int pos = position; Ident name = eatIdent(); @@ -265,12 +260,10 @@ public class Parser { Optional.<ClassTy>empty(), ImmutableList.<ClassTy>of(), members, - TurbineTyKind.ANNOTATION, - javadoc); + TurbineTyKind.ANNOTATION); } private TyDecl enumDeclaration(EnumSet<TurbineModifier> access, ImmutableList<Anno> annos) { - String javadoc = lexer.javadoc(); eat(Token.ENUM); int pos = position; Ident name = eatIdent(); @@ -294,8 +287,7 @@ public class Parser { Optional.<ClassTy>empty(), interfaces.build(), members, - TurbineTyKind.ENUM, - javadoc); + TurbineTyKind.ENUM); } private String moduleName() { @@ -348,7 +340,7 @@ public class Parser { return new ModDecl(pos, annos, open, moduleName, directives.build()); } - private static String flatname(char join, ImmutableList<Ident> idents) { + private String flatname(char join, ImmutableList<Ident> idents) { StringBuilder sb = new StringBuilder(); boolean first = true; for (Ident ident : idents) { @@ -474,8 +466,7 @@ public class Parser { ImmutableList.<Type>of(), ImmutableList.of()), name, - Optional.<Expression>empty(), - null)); + Optional.<Expression>empty())); annos = ImmutableList.builder(); break; } @@ -487,9 +478,8 @@ public class Parser { annos = ImmutableList.builder(); break OUTER; case AT: - int pos = position; next(); - annos.add(annotation(pos)); + annos.add(annotation()); break; default: throw error(token); @@ -499,7 +489,6 @@ public class Parser { } private TyDecl classDeclaration(EnumSet<TurbineModifier> access, ImmutableList<Anno> annos) { - String javadoc = lexer.javadoc(); eat(Token.CLASS); int pos = position; Ident name = eatIdent(); @@ -531,8 +520,7 @@ public class Parser { Optional.ofNullable(xtnds), interfaces.build(), members, - TurbineTyKind.CLASS, - javadoc); + TurbineTyKind.CLASS); } private ImmutableList<Tree> classMembers() { @@ -592,14 +580,13 @@ public class Parser { case AT: { // TODO(cushon): de-dup with top-level parsing - int pos = position; next(); if (token == INTERFACE) { acc.add(annotationDeclaration(access, annos.build())); access = EnumSet.noneOf(TurbineModifier.class); annos = ImmutableList.builder(); } else { - annos.add(annotation(pos)); + annos.add(annotation()); } break; } @@ -782,9 +769,8 @@ public class Parser { } ImmutableList.Builder<Anno> builder = ImmutableList.builder(); while (token == Token.AT) { - int pos = position; next(); - builder.add(annotation(pos)); + builder.add(annotation()); } return builder.build(); } @@ -821,7 +807,6 @@ public class Parser { ImmutableList<Anno> annos, Type baseTy, Ident name) { - String javadoc = lexer.javadoc(); ImmutableList.Builder<Tree> result = ImmutableList.builder(); VariableInitializerParser initializerParser = new VariableInitializerParser(token, lexer); List<List<SavedToken>> bits = initializerParser.parseInitializers(); @@ -846,7 +831,7 @@ public class Parser { if (init != null && init.kind() == Tree.Kind.ARRAY_INIT) { init = null; } - result.add(new VarDecl(pos, access, annos, ty, name, Optional.ofNullable(init), javadoc)); + result.add(new VarDecl(pos, access, annos, ty, name, Optional.ofNullable(init))); } if (token != SEMI) { throw TurbineError.format(lexer.source(), expressionStart, ErrorKind.UNTERMINATED_EXPRESSION); @@ -862,7 +847,6 @@ public class Parser { ImmutableList<TyParam> typaram, Type result, Ident name) { - String javadoc = lexer.javadoc(); eat(Token.LPAREN); ImmutableList.Builder<VarDecl> formals = ImmutableList.builder(); formalParams(formals, access); @@ -889,9 +873,8 @@ public class Parser { Tree expr = cparser.expression(); token = cparser.token; if (expr == null && token == Token.AT) { - int annoPos = position; next(); - expr = annotation(annoPos); + expr = annotation(); } if (expr == null) { throw error(token); @@ -915,8 +898,7 @@ public class Parser { name, formals.build(), exceptions.build(), - Optional.ofNullable(defaultValue), - javadoc); + Optional.ofNullable(defaultValue)); } /** @@ -946,10 +928,6 @@ public class Parser { if (extra.isEmpty()) { return type; } - if (type == null) { - // trailing dims without a type, e.g. for a constructor declaration - throw error(token); - } if (type.kind() == Kind.ARR_TY) { ArrTy arrTy = (ArrTy) type; return new ArrTy(arrTy.position(), arrTy.annos(), extraDims(arrTy.elem(), extra)); @@ -984,29 +962,13 @@ public class Parser { private VarDecl formalParam() { ImmutableList.Builder<Anno> annos = ImmutableList.builder(); EnumSet<TurbineModifier> access = modifiersAndAnnotations(annos); - Type ty = referenceTypeWithoutDims(ImmutableList.of()); + Type ty = referenceType(ImmutableList.of()); ImmutableList<Anno> typeAnnos = maybeAnnos(); - OUTER: - while (true) { - switch (token) { - case LBRACK: - next(); - eat(Token.RBRACK); - ty = new ArrTy(position, typeAnnos, ty); - typeAnnos = maybeAnnos(); - break; - case ELLIPSIS: - next(); - access.add(VARARGS); - ty = new ArrTy(position, typeAnnos, ty); - typeAnnos = ImmutableList.of(); - break OUTER; - default: - break OUTER; - } - } - if (!typeAnnos.isEmpty()) { - throw error(token); + if (maybe(Token.ELLIPSIS)) { + access.add(TurbineModifier.VARARGS); + ty = new ArrTy(position, typeAnnos, ty); + } else { + ty = maybeDims(typeAnnos, ty); } // the parameter name is `this` for receiver parameters, and a qualified this expression // for inner classes @@ -1017,8 +979,7 @@ public class Parser { name = identOrThis(); } ty = extraDims(ty); - return new VarDecl( - position, access, annos.build(), ty, name, Optional.<Expression>empty(), null); + return new VarDecl(position, access, annos.build(), ty, name, Optional.<Expression>empty()); } private Ident identOrThis() { @@ -1080,14 +1041,13 @@ public class Parser { OUTER: while (true) { ImmutableList<Anno> annotations = maybeAnnos(); - int pos = position; Ident name = eatIdent(); ImmutableList<Tree> bounds = ImmutableList.of(); if (token == Token.EXTENDS) { next(); bounds = tybounds(); } - acc.add(new TyParam(pos, name, bounds, annotations)); + acc.add(new TyParam(position, name, bounds, annotations)); switch (token) { case COMMA: eat(Token.COMMA); @@ -1206,42 +1166,49 @@ public class Parser { return acc.build(); } - private Type referenceTypeWithoutDims(ImmutableList<Anno> typeAnnos) { + private Type referenceType(ImmutableList<Anno> typeAnnos) { + Type ty; switch (token) { case IDENT: - return classty(null, typeAnnos); + ty = classty(null, typeAnnos); + break; case BOOLEAN: next(); - return new PrimTy(position, typeAnnos, TurbineConstantTypeKind.BOOLEAN); + ty = new PrimTy(position, typeAnnos, TurbineConstantTypeKind.BOOLEAN); + break; case BYTE: next(); - return new PrimTy(position, typeAnnos, TurbineConstantTypeKind.BYTE); + ty = new PrimTy(position, typeAnnos, TurbineConstantTypeKind.BYTE); + break; case SHORT: next(); - return new PrimTy(position, typeAnnos, TurbineConstantTypeKind.SHORT); + ty = new PrimTy(position, typeAnnos, TurbineConstantTypeKind.SHORT); + break; case INT: next(); - return new PrimTy(position, typeAnnos, TurbineConstantTypeKind.INT); + ty = new PrimTy(position, typeAnnos, TurbineConstantTypeKind.INT); + break; case LONG: next(); - return new PrimTy(position, typeAnnos, TurbineConstantTypeKind.LONG); + ty = new PrimTy(position, typeAnnos, TurbineConstantTypeKind.LONG); + break; case CHAR: next(); - return new PrimTy(position, typeAnnos, TurbineConstantTypeKind.CHAR); + ty = new PrimTy(position, typeAnnos, TurbineConstantTypeKind.CHAR); + break; case DOUBLE: next(); - return new PrimTy(position, typeAnnos, TurbineConstantTypeKind.DOUBLE); + ty = new PrimTy(position, typeAnnos, TurbineConstantTypeKind.DOUBLE); + break; case FLOAT: next(); - return new PrimTy(position, typeAnnos, TurbineConstantTypeKind.FLOAT); + ty = new PrimTy(position, typeAnnos, TurbineConstantTypeKind.FLOAT); + break; default: throw error(token); } - } - - private Type referenceType(ImmutableList<Anno> typeAnnos) { - Type ty = referenceTypeWithoutDims(typeAnnos); - return maybeDims(maybeAnnos(), ty); + ty = maybeDims(maybeAnnos(), ty); + return ty; } private Type maybeDims(ImmutableList<Anno> typeAnnos, Type ty) { @@ -1302,9 +1269,8 @@ public class Parser { access.add(TurbineModifier.STRICTFP); break; case AT: - int pos = position; next(); - annos.add(annotation(pos)); + annos.add(annotation()); break; default: return access; @@ -1352,7 +1318,8 @@ public class Parser { return name.build(); } - private Anno annotation(int pos) { + private Anno annotation() { + int pos = position; ImmutableList<Ident> name = qualIdent(); ImmutableList.Builder<Expression> args = ImmutableList.builder(); diff --git a/java/com/google/turbine/parse/StreamLexer.java b/java/com/google/turbine/parse/StreamLexer.java index 2e20c26..74b0ce8 100644 --- a/java/com/google/turbine/parse/StreamLexer.java +++ b/java/com/google/turbine/parse/StreamLexer.java @@ -16,9 +16,9 @@ package com.google.turbine.parse; -import static com.google.common.base.Verify.verify; import static com.google.turbine.parse.UnicodeEscapePreprocessor.ASCII_SUB; +import com.google.common.base.Verify; import com.google.turbine.diag.SourceFile; import com.google.turbine.diag.TurbineError; import com.google.turbine.diag.TurbineError.ErrorKind; @@ -40,9 +40,6 @@ public class StreamLexer implements Lexer { /** The value of the current string or character literal token. */ private String value = null; - /** A saved javadoc comment. */ - private String javadoc = null; - public StreamLexer(UnicodeEscapePreprocessor reader) { this.reader = reader; eat(); @@ -65,17 +62,6 @@ public class StreamLexer implements Lexer { } @Override - public String javadoc() { - String result = javadoc; - javadoc = null; - if (result == null) { - return null; - } - verify(result.endsWith("*/"), result); - return result.substring(0, result.length() - "*/".length()); - } - - @Override public String stringValue() { if (value != null) { return value; @@ -125,51 +111,30 @@ public class StreamLexer implements Lexer { } eat(); break; - default: // fall out } } case '*': - eat(); boolean sawStar = false; - boolean isJavadoc = false; - if (ch == '*') { - eat(); - // handle empty non-javadoc comments: `/**/` - if (ch == '/') { - eat(); - continue OUTER; - } - isJavadoc = true; - readFrom(); - } while (true) { + eat(); switch (ch) { case '*': - eat(); sawStar = true; break; case '/': - eat(); if (sawStar) { - if (isJavadoc) { - // Save the comment, excluding the leading `/**` and including - // the trailing `/*`. The comment is trimmed and normalized later. - javadoc = stringValue(); - } + eat(); continue OUTER; } sawStar = false; break; case ASCII_SUB: if (reader.done()) { - throw TurbineError.format( - reader.source(), position, ErrorKind.UNCLOSED_COMMENT); + return Token.EOF; } eat(); - sawStar = false; break; default: - eat(); sawStar = false; break; } @@ -240,9 +205,7 @@ public class StreamLexer implements Lexer { return identifier(); case ASCII_SUB: - if (!reader.done()) { - throw error(ErrorKind.UNEXPECTED_EOF); - } + Verify.verify(reader.done()); return Token.EOF; case '-': @@ -549,7 +512,6 @@ public class StreamLexer implements Lexer { eat(); signedInteger(); break; - default: // fall out } return floatTypeSuffix(); } @@ -564,7 +526,6 @@ public class StreamLexer implements Lexer { eat(); signedInteger(); break; - default: // fall out } return floatTypeSuffix(); } @@ -1028,7 +989,7 @@ public class StreamLexer implements Lexer { return makeIdent(stringValue()); } - private static Token makeIdent(String s) { + private Token makeIdent(String s) { switch (s) { case "abstract": return Token.ABSTRACT; diff --git a/java/com/google/turbine/parse/UnicodeEscapePreprocessor.java b/java/com/google/turbine/parse/UnicodeEscapePreprocessor.java index 3f38561..58f129d 100644 --- a/java/com/google/turbine/parse/UnicodeEscapePreprocessor.java +++ b/java/com/google/turbine/parse/UnicodeEscapePreprocessor.java @@ -16,10 +16,7 @@ package com.google.turbine.parse; -import com.google.errorprone.annotations.CheckReturnValue; import com.google.turbine.diag.SourceFile; -import com.google.turbine.diag.TurbineError; -import com.google.turbine.diag.TurbineError.ErrorKind; /** Preprocesses Unicode escape characters in Java source code, as described in JLS §3.3. */ public class UnicodeEscapePreprocessor { @@ -88,7 +85,7 @@ public class UnicodeEscapePreprocessor { } /** Consumes a hex digit. */ - private int hexDigit(char d) { + private static int hexDigit(char d) { switch (d) { case '0': case '1': @@ -116,9 +113,9 @@ public class UnicodeEscapePreprocessor { case 'f': return ((d - 'a') + 10); case ASCII_SUB: - throw error(ErrorKind.UNEXPECTED_EOF); + throw new AssertionError("unexpected end of input"); default: - throw error(ErrorKind.INVALID_UNICODE); + throw new AssertionError(String.format("unexpected hex digit: 0x%x", (int) d)); } } @@ -137,10 +134,4 @@ public class UnicodeEscapePreprocessor { public SourceFile source() { return source; } - - @CheckReturnValue - private TurbineError error(ErrorKind kind, Object... args) { - throw TurbineError.format( - source(), Math.min(position(), source().source().length() - 1), kind, args); - } } diff --git a/java/com/google/turbine/parse/VariableInitializerParser.java b/java/com/google/turbine/parse/VariableInitializerParser.java index 4ad9272..a39e9e8 100644 --- a/java/com/google/turbine/parse/VariableInitializerParser.java +++ b/java/com/google/turbine/parse/VariableInitializerParser.java @@ -149,6 +149,8 @@ public class VariableInitializerParser { case START: case TYPE: break OUTER; + default: + break; } save(); next(); @@ -161,6 +163,8 @@ public class VariableInitializerParser { case TYPE: commas.add(tokens.size()); break; + default: + break; } break; case DOT: @@ -205,14 +209,14 @@ public class VariableInitializerParser { result.add( ImmutableList.<SavedToken>builder() .addAll(tokens.subList(start, idx - 1)) - .add(new SavedToken(Token.EOF, null, tokens.get(idx - 1).position)) + .add(new SavedToken(Token.EOF, null, -1)) .build()); start = idx; } result.add( ImmutableList.<SavedToken>builder() .addAll(tokens.subList(start, tokens.size())) - .add(new SavedToken(Token.EOF, null, lexer.position())) + .add(new SavedToken(Token.EOF, null, -1)) .build()); return result; } @@ -280,9 +284,6 @@ public class VariableInitializerParser { int lastType = -1; int lastComma = -1; for (int i = 0; i < many; i++) { - if (ltIndices.isEmpty()) { - throw error(ErrorKind.UNEXPECTED_TOKEN, ">"); - } lastType = ltIndices.removeLast(); lastComma = commaIndices.removeLast(); } diff --git a/java/com/google/turbine/processing/ClassHierarchy.java b/java/com/google/turbine/processing/ClassHierarchy.java deleted file mode 100644 index 50c929c..0000000 --- a/java/com/google/turbine/processing/ClassHierarchy.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Iterables; -import com.google.turbine.binder.bound.TypeBoundClass; -import com.google.turbine.binder.env.CompoundEnv; -import com.google.turbine.binder.env.Env; -import com.google.turbine.binder.sym.ClassSymbol; -import com.google.turbine.diag.TurbineError; -import com.google.turbine.diag.TurbineError.ErrorKind; -import com.google.turbine.type.Type; -import com.google.turbine.type.Type.ClassTy; -import com.google.turbine.type.Type.TyKind; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Set; - -/** - * A representation of the class hierarchy, with logic for performing search between subtypes and - * their supertypes. - */ -public class ClassHierarchy { - - private final Map<ClassSymbol, HierarchyNode> cache = new HashMap<>(); - private Env<ClassSymbol, ? extends TypeBoundClass> env; - - ClassHierarchy(Env<ClassSymbol, ? extends TypeBoundClass> env) { - this.env = env; - } - - public void round(CompoundEnv<ClassSymbol, TypeBoundClass> env) { - cache.clear(); - this.env = env; - } - - /** A linked list between two types in the hierarchy. */ - private static class PathNode { - - /** The class for this node. */ - final ClassTy type; - - /** The node corresponding to a direct super-type of this class, or {@code null}. */ - final PathNode ancestor; - - PathNode(ClassTy type, PathNode ancestor) { - this.type = type; - this.ancestor = ancestor; - } - } - - /** - * A node in the type hierarchy, corresponding to a class symbol U. For each type V in the - * transitive supertype hierarchy of U, we save a mapping from the class symbol for V to the path - * from U to V in the type hierarchy. - */ - private class HierarchyNode { - - private final ClassSymbol sym; - private final Map<ClassSymbol, PathNode> ancestors = new LinkedHashMap<>(); - - HierarchyNode(ClassSymbol sym) { - this.sym = sym; - } - - /** Adds a child (direct supertype) of this node. */ - private void add(Type type) { - if (type.tyKind() != TyKind.CLASS_TY) { - // ignore any erroneous types that ended up in the hierarchy - return; - } - ClassTy classTy = (ClassTy) type; - HierarchyNode child = get(classTy.sym()); - // add a new edge to the direct supertype - PathNode existing = ancestors.putIfAbsent(child.sym, new PathNode(classTy, null)); - if (existing != null) { - // if this child has already been added don't re-process its ancestors - return; - } - // copy and extend edges for the transitive supertypes - for (Map.Entry<ClassSymbol, PathNode> n : child.ancestors.entrySet()) { - ancestors.putIfAbsent(n.getKey(), new PathNode(classTy, n.getValue())); - } - } - - /** The supertype closure of this node. */ - private Set<ClassSymbol> closure() { - return ancestors.keySet(); - } - } - - private HierarchyNode compute(ClassSymbol sym) { - HierarchyNode node = new HierarchyNode(sym); - TypeBoundClass info = env.get(sym); - if (info == null) { - throw TurbineError.format(/* source= */ null, ErrorKind.SYMBOL_NOT_FOUND, sym); - } - if (info.superClassType() != null) { - node.add(info.superClassType()); - } - for (Type type : info.interfaceTypes()) { - node.add(type); - } - return node; - } - - private HierarchyNode get(ClassSymbol sym) { - // dont use computeIfAbsent, to support re-entrant lookups - HierarchyNode result = cache.get(sym); - if (result != null) { - return result; - } - result = compute(sym); - cache.put(sym, result); - return result; - } - - /** - * Returns a list of types on the path between the given type {@code t} and a transitive - * superclass {@code s}, or an empty list if no such path exists. - */ - ImmutableList<ClassTy> search(Type t, ClassSymbol s) { - if (t.tyKind() != TyKind.CLASS_TY) { - return ImmutableList.of(); - } - ClassTy classTy = (ClassTy) t; - if (classTy.sym().equals(s)) { - return ImmutableList.of(classTy); - } - HierarchyNode node = get(classTy.sym()); - PathNode path = node.ancestors.get(s); - if (path == null) { - return ImmutableList.of(); - } - ImmutableList.Builder<ClassTy> result = ImmutableList.builder(); - result.add(classTy); - while (path != null) { - result.add(path.type); - path = path.ancestor; - } - return result.build().reverse(); - } - - /** - * Returns all classes in the transitive supertype hierarchy of the given class, including the - * class itself. - * - * <p>The iteration order of the results is undefined, and in particular no guarantees are made - * about the ordering of sub-types and super-types. - */ - public Iterable<ClassSymbol> transitiveSupertypes(ClassSymbol s) { - return Iterables.concat(ImmutableList.of(s), get(s).closure()); - } -} diff --git a/java/com/google/turbine/processing/ModelFactory.java b/java/com/google/turbine/processing/ModelFactory.java deleted file mode 100644 index 9b782cd..0000000 --- a/java/com/google/turbine/processing/ModelFactory.java +++ /dev/null @@ -1,391 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import static com.google.common.collect.Iterables.getOnlyElement; -import static java.util.Objects.requireNonNull; - -import com.google.common.base.Splitter; -import com.google.common.base.Supplier; -import com.google.common.base.Verify; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.turbine.binder.bound.TypeBoundClass; -import com.google.turbine.binder.bound.TypeBoundClass.FieldInfo; -import com.google.turbine.binder.bound.TypeBoundClass.MethodInfo; -import com.google.turbine.binder.bound.TypeBoundClass.ParamInfo; -import com.google.turbine.binder.bound.TypeBoundClass.TyVarInfo; -import com.google.turbine.binder.env.CompoundEnv; -import com.google.turbine.binder.env.Env; -import com.google.turbine.binder.lookup.LookupKey; -import com.google.turbine.binder.lookup.LookupResult; -import com.google.turbine.binder.lookup.TopLevelIndex; -import com.google.turbine.binder.sym.ClassSymbol; -import com.google.turbine.binder.sym.FieldSymbol; -import com.google.turbine.binder.sym.MethodSymbol; -import com.google.turbine.binder.sym.PackageSymbol; -import com.google.turbine.binder.sym.ParamSymbol; -import com.google.turbine.binder.sym.Symbol; -import com.google.turbine.binder.sym.TyVarSymbol; -import com.google.turbine.model.TurbineConstantTypeKind; -import com.google.turbine.processing.TurbineElement.TurbineExecutableElement; -import com.google.turbine.processing.TurbineElement.TurbineFieldElement; -import com.google.turbine.processing.TurbineElement.TurbineNoTypeElement; -import com.google.turbine.processing.TurbineElement.TurbinePackageElement; -import com.google.turbine.processing.TurbineElement.TurbineParameterElement; -import com.google.turbine.processing.TurbineElement.TurbineTypeElement; -import com.google.turbine.processing.TurbineElement.TurbineTypeParameterElement; -import com.google.turbine.processing.TurbineTypeMirror.TurbineArrayType; -import com.google.turbine.processing.TurbineTypeMirror.TurbineDeclaredType; -import com.google.turbine.processing.TurbineTypeMirror.TurbineErrorType; -import com.google.turbine.processing.TurbineTypeMirror.TurbineExecutableType; -import com.google.turbine.processing.TurbineTypeMirror.TurbineIntersectionType; -import com.google.turbine.processing.TurbineTypeMirror.TurbineNoType; -import com.google.turbine.processing.TurbineTypeMirror.TurbineNullType; -import com.google.turbine.processing.TurbineTypeMirror.TurbinePackageType; -import com.google.turbine.processing.TurbineTypeMirror.TurbinePrimitiveType; -import com.google.turbine.processing.TurbineTypeMirror.TurbineTypeVariable; -import com.google.turbine.processing.TurbineTypeMirror.TurbineVoidType; -import com.google.turbine.processing.TurbineTypeMirror.TurbineWildcardType; -import com.google.turbine.tree.Tree.Ident; -import com.google.turbine.type.Type; -import com.google.turbine.type.Type.ArrayTy; -import com.google.turbine.type.Type.ClassTy; -import com.google.turbine.type.Type.ErrorTy; -import com.google.turbine.type.Type.IntersectionTy; -import com.google.turbine.type.Type.MethodTy; -import com.google.turbine.type.Type.PrimTy; -import com.google.turbine.type.Type.TyVar; -import com.google.turbine.type.Type.WildTy; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; -import javax.lang.model.element.Element; -import javax.lang.model.element.VariableElement; -import javax.lang.model.type.NoType; -import javax.lang.model.type.NullType; -import javax.lang.model.type.TypeMirror; - -/** - * A factoy for turbine's implementations of {@link Element} and {@link TypeMirror}. - * - * <p>The model provided by those interfaces contains cycles between types and elements, e.g. {@link - * Element#asType} and {@link javax.lang.model.type.DeclaredType#asElement}. Turbine's internal - * model uses an immutable representation of classes and types which cannot represent cycles - * directly. Instead, the implementations in {@link TurbineElement} and {@link TurbineTypeMirror} - * maintain a reference to this class, and use it to lazily construct edges in the type and element - * graph. - */ -public class ModelFactory { - - public Env<ClassSymbol, ? extends TypeBoundClass> env; - - private final AtomicInteger round = new AtomicInteger(0); - - public void round(CompoundEnv<ClassSymbol, TypeBoundClass> env, TopLevelIndex tli) { - this.env = env; - this.tli = tli; - round.getAndIncrement(); - cha.round(env); - } - - private final HashMap<Type, TurbineTypeMirror> typeCache = new HashMap<>(); - - private final Map<FieldSymbol, TurbineFieldElement> fieldCache = new HashMap<>(); - private final Map<MethodSymbol, TurbineExecutableElement> methodCache = new HashMap<>(); - private final Map<ClassSymbol, TurbineTypeElement> classCache = new HashMap<>(); - private final Map<ParamSymbol, TurbineParameterElement> paramCache = new HashMap<>(); - private final Map<TyVarSymbol, TurbineTypeParameterElement> tyParamCache = new HashMap<>(); - private final Map<PackageSymbol, TurbinePackageElement> packageCache = new HashMap<>(); - - private final HashMap<CharSequence, ClassSymbol> inferSymbolCache = new HashMap<>(); - - private final ClassHierarchy cha; - private final ClassLoader processorLoader; - - private TopLevelIndex tli; - - public ModelFactory( - Env<ClassSymbol, ? extends TypeBoundClass> env, - ClassLoader processorLoader, - TopLevelIndex tli) { - this.env = requireNonNull(env); - this.cha = new ClassHierarchy(env); - this.processorLoader = requireNonNull(processorLoader); - this.tli = requireNonNull(tli); - } - - TypeMirror asTypeMirror(Type type) { - return typeCache.computeIfAbsent(type, this::createTypeMirror); - } - - /** - * Returns a supplier that memoizes the result of the input supplier. - * - * <p>It ensures that the results are invalidated after each annotation processing round, to - * support computations that depend on information in the current round and which might change in - * future, e.g. as additional types are generated. - */ - <T> Supplier<T> memoize(Supplier<T> s) { - return new Supplier<T>() { - T v; - int initializedInRound = -1; - - @Override - public T get() { - int r = round.get(); - if (initializedInRound != r) { - v = s.get(); - initializedInRound = r; - } - return v; - } - }; - } - - /** Creates a {@link TurbineTypeMirror} backed by a {@link Type}. */ - private TurbineTypeMirror createTypeMirror(Type type) { - switch (type.tyKind()) { - case PRIM_TY: - if (((PrimTy) type).primkind() == TurbineConstantTypeKind.STRING) { - return new TurbineDeclaredType(this, ClassTy.STRING); - } - return new TurbinePrimitiveType(this, (PrimTy) type); - case CLASS_TY: - return new TurbineDeclaredType(this, (ClassTy) type); - case ARRAY_TY: - return new TurbineArrayType(this, (ArrayTy) type); - case VOID_TY: - return new TurbineVoidType(this); - case WILD_TY: - return new TurbineWildcardType(this, (WildTy) type); - case TY_VAR: - return new TurbineTypeVariable(this, (TyVar) type); - case INTERSECTION_TY: - IntersectionTy intersectionTy = (IntersectionTy) type; - switch (intersectionTy.bounds().size()) { - case 0: - return createTypeMirror(ClassTy.OBJECT); - case 1: - return createTypeMirror(getOnlyElement(intersectionTy.bounds())); - default: - return new TurbineIntersectionType(this, intersectionTy); - } - case NONE_TY: - return new TurbineNoType(this); - case METHOD_TY: - return new TurbineExecutableType(this, (MethodTy) type); - case ERROR_TY: - return new TurbineErrorType(this, (ErrorTy) type); - } - throw new AssertionError(type.tyKind()); - } - - /** Creates a list of {@link TurbineTypeMirror}s backed by the given {@link Type}s. */ - ImmutableList<TypeMirror> asTypeMirrors(Iterable<? extends Type> types) { - ImmutableList.Builder<TypeMirror> result = ImmutableList.builder(); - for (Type type : types) { - result.add(asTypeMirror(type)); - } - return result.build(); - } - - NoType noType() { - return (NoType) asTypeMirror(Type.NONE); - } - - NoType packageType(PackageSymbol symbol) { - return new TurbinePackageType(this, symbol); - } - - public NullType nullType() { - return new TurbineNullType(this); - } - - /** Creates an {@link Element} backed by the given {@link Symbol}. */ - Element element(Symbol symbol) { - switch (symbol.symKind()) { - case CLASS: - return typeElement((ClassSymbol) symbol); - case TY_PARAM: - return typeParameterElement((TyVarSymbol) symbol); - case METHOD: - return executableElement((MethodSymbol) symbol); - case FIELD: - return fieldElement((FieldSymbol) symbol); - case PARAMETER: - return parameterElement((ParamSymbol) symbol); - case PACKAGE: - return packageElement((PackageSymbol) symbol); - case MODULE: - break; - } - throw new AssertionError(symbol.symKind()); - } - - Element noElement(String name) { - return new TurbineNoTypeElement(this, name); - } - - TurbineFieldElement fieldElement(FieldSymbol symbol) { - return fieldCache.computeIfAbsent(symbol, k -> new TurbineFieldElement(this, symbol)); - } - - TurbineExecutableElement executableElement(MethodSymbol symbol) { - return methodCache.computeIfAbsent(symbol, k -> new TurbineExecutableElement(this, symbol)); - } - - public TurbineTypeElement typeElement(ClassSymbol symbol) { - Verify.verify(!symbol.simpleName().equals("package-info"), "%s", symbol); - return classCache.computeIfAbsent(symbol, k -> new TurbineTypeElement(this, symbol)); - } - - TurbinePackageElement packageElement(PackageSymbol symbol) { - return packageCache.computeIfAbsent(symbol, k -> new TurbinePackageElement(this, symbol)); - } - - VariableElement parameterElement(ParamSymbol sym) { - return paramCache.computeIfAbsent(sym, k -> new TurbineParameterElement(this, sym)); - } - - TurbineTypeParameterElement typeParameterElement(TyVarSymbol sym) { - return tyParamCache.computeIfAbsent(sym, k -> new TurbineTypeParameterElement(this, sym)); - } - - ImmutableSet<Element> elements(ImmutableSet<? extends Symbol> symbols) { - ImmutableSet.Builder<Element> result = ImmutableSet.builder(); - for (Symbol symbol : symbols) { - result.add(element(symbol)); - } - return result.build(); - } - - public ClassSymbol inferSymbol(CharSequence name) { - return inferSymbolCache.computeIfAbsent(name, key -> inferSymbolImpl(name)); - } - - private ClassSymbol inferSymbolImpl(CharSequence name) { - LookupResult lookup = tli.scope().lookup(new LookupKey(asIdents(name))); - if (lookup == null) { - return null; - } - ClassSymbol sym = (ClassSymbol) lookup.sym(); - for (Ident bit : lookup.remaining()) { - sym = getSymbol(sym).children().get(bit.value()); - if (sym == null) { - return null; - } - } - return sym; - } - - private static ImmutableList<Ident> asIdents(CharSequence name) { - ImmutableList.Builder<Ident> result = ImmutableList.builder(); - for (String bit : Splitter.on('.').split(name)) { - result.add(new Ident(-1, bit)); - } - return result.build(); - } - - /** - * Returns the {@link TypeBoundClass} for the given {@link ClassSymbol} from the current - * environment. - */ - TypeBoundClass getSymbol(ClassSymbol sym) { - return env.get(sym); - } - - MethodInfo getMethodInfo(MethodSymbol method) { - TypeBoundClass info = getSymbol(method.owner()); - for (MethodInfo m : info.methods()) { - if (m.sym().equals(method)) { - return m; - } - } - return null; - } - - ParamInfo getParamInfo(ParamSymbol sym) { - MethodInfo info = getMethodInfo(sym.owner()); - for (ParamInfo p : info.parameters()) { - if (p.sym().equals(sym)) { - return p; - } - } - return null; - } - - FieldInfo getFieldInfo(FieldSymbol symbol) { - TypeBoundClass info = getSymbol(symbol.owner()); - requireNonNull(info, symbol.owner().toString()); - for (FieldInfo field : info.fields()) { - if (field.sym().equals(symbol)) { - return field; - } - } - throw new AssertionError(symbol); - } - - TyVarInfo getTyVarInfo(TyVarSymbol tyVar) { - Symbol owner = tyVar.owner(); - Verify.verifyNotNull(owner); // TODO(cushon): capture variables - ImmutableMap<TyVarSymbol, TyVarInfo> tyParams; - switch (owner.symKind()) { - case METHOD: - tyParams = getMethodInfo((MethodSymbol) owner).tyParams(); - break; - case CLASS: - tyParams = getSymbol((ClassSymbol) owner).typeParameterTypes(); - break; - default: - throw new AssertionError(owner.symKind()); - } - return tyParams.get(tyVar); - } - - static ClassSymbol enclosingClass(Symbol sym) { - switch (sym.symKind()) { - case CLASS: - return (ClassSymbol) sym; - case TY_PARAM: - return enclosingClass(((TyVarSymbol) sym).owner()); - case METHOD: - return ((MethodSymbol) sym).owner(); - case FIELD: - return ((FieldSymbol) sym).owner(); - case PARAMETER: - return ((ParamSymbol) sym).owner().owner(); - case PACKAGE: - case MODULE: - throw new IllegalArgumentException(sym.toString()); - } - throw new AssertionError(sym.symKind()); - } - - ClassHierarchy cha() { - return cha; - } - - ClassLoader processorLoader() { - return processorLoader; - } - - TopLevelIndex tli() { - return tli; - } -} diff --git a/java/com/google/turbine/processing/TurbineAnnotationMirror.java b/java/com/google/turbine/processing/TurbineAnnotationMirror.java deleted file mode 100644 index 5ea3de1..0000000 --- a/java/com/google/turbine/processing/TurbineAnnotationMirror.java +++ /dev/null @@ -1,349 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import static com.google.common.base.Preconditions.checkState; -import static com.google.common.collect.Iterables.getLast; - -import com.google.common.base.Joiner; -import com.google.common.base.Supplier; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.turbine.binder.bound.EnumConstantValue; -import com.google.turbine.binder.bound.TurbineAnnotationValue; -import com.google.turbine.binder.bound.TurbineClassValue; -import com.google.turbine.binder.bound.TypeBoundClass.MethodInfo; -import com.google.turbine.model.Const; -import com.google.turbine.model.Const.ArrayInitValue; -import com.google.turbine.processing.TurbineElement.TurbineExecutableElement; -import com.google.turbine.processing.TurbineElement.TurbineFieldElement; -import com.google.turbine.type.AnnoInfo; -import com.google.turbine.type.Type.ErrorTy; -import com.google.turbine.type.Type.TyKind; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.AnnotationValue; -import javax.lang.model.element.AnnotationValueVisitor; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.ErrorType; -import javax.lang.model.type.TypeMirror; - -/** - * An implementation of {@link AnnotationMirror} and {@link AnnotationValue} backed by {@link - * AnnoInfo} and {@link Const.Value}. - */ -class TurbineAnnotationMirror implements TurbineAnnotationValueMirror, AnnotationMirror { - - static TurbineAnnotationValueMirror annotationValue(ModelFactory factory, Const value) { - switch (value.kind()) { - case ARRAY: - return new TurbineArrayConstant(factory, (ArrayInitValue) value); - case PRIMITIVE: - return new TurbinePrimitiveConstant((Const.Value) value); - case CLASS_LITERAL: - return new TurbineClassConstant(factory, (TurbineClassValue) value); - case ENUM_CONSTANT: - return new TurbineEnumConstant(factory, (EnumConstantValue) value); - case ANNOTATION: - return new TurbineAnnotationMirror(factory, (TurbineAnnotationValue) value); - } - throw new AssertionError(value.kind()); - } - - static TurbineAnnotationMirror create(ModelFactory factory, AnnoInfo anno) { - return new TurbineAnnotationMirror(factory, new TurbineAnnotationValue(anno)); - } - - private final TurbineAnnotationValue value; - private final AnnoInfo anno; - private final Supplier<DeclaredType> type; - private final Supplier<ImmutableMap<String, MethodInfo>> elements; - private final Supplier<ImmutableMap<ExecutableElement, AnnotationValue>> elementValues; - private final Supplier<ImmutableMap<ExecutableElement, AnnotationValue>> - elementValuesWithDefaults; - - private TurbineAnnotationMirror(ModelFactory factory, TurbineAnnotationValue value) { - this.value = value; - this.anno = value.info(); - this.type = - factory.memoize( - new Supplier<DeclaredType>() { - @Override - public DeclaredType get() { - if (anno.sym() == null) { - return (ErrorType) - factory.asTypeMirror(ErrorTy.create(getLast(anno.tree().name()).value())); - } - return (DeclaredType) factory.typeElement(anno.sym()).asType(); - } - }); - this.elements = - factory.memoize( - new Supplier<ImmutableMap<String, MethodInfo>>() { - @Override - public ImmutableMap<String, MethodInfo> get() { - ImmutableMap.Builder<String, MethodInfo> result = ImmutableMap.builder(); - for (MethodInfo m : factory.getSymbol(anno.sym()).methods()) { - checkState(m.parameters().isEmpty()); - result.put(m.name(), m); - } - return result.build(); - } - }); - this.elementValues = - factory.memoize( - new Supplier<ImmutableMap<ExecutableElement, AnnotationValue>>() { - @Override - public ImmutableMap<ExecutableElement, AnnotationValue> get() { - ImmutableMap.Builder<ExecutableElement, AnnotationValue> result = - ImmutableMap.builder(); - for (Map.Entry<String, Const> value : anno.values().entrySet()) { - result.put( - factory.executableElement(elements.get().get(value.getKey()).sym()), - annotationValue(factory, value.getValue())); - } - return result.build(); - } - }); - this.elementValuesWithDefaults = - factory.memoize( - new Supplier<ImmutableMap<ExecutableElement, AnnotationValue>>() { - @Override - public ImmutableMap<ExecutableElement, AnnotationValue> get() { - Map<ExecutableElement, AnnotationValue> result = new LinkedHashMap<>(); - result.putAll(getElementValues()); - for (MethodInfo method : elements.get().values()) { - if (method.defaultValue() == null) { - continue; - } - TurbineExecutableElement element = factory.executableElement(method.sym()); - if (result.containsKey(element)) { - continue; - } - result.put(element, annotationValue(factory, method.defaultValue())); - } - return ImmutableMap.copyOf(result); - } - }); - } - - @Override - public int hashCode() { - return anno.hashCode(); - } - - @Override - public boolean equals(Object obj) { - return obj instanceof TurbineAnnotationMirror - && anno.equals(((TurbineAnnotationMirror) obj).anno); - } - - @Override - public String toString() { - return anno.toString(); - } - - @Override - public DeclaredType getAnnotationType() { - return type.get(); - } - - public Map<? extends ExecutableElement, ? extends AnnotationValue> - getElementValuesWithDefaults() { - return elementValuesWithDefaults.get(); - } - - @Override - public Map<? extends ExecutableElement, ? extends AnnotationValue> getElementValues() { - return elementValues.get(); - } - - @Override - public AnnotationMirror getValue() { - return this; - } - - @Override - public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) { - return v.visitAnnotation(getValue(), p); - } - - public AnnoInfo anno() { - return anno; - } - - @Override - public Const value() { - return value; - } - - private static class TurbineArrayConstant implements TurbineAnnotationValueMirror { - - private final ArrayInitValue value; - private final Supplier<ImmutableList<AnnotationValue>> elements; - - private TurbineArrayConstant(ModelFactory factory, ArrayInitValue value) { - this.value = value; - this.elements = - factory.memoize( - new Supplier<ImmutableList<AnnotationValue>>() { - @Override - public ImmutableList<AnnotationValue> get() { - ImmutableList.Builder<AnnotationValue> values = ImmutableList.builder(); - for (Const element : value.elements()) { - values.add(annotationValue(factory, element)); - } - return values.build(); - } - }); - } - - @Override - public List<AnnotationValue> getValue() { - return elements.get(); - } - - @Override - public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) { - return v.visitArray(elements.get(), p); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder("{"); - Joiner.on(", ").appendTo(sb, elements.get()); - sb.append("}"); - return sb.toString(); - } - - @Override - public Const value() { - return value; - } - } - - private static class TurbineClassConstant implements TurbineAnnotationValueMirror { - - private final TurbineClassValue value; - private final TypeMirror typeMirror; - - private TurbineClassConstant(ModelFactory factory, TurbineClassValue value) { - this.value = value; - this.typeMirror = factory.asTypeMirror(value.type()); - } - - @Override - public TypeMirror getValue() { - return typeMirror; - } - - @Override - public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) { - if (value.type().tyKind() == TyKind.ERROR_TY) { - // represent unresolvable class literals as the string value "<error>" for compatibility - // with javac: https://bugs.openjdk.java.net/browse/JDK-8229535 - return v.visitString("<error>", p); - } else { - return v.visitType(getValue(), p); - } - } - - @Override - public String toString() { - return typeMirror + ".class"; - } - - @Override - public Const value() { - return value; - } - } - - private static class TurbineEnumConstant implements TurbineAnnotationValueMirror { - - private final EnumConstantValue value; - private final TurbineFieldElement fieldElement; - - private TurbineEnumConstant(ModelFactory factory, EnumConstantValue value) { - this.value = value; - this.fieldElement = factory.fieldElement(value.sym()); - } - - @Override - public Object getValue() { - return fieldElement; - } - - @Override - public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) { - return v.visitEnumConstant(fieldElement, p); - } - - @Override - public String toString() { - return fieldElement.getEnclosingElement() + "." + fieldElement.getSimpleName(); - } - - @Override - public Const value() { - return value; - } - } - - private static class TurbinePrimitiveConstant implements TurbineAnnotationValueMirror { - - private final Const.Value value; - - public TurbinePrimitiveConstant(Const.Value value) { - this.value = value; - } - - @Override - public Object getValue() { - return value.getValue(); - } - - @Override - public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) { - return value.accept(v, p); - } - - @Override - public String toString() { - return value.toString(); - } - - @Override - public int hashCode() { - return value.hashCode(); - } - - @Override - public boolean equals(Object obj) { - return obj instanceof TurbinePrimitiveConstant - && value.equals(((TurbinePrimitiveConstant) obj).value); - } - - @Override - public Const value() { - return value; - } - } -} diff --git a/java/com/google/turbine/processing/TurbineAnnotationProxy.java b/java/com/google/turbine/processing/TurbineAnnotationProxy.java deleted file mode 100644 index c39f310..0000000 --- a/java/com/google/turbine/processing/TurbineAnnotationProxy.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import static com.google.common.base.Preconditions.checkArgument; - -import com.google.turbine.binder.bound.EnumConstantValue; -import com.google.turbine.binder.bound.TurbineAnnotationValue; -import com.google.turbine.binder.bound.TurbineClassValue; -import com.google.turbine.binder.bound.TypeBoundClass; -import com.google.turbine.model.Const; -import com.google.turbine.model.Const.ArrayInitValue; -import com.google.turbine.model.Const.Value; -import com.google.turbine.type.AnnoInfo; -import java.lang.annotation.Annotation; -import java.lang.reflect.Array; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.ArrayList; -import java.util.List; -import javax.lang.model.type.MirroredTypeException; -import javax.lang.model.type.MirroredTypesException; -import javax.lang.model.type.TypeMirror; - -/** An {@link InvocationHandler} for reflectively accessing annotations. */ -class TurbineAnnotationProxy implements InvocationHandler { - - static <A extends Annotation> A create( - ModelFactory factory, Class<A> annotationType, AnnoInfo anno) { - ClassLoader loader = annotationType.getClassLoader(); - if (loader == null) { - // annotation was loaded from the system classloader, e.g. java.lang.annotation.* - loader = factory.processorLoader(); - } - return annotationType.cast( - Proxy.newProxyInstance( - loader, - new Class<?>[] {annotationType}, - new TurbineAnnotationProxy(factory, loader, annotationType, anno))); - } - - private final ModelFactory factory; - private final ClassLoader loader; - private final Class<?> annotationType; - private final AnnoInfo anno; - - TurbineAnnotationProxy( - ModelFactory factory, ClassLoader loader, Class<?> annotationType, AnnoInfo anno) { - this.factory = factory; - this.loader = loader; - this.annotationType = annotationType; - this.anno = anno; - } - - @Override - public Object invoke(Object proxy, Method method, Object[] args) { - switch (method.getName()) { - case "hashCode": - checkArgument(args == null); - return anno.hashCode(); - case "annotationType": - checkArgument(args == null); - return annotationType; - case "equals": - checkArgument(args.length == 1); - return proxyEquals(args[0]); - case "toString": - checkArgument(args == null); - return anno.toString(); - default: - break; - } - Const value = anno.values().get(method.getName()); - if (value != null) { - return constValue(method.getReturnType(), factory, loader, value); - } - for (TypeBoundClass.MethodInfo m : factory.getSymbol(anno.sym()).methods()) { - if (m.name().contentEquals(method.getName())) { - return constValue(method.getReturnType(), factory, loader, m.defaultValue()); - } - } - throw new NoSuchMethodError(method.getName()); - } - - public boolean proxyEquals(Object other) { - if (!annotationType.isInstance(other)) { - return false; - } - if (!Proxy.isProxyClass(other.getClass())) { - return false; - } - InvocationHandler handler = Proxy.getInvocationHandler(other); - if (!(handler instanceof TurbineAnnotationProxy)) { - return false; - } - TurbineAnnotationProxy that = (TurbineAnnotationProxy) handler; - return anno.equals(that.anno); - } - - static Object constValue( - Class<?> returnType, ModelFactory factory, ClassLoader loader, Const value) { - switch (value.kind()) { - case PRIMITIVE: - return ((Value) value).getValue(); - case ARRAY: - return constArrayValue(returnType, factory, loader, (Const.ArrayInitValue) value); - case ENUM_CONSTANT: - return constEnumValue(loader, (EnumConstantValue) value); - case ANNOTATION: - return constAnnotationValue(factory, loader, (TurbineAnnotationValue) value); - case CLASS_LITERAL: - return constClassValue(factory, (TurbineClassValue) value); - } - throw new AssertionError(value.kind()); - } - - private static Object constArrayValue( - Class<?> returnType, ModelFactory factory, ClassLoader loader, ArrayInitValue value) { - if (returnType.getComponentType().equals(Class.class)) { - List<TypeMirror> result = new ArrayList<>(); - for (Const element : value.elements()) { - result.add(factory.asTypeMirror(((TurbineClassValue) element).type())); - } - throw new MirroredTypesException(result); - } - Object result = Array.newInstance(returnType.getComponentType(), value.elements().size()); - int idx = 0; - for (Const element : value.elements()) { - Object v = constValue(returnType, factory, loader, element); - Array.set(result, idx++, v); - } - return result; - } - - @SuppressWarnings("unchecked") // Enum.class - private static Object constEnumValue(ClassLoader loader, EnumConstantValue value) { - Class<?> clazz; - try { - clazz = loader.loadClass(value.sym().owner().toString()); - } catch (ClassNotFoundException e) { - throw new LinkageError(e.getMessage(), e); - } - return Enum.valueOf(clazz.asSubclass(Enum.class), value.sym().name()); - } - - private static Object constAnnotationValue( - ModelFactory factory, ClassLoader loader, TurbineAnnotationValue value) { - try { - String name = value.sym().binaryName().replace('/', '.'); - Class<? extends Annotation> clazz = - Class.forName(name, false, loader).asSubclass(Annotation.class); - return create(factory, clazz, value.info()); - } catch (ClassNotFoundException e) { - throw new LinkageError(e.getMessage(), e); - } - } - - private static Object constClassValue(ModelFactory factory, TurbineClassValue value) { - throw new MirroredTypeException(factory.asTypeMirror(value.type())); - } -} diff --git a/java/com/google/turbine/processing/TurbineAnnotationValueMirror.java b/java/com/google/turbine/processing/TurbineAnnotationValueMirror.java deleted file mode 100644 index a196750..0000000 --- a/java/com/google/turbine/processing/TurbineAnnotationValueMirror.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import com.google.turbine.model.Const; -import javax.lang.model.element.AnnotationValue; - -/** An {@link AnnotationValue} backed by a {@link Const}. */ -public interface TurbineAnnotationValueMirror extends AnnotationValue { - Const value(); -} diff --git a/java/com/google/turbine/processing/TurbineElement.java b/java/com/google/turbine/processing/TurbineElement.java deleted file mode 100644 index c22a442..0000000 --- a/java/com/google/turbine/processing/TurbineElement.java +++ /dev/null @@ -1,1298 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import static java.util.Objects.requireNonNull; - -import com.google.common.base.Joiner; -import com.google.common.base.Splitter; -import com.google.common.base.Supplier; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Iterables; -import com.google.common.collect.Sets; -import com.google.turbine.binder.bound.AnnotationMetadata; -import com.google.turbine.binder.bound.SourceTypeBoundClass; -import com.google.turbine.binder.bound.TurbineAnnotationValue; -import com.google.turbine.binder.bound.TypeBoundClass; -import com.google.turbine.binder.bound.TypeBoundClass.FieldInfo; -import com.google.turbine.binder.bound.TypeBoundClass.MethodInfo; -import com.google.turbine.binder.bound.TypeBoundClass.ParamInfo; -import com.google.turbine.binder.bound.TypeBoundClass.TyVarInfo; -import com.google.turbine.binder.lookup.PackageScope; -import com.google.turbine.binder.sym.ClassSymbol; -import com.google.turbine.binder.sym.FieldSymbol; -import com.google.turbine.binder.sym.MethodSymbol; -import com.google.turbine.binder.sym.PackageSymbol; -import com.google.turbine.binder.sym.ParamSymbol; -import com.google.turbine.binder.sym.Symbol; -import com.google.turbine.binder.sym.TyVarSymbol; -import com.google.turbine.diag.TurbineError; -import com.google.turbine.diag.TurbineError.ErrorKind; -import com.google.turbine.model.Const; -import com.google.turbine.model.Const.ArrayInitValue; -import com.google.turbine.model.TurbineFlag; -import com.google.turbine.model.TurbineTyKind; -import com.google.turbine.tree.Tree.MethDecl; -import com.google.turbine.tree.Tree.TyDecl; -import com.google.turbine.tree.Tree.VarDecl; -import com.google.turbine.type.AnnoInfo; -import com.google.turbine.type.Type; -import com.google.turbine.type.Type.ClassTy; -import com.google.turbine.type.Type.ClassTy.SimpleClassTy; -import com.google.turbine.type.Type.ErrorTy; -import java.lang.annotation.Annotation; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Deque; -import java.util.EnumSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.AnnotationValue; -import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.ElementVisitor; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.Name; -import javax.lang.model.element.NestingKind; -import javax.lang.model.element.PackageElement; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.TypeParameterElement; -import javax.lang.model.element.VariableElement; -import javax.lang.model.type.TypeMirror; -import org.checkerframework.checker.nullness.qual.Nullable; - -/** An {@link Element} implementation backed by a {@link Symbol}. */ -public abstract class TurbineElement implements Element { - - public abstract Symbol sym(); - - public abstract String javadoc(); - - @Override - public abstract int hashCode(); - - @Override - public abstract boolean equals(Object obj); - - protected final ModelFactory factory; - private final Supplier<ImmutableList<AnnotationMirror>> annotationMirrors; - - protected <T> Supplier<T> memoize(Supplier<T> supplier) { - return factory.memoize(supplier); - } - - protected TurbineElement(ModelFactory factory) { - this.factory = requireNonNull(factory); - this.annotationMirrors = - factory.memoize( - new Supplier<ImmutableList<AnnotationMirror>>() { - @Override - public ImmutableList<AnnotationMirror> get() { - ImmutableList.Builder<AnnotationMirror> result = ImmutableList.builder(); - for (AnnoInfo anno : annos()) { - result.add(TurbineAnnotationMirror.create(factory, anno)); - } - return result.build(); - } - }); - } - - static AnnoInfo getAnnotation(Iterable<AnnoInfo> annos, ClassSymbol sym) { - for (AnnoInfo anno : annos) { - if (Objects.equals(anno.sym(), sym)) { - return anno; - } - } - return null; - } - - @Override - public <A extends Annotation> A getAnnotation(Class<A> annotationType) { - ClassSymbol sym = new ClassSymbol(annotationType.getName().replace('.', '/')); - TypeBoundClass info = factory.getSymbol(sym); - if (info == null) { - return null; - } - AnnoInfo anno = getAnnotation(annos(), sym); - if (anno == null) { - return null; - } - return TurbineAnnotationProxy.create(factory, annotationType, anno); - } - - @Override - public final <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType) { - ClassSymbol sym = new ClassSymbol(annotationType.getName().replace('.', '/')); - TypeBoundClass info = factory.getSymbol(sym); - if (info == null) { - return null; - } - AnnotationMetadata metadata = info.annotationMetadata(); - if (metadata == null) { - return null; - } - List<A> result = new ArrayList<>(); - for (AnnoInfo anno : annos()) { - if (anno.sym().equals(sym)) { - result.add(TurbineAnnotationProxy.create(factory, annotationType, anno)); - continue; - } - if (anno.sym().equals(metadata.repeatable())) { - ArrayInitValue arrayValue = (ArrayInitValue) anno.values().get("value"); - for (Const element : arrayValue.elements()) { - result.add( - TurbineAnnotationProxy.create( - factory, annotationType, ((TurbineAnnotationValue) element).info())); - } - } - } - return Iterables.toArray(result, annotationType); - } - - @Override - public final List<? extends AnnotationMirror> getAnnotationMirrors() { - return annotationMirrors.get(); - } - - List<? extends AnnotationMirror> getAllAnnotationMirrors() { - return getAnnotationMirrors(); - } - - protected abstract ImmutableList<AnnoInfo> annos(); - - /** A {@link TypeElement} implementation backed by a {@link ClassSymbol}. */ - static class TurbineTypeElement extends TurbineElement implements TypeElement { - - @Override - public int hashCode() { - return sym.hashCode(); - } - - private final ClassSymbol sym; - private final Supplier<TypeBoundClass> info; - - TurbineTypeElement(ModelFactory factory, ClassSymbol sym) { - super(factory); - this.sym = requireNonNull(sym); - this.info = - memoize( - new Supplier<TypeBoundClass>() { - @Override - public TypeBoundClass get() { - return factory.getSymbol(sym); - } - }); - } - - @Nullable - TypeBoundClass info() { - return info.get(); - } - - TypeBoundClass infoNonNull() { - TypeBoundClass info = info(); - if (info == null) { - throw TurbineError.format(/* source= */ null, ErrorKind.SYMBOL_NOT_FOUND, sym); - } - return info; - } - - @Override - public NestingKind getNestingKind() { - TypeBoundClass info = info(); - return (info != null && info.owner() != null) ? NestingKind.MEMBER : NestingKind.TOP_LEVEL; - } - - private final Supplier<TurbineName> qualifiedName = - memoize( - new Supplier<TurbineName>() { - @Override - public TurbineName get() { - TypeBoundClass info = info(); - if (info == null || info.owner() == null) { - return new TurbineName(sym.toString()); - } - ClassSymbol sym = sym(); - Deque<String> flat = new ArrayDeque<>(); - while (info.owner() != null) { - flat.addFirst(sym.binaryName().substring(info.owner().binaryName().length() + 1)); - sym = info.owner(); - info = factory.getSymbol(sym); - } - flat.addFirst(sym.toString()); - return new TurbineName(Joiner.on('.').join(flat)); - } - }); - - @Override - public Name getQualifiedName() { - return qualifiedName.get(); - } - - private final Supplier<TypeMirror> superclass = - memoize( - new Supplier<TypeMirror>() { - @Override - public TypeMirror get() { - TypeBoundClass info = infoNonNull(); - switch (info.kind()) { - case CLASS: - case ENUM: - if (info.superclass() != null) { - return factory.asTypeMirror(info.superClassType()); - } - if (info instanceof SourceTypeBoundClass) { - // support simple name for stuff that doesn't exist - TyDecl decl = ((SourceTypeBoundClass) info).decl(); - if (decl.xtnds().isPresent()) { - return factory.asTypeMirror( - ErrorTy.create(decl.xtnds().get().name().value())); - } - } - return factory.noType(); - case INTERFACE: - case ANNOTATION: - return factory.noType(); - } - throw new AssertionError(info.kind()); - } - }); - - @Override - public TypeMirror getSuperclass() { - return superclass.get(); - } - - @Override - public String toString() { - return getQualifiedName().toString(); - } - - private final Supplier<List<TypeMirror>> interfaces = - memoize( - new Supplier<List<TypeMirror>>() { - @Override - public List<TypeMirror> get() { - return factory.asTypeMirrors(infoNonNull().interfaceTypes()); - } - }); - - @Override - public List<? extends TypeMirror> getInterfaces() { - return interfaces.get(); - } - - private final Supplier<ImmutableList<TypeParameterElement>> typeParameters = - memoize( - new Supplier<ImmutableList<TypeParameterElement>>() { - @Override - public ImmutableList<TypeParameterElement> get() { - ImmutableList.Builder<TypeParameterElement> result = ImmutableList.builder(); - for (TyVarSymbol p : infoNonNull().typeParameters().values()) { - result.add(factory.typeParameterElement(p)); - } - return result.build(); - } - }); - - @Override - public List<? extends TypeParameterElement> getTypeParameters() { - return typeParameters.get(); - } - - private final Supplier<TypeMirror> type = - memoize( - new Supplier<TypeMirror>() { - @Override - public TypeMirror get() { - return factory.asTypeMirror(asGenericType(sym)); - } - - ClassTy asGenericType(ClassSymbol symbol) { - TypeBoundClass info = info(); - if (info == null) { - return ClassTy.asNonParametricClassTy(symbol); - } - Deque<Type.ClassTy.SimpleClassTy> simples = new ArrayDeque<>(); - simples.addFirst(simple(symbol, info)); - while (info.owner() != null && (info.access() & TurbineFlag.ACC_STATIC) == 0) { - symbol = info.owner(); - info = factory.getSymbol(symbol); - simples.addFirst(simple(symbol, info)); - } - return ClassTy.create(ImmutableList.copyOf(simples)); - } - - private SimpleClassTy simple(ClassSymbol sym, TypeBoundClass info) { - ImmutableList.Builder<Type> args = ImmutableList.builder(); - for (TyVarSymbol t : info.typeParameters().values()) { - args.add(Type.TyVar.create(t, ImmutableList.of())); - } - return SimpleClassTy.create(sym, args.build(), ImmutableList.of()); - } - }); - - @Override - public TypeMirror asType() { - return type.get(); - } - - @Override - public ElementKind getKind() { - TypeBoundClass info = infoNonNull(); - switch (info.kind()) { - case CLASS: - return ElementKind.CLASS; - case INTERFACE: - return ElementKind.INTERFACE; - case ENUM: - return ElementKind.ENUM; - case ANNOTATION: - return ElementKind.ANNOTATION_TYPE; - } - throw new AssertionError(info.kind()); - } - - @Override - public Set<Modifier> getModifiers() { - return asModifierSet(ModifierOwner.TYPE, infoNonNull().access() & ~TurbineFlag.ACC_SUPER); - } - - private final Supplier<TurbineName> simpleName = - memoize( - new Supplier<TurbineName>() { - @Override - public TurbineName get() { - TypeBoundClass info = info(); - if (info == null || info.owner() == null) { - return new TurbineName(sym.simpleName()); - } - return new TurbineName( - sym.binaryName().substring(info.owner().binaryName().length() + 1)); - } - }); - - @Override - public Name getSimpleName() { - return simpleName.get(); - } - - private final Supplier<Element> enclosing = - memoize( - new Supplier<Element>() { - @Override - public Element get() { - return getNestingKind().equals(NestingKind.TOP_LEVEL) - ? factory.packageElement(sym.owner()) - : factory.typeElement(info().owner()); - } - }); - - @Override - public Element getEnclosingElement() { - return enclosing.get(); - } - - private final Supplier<ImmutableList<Element>> enclosed = - memoize( - new Supplier<ImmutableList<Element>>() { - @Override - public ImmutableList<Element> get() { - TypeBoundClass info = infoNonNull(); - ImmutableList.Builder<Element> result = ImmutableList.builder(); - for (FieldInfo field : info.fields()) { - result.add(factory.fieldElement(field.sym())); - } - for (MethodInfo method : info.methods()) { - result.add(factory.executableElement(method.sym())); - } - for (ClassSymbol child : info.children().values()) { - result.add(factory.typeElement(child)); - } - return result.build(); - } - }); - - @Override - public List<? extends Element> getEnclosedElements() { - return enclosed.get(); - } - - @Override - public <R, P> R accept(ElementVisitor<R, P> v, P p) { - return v.visitType(this, p); - } - - @Override - public ClassSymbol sym() { - return sym; - } - - @Override - public String javadoc() { - TypeBoundClass info = info(); - if (!(info instanceof SourceTypeBoundClass)) { - return null; - } - return ((SourceTypeBoundClass) info).decl().javadoc(); - } - - @Override - public boolean equals(Object obj) { - return obj instanceof TurbineTypeElement && sym.equals(((TurbineTypeElement) obj).sym); - } - - @Override - protected ImmutableList<AnnoInfo> annos() { - return infoNonNull().annotations(); - } - - @Override - public final <A extends Annotation> A getAnnotation(Class<A> annotationType) { - ClassSymbol sym = new ClassSymbol(annotationType.getName().replace('.', '/')); - AnnoInfo anno = getAnnotation(annos(), sym); - if (anno != null) { - return TurbineAnnotationProxy.create(factory, annotationType, anno); - } - if (!isAnnotationInherited(sym)) { - return null; - } - ClassSymbol superclass = infoNonNull().superclass(); - while (superclass != null) { - TypeBoundClass info = factory.getSymbol(superclass); - if (info == null) { - break; - } - anno = getAnnotation(info.annotations(), sym); - if (anno != null) { - return TurbineAnnotationProxy.create(factory, annotationType, anno); - } - superclass = info.superclass(); - } - return null; - } - - @Override - List<? extends AnnotationMirror> getAllAnnotationMirrors() { - Map<ClassSymbol, AnnotationMirror> result = new LinkedHashMap<>(); - for (AnnoInfo anno : annos()) { - result.put(anno.sym(), TurbineAnnotationMirror.create(factory, anno)); - } - ClassSymbol superclass = infoNonNull().superclass(); - while (superclass != null) { - TypeBoundClass i = factory.getSymbol(superclass); - if (i == null) { - break; - } - for (AnnoInfo anno : i.annotations()) { - addAnnotationFromSuper(result, anno); - } - superclass = i.superclass(); - } - return ImmutableList.copyOf(result.values()); - } - - private void addAnnotationFromSuper(Map<ClassSymbol, AnnotationMirror> result, AnnoInfo anno) { - if (!isAnnotationInherited(anno.sym())) { - return; - } - if (result.containsKey(anno.sym())) { - // if the same inherited annotation is present on multiple supertypes, only return one - return; - } - result.put(anno.sym(), TurbineAnnotationMirror.create(factory, anno)); - } - - private boolean isAnnotationInherited(ClassSymbol sym) { - TypeBoundClass annoInfo = factory.getSymbol(sym); - if (annoInfo == null) { - return false; - } - for (AnnoInfo anno : annoInfo.annotations()) { - if (anno.sym().equals(ClassSymbol.INHERITED)) { - return true; - } - } - return false; - } - } - - /** A {@link TypeParameterElement} implementation backed by a {@link TyVarSymbol}. */ - static class TurbineTypeParameterElement extends TurbineElement implements TypeParameterElement { - - @Override - public int hashCode() { - return sym.hashCode(); - } - - @Override - public boolean equals(Object obj) { - return obj instanceof TurbineTypeParameterElement - && sym.equals(((TurbineTypeParameterElement) obj).sym); - } - - private final TyVarSymbol sym; - - public TurbineTypeParameterElement(ModelFactory factory, TyVarSymbol sym) { - super(factory); - this.sym = sym; - } - - private final Supplier<TyVarInfo> info = - memoize( - new Supplier<TyVarInfo>() { - @Override - public TyVarInfo get() { - return factory.getTyVarInfo(sym); - } - }); - - @Nullable - private TyVarInfo info() { - return info.get(); - } - - @Override - public String toString() { - return sym.name(); - } - - @Override - public Element getGenericElement() { - return factory.element(sym.owner()); - } - - @Override - public List<? extends TypeMirror> getBounds() { - ImmutableList<Type> bounds = info().upperBound().bounds(); - return factory.asTypeMirrors(bounds.isEmpty() ? ImmutableList.of(ClassTy.OBJECT) : bounds); - } - - @Override - public TypeMirror asType() { - return factory.asTypeMirror(Type.TyVar.create(sym, info().annotations())); - } - - @Override - public ElementKind getKind() { - return ElementKind.TYPE_PARAMETER; - } - - @Override - public Set<Modifier> getModifiers() { - return ImmutableSet.of(); - } - - @Override - public Name getSimpleName() { - return new TurbineName(sym.name()); - } - - @Override - public Element getEnclosingElement() { - return getGenericElement(); - } - - @Override - public List<? extends Element> getEnclosedElements() { - return ImmutableList.of(); - } - - @Override - public <R, P> R accept(ElementVisitor<R, P> v, P p) { - return v.visitTypeParameter(this, p); - } - - @Override - public TyVarSymbol sym() { - return sym; - } - - @Override - public String javadoc() { - return null; - } - - @Override - protected ImmutableList<AnnoInfo> annos() { - return info().annotations(); - } - } - - /** An {@link ExecutableElement} implementation backed by a {@link MethodSymbol}. */ - static class TurbineExecutableElement extends TurbineElement implements ExecutableElement { - - private final MethodSymbol sym; - - private final Supplier<MethodInfo> info = - memoize( - new Supplier<MethodInfo>() { - @Override - public MethodInfo get() { - return factory.getMethodInfo(sym); - } - }); - - @Nullable - MethodInfo info() { - return info.get(); - } - - TurbineExecutableElement(ModelFactory factory, MethodSymbol sym) { - super(factory); - this.sym = sym; - } - - @Override - public MethodSymbol sym() { - return sym; - } - - @Override - public String javadoc() { - MethDecl decl = info().decl(); - return decl != null ? decl.javadoc() : null; - } - - @Override - public int hashCode() { - return sym.hashCode(); - } - - @Override - public boolean equals(Object obj) { - return obj instanceof TurbineExecutableElement - && sym.equals(((TurbineExecutableElement) obj).sym); - } - - @Override - public List<? extends TypeParameterElement> getTypeParameters() { - ImmutableList.Builder<TurbineTypeParameterElement> result = ImmutableList.builder(); - for (Map.Entry<TyVarSymbol, TyVarInfo> p : info().tyParams().entrySet()) { - result.add(factory.typeParameterElement(p.getKey())); - } - return result.build(); - } - - @Override - public TypeMirror getReturnType() { - return factory.asTypeMirror(info().returnType()); - } - - private final Supplier<ImmutableList<VariableElement>> parameters = - memoize( - new Supplier<ImmutableList<VariableElement>>() { - @Override - public ImmutableList<VariableElement> get() { - ImmutableList.Builder<VariableElement> result = ImmutableList.builder(); - for (ParamInfo param : info().parameters()) { - if (param.synthetic()) { - // ExecutableElement#getParameters doesn't expect synthetic or mandated - // parameters - continue; - } - result.add(factory.parameterElement(param.sym())); - } - return result.build(); - } - }); - - @Override - public List<? extends VariableElement> getParameters() { - return parameters.get(); - } - - @Override - public String toString() { - MethodInfo info = info(); - StringBuilder sb = new StringBuilder(); - if (!info.tyParams().isEmpty()) { - sb.append('<'); - Joiner.on(',').appendTo(sb, info.tyParams().keySet()); - sb.append('>'); - } - if (getKind() == ElementKind.CONSTRUCTOR) { - sb.append(info.sym().owner().simpleName()); - } else { - sb.append(info.sym().name()); - } - sb.append('('); - boolean first = true; - for (ParamInfo p : info.parameters()) { - if (!first) { - sb.append(','); - } - sb.append(p.type()); - first = false; - } - sb.append(')'); - return sb.toString(); - } - - @Override - public TypeMirror getReceiverType() { - return info().receiver() != null - ? factory.asTypeMirror(info().receiver().type()) - : factory.noType(); - } - - @Override - public boolean isVarArgs() { - return (info().access() & TurbineFlag.ACC_VARARGS) == TurbineFlag.ACC_VARARGS; - } - - @Override - public boolean isDefault() { - return (info().access() & TurbineFlag.ACC_DEFAULT) == TurbineFlag.ACC_DEFAULT; - } - - @Override - public List<? extends TypeMirror> getThrownTypes() { - return factory.asTypeMirrors(info().exceptions()); - } - - @Override - public AnnotationValue getDefaultValue() { - return info().defaultValue() != null - ? TurbineAnnotationMirror.annotationValue(factory, info().defaultValue()) - : null; - } - - @Override - public TypeMirror asType() { - return factory.asTypeMirror(info().asType()); - } - - @Override - public ElementKind getKind() { - return info().name().equals("<init>") ? ElementKind.CONSTRUCTOR : ElementKind.METHOD; - } - - @Override - public Set<Modifier> getModifiers() { - int access = info().access(); - if (factory.getSymbol(info().sym().owner()).kind() == TurbineTyKind.INTERFACE) { - if ((access & (TurbineFlag.ACC_ABSTRACT | TurbineFlag.ACC_STATIC)) == 0) { - access |= TurbineFlag.ACC_DEFAULT; - } - } - return asModifierSet(ModifierOwner.METHOD, access); - } - - @Override - public Name getSimpleName() { - return new TurbineName(info().sym().name()); - } - - @Override - public Element getEnclosingElement() { - return factory.typeElement(info().sym().owner()); - } - - @Override - public List<? extends Element> getEnclosedElements() { - return ImmutableList.of(); - } - - @Override - public <R, P> R accept(ElementVisitor<R, P> v, P p) { - return v.visitExecutable(this, p); - } - - @Override - protected ImmutableList<AnnoInfo> annos() { - return info().annotations(); - } - } - - /** An {@link VariableElement} implementation backed by a {@link FieldSymbol}. */ - static class TurbineFieldElement extends TurbineElement implements VariableElement { - - @Override - public String toString() { - return sym.name(); - } - - @Override - public boolean equals(Object obj) { - return obj instanceof TurbineFieldElement && sym.equals(((TurbineFieldElement) obj).sym); - } - - @Override - public int hashCode() { - return sym.hashCode(); - } - - private final FieldSymbol sym; - - @Override - public FieldSymbol sym() { - return sym; - } - - @Override - public String javadoc() { - VarDecl decl = info().decl(); - return decl != null ? decl.javadoc() : null; - } - - private final Supplier<FieldInfo> info = - memoize( - new Supplier<FieldInfo>() { - @Override - public FieldInfo get() { - return factory.getFieldInfo(sym); - } - }); - - @Nullable - FieldInfo info() { - return info.get(); - } - - TurbineFieldElement(ModelFactory factory, FieldSymbol sym) { - super(factory); - this.sym = sym; - } - - @Override - public Object getConstantValue() { - if (info().value() == null) { - return null; - } - return info().value().getValue(); - } - - @Override - public TypeMirror asType() { - return factory.asTypeMirror(info().type()); - } - - @Override - public ElementKind getKind() { - return ((info().access() & TurbineFlag.ACC_ENUM) == TurbineFlag.ACC_ENUM) - ? ElementKind.ENUM_CONSTANT - : ElementKind.FIELD; - } - - @Override - public Set<Modifier> getModifiers() { - return asModifierSet(ModifierOwner.FIELD, info().access()); - } - - @Override - public Name getSimpleName() { - return new TurbineName(sym.name()); - } - - @Override - public Element getEnclosingElement() { - return factory.typeElement(sym.owner()); - } - - @Override - public List<? extends Element> getEnclosedElements() { - return ImmutableList.of(); - } - - @Override - public <R, P> R accept(ElementVisitor<R, P> v, P p) { - return v.visitVariable(this, p); - } - - @Override - protected ImmutableList<AnnoInfo> annos() { - return info().annotations(); - } - } - - private enum ModifierOwner { - TYPE, - PARAMETER, - FIELD, - METHOD - } - - private static ImmutableSet<Modifier> asModifierSet(ModifierOwner modifierOwner, int access) { - EnumSet<Modifier> modifiers = EnumSet.noneOf(Modifier.class); - if ((access & TurbineFlag.ACC_PUBLIC) == TurbineFlag.ACC_PUBLIC) { - modifiers.add(Modifier.PUBLIC); - } - if ((access & TurbineFlag.ACC_PROTECTED) == TurbineFlag.ACC_PROTECTED) { - modifiers.add(Modifier.PROTECTED); - } - if ((access & TurbineFlag.ACC_PRIVATE) == TurbineFlag.ACC_PRIVATE) { - modifiers.add(Modifier.PRIVATE); - } - if ((access & TurbineFlag.ACC_ABSTRACT) == TurbineFlag.ACC_ABSTRACT) { - modifiers.add(Modifier.ABSTRACT); - } - if ((access & TurbineFlag.ACC_FINAL) == TurbineFlag.ACC_FINAL) { - modifiers.add(Modifier.FINAL); - } - if ((access & TurbineFlag.ACC_DEFAULT) == TurbineFlag.ACC_DEFAULT) { - modifiers.add(Modifier.DEFAULT); - } - if ((access & TurbineFlag.ACC_STATIC) == TurbineFlag.ACC_STATIC) { - modifiers.add(Modifier.STATIC); - } - if ((access & TurbineFlag.ACC_TRANSIENT) == TurbineFlag.ACC_TRANSIENT) { - switch (modifierOwner) { - case METHOD: - case PARAMETER: - // varargs and transient use the same bits - break; - default: - modifiers.add(Modifier.TRANSIENT); - } - } - if ((access & TurbineFlag.ACC_VOLATILE) == TurbineFlag.ACC_VOLATILE) { - modifiers.add(Modifier.VOLATILE); - } - if ((access & TurbineFlag.ACC_SYNCHRONIZED) == TurbineFlag.ACC_SYNCHRONIZED) { - modifiers.add(Modifier.SYNCHRONIZED); - } - if ((access & TurbineFlag.ACC_NATIVE) == TurbineFlag.ACC_NATIVE) { - modifiers.add(Modifier.NATIVE); - } - if ((access & TurbineFlag.ACC_STRICT) == TurbineFlag.ACC_STRICT) { - modifiers.add(Modifier.STRICTFP); - } - - return Sets.immutableEnumSet(modifiers); - } - - /** A {@link PackageElement} implementation backed by a {@link PackageSymbol}. */ - static class TurbinePackageElement extends TurbineElement implements PackageElement { - - private final PackageSymbol sym; - - public TurbinePackageElement(ModelFactory factory, PackageSymbol sym) { - super(factory); - this.sym = sym; - } - - @Override - public Name getQualifiedName() { - return new TurbineName(sym.toString()); - } - - @Override - public boolean isUnnamed() { - return sym.binaryName().isEmpty(); - } - - @Override - public TypeMirror asType() { - return factory.packageType(sym); - } - - @Override - public ElementKind getKind() { - return ElementKind.PACKAGE; - } - - @Override - public Set<Modifier> getModifiers() { - return ImmutableSet.of(); - } - - @Override - public Name getSimpleName() { - return new TurbineName(sym.binaryName().substring(sym.binaryName().lastIndexOf('/') + 1)); - } - - @Override - public Element getEnclosingElement() { - // a package is not enclosed by another element - return null; - } - - @Override - public List<TurbineTypeElement> getEnclosedElements() { - ImmutableSet.Builder<TurbineTypeElement> result = ImmutableSet.builder(); - PackageScope scope = factory.tli().lookupPackage(Splitter.on('/').split(sym.binaryName())); - for (ClassSymbol key : scope.classes()) { - if (key.binaryName().contains("$") && factory.getSymbol(key).owner() != null) { - // Skip member classes: only top-level classes are enclosed by the package. - // The initial check for '$' is an optimization. - continue; - } - if (key.simpleName().equals("package-info")) { - continue; - } - result.add(factory.typeElement(key)); - } - return result.build().asList(); - } - - @Override - public <R, P> R accept(ElementVisitor<R, P> v, P p) { - return v.visitPackage(this, p); - } - - @Override - public PackageSymbol sym() { - return sym; - } - - @Override - public String javadoc() { - return null; - } - - @Override - public int hashCode() { - return sym.hashCode(); - } - - @Override - public boolean equals(Object obj) { - return obj instanceof TurbinePackageElement && sym.equals(((TurbinePackageElement) obj).sym); - } - - private final Supplier<ImmutableList<AnnoInfo>> annos = - memoize( - new Supplier<ImmutableList<AnnoInfo>>() { - @Override - public ImmutableList<AnnoInfo> get() { - TypeBoundClass info = - factory.getSymbol(new ClassSymbol(sym.binaryName() + "/package-info")); - return info != null ? info.annotations() : ImmutableList.of(); - } - }); - - @Override - protected ImmutableList<AnnoInfo> annos() { - return annos.get(); - } - - @Override - public String toString() { - return sym.toString(); - } - } - - /** A {@link VariableElement} implementation backed by a {@link ParamSymbol}. */ - static class TurbineParameterElement extends TurbineElement implements VariableElement { - - @Override - public ParamSymbol sym() { - return sym; - } - - @Override - public String javadoc() { - return null; - } - - @Override - public int hashCode() { - return sym.hashCode(); - } - - @Override - public boolean equals(Object obj) { - return obj instanceof TurbineParameterElement - && sym.equals(((TurbineParameterElement) obj).sym); - } - - private final ParamSymbol sym; - - private final Supplier<ParamInfo> info = - memoize( - new Supplier<ParamInfo>() { - @Override - public ParamInfo get() { - return factory.getParamInfo(sym); - } - }); - - @Nullable - ParamInfo info() { - return info.get(); - } - - public TurbineParameterElement(ModelFactory factory, ParamSymbol sym) { - super(factory); - this.sym = sym; - } - - @Override - public Object getConstantValue() { - return null; - } - - private final Supplier<TypeMirror> type = - memoize( - new Supplier<TypeMirror>() { - @Override - public TypeMirror get() { - return factory.asTypeMirror(info().type()); - } - }); - - @Override - public TypeMirror asType() { - return type.get(); - } - - @Override - public ElementKind getKind() { - return ElementKind.PARAMETER; - } - - @Override - public Set<Modifier> getModifiers() { - return asModifierSet(ModifierOwner.PARAMETER, info().access()); - } - - @Override - public Name getSimpleName() { - return new TurbineName(sym.name()); - } - - @Override - public Element getEnclosingElement() { - return factory.executableElement(sym.owner()); - } - - @Override - public List<? extends Element> getEnclosedElements() { - return ImmutableList.of(); - } - - @Override - public <R, P> R accept(ElementVisitor<R, P> v, P p) { - return v.visitVariable(this, p); - } - - @Override - public String toString() { - return String.valueOf(sym.name()); - } - - @Override - protected ImmutableList<AnnoInfo> annos() { - return info().annotations(); - } - } - - static class TurbineNoTypeElement implements TypeElement { - - private final ModelFactory factory; - private final String name; - - public TurbineNoTypeElement(ModelFactory factory, String name) { - this.factory = factory; - this.name = requireNonNull(name); - } - - @Override - public TypeMirror asType() { - return factory.noType(); - } - - @Override - public ElementKind getKind() { - return ElementKind.CLASS; - } - - @Override - public Set<Modifier> getModifiers() { - return ImmutableSet.of(); - } - - @Override - public Name getSimpleName() { - return new TurbineName(name.substring(name.lastIndexOf('.') + 1)); - } - - @Override - public TypeMirror getSuperclass() { - return factory.noType(); - } - - @Override - public List<? extends TypeMirror> getInterfaces() { - return ImmutableList.of(); - } - - @Override - public List<? extends TypeParameterElement> getTypeParameters() { - return ImmutableList.of(); - } - - @Override - public Element getEnclosingElement() { - int idx = name.lastIndexOf('.'); - String packageName; - if (idx == -1) { - packageName = ""; - } else { - packageName = name.substring(0, idx).replace('.', '/'); - } - return factory.packageElement(new PackageSymbol(packageName)); - } - - @Override - public List<? extends Element> getEnclosedElements() { - return ImmutableList.of(); - } - - @Override - public NestingKind getNestingKind() { - return NestingKind.TOP_LEVEL; - } - - @Override - public Name getQualifiedName() { - return new TurbineName(name); - } - - @Override - public List<? extends AnnotationMirror> getAnnotationMirrors() { - return ImmutableList.of(); - } - - @Override - public <A extends Annotation> A getAnnotation(Class<A> aClass) { - return null; - } - - @Override - public <A extends Annotation> A[] getAnnotationsByType(Class<A> aClass) { - return null; - } - - @Override - public <R, P> R accept(ElementVisitor<R, P> elementVisitor, P p) { - return elementVisitor.visitType(this, p); - } - - @Override - public String toString() { - return getSimpleName().toString(); - } - } -} diff --git a/java/com/google/turbine/processing/TurbineElements.java b/java/com/google/turbine/processing/TurbineElements.java deleted file mode 100644 index 9da210e..0000000 --- a/java/com/google/turbine/processing/TurbineElements.java +++ /dev/null @@ -1,360 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import static com.google.common.base.Preconditions.checkState; - -import com.google.common.base.CharMatcher; -import com.google.common.base.Joiner; -import com.google.common.base.Splitter; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Multimap; -import com.google.common.collect.MultimapBuilder; -import com.google.turbine.binder.sym.ClassSymbol; -import com.google.turbine.binder.sym.FieldSymbol; -import com.google.turbine.binder.sym.PackageSymbol; -import com.google.turbine.binder.sym.Symbol; -import com.google.turbine.model.Const; -import com.google.turbine.model.TurbineVisibility; -import com.google.turbine.processing.TurbineElement.TurbineExecutableElement; -import com.google.turbine.processing.TurbineElement.TurbineFieldElement; -import com.google.turbine.processing.TurbineElement.TurbineTypeElement; -import com.google.turbine.processing.TurbineTypeMirror.TurbineExecutableType; -import com.google.turbine.type.AnnoInfo; -import java.io.PrintWriter; -import java.io.Writer; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.AnnotationValue; -import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Name; -import javax.lang.model.element.PackageElement; -import javax.lang.model.element.TypeElement; -import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.Elements; - -/** An implementation of {@link Elements} backed by turbine's {@link Element}. */ -public class TurbineElements implements Elements { - - private final ModelFactory factory; - private final TurbineTypes types; - - public TurbineElements(ModelFactory factory, TurbineTypes types) { - this.factory = factory; - this.types = types; - } - - private static Symbol asSymbol(Element element) { - if (!(element instanceof TurbineElement)) { - throw new IllegalArgumentException(element.toString()); - } - return ((TurbineElement) element).sym(); - } - - @Override - public PackageElement getPackageElement(CharSequence name) { - ImmutableList<String> packageName = ImmutableList.copyOf(Splitter.on('.').split(name)); - if (factory.tli().lookupPackage(packageName) == null) { - return null; - } - return factory.packageElement(new PackageSymbol(Joiner.on('/').join(packageName))); - } - - @Override - public TypeElement getTypeElement(CharSequence name) { - ClassSymbol sym = factory.inferSymbol(name); - if (sym == null) { - return null; - } - if (factory.getSymbol(sym) == null) { - return null; - } - return factory.typeElement(sym); - } - - @Override - public Map<? extends ExecutableElement, ? extends AnnotationValue> getElementValuesWithDefaults( - AnnotationMirror a) { - return ((TurbineAnnotationMirror) a).getElementValuesWithDefaults(); - } - - @Override - public String getDocComment(Element e) { - if (!(e instanceof TurbineElement)) { - throw new IllegalArgumentException(e.toString()); - } - String comment = ((TurbineElement) e).javadoc(); - if (comment == null) { - return null; - } - StringBuilder sb = new StringBuilder(); - boolean first = true; - for (String line : Splitter.on('\n').split(comment)) { - int start = 0; - if (!first) { - sb.append('\n'); - while (start < line.length() && CharMatcher.whitespace().matches(line.charAt(start))) { - start++; - } - while (start < line.length() && line.charAt(start) == '*') { - start++; - } - } - sb.append(line, start, line.length()); - first = false; - } - return sb.toString(); - } - - @Override - public boolean isDeprecated(Element element) { - if (!(element instanceof TurbineElement)) { - throw new IllegalArgumentException(element.toString()); - } - for (AnnoInfo a : ((TurbineTypeElement) element).annos()) { - if (a.sym().equals(ClassSymbol.DEPRECATED)) { - return true; - } - } - return false; - } - - @Override - public Name getBinaryName(TypeElement element) { - if (!(element instanceof TurbineTypeElement)) { - throw new IllegalArgumentException(element.toString()); - } - return getName(((TurbineTypeElement) element).sym().binaryName().replace('/', '.')); - } - - /** - * {@inheritDoc} - * - * @throws IllegalArgumentException for module elements - */ - @Override - public PackageElement getPackageOf(Element element) { - Symbol sym = asSymbol(element); - return factory.packageElement(packageSymbol(sym)); - } - - private static PackageSymbol packageSymbol(Symbol sym) { - if (sym.symKind().equals(Symbol.Kind.PACKAGE)) { - return (PackageSymbol) sym; - } - return ModelFactory.enclosingClass(sym).owner(); - } - - @Override - public List<? extends Element> getAllMembers(TypeElement type) { - ClassSymbol s = (ClassSymbol) asSymbol(type); - PackageSymbol from = packageSymbol(s); - - // keep track of processed methods grouped by their names, to handle overrides more efficiently - Multimap<String, TurbineExecutableElement> methods = - MultimapBuilder.linkedHashKeys().linkedHashSetValues().build(); - - // collect all members of each transitive supertype of the input - ImmutableList.Builder<Element> results = ImmutableList.builder(); - for (ClassSymbol superType : factory.cha().transitiveSupertypes(s)) { - // Most of JSR-269 is implemented on top of turbine's model, instead of the Element and - // TypeMirror wrappers. We don't do that here because we need most of the Elements returned - // by getEnclosedElements anyways, and the work below benefits from some of the caching done - // by TurbineElement. - for (Element el : factory.typeElement(superType).getEnclosedElements()) { - Symbol sym = asSymbol(el); - switch (sym.symKind()) { - case METHOD: - TurbineExecutableElement m = (TurbineExecutableElement) el; - if (shouldAdd(s, from, methods, m)) { - methods.put(m.info().name(), m); - results.add(el); - } - break; - case FIELD: - if (shouldAdd(s, from, (TurbineFieldElement) el)) { - results.add(el); - } - break; - default: - results.add(el); - } - } - } - return results.build(); - } - - private boolean shouldAdd( - ClassSymbol s, - PackageSymbol from, - Multimap<String, TurbineExecutableElement> methods, - TurbineExecutableElement m) { - if (m.sym().owner().equals(s)) { - // always include methods (and constructors) declared in the given type - return true; - } - if (m.getKind() == ElementKind.CONSTRUCTOR) { - // skip constructors from super-types, because the spec says so - return false; - } - if (!isVisible(from, packageSymbol(m.sym()), TurbineVisibility.fromAccess(m.info().access()))) { - // skip invisible methods in supers - return false; - } - // otherwise check if we've seen methods that override, or are overridden by, the - // current method - Set<TurbineExecutableElement> overrides = new HashSet<>(); - Set<TurbineExecutableElement> overridden = new HashSet<>(); - String name = m.info().name(); - for (TurbineExecutableElement other : methods.get(name)) { - if (overrides(m, other, (TypeElement) m.getEnclosingElement())) { - overrides.add(other); - continue; - } - if (overrides(other, m, (TypeElement) other.getEnclosingElement())) { - overridden.add(other); - continue; - } - } - if (!overridden.isEmpty()) { - // We've already processed method(s) that override this one; nothing to do here. - // If that's true, and we've *also* processed a methods that this one overrides, - // something has gone terribly wrong: since overriding is transitive the results - // contain a pair of methods that override each other. - checkState(overrides.isEmpty()); - return false; - } - // Add this method, and remove any methods we've already processed that it overrides. - for (TurbineExecutableElement override : overrides) { - methods.remove(name, override); - } - return true; - } - - private static boolean shouldAdd(ClassSymbol s, PackageSymbol from, TurbineFieldElement f) { - FieldSymbol sym = f.sym(); - if (sym.owner().equals(s)) { - // always include fields declared in the given type - return true; - } - if (!isVisible(from, packageSymbol(sym), TurbineVisibility.fromAccess(f.info().access()))) { - // skip invisible fields in supers - return false; - } - return true; - } - - /** - * Returns true if an element with the given {@code visibility} and located in package {@from} is - * visible to elements in package {@code to}. - */ - private static boolean isVisible( - PackageSymbol from, PackageSymbol to, TurbineVisibility visibility) { - switch (visibility) { - case PUBLIC: - case PROTECTED: - break; - case PACKAGE: - return from.equals(to); - case PRIVATE: - return false; - } - return true; - } - - @Override - public List<? extends AnnotationMirror> getAllAnnotationMirrors(Element element) { - return ((TurbineElement) element).getAllAnnotationMirrors(); - } - - @Override - public boolean hides(Element hider, Element hidden) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean overrides( - ExecutableElement overrider, ExecutableElement overridden, TypeElement type) { - if (!overrider.getSimpleName().contentEquals(overridden.getSimpleName())) { - return false; - } - TypeMirror a = overrider.asType(); - TypeMirror b = types.asMemberOf((DeclaredType) type.asType(), overridden); - if (b == null) { - return false; - } - if (!types.isSubsignature((TurbineExecutableType) a, (TurbineExecutableType) b)) { - return false; - } - return isVisible( - packageSymbol(asSymbol(overrider)), - packageSymbol(asSymbol(overridden)), - TurbineVisibility.fromAccess(((TurbineExecutableElement) overridden).info().access())); - } - - @Override - public String getConstantExpression(Object value) { - if (value instanceof Byte) { - return new Const.ByteValue((Byte) value).toString(); - } - if (value instanceof Long) { - return new Const.LongValue((Long) value).toString(); - } - if (value instanceof Float) { - return new Const.FloatValue((Float) value).toString(); - } - if (value instanceof Double) { - return new Const.DoubleValue((Double) value).toString(); - } - if (value instanceof Short) { - // Special-case short for consistency with javac, see: - // https://bugs.openjdk.java.net/browse/JDK-8227617 - return String.format("(short)%d", (Short) value); - } - if (value instanceof String) { - return new Const.StringValue((String) value).toString(); - } - if (value instanceof Character) { - return new Const.CharValue((Character) value).toString(); - } - return String.valueOf(value); - } - - @Override - public void printElements(Writer w, Element... elements) { - PrintWriter pw = new PrintWriter(w, true); - for (Element element : elements) { - pw.println(element.toString()); - } - } - - @Override - public Name getName(CharSequence cs) { - return new TurbineName(cs.toString()); - } - - @Override - public boolean isFunctionalInterface(TypeElement type) { - throw new UnsupportedOperationException(); - } -} diff --git a/java/com/google/turbine/processing/TurbineFiler.java b/java/com/google/turbine/processing/TurbineFiler.java deleted file mode 100644 index 186eb7f..0000000 --- a/java/com/google/turbine/processing/TurbineFiler.java +++ /dev/null @@ -1,435 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import static com.google.common.base.Preconditions.checkArgument; -import static java.nio.charset.StandardCharsets.UTF_8; - -import com.google.common.base.Function; -import com.google.common.base.Supplier; -import com.google.common.base.Suppliers; -import com.google.common.collect.ImmutableMap; -import com.google.common.io.ByteStreams; -import com.google.turbine.diag.SourceFile; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.Reader; -import java.io.StringReader; -import java.io.Writer; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import javax.annotation.processing.Filer; -import javax.annotation.processing.FilerException; -import javax.lang.model.element.Element; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.NestingKind; -import javax.tools.FileObject; -import javax.tools.JavaFileManager.Location; -import javax.tools.JavaFileObject; -import javax.tools.JavaFileObject.Kind; -import javax.tools.StandardLocation; - -/** Turbine's implementation of {@link Filer}. */ -public class TurbineFiler implements Filer { - - /** - * Existing paths of file objects that cannot be regenerated, including the original compilation - * inputs and source or class files generated during any annotation processing round. - */ - private final Set<String> seen; - - /** - * File objects generated during the current processing round. Each entry has a unique path, which - * is enforced by {@link #seen}. - */ - private final List<TurbineJavaFileObject> files = new ArrayList<>(); - - /** Loads resources from the classpath. */ - private final Function<String, Supplier<byte[]>> classPath; - - /** The {@link ClassLoader} for the annotation processor path, for loading resources. */ - private final ClassLoader loader; - - private final Map<String, SourceFile> generatedSources = new LinkedHashMap<>(); - private final Map<String, byte[]> generatedClasses = new LinkedHashMap<>(); - - /** Generated source file objects from all rounds. */ - public ImmutableMap<String, SourceFile> generatedSources() { - return ImmutableMap.copyOf(generatedSources); - } - - /** Generated class file objects from all rounds. */ - public ImmutableMap<String, byte[]> generatedClasses() { - return ImmutableMap.copyOf(generatedClasses); - } - - public TurbineFiler( - Set<String> seen, Function<String, Supplier<byte[]>> classPath, ClassLoader loader) { - this.seen = seen; - this.classPath = classPath; - this.loader = loader; - } - - /** - * Called when the current annotation processing round is complete, and returns the sources - * generated in that round. - */ - public Collection<SourceFile> finishRound() { - Map<String, SourceFile> roundSources = new LinkedHashMap<>(); - for (TurbineJavaFileObject e : files) { - String path = e.getName(); - switch (e.getKind()) { - case SOURCE: - roundSources.put(path, new SourceFile(path, e.contents())); - break; - case CLASS: - generatedClasses.put(path, e.bytes()); - break; - case OTHER: - switch (e.location()) { - case CLASS_OUTPUT: - generatedClasses.put(path, e.bytes()); - break; - case SOURCE_OUTPUT: - this.generatedSources.put(path, new SourceFile(path, e.contents())); - break; - default: - throw new AssertionError(e.location()); - } - break; - case HTML: - throw new UnsupportedOperationException(String.valueOf(e.getKind())); - } - } - files.clear(); - this.generatedSources.putAll(roundSources); - return roundSources.values(); - } - - @Override - public JavaFileObject createSourceFile(CharSequence n, Element... originatingElements) - throws IOException { - String name = n.toString(); - checkArgument(!name.contains("/"), "invalid type name: %s", name); - return create(StandardLocation.SOURCE_OUTPUT, Kind.SOURCE, name.replace('.', '/') + ".java"); - } - - @Override - public JavaFileObject createClassFile(CharSequence n, Element... originatingElements) - throws IOException { - String name = n.toString(); - checkArgument(!name.contains("/"), "invalid type name: %s", name); - return create(StandardLocation.CLASS_OUTPUT, Kind.CLASS, name.replace('.', '/') + ".class"); - } - - @Override - public FileObject createResource( - Location location, CharSequence p, CharSequence r, Element... originatingElements) - throws IOException { - checkArgument(location instanceof StandardLocation, "%s", location); - String pkg = p.toString(); - String relativeName = r.toString(); - checkArgument(!pkg.contains("/"), "invalid package: %s", pkg); - String path = packageRelativePath(pkg, relativeName); - return create((StandardLocation) location, Kind.OTHER, path); - } - - private JavaFileObject create(StandardLocation location, Kind kind, String path) - throws FilerException { - checkArgument(location.isOutputLocation()); - if (!seen.add(path)) { - throw new FilerException("already created " + path); - } - TurbineJavaFileObject result = new TurbineJavaFileObject(location, kind, path); - files.add(result); - return result; - } - - @Override - public FileObject getResource(Location location, CharSequence p, CharSequence r) - throws IOException { - String pkg = p.toString(); - String relativeName = r.toString(); - checkArgument(!pkg.contains("/"), "invalid package: %s", pkg); - checkArgument(location instanceof StandardLocation, "unsupported location %s", location); - StandardLocation standardLocation = (StandardLocation) location; - String path = packageRelativePath(pkg, relativeName); - switch (standardLocation) { - case CLASS_OUTPUT: - byte[] generated = generatedClasses.get(path); - if (generated == null) { - throw new FileNotFoundException(path); - } - return new BytesFileObject(path, Suppliers.ofInstance(generated)); - case SOURCE_OUTPUT: - SourceFile source = generatedSources.get(path); - if (source == null) { - throw new FileNotFoundException(path); - } - return new SourceFileObject(path, source.source()); - case ANNOTATION_PROCESSOR_PATH: - if (loader.getResource(path) == null) { - throw new FileNotFoundException(path); - } - return new ResourceFileObject(loader, path); - case CLASS_PATH: - Supplier<byte[]> bytes = classPath.apply(path); - if (bytes == null) { - throw new FileNotFoundException(path); - } - return new BytesFileObject(path, bytes); - default: - throw new IllegalArgumentException(standardLocation.getName()); - } - } - - private static String packageRelativePath(String pkg, String relativeName) { - if (pkg.isEmpty()) { - return relativeName; - } - return pkg.replace('.', '/') + '/' + relativeName; - } - - private abstract static class ReadOnlyFileObject implements FileObject { - - protected final String path; - - public ReadOnlyFileObject(String path) { - this.path = path; - } - - @Override - public final String getName() { - return path; - } - - @Override - public URI toUri() { - return URI.create("file://" + path); - } - - @Override - public final OutputStream openOutputStream() { - throw new IllegalStateException(); - } - - @Override - public final Writer openWriter() { - throw new IllegalStateException(); - } - - @Override - public final long getLastModified() { - return 0; - } - - @Override - public final boolean delete() { - throw new IllegalStateException(); - } - } - - private abstract static class WriteOnlyFileObject implements FileObject { - - @Override - public final InputStream openInputStream() { - throw new IllegalStateException(); - } - - @Override - public final Reader openReader(boolean ignoreEncodingErrors) { - throw new IllegalStateException(); - } - - @Override - public final CharSequence getCharContent(boolean ignoreEncodingErrors) { - throw new IllegalStateException(); - } - } - - private static class TurbineJavaFileObject extends WriteOnlyFileObject implements JavaFileObject { - - private final StandardLocation location; - private final Kind kind; - private final CharSequence name; - private final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - - public TurbineJavaFileObject(StandardLocation location, Kind kind, CharSequence name) { - this.location = location; - this.kind = kind; - this.name = name; - } - - @Override - public Kind getKind() { - return kind; - } - - @Override - public boolean isNameCompatible(String simpleName, Kind kind) { - throw new UnsupportedOperationException(); - } - - @Override - public NestingKind getNestingKind() { - throw new UnsupportedOperationException(); - } - - @Override - public Modifier getAccessLevel() { - throw new UnsupportedOperationException(); - } - - @Override - public URI toUri() { - return URI.create("file://" + name + kind.extension); - } - - @Override - public String getName() { - return name.toString(); - } - - @Override - public OutputStream openOutputStream() { - return baos; - } - - @Override - public Writer openWriter() { - return new OutputStreamWriter(openOutputStream(), UTF_8); - } - - @Override - public long getLastModified() { - return 0; - } - - @Override - public boolean delete() { - throw new IllegalStateException(); - } - - public byte[] bytes() { - return baos.toByteArray(); - } - - public String contents() { - return new String(baos.toByteArray(), UTF_8); - } - - public StandardLocation location() { - return location; - } - } - - private static class ResourceFileObject extends ReadOnlyFileObject { - - private final ClassLoader loader; - - public ResourceFileObject(ClassLoader loader, String path) { - super(path); - this.loader = loader; - } - - @Override - public URI toUri() { - try { - return loader.getResource(path).toURI(); - } catch (URISyntaxException e) { - throw new AssertionError(e); - } - } - - @Override - public InputStream openInputStream() { - return loader.getResourceAsStream(path); - } - - @Override - public Reader openReader(boolean ignoreEncodingErrors) throws IOException { - return new InputStreamReader(openInputStream(), UTF_8); - } - - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { - return new String(ByteStreams.toByteArray(openInputStream()), UTF_8); - } - } - - private static class BytesFileObject extends ReadOnlyFileObject { - - private final Supplier<byte[]> bytes; - - public BytesFileObject(String path, Supplier<byte[]> bytes) { - super(path); - this.bytes = bytes; - } - - @Override - public InputStream openInputStream() { - return new ByteArrayInputStream(bytes.get()); - } - - @Override - public Reader openReader(boolean ignoreEncodingErrors) { - return new InputStreamReader(openInputStream(), UTF_8); - } - - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) { - return new String(bytes.get(), UTF_8); - } - } - - private static class SourceFileObject extends ReadOnlyFileObject { - - private final String source; - - public SourceFileObject(String path, String source) { - super(path); - this.source = source; - } - - @Override - public InputStream openInputStream() { - return new ByteArrayInputStream(source.getBytes(UTF_8)); - } - - @Override - public Reader openReader(boolean ignoreEncodingErrors) { - return new StringReader(source); - } - - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) { - return source; - } - } -} diff --git a/java/com/google/turbine/processing/TurbineMessager.java b/java/com/google/turbine/processing/TurbineMessager.java deleted file mode 100644 index 9c333b2..0000000 --- a/java/com/google/turbine/processing/TurbineMessager.java +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.turbine.binder.bound.SourceTypeBoundClass; -import com.google.turbine.binder.bound.TurbineAnnotationValue; -import com.google.turbine.binder.bound.TypeBoundClass; -import com.google.turbine.binder.bound.TypeBoundClass.MethodInfo; -import com.google.turbine.binder.bound.TypeBoundClass.TyVarInfo; -import com.google.turbine.binder.sym.ClassSymbol; -import com.google.turbine.binder.sym.FieldSymbol; -import com.google.turbine.binder.sym.MethodSymbol; -import com.google.turbine.binder.sym.ParamSymbol; -import com.google.turbine.binder.sym.Symbol; -import com.google.turbine.binder.sym.TyVarSymbol; -import com.google.turbine.diag.SourceFile; -import com.google.turbine.diag.TurbineError; -import com.google.turbine.diag.TurbineLog; -import com.google.turbine.model.Const; -import com.google.turbine.processing.TurbineElement.TurbineNoTypeElement; -import com.google.turbine.tree.Tree; -import com.google.turbine.type.AnnoInfo; -import java.util.Iterator; -import javax.annotation.processing.Messager; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.AnnotationValue; -import javax.lang.model.element.Element; -import javax.tools.Diagnostic; -import org.checkerframework.checker.nullness.qual.Nullable; - -/** Turbine's implementation of {@link Messager}. */ -public class TurbineMessager implements Messager { - private final ModelFactory factory; - private final TurbineLog log; - - public TurbineMessager(ModelFactory factory, TurbineLog log) { - this.factory = factory; - this.log = log; - } - - @Override - public void printMessage(Diagnostic.Kind kind, CharSequence msg) { - // TODO(cushon): null-check `msg` after fixing affected processors - log.diagnostic(kind, String.valueOf(msg)); - } - - @Override - public void printMessage(Diagnostic.Kind kind, CharSequence msg, Element e) { - if (e == null || e instanceof TurbineNoTypeElement) { - printMessage(kind, msg); - return; - } - Symbol sym = ((TurbineElement) e).sym(); - SourceFile source = getSource(sym); - int position = getPosition(sym); - log.withSource(source).diagnostic(kind, position, TurbineError.ErrorKind.PROC, msg); - } - - @Override - public void printMessage(Diagnostic.Kind kind, CharSequence msg, Element e, AnnotationMirror a) { - if (a == null || e == null || e instanceof TurbineNoTypeElement) { - printMessage(kind, msg, e); - return; - } - SourceFile source = getSource(((TurbineElement) e).sym()); - int position = ((TurbineAnnotationMirror) a).anno().tree().position(); - log.withSource(source).diagnostic(kind, position, TurbineError.ErrorKind.PROC, msg); - } - - @Override - public void printMessage( - Diagnostic.Kind kind, CharSequence msg, Element e, AnnotationMirror a, AnnotationValue v) { - if (a == null || e == null || e instanceof TurbineNoTypeElement || v == null) { - printMessage(kind, msg, e, a); - return; - } - SourceFile source = getSource(((TurbineElement) e).sym()); - AnnoInfo anno = ((TurbineAnnotationMirror) a).anno(); - int position = locateInAnnotation(((TurbineAnnotationValueMirror) v).value(), anno); - if (position == -1) { - position = anno.tree().position(); - } - log.withSource(source).diagnostic(kind, position, TurbineError.ErrorKind.PROC, msg); - } - - /** - * Returns the {@link SourceFile} that contains the declaration of the given {@link Symbol}, or - * {@code null} if the symbol was not compiled from source. - */ - @Nullable - private SourceFile getSource(Symbol sym) { - ClassSymbol encl = ModelFactory.enclosingClass(sym); - TypeBoundClass info = factory.getSymbol(encl); - if (!(info instanceof SourceTypeBoundClass)) { - return null; - } - return ((SourceTypeBoundClass) info).source(); - } - - /** - * Returns the position of the given {@link Symbol}'s declaration, or {@code null} if it was not - * compiled from source. - */ - private int getPosition(Symbol sym) { - switch (sym.symKind()) { - case CLASS: - return classPosition((ClassSymbol) sym); - case TY_PARAM: - return tyParamPosition((TyVarSymbol) sym); - case METHOD: - return methodPosition((MethodSymbol) sym); - case FIELD: - return fieldPosition((FieldSymbol) sym); - case PARAMETER: - return paramPosition((ParamSymbol) sym); - case MODULE: - case PACKAGE: - break; - } - throw new AssertionError(sym.symKind()); - } - - private int fieldPosition(FieldSymbol sym) { - Tree.VarDecl decl = factory.getFieldInfo(sym).decl(); - return decl != null ? decl.position() : -1; - } - - private int paramPosition(ParamSymbol sym) { - MethodInfo minfo = factory.getMethodInfo(sym.owner()); - if (minfo.decl() == null) { - return -1; - } - int idx = minfo.parameters().indexOf(factory.getParamInfo(sym)); - return minfo.decl().params().get(idx).position(); - } - - private int methodPosition(MethodSymbol sym) { - MethodInfo methodInfo = factory.getMethodInfo(sym); - Tree.MethDecl decl = methodInfo.decl(); - if (decl != null) { - return decl.position(); - } - // use the enclosing class position for synthetic methods - int position = classPosition(sym.owner()); - if (position == -1) { - return -1; - } - // TODO(b/139079081): change diagnostic position of declarations instead of the -= 6 fixup - position -= 6; // adjust to start of `class ` for parity with javac - return position; - } - - private int classPosition(ClassSymbol owner) { - TypeBoundClass symbol = factory.getSymbol(owner); - if (!(symbol instanceof SourceTypeBoundClass)) { - return -1; - } - return ((SourceTypeBoundClass) symbol).decl().position(); - } - - private int tyParamPosition(TyVarSymbol sym) { - TyVarSymbol tyVarSymbol = sym; - Symbol owner = tyVarSymbol.owner(); - ImmutableMap<TyVarSymbol, TyVarInfo> tyVars; - ImmutableList<Tree.TyParam> trees; - switch (owner.symKind()) { - case CLASS: - TypeBoundClass cinfo = factory.getSymbol((ClassSymbol) owner); - if (!(cinfo instanceof SourceTypeBoundClass)) { - return -1; - } - tyVars = cinfo.typeParameterTypes(); - trees = ((SourceTypeBoundClass) cinfo).decl().typarams(); - break; - case METHOD: - MethodInfo minfo = factory.getMethodInfo((MethodSymbol) owner); - if (minfo.decl() == null) { - return -1; - } - tyVars = minfo.tyParams(); - trees = minfo.decl().typarams(); - break; - default: - throw new AssertionError(owner.symKind()); - } - return trees.get(tyVars.keySet().asList().indexOf(tyVarSymbol)).position(); - } - - /** Returns the position of the given annotation value {@code v} in the given annotation. */ - private static int locateInAnnotation(Const v, AnnoInfo anno) { - return locate(v, anno.values().values().asList(), anno.tree().args()); - } - - /** - * Returns the position of the given annotation value {@code toFind} within the given constant - * {@code v} (which may be a compound value, i.e. a nested annotation or array value), and given - * the corresponding expression tree. - */ - private static int locate(Const toFind, Const v, Tree.Expression t) { - // the element name can be omitted for `value`, e.g. in `@A({1, 2, 3})` - t = t.kind().equals(Tree.Kind.ASSIGN) ? ((Tree.Assign) t).expr() : t; - if (toFind.equals(v)) { - return t.position(); - } - switch (v.kind()) { - case ARRAY: - ImmutableList<Tree.Expression> elements = - t.kind().equals(Tree.Kind.ARRAY_INIT) - ? ((Tree.ArrayInit) t).exprs() - : ImmutableList.of(t); - return locate(toFind, ((Const.ArrayInitValue) v).elements(), elements); - case ANNOTATION: - return locateInAnnotation(toFind, ((TurbineAnnotationValue) v).info()); - default: - return -1; - } - } - - /** - * Returns the position of the given annotation value {@code toFind}, given a list of annotation - * values corresponding to the element values of a (possibly nested) annotation or an array value, - * and the corresponding expression trees. - */ - private static int locate( - Const toFind, ImmutableList<Const> vx, ImmutableList<Tree.Expression> tx) { - Iterator<Const> vi = vx.iterator(); - Iterator<Tree.Expression> ti = tx.iterator(); - while (vi.hasNext()) { - int result = locate(toFind, vi.next(), ti.next()); - if (result != -1) { - return result; - } - } - return -1; - } -} diff --git a/java/com/google/turbine/processing/TurbineName.java b/java/com/google/turbine/processing/TurbineName.java deleted file mode 100644 index 584b1b1..0000000 --- a/java/com/google/turbine/processing/TurbineName.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import static java.util.Objects.requireNonNull; - -import javax.lang.model.element.Name; - -/** An implementation of {@link Name} backed by a {@link CharSequence}. */ -public class TurbineName implements Name { - - private final String name; - - public TurbineName(String name) { - requireNonNull(name); - this.name = name; - } - - @Override - public boolean contentEquals(CharSequence cs) { - return name.contentEquals(cs); - } - - @Override - public int length() { - return name.length(); - } - - @Override - public char charAt(int index) { - return name.charAt(index); - } - - @Override - public CharSequence subSequence(int start, int end) { - return name.subSequence(start, end); - } - - @Override - public String toString() { - return name; - } - - @Override - public int hashCode() { - return name.hashCode(); - } - - @Override - public boolean equals(Object obj) { - return obj instanceof TurbineName && contentEquals(((TurbineName) obj).name); - } -} diff --git a/java/com/google/turbine/processing/TurbineProcessingEnvironment.java b/java/com/google/turbine/processing/TurbineProcessingEnvironment.java deleted file mode 100644 index 726d075..0000000 --- a/java/com/google/turbine/processing/TurbineProcessingEnvironment.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import java.util.Locale; -import java.util.Map; -import javax.annotation.processing.Filer; -import javax.annotation.processing.Messager; -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.SourceVersion; -import javax.lang.model.util.Elements; -import javax.lang.model.util.Types; -import org.checkerframework.checker.nullness.qual.Nullable; - -/** Turbine's {@link ProcessingEnvironment). */ -public class TurbineProcessingEnvironment implements ProcessingEnvironment { - - private final Filer filer; - private final Types types; - private final Map<String, String> processorOptions; - private final Elements elements; - private final Map<String, byte[]> statistics; - private final SourceVersion sourceVersion; - private final Messager messager; - private final ClassLoader processorLoader; - - public TurbineProcessingEnvironment( - Filer filer, - Types types, - Elements elements, - Messager messager, - Map<String, String> processorOptions, - SourceVersion sourceVersion, - @Nullable ClassLoader processorLoader, - Map<String, byte[]> statistics) { - this.filer = filer; - this.types = types; - this.processorOptions = processorOptions; - this.sourceVersion = sourceVersion; - this.elements = elements; - this.statistics = statistics; - this.messager = messager; - this.processorLoader = processorLoader; - } - - @Override - public Map<String, String> getOptions() { - return processorOptions; - } - - @Override - public Messager getMessager() { - return messager; - } - - @Override - public Filer getFiler() { - return filer; - } - - @Override - public Elements getElementUtils() { - return elements; - } - - @Override - public Types getTypeUtils() { - return types; - } - - @Override - public SourceVersion getSourceVersion() { - return sourceVersion; - } - - @Override - public Locale getLocale() { - return Locale.ENGLISH; - } - - public ClassLoader processorLoader() { - return processorLoader; - } - - public void addStatistics(String key, byte[] extension) { - byte[] existing = statistics.put(key, extension); - if (existing != null) { - throw new IllegalStateException("duplicate statistics reported for " + key); - } - } -} diff --git a/java/com/google/turbine/processing/TurbineRoundEnvironment.java b/java/com/google/turbine/processing/TurbineRoundEnvironment.java deleted file mode 100644 index d63a4e8..0000000 --- a/java/com/google/turbine/processing/TurbineRoundEnvironment.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import com.google.common.base.Supplier; -import com.google.common.base.Suppliers; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.ImmutableSetMultimap; -import com.google.turbine.binder.sym.ClassSymbol; -import com.google.turbine.binder.sym.Symbol; -import com.google.turbine.processing.TurbineElement.TurbineTypeElement; -import java.lang.annotation.Annotation; -import java.util.Set; -import javax.annotation.processing.RoundEnvironment; -import javax.lang.model.element.Element; -import javax.lang.model.element.TypeElement; - -/** A {@link RoundEnvironment}. */ -public class TurbineRoundEnvironment implements RoundEnvironment { - - private final ModelFactory factory; - private final ImmutableSet<ClassSymbol> syms; - private final boolean processingOver; - private final boolean errorRaised; - private final ImmutableSetMultimap<ClassSymbol, Symbol> allAnnotations; - - // the round environment doesn't outlive the round, so don't worry about resetting this cache - private final Supplier<ImmutableSet<TurbineTypeElement>> rootElements = - Suppliers.memoize( - new Supplier<ImmutableSet<TurbineTypeElement>>() { - @Override - public ImmutableSet<TurbineTypeElement> get() { - ImmutableSet.Builder<TurbineTypeElement> result = ImmutableSet.builder(); - for (ClassSymbol sym : syms) { - if (sym.simpleName().contains("$") && factory.getSymbol(sym).owner() != null) { - continue; - } - if (sym.simpleName().equals("package-info")) { - continue; - } - result.add(factory.typeElement(sym)); - } - return result.build(); - } - }); - - public TurbineRoundEnvironment( - ModelFactory factory, - ImmutableSet<ClassSymbol> syms, - boolean processingOver, - boolean errorRaised, - ImmutableSetMultimap<ClassSymbol, Symbol> allAnnotations) { - this.factory = factory; - this.syms = syms; - this.processingOver = processingOver; - this.errorRaised = errorRaised; - this.allAnnotations = allAnnotations; - } - - @Override - public boolean processingOver() { - return processingOver; - } - - @Override - public boolean errorRaised() { - return errorRaised; - } - - @Override - public ImmutableSet<TurbineTypeElement> getRootElements() { - return rootElements.get(); - } - - @Override - public Set<? extends Element> getElementsAnnotatedWith(TypeElement a) { - return factory.elements(allAnnotations.get(((TurbineTypeElement) a).sym())); - } - - @Override - public Set<? extends Element> getElementsAnnotatedWith(Class<? extends Annotation> a) { - return getElementsAnnotatedWith( - factory.typeElement(new ClassSymbol(a.getName().replace('.', '/')))); - } -} diff --git a/java/com/google/turbine/processing/TurbineTypeMirror.java b/java/com/google/turbine/processing/TurbineTypeMirror.java deleted file mode 100644 index e94672c..0000000 --- a/java/com/google/turbine/processing/TurbineTypeMirror.java +++ /dev/null @@ -1,770 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import static com.google.common.collect.Iterables.getLast; -import static java.util.Objects.requireNonNull; - -import com.google.common.base.Ascii; -import com.google.common.base.Joiner; -import com.google.common.base.Supplier; -import com.google.common.collect.ImmutableList; -import com.google.turbine.binder.bound.TypeBoundClass; -import com.google.turbine.binder.bound.TypeBoundClass.TyVarInfo; -import com.google.turbine.binder.sym.PackageSymbol; -import com.google.turbine.binder.sym.TyVarSymbol; -import com.google.turbine.model.TurbineConstantTypeKind; -import com.google.turbine.model.TurbineFlag; -import com.google.turbine.model.TurbineTyKind; -import com.google.turbine.type.AnnoInfo; -import com.google.turbine.type.Type; -import com.google.turbine.type.Type.ArrayTy; -import com.google.turbine.type.Type.ClassTy; -import com.google.turbine.type.Type.ErrorTy; -import com.google.turbine.type.Type.IntersectionTy; -import com.google.turbine.type.Type.MethodTy; -import com.google.turbine.type.Type.PrimTy; -import com.google.turbine.type.Type.TyVar; -import com.google.turbine.type.Type.WildTy; -import com.google.turbine.type.Type.WildTy.BoundKind; -import java.lang.annotation.Annotation; -import java.util.List; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.Element; -import javax.lang.model.type.ArrayType; -import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.ErrorType; -import javax.lang.model.type.ExecutableType; -import javax.lang.model.type.IntersectionType; -import javax.lang.model.type.NoType; -import javax.lang.model.type.NullType; -import javax.lang.model.type.PrimitiveType; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.type.TypeVariable; -import javax.lang.model.type.TypeVisitor; -import javax.lang.model.type.WildcardType; - -/** A {@link TypeMirror} implementation backed by a {@link Type}. */ -public abstract class TurbineTypeMirror implements TypeMirror { - - protected final ModelFactory factory; - - protected TurbineTypeMirror(ModelFactory factory) { - this.factory = requireNonNull(factory); - } - - protected abstract ImmutableList<AnnoInfo> annos(); - - @Override - public final List<? extends AnnotationMirror> getAnnotationMirrors() { - ImmutableList.Builder<AnnotationMirror> result = ImmutableList.builder(); - for (AnnoInfo anno : annos()) { - result.add(TurbineAnnotationMirror.create(factory, anno)); - } - return result.build(); - } - - @Override - public final <A extends Annotation> A getAnnotation(Class<A> annotationType) { - throw new AssertionError(); - } - - @Override - public final <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType) { - throw new AssertionError(); - } - - public abstract Type asTurbineType(); - - @Override - public String toString() { - return asTurbineType().toString(); - } - - /** A {@link PrimitiveType} implementation backed by a {@link PrimTy}. */ - static class TurbinePrimitiveType extends TurbineTypeMirror implements PrimitiveType { - - @Override - public String toString() { - return Ascii.toLowerCase(type.primkind().toString()); - } - - @Override - public Type asTurbineType() { - return type; - } - - public final PrimTy type; - - TurbinePrimitiveType(ModelFactory factory, PrimTy type) { - super(factory); - if (type.primkind() == TurbineConstantTypeKind.STRING) { - throw new AssertionError(type); - } - this.type = type; - } - - @Override - public TypeKind getKind() { - switch (type.primkind()) { - case CHAR: - return TypeKind.CHAR; - case SHORT: - return TypeKind.SHORT; - case INT: - return TypeKind.INT; - case LONG: - return TypeKind.LONG; - case FLOAT: - return TypeKind.FLOAT; - case DOUBLE: - return TypeKind.DOUBLE; - case BOOLEAN: - return TypeKind.BOOLEAN; - case BYTE: - return TypeKind.BYTE; - case NULL: - return TypeKind.NULL; - case STRING: - } - throw new AssertionError(type.primkind()); - } - - @Override - public <R, P> R accept(TypeVisitor<R, P> v, P p) { - return v.visitPrimitive(this, p); - } - - @Override - protected ImmutableList<AnnoInfo> annos() { - return type.annos(); - } - } - - /** A {@link DeclaredType} implementation backed by a {@link ClassTy}. */ - static class TurbineDeclaredType extends TurbineTypeMirror implements DeclaredType { - - @Override - public int hashCode() { - return type.sym().hashCode(); - } - - @Override - public boolean equals(Object obj) { - return obj instanceof TurbineDeclaredType && type.equals(((TurbineDeclaredType) obj).type); - } - - @Override - public ClassTy asTurbineType() { - return type; - } - - private final ClassTy type; - - TurbineDeclaredType(ModelFactory factory, ClassTy type) { - super(factory); - this.type = type; - } - - @Override - public String toString() { - return type.toString(); - } - - final Supplier<Element> element = - factory.memoize( - new Supplier<Element>() { - @Override - public Element get() { - return factory.typeElement(type.sym()); - } - }); - - @Override - public Element asElement() { - return element.get(); - } - - final Supplier<TypeMirror> enclosing = - factory.memoize( - new Supplier<TypeMirror>() { - @Override - public TypeMirror get() { - TypeBoundClass info = factory.getSymbol(type.sym()); - if (info != null - && info.owner() != null - && ((info.access() & TurbineFlag.ACC_STATIC) == 0) - && info.kind() == TurbineTyKind.CLASS) { - if (type.classes().size() > 1) { - return factory.asTypeMirror( - ClassTy.create(type.classes().subList(0, type.classes().size() - 1))); - } - return factory.asTypeMirror(ClassTy.asNonParametricClassTy(info.owner())); - } - return factory.noType(); - } - }); - - @Override - public TypeMirror getEnclosingType() { - return enclosing.get(); - } - - final Supplier<ImmutableList<TypeMirror>> typeArguments = - factory.memoize( - new Supplier<ImmutableList<TypeMirror>>() { - @Override - public ImmutableList<TypeMirror> get() { - return factory.asTypeMirrors(getLast(type.classes()).targs()); - } - }); - - @Override - public List<? extends TypeMirror> getTypeArguments() { - return typeArguments.get(); - } - - @Override - public TypeKind getKind() { - return TypeKind.DECLARED; - } - - @Override - public <R, P> R accept(TypeVisitor<R, P> v, P p) { - return v.visitDeclared(this, p); - } - - public ClassTy type() { - return type; - } - - @Override - protected ImmutableList<AnnoInfo> annos() { - return getLast(type.classes()).annos(); - } - } - - /** An {@link ArrayType} implementation backed by a {@link ArrayTy}. */ - static class TurbineArrayType extends TurbineTypeMirror implements ArrayType { - - @Override - public Type asTurbineType() { - return type; - } - - private final ArrayTy type; - - TurbineArrayType(ModelFactory factory, ArrayTy type) { - super(factory); - this.type = type; - } - - @Override - public TypeMirror getComponentType() { - return factory.asTypeMirror(type.elementType()); - } - - @Override - public TypeKind getKind() { - return TypeKind.ARRAY; - } - - @Override - public <R, P> R accept(TypeVisitor<R, P> v, P p) { - return v.visitArray(this, p); - } - - @Override - protected ImmutableList<AnnoInfo> annos() { - return type.annos(); - } - } - - /** An {@link ErrorType} implementation backed by a {@link ErrorTy}. */ - static class TurbineErrorType extends TurbineTypeMirror implements ErrorType { - - private final ErrorTy type; - - public TurbineErrorType(ModelFactory factory, ErrorTy type) { - super(factory); - this.type = type; - } - - @Override - public TypeKind getKind() { - return TypeKind.ERROR; - } - - @Override - public <R, P> R accept(TypeVisitor<R, P> v, P p) { - return v.visitError(this, p); - } - - @Override - protected ImmutableList<AnnoInfo> annos() { - return ImmutableList.of(); - } - - @Override - public Type asTurbineType() { - return type; - } - - @Override - public Element asElement() { - return factory.noElement(type.name()); - } - - @Override - public TypeMirror getEnclosingType() { - return factory.noType(); - } - - @Override - public List<? extends TypeMirror> getTypeArguments() { - return ImmutableList.of(); - } - - @Override - public String toString() { - return type.toString(); - } - } - - /** A 'package type' implementation backed by a {@link PackageSymbol}. */ - static class TurbinePackageType extends TurbineTypeMirror implements NoType { - - @Override - public Type asTurbineType() { - throw new UnsupportedOperationException(); - } - - final PackageSymbol symbol; - - TurbinePackageType(ModelFactory factory, PackageSymbol symbol) { - super(factory); - this.symbol = symbol; - } - - @Override - public TypeKind getKind() { - return TypeKind.PACKAGE; - } - - @Override - public <R, P> R accept(TypeVisitor<R, P> v, P p) { - return v.visitNoType(this, p); - } - - @Override - public String toString() { - return symbol.toString(); - } - - @Override - public boolean equals(Object other) { - return other instanceof TurbinePackageType - && symbol.equals(((TurbinePackageType) other).symbol); - } - - @Override - public int hashCode() { - return symbol.hashCode(); - } - - @Override - protected ImmutableList<AnnoInfo> annos() { - return ImmutableList.of(); - } - } - - /** The absence of a type, {@see javax.lang.model.util.Types#getNoType}. */ - static class TurbineNoType extends TurbineTypeMirror implements NoType { - - @Override - public Type asTurbineType() { - return Type.NONE; - } - - TurbineNoType(ModelFactory factory) { - super(factory); - } - - @Override - public TypeKind getKind() { - return TypeKind.NONE; - } - - @Override - public <R, P> R accept(TypeVisitor<R, P> v, P p) { - return v.visitNoType(this, p); - } - - @Override - public String toString() { - return "none"; - } - - @Override - public boolean equals(Object other) { - return other instanceof TurbineNoType; - } - - @Override - public int hashCode() { - return getKind().hashCode(); - } - - @Override - protected ImmutableList<AnnoInfo> annos() { - return ImmutableList.of(); - } - } - - /** A void type, {@see javax.lang.model.util.Types#getNoType}. */ - static class TurbineVoidType extends TurbineTypeMirror implements NoType { - - @Override - public Type asTurbineType() { - return Type.VOID; - } - - TurbineVoidType(ModelFactory factory) { - super(factory); - } - - @Override - public TypeKind getKind() { - return TypeKind.VOID; - } - - @Override - public <R, P> R accept(TypeVisitor<R, P> v, P p) { - return v.visitNoType(this, p); - } - - @Override - protected ImmutableList<AnnoInfo> annos() { - return ImmutableList.of(); - } - } - - /** A {@link TypeVariable} implementation backed by a {@link TyVar}. */ - static class TurbineTypeVariable extends TurbineTypeMirror implements TypeVariable { - - @Override - public int hashCode() { - return type.hashCode(); - } - - @Override - public boolean equals(Object obj) { - return obj instanceof TurbineTypeVariable && type.equals(((TurbineTypeVariable) obj).type); - } - - @Override - public Type asTurbineType() { - return type; - } - - private final TyVar type; - - private final Supplier<TyVarInfo> info = - factory.memoize( - new Supplier<TyVarInfo>() { - @Override - public TyVarInfo get() { - return factory.getTyVarInfo(type.sym()); - } - }); - - private TyVarInfo info() { - return info.get(); - } - - TurbineTypeVariable(ModelFactory factory, Type.TyVar type) { - super(factory); - this.type = type; - } - - @Override - public TypeKind getKind() { - return TypeKind.TYPEVAR; - } - - @Override - public <R, P> R accept(TypeVisitor<R, P> v, P p) { - return v.visitTypeVariable(this, p); - } - - @Override - public Element asElement() { - return factory.typeParameterElement(type.sym()); - } - - @Override - public TypeMirror getUpperBound() { - return factory.asTypeMirror(info().upperBound()); - } - - @Override - public TypeMirror getLowerBound() { - return info().lowerBound() != null - ? factory.asTypeMirror(info().lowerBound()) - : factory.noType(); - } - - @Override - public String toString() { - return type.toString(); - } - - @Override - protected ImmutableList<AnnoInfo> annos() { - return type.annos(); - } - } - - /** A {@link WildcardType} implementation backed by a {@link WildTy}. */ - static class TurbineWildcardType extends TurbineTypeMirror implements WildcardType { - - @Override - public Type asTurbineType() { - return type; - } - - private final WildTy type; - - public TurbineWildcardType(ModelFactory factory, WildTy type) { - super(factory); - this.type = type; - } - - @Override - public TypeKind getKind() { - return TypeKind.WILDCARD; - } - - @Override - public <R, P> R accept(TypeVisitor<R, P> v, P p) { - return v.visitWildcard(this, p); - } - - @Override - public boolean equals(Object obj) { - return obj instanceof TurbineWildcardType && type.equals(((TurbineWildcardType) obj).type); - } - - @Override - public int hashCode() { - return type.hashCode(); - } - - @Override - public TypeMirror getExtendsBound() { - return type.boundKind() == BoundKind.UPPER ? factory.asTypeMirror(type.bound()) : null; - } - - @Override - public TypeMirror getSuperBound() { - return type.boundKind() == BoundKind.LOWER ? factory.asTypeMirror(type.bound()) : null; - } - - @Override - protected ImmutableList<AnnoInfo> annos() { - return type.annotations(); - } - } - - /** A {@link IntersectionType} implementation backed by a {@link IntersectionTy}. */ - static class TurbineIntersectionType extends TurbineTypeMirror implements IntersectionType { - - @Override - public Type asTurbineType() { - return type; - } - - private final IntersectionTy type; - - TurbineIntersectionType(ModelFactory factory, IntersectionTy type) { - super(factory); - this.type = type; - } - - @Override - public boolean equals(Object obj) { - return obj instanceof TurbineIntersectionType - && type.equals(((TurbineIntersectionType) obj).type); - } - - @Override - public int hashCode() { - return type.hashCode(); - } - - @Override - public TypeKind getKind() { - return TypeKind.INTERSECTION; - } - - @Override - public <R, P> R accept(TypeVisitor<R, P> v, P p) { - return v.visitIntersection(this, p); - } - - final Supplier<ImmutableList<TypeMirror>> bounds = - factory.memoize( - new Supplier<ImmutableList<TypeMirror>>() { - @Override - public ImmutableList<TypeMirror> get() { - return factory.asTypeMirrors(TurbineTypes.getBounds(factory, type)); - } - }); - - @Override - public List<? extends TypeMirror> getBounds() { - return bounds.get(); - } - - @Override - public String toString() { - return Joiner.on('&').join(getBounds()); - } - - @Override - protected ImmutableList<AnnoInfo> annos() { - return ImmutableList.of(); - } - } - - /** A {@link NullType} implementation. */ - public static class TurbineNullType extends TurbineTypeMirror implements NullType { - - @Override - public Type asTurbineType() { - return Type.PrimTy.create(TurbineConstantTypeKind.NULL, ImmutableList.of()); - } - - public TurbineNullType(ModelFactory factory) { - super(factory); - } - - @Override - protected ImmutableList<AnnoInfo> annos() { - return ImmutableList.of(); - } - - @Override - public boolean equals(Object obj) { - return obj instanceof NullType; - } - - @Override - public int hashCode() { - return super.hashCode(); - } - - @Override - public TypeKind getKind() { - return TypeKind.NULL; - } - - @Override - public <R, P> R accept(TypeVisitor<R, P> v, P p) { - return v.visitNull(this, p); - } - } - - /** An {@link ExecutableType} implementation backed by a {@link MethodTy}. */ - public static class TurbineExecutableType extends TurbineTypeMirror implements ExecutableType { - - @Override - public String toString() { - return type.toString(); - } - - @Override - public MethodTy asTurbineType() { - return type; - } - - public final MethodTy type; - - TurbineExecutableType(ModelFactory factory, MethodTy type) { - super(factory); - this.type = type; - } - - @Override - public boolean equals(Object obj) { - return obj instanceof TurbineExecutableType - && type.equals(((TurbineExecutableType) obj).type); - } - - @Override - public int hashCode() { - return type.hashCode(); - } - - @Override - public List<? extends TypeVariable> getTypeVariables() { - ImmutableList.Builder<TypeVariable> result = ImmutableList.builder(); - for (TyVarSymbol tyVar : type.tyParams()) { - result.add((TypeVariable) factory.asTypeMirror(TyVar.create(tyVar, ImmutableList.of()))); - } - return result.build(); - } - - @Override - public TypeMirror getReturnType() { - return factory.asTypeMirror(type.returnType()); - } - - @Override - public List<? extends TypeMirror> getParameterTypes() { - return factory.asTypeMirrors(type.parameters()); - } - - @Override - public TypeMirror getReceiverType() { - return type.receiverType() != null - ? factory.asTypeMirror(type.receiverType()) - : factory.noType(); - } - - @Override - public List<? extends TypeMirror> getThrownTypes() { - return factory.asTypeMirrors(type.thrown()); - } - - @Override - public TypeKind getKind() { - return TypeKind.EXECUTABLE; - } - - @Override - public <R, P> R accept(TypeVisitor<R, P> v, P p) { - return v.visitExecutable(this, p); - } - - @Override - protected ImmutableList<AnnoInfo> annos() { - return ImmutableList.of(); - } - } -} diff --git a/java/com/google/turbine/processing/TurbineTypes.java b/java/com/google/turbine/processing/TurbineTypes.java deleted file mode 100644 index f65f921..0000000 --- a/java/com/google/turbine/processing/TurbineTypes.java +++ /dev/null @@ -1,1132 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Verify.verify; -import static java.util.Objects.requireNonNull; - -import com.google.common.base.Function; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.turbine.binder.bound.TypeBoundClass; -import com.google.turbine.binder.bound.TypeBoundClass.TyVarInfo; -import com.google.turbine.binder.sym.ClassSymbol; -import com.google.turbine.binder.sym.FieldSymbol; -import com.google.turbine.binder.sym.MethodSymbol; -import com.google.turbine.binder.sym.ParamSymbol; -import com.google.turbine.binder.sym.Symbol; -import com.google.turbine.binder.sym.TyVarSymbol; -import com.google.turbine.model.TurbineConstantTypeKind; -import com.google.turbine.model.TurbineTyKind; -import com.google.turbine.processing.TurbineElement.TurbineExecutableElement; -import com.google.turbine.processing.TurbineElement.TurbineFieldElement; -import com.google.turbine.processing.TurbineElement.TurbineTypeElement; -import com.google.turbine.processing.TurbineElement.TurbineTypeParameterElement; -import com.google.turbine.processing.TurbineTypeMirror.TurbineDeclaredType; -import com.google.turbine.processing.TurbineTypeMirror.TurbineErrorType; -import com.google.turbine.processing.TurbineTypeMirror.TurbineTypeVariable; -import com.google.turbine.type.Type; -import com.google.turbine.type.Type.ArrayTy; -import com.google.turbine.type.Type.ClassTy; -import com.google.turbine.type.Type.ClassTy.SimpleClassTy; -import com.google.turbine.type.Type.IntersectionTy; -import com.google.turbine.type.Type.MethodTy; -import com.google.turbine.type.Type.PrimTy; -import com.google.turbine.type.Type.TyKind; -import com.google.turbine.type.Type.TyVar; -import com.google.turbine.type.Type.WildTy; -import com.google.turbine.type.Type.WildTy.BoundKind; -import com.google.turbine.type.Type.WildUnboundedTy; -import com.google.turbine.types.Erasure; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import javax.lang.model.element.Element; -import javax.lang.model.element.TypeElement; -import javax.lang.model.type.ArrayType; -import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.ExecutableType; -import javax.lang.model.type.NoType; -import javax.lang.model.type.NullType; -import javax.lang.model.type.PrimitiveType; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.type.WildcardType; -import javax.lang.model.util.Types; -import org.checkerframework.checker.nullness.qual.Nullable; - -/** An implementation of {@link Types} backed by turbine's {@link TypeMirror}. */ -public class TurbineTypes implements Types { - - private final ModelFactory factory; - - public TurbineTypes(ModelFactory factory) { - this.factory = factory; - } - - private static Type asTurbineType(TypeMirror typeMirror) { - if (!(typeMirror instanceof TurbineTypeMirror)) { - throw new IllegalArgumentException(typeMirror.toString()); - } - return ((TurbineTypeMirror) typeMirror).asTurbineType(); - } - - @Override - public Element asElement(TypeMirror t) { - switch (t.getKind()) { - case DECLARED: - return ((TurbineDeclaredType) t).asElement(); - case TYPEVAR: - return ((TurbineTypeVariable) t).asElement(); - case ERROR: - return ((TurbineErrorType) t).asElement(); - default: - return null; - } - } - - @Override - public boolean isSameType(TypeMirror a, TypeMirror b) { - Type t1 = asTurbineType(a); - Type t2 = asTurbineType(b); - if (t1.tyKind() == TyKind.WILD_TY || t2.tyKind() == TyKind.WILD_TY) { - // wild card types that appear at the top-level are never equal to each other. - // Note that generics parameterized by wildcards may be equal, so the recursive - // `isSameType(Type, Type)` below does handle wildcards. - return false; - } - return isSameType(t1, t2); - } - - private boolean isSameType(Type a, Type b) { - switch (a.tyKind()) { - case PRIM_TY: - return b.tyKind() == TyKind.PRIM_TY && ((PrimTy) a).primkind() == ((PrimTy) b).primkind(); - case VOID_TY: - return b.tyKind() == TyKind.VOID_TY; - case NONE_TY: - return b.tyKind() == TyKind.NONE_TY; - case CLASS_TY: - return isSameClassType((ClassTy) a, b); - case ARRAY_TY: - return b.tyKind() == TyKind.ARRAY_TY - && isSameType(((ArrayTy) a).elementType(), ((ArrayTy) b).elementType()); - case TY_VAR: - return b.tyKind() == TyKind.TY_VAR && ((TyVar) a).sym().equals(((TyVar) b).sym()); - case WILD_TY: - return isSameWildType((WildTy) a, b); - case INTERSECTION_TY: - return b.tyKind() == TyKind.INTERSECTION_TY - && isSameIntersectionType((IntersectionTy) a, (IntersectionTy) b); - case METHOD_TY: - return b.tyKind() == TyKind.METHOD_TY && isSameMethodType((MethodTy) a, (MethodTy) b); - case ERROR_TY: - return false; - } - throw new AssertionError(a.tyKind()); - } - - /** - * Returns true if the given method types are equivalent. - * - * <p>Receiver parameters are ignored, regardless of whether they were explicitly specified in - * source. Thrown exception types are also ignored. - */ - private boolean isSameMethodType(MethodTy a, MethodTy b) { - ImmutableMap<TyVarSymbol, Type> mapping = getMapping(a, b); - if (mapping == null) { - return false; - } - if (!sameTypeParameterBounds(a, b, mapping)) { - return false; - } - if (!isSameType(a.returnType(), subst(b.returnType(), mapping))) { - return false; - } - if (!isSameTypes(a.parameters(), substAll(b.parameters(), mapping))) { - return false; - } - return true; - } - - private boolean sameTypeParameterBounds( - MethodTy a, MethodTy b, ImmutableMap<TyVarSymbol, Type> mapping) { - if (a.tyParams().size() != b.tyParams().size()) { - return false; - } - Iterator<TyVarSymbol> ax = a.tyParams().iterator(); - Iterator<TyVarSymbol> bx = b.tyParams().iterator(); - while (ax.hasNext()) { - TyVarSymbol x = ax.next(); - TyVarSymbol y = bx.next(); - if (!isSameType( - factory.getTyVarInfo(x).upperBound(), - subst(factory.getTyVarInfo(y).upperBound(), mapping))) { - return false; - } - } - return true; - } - - private boolean isSameTypes(ImmutableList<Type> a, ImmutableList<Type> b) { - if (a.size() != b.size()) { - return false; - } - Iterator<Type> ax = a.iterator(); - Iterator<Type> bx = b.iterator(); - while (ax.hasNext()) { - if (!isSameType(ax.next(), bx.next())) { - return false; - } - } - return true; - } - - private boolean isSameIntersectionType(IntersectionTy a, IntersectionTy b) { - return isSameTypes(getBounds(a), getBounds(b)); - } - - private ImmutableList<Type> getBounds(IntersectionTy a) { - return getBounds(factory, a); - } - - static ImmutableList<Type> getBounds(ModelFactory factory, IntersectionTy type) { - ImmutableList<Type> bounds = type.bounds(); - if (implicitObjectBound(factory, bounds)) { - return ImmutableList.<Type>builder().add(ClassTy.OBJECT).addAll(bounds).build(); - } - return bounds; - } - - private static boolean implicitObjectBound(ModelFactory factory, ImmutableList<Type> bounds) { - if (bounds.isEmpty()) { - return true; - } - ClassTy first = (ClassTy) bounds.get(0); - return factory.getSymbol(first.sym()).kind().equals(TurbineTyKind.INTERFACE); - } - - private boolean isSameWildType(WildTy a, Type other) { - switch (other.tyKind()) { - case WILD_TY: - break; - case CLASS_TY: - // `? super Object` = Object - return ((ClassTy) other).sym().equals(ClassSymbol.OBJECT) - && a.boundKind() == BoundKind.LOWER - && a.bound().tyKind() == TyKind.CLASS_TY - && ((ClassTy) a.bound()).sym().equals(ClassSymbol.OBJECT); - default: - return false; - } - WildTy b = (WildTy) other; - switch (a.boundKind()) { - case NONE: - switch (b.boundKind()) { - case UPPER: - // `?` = `? extends Object` - return isObjectType(b.bound()); - case LOWER: - return false; - case NONE: - return true; - } - break; - case UPPER: - switch (b.boundKind()) { - case UPPER: - return isSameType(a.bound(), b.bound()); - case LOWER: - return false; - case NONE: - // `? extends Object` = `?` - return isObjectType(a.bound()); - } - break; - case LOWER: - return b.boundKind() == BoundKind.LOWER && isSameType(a.bound(), b.bound()); - } - throw new AssertionError(a.boundKind()); - } - - private boolean isSameClassType(ClassTy a, Type other) { - switch (other.tyKind()) { - case CLASS_TY: - break; - case WILD_TY: - WildTy w = (WildTy) other; - return a.sym().equals(ClassSymbol.OBJECT) - && w.boundKind() == BoundKind.LOWER - && w.bound().tyKind() == TyKind.CLASS_TY - && ((ClassTy) w.bound()).sym().equals(ClassSymbol.OBJECT); - default: - return false; - } - ClassTy b = (ClassTy) other; - if (!a.sym().equals(b.sym())) { - return false; - } - Iterator<SimpleClassTy> ax = a.classes().reverse().iterator(); - Iterator<SimpleClassTy> bx = b.classes().reverse().iterator(); - while (ax.hasNext() && bx.hasNext()) { - if (!isSameSimpleClassType(ax.next(), bx.next())) { - return false; - } - } - // The class type may be in non-canonical form, e.g. may or may not have entries in 'classes' - // corresponding to enclosing instances. Don't require the enclosing instances' representations - // to be identical unless one of them has type arguments. - if (hasTyArgs(ax) || hasTyArgs(bx)) { - return false; - } - return true; - } - - /** Returns true if any {@link SimpleClassTy} in the given iterator has type arguments. */ - private static boolean hasTyArgs(Iterator<SimpleClassTy> it) { - while (it.hasNext()) { - if (!it.next().targs().isEmpty()) { - return true; - } - } - return false; - } - - private boolean isSameSimpleClassType(SimpleClassTy a, SimpleClassTy b) { - return a.sym().equals(b.sym()) && isSameTypes(a.targs(), b.targs()); - } - - /** Returns true if type {@code a} is a subtype of type {@code b}. See JLS 4.1.0, 'subtyping'. */ - @Override - public boolean isSubtype(TypeMirror a, TypeMirror b) { - return isSubtype(asTurbineType(a), asTurbineType(b), /* strict= */ true); - } - - /** - * Returns true if type {@code a} is a subtype of type {@code b}. See JLS 4.1.0, 'subtyping'. - * - * @param strict true if raw types should not be considered subtypes of parameterized types. See - * also {@link #isAssignable}, which sets {@code strict} to {@code false} to handle unchecked - * conversions. - */ - private boolean isSubtype(Type a, Type b, boolean strict) { - if (b.tyKind() == TyKind.INTERSECTION_TY) { - for (Type bound : getBounds((IntersectionTy) b)) { - // TODO(cushon): javac rejects e.g. `|List| isAssignable Serializable&ArrayList<?>`, - // i.e. it does a strict subtype test against the intersection type. Is that a bug? - if (!isSubtype(a, bound, /* strict= */ true)) { - return false; - } - } - return true; - } - switch (a.tyKind()) { - case CLASS_TY: - return isClassSubtype((ClassTy) a, b, strict); - case PRIM_TY: - return isPrimSubtype((PrimTy) a, b); - case ARRAY_TY: - return isArraySubtype((ArrayTy) a, b, strict); - case TY_VAR: - return isTyVarSubtype((TyVar) a, b, strict); - case INTERSECTION_TY: - return isIntersectionSubtype((IntersectionTy) a, b, strict); - case VOID_TY: - return b.tyKind() == TyKind.VOID_TY; - case NONE_TY: - return b.tyKind() == TyKind.NONE_TY; - case WILD_TY: - // TODO(cushon): javac takes wildcards as input to isSubtype and sometimes returns `true`, - // see JDK-8039198 - return false; - case ERROR_TY: - // for compatibility with javac, treat error as bottom - return true; - case METHOD_TY: - return false; - } - throw new AssertionError(a.tyKind()); - } - - private boolean isTyVarSubtype(TyVar a, Type b, boolean strict) { - if (b.tyKind() == TyKind.TY_VAR) { - return a.sym().equals(((TyVar) b).sym()); - } - TyVarInfo tyVarInfo = factory.getTyVarInfo(a.sym()); - return isSubtype(tyVarInfo.upperBound(), b, strict); - } - - private boolean isIntersectionSubtype(IntersectionTy a, Type b, boolean strict) { - for (Type bound : getBounds(a)) { - if (isSubtype(bound, b, strict)) { - return true; - } - } - return false; - } - - // see JLS 4.10.3, 'subtyping among array types' - // https://docs.oracle.com/javase/specs/jls/se11/html/jls-4.html#jls-4.10.3 - private boolean isArraySubtype(ArrayTy a, Type b, boolean strict) { - switch (b.tyKind()) { - case ARRAY_TY: - Type ae = a.elementType(); - Type be = ((ArrayTy) b).elementType(); - if (ae.tyKind() == TyKind.PRIM_TY) { - return isSameType(ae, be); - } - return isSubtype(ae, be, strict); - case CLASS_TY: - ClassSymbol bsym = ((ClassTy) b).sym(); - switch (bsym.binaryName()) { - case "java/lang/Object": - case "java/lang/Cloneable": - case "java/io/Serializable": - return true; - default: - return false; - } - default: - return false; - } - } - - // see JLS 4.10.1, 'subtyping among primitive types' - // https://docs.oracle.com/javase/specs/jls/se11/html/jls-4.html#jls-4.10.1 - private static boolean isPrimSubtype(PrimTy a, Type other) { - if (other.tyKind() != TyKind.PRIM_TY) { - return false; - } - PrimTy b = (PrimTy) other; - switch (a.primkind()) { - case CHAR: - switch (b.primkind()) { - case CHAR: - case INT: - case LONG: - case FLOAT: - case DOUBLE: - return true; - default: - return false; - } - case BYTE: - switch (b.primkind()) { - case BYTE: - case SHORT: - case INT: - case LONG: - case FLOAT: - case DOUBLE: - return true; - default: - return false; - } - case SHORT: - switch (b.primkind()) { - case SHORT: - case INT: - case LONG: - case FLOAT: - case DOUBLE: - return true; - default: - return false; - } - case INT: - switch (b.primkind()) { - case INT: - case LONG: - case FLOAT: - case DOUBLE: - return true; - default: - return false; - } - case LONG: - switch (b.primkind()) { - case LONG: - case FLOAT: - case DOUBLE: - return true; - default: - return false; - } - case FLOAT: - switch (b.primkind()) { - case FLOAT: - case DOUBLE: - return true; - default: - return false; - } - case DOUBLE: - case STRING: - case BOOLEAN: - return a.primkind() == b.primkind(); - case NULL: - break; - } - throw new AssertionError(a.primkind()); - } - - private boolean isClassSubtype(ClassTy a, Type other, boolean strict) { - if (other.tyKind() != TyKind.CLASS_TY) { - return false; - } - ClassTy b = (ClassTy) other; - if (!a.sym().equals(b.sym())) { - // find a path from a to b in the type hierarchy - ImmutableList<ClassTy> path = factory.cha().search(a, b.sym()); - if (path.isEmpty()) { - return false; - } - // perform repeated type substitution to get an instance of B with the type arguments - // provided by A - a = path.get(0); - for (ClassTy ty : path) { - ImmutableMap<TyVarSymbol, Type> mapping = getMapping(ty); - if (mapping == null) { - // if we encounter a raw type on the path from A to B the result is erased - a = (ClassTy) erasure(a); - break; - } - a = substClassTy(a, mapping); - } - } - Iterator<SimpleClassTy> ax = a.classes().reverse().iterator(); - Iterator<SimpleClassTy> bx = b.classes().reverse().iterator(); - while (ax.hasNext() && bx.hasNext()) { - if (!tyArgsContains(ax.next(), bx.next(), strict)) { - return false; - } - } - return !hasTyArgs(ax) && !hasTyArgs(bx); - } - - /** - * Given two parameterizations of the same {@link SimpleClassTy}, {@code a} and {@code b}, teturns - * true if the type arguments of {@code a} are pairwise contained by the type arguments of {@code - * b}. - * - * @see {@link #contains} and JLS 4.5.1. - */ - private boolean tyArgsContains(SimpleClassTy a, SimpleClassTy b, boolean strict) { - verify(a.sym().equals(b.sym())); - Iterator<Type> ax = a.targs().iterator(); - Iterator<Type> bx = b.targs().iterator(); - while (ax.hasNext() && bx.hasNext()) { - if (!containedBy(ax.next(), bx.next(), strict)) { - return false; - } - } - // C<F1, ..., FN> <= |C|, but |C| is not a subtype of C<F1, ..., FN> - // https://docs.oracle.com/javase/specs/jls/se11/html/jls-4.html#jls-4.8 - if (strict) { - return !bx.hasNext(); - } - return true; - } - - private Type subst(Type type, Map<TyVarSymbol, Type> mapping) { - switch (type.tyKind()) { - case CLASS_TY: - return substClassTy((ClassTy) type, mapping); - case ARRAY_TY: - return substArrayTy((ArrayTy) type, mapping); - case TY_VAR: - return substTyVar((TyVar) type, mapping); - case PRIM_TY: - case VOID_TY: - case NONE_TY: - case ERROR_TY: - return type; - case METHOD_TY: - return substMethod((MethodTy) type, mapping); - case INTERSECTION_TY: - return substIntersectionTy((IntersectionTy) type, mapping); - case WILD_TY: - return substWildTy((WildTy) type, mapping); - } - throw new AssertionError(type.tyKind()); - } - - private Type substWildTy(WildTy type, Map<TyVarSymbol, Type> mapping) { - switch (type.boundKind()) { - case NONE: - return type; - case UPPER: - return Type.WildUpperBoundedTy.create(subst(type.bound(), mapping), ImmutableList.of()); - case LOWER: - return Type.WildLowerBoundedTy.create(subst(type.bound(), mapping), ImmutableList.of()); - } - throw new AssertionError(type.boundKind()); - } - - private Type substIntersectionTy(IntersectionTy type, Map<TyVarSymbol, Type> mapping) { - return IntersectionTy.create(substAll(getBounds(type), mapping)); - } - - private MethodTy substMethod(MethodTy method, Map<TyVarSymbol, Type> mapping) { - return MethodTy.create( - method.tyParams(), - subst(method.returnType(), mapping), - method.receiverType() != null ? subst(method.receiverType(), mapping) : null, - substAll(method.parameters(), mapping), - substAll(method.thrown(), mapping)); - } - - private ImmutableList<Type> substAll( - ImmutableList<? extends Type> types, Map<TyVarSymbol, Type> mapping) { - ImmutableList.Builder<Type> result = ImmutableList.builder(); - for (Type type : types) { - result.add(subst(type, mapping)); - } - return result.build(); - } - - private Type substTyVar(TyVar type, Map<TyVarSymbol, Type> mapping) { - return mapping.getOrDefault(type.sym(), type); - } - - private Type substArrayTy(ArrayTy type, Map<TyVarSymbol, Type> mapping) { - return ArrayTy.create(subst(type.elementType(), mapping), type.annos()); - } - - private ClassTy substClassTy(ClassTy type, Map<TyVarSymbol, Type> mapping) { - ImmutableList.Builder<SimpleClassTy> simples = ImmutableList.builder(); - for (SimpleClassTy simple : type.classes()) { - ImmutableList.Builder<Type> args = ImmutableList.builder(); - for (Type arg : simple.targs()) { - args.add(subst(arg, mapping)); - } - simples.add(SimpleClassTy.create(simple.sym(), args.build(), simple.annos())); - } - return ClassTy.create(simples.build()); - } - - /** - * Returns a mapping that can be used to adapt the signature 'b' to the type parameters of 'a', or - * {@code null} if no such mapping exists. - */ - @Nullable - private static ImmutableMap<TyVarSymbol, Type> getMapping(MethodTy a, MethodTy b) { - if (a.tyParams().size() != b.tyParams().size()) { - return null; - } - Iterator<TyVarSymbol> ax = a.tyParams().iterator(); - Iterator<TyVarSymbol> bx = b.tyParams().iterator(); - ImmutableMap.Builder<TyVarSymbol, Type> mapping = ImmutableMap.builder(); - while (ax.hasNext()) { - TyVarSymbol s = ax.next(); - TyVarSymbol t = bx.next(); - mapping.put(t, TyVar.create(s, ImmutableList.of())); - } - return mapping.build(); - } - - /** - * Returns a map from formal type parameters to their arguments for a given class type, or an - * empty map for non-parameterized types, or {@code null} for raw types. - */ - @Nullable - private ImmutableMap<TyVarSymbol, Type> getMapping(ClassTy ty) { - ImmutableMap.Builder<TyVarSymbol, Type> mapping = ImmutableMap.builder(); - for (SimpleClassTy s : ty.classes()) { - TypeBoundClass info = factory.getSymbol(s.sym()); - if (s.targs().isEmpty() && !info.typeParameters().isEmpty()) { - return null; // rawtypes - } - Iterator<TyVarSymbol> ax = info.typeParameters().values().iterator(); - Iterator<Type> bx = s.targs().iterator(); - while (ax.hasNext()) { - mapping.put(ax.next(), bx.next()); - } - verify(!bx.hasNext()); - } - return mapping.build(); - } - - @Override - public boolean isAssignable(TypeMirror a1, TypeMirror a2) { - return isAssignable(asTurbineType(a1), asTurbineType(a2)); - } - - private boolean isAssignable(Type t1, Type t2) { - switch (t1.tyKind()) { - case PRIM_TY: - if (t2.tyKind() == TyKind.CLASS_TY) { - ClassSymbol boxed = boxedClass(((PrimTy) t1).primkind()); - t1 = ClassTy.asNonParametricClassTy(boxed); - } - break; - case CLASS_TY: - switch (t2.tyKind()) { - case PRIM_TY: - TurbineConstantTypeKind unboxed = unboxedType((ClassTy) t1); - if (unboxed == null) { - return false; - } - t1 = PrimTy.create(unboxed, ImmutableList.of()); - break; - case CLASS_TY: - break; - default: // fall out - } - break; - default: // fall out - } - return isSubtype(t1, t2, /* strict= */ false); - } - - private static boolean isObjectType(Type type) { - return type.tyKind() == TyKind.CLASS_TY && ((ClassTy) type).sym().equals(ClassSymbol.OBJECT); - } - - @Override - public boolean contains(TypeMirror a, TypeMirror b) { - return contains(asTurbineType(a), asTurbineType(b), /* strict= */ true); - } - - private boolean contains(Type t1, Type t2, boolean strict) { - return containedBy(t2, t1, strict); - } - - // See JLS 4.5.1, 'type containment' - // https://docs.oracle.com/javase/specs/jls/se11/html/jls-4.html#jls-4.5.1 - private boolean containedBy(Type t1, Type t2, boolean strict) { - if (t1.tyKind() == TyKind.WILD_TY) { - WildTy w1 = (WildTy) t1; - Type t; - switch (w1.boundKind()) { - case UPPER: - t = w1.bound(); - if (t2.tyKind() == TyKind.WILD_TY) { - WildTy w2 = (WildTy) t2; - switch (w2.boundKind()) { - case UPPER: - // ? extends T <= ? extends S if T <: S - return isSubtype(t, w2.bound(), strict); - case NONE: - // ? extends T <= ? [extends Object] if T <: Object - return true; - case LOWER: - // ? extends T <= ? super S - return false; - } - throw new AssertionError(w1.boundKind()); - } - return false; - case LOWER: - t = w1.bound(); - if (t2.tyKind() == TyKind.WILD_TY) { - WildTy w2 = (WildTy) t2; - switch (w2.boundKind()) { - case LOWER: - // ? super T <= ? super S if S <: T - return isSubtype(w2.bound(), t, strict); - case NONE: - // ? super T <= ? [extends Object] - return true; - case UPPER: - // ? super T <= ? extends Object - return isObjectType(w2.bound()); - } - throw new AssertionError(w2.boundKind()); - } - // ? super Object <= Object - return isObjectType(t2) && isObjectType(t); - case NONE: - if (t2.tyKind() == TyKind.WILD_TY) { - WildTy w2 = (WildTy) t2; - switch (w2.boundKind()) { - case NONE: - // ? [extends Object] <= ? extends Object - return true; - case LOWER: - // ? [extends Object] <= ? super S - return false; - case UPPER: - // ? [extends Object] <= ? extends S if Object <: S - return isObjectType(w2.bound()); - } - throw new AssertionError(w2.boundKind()); - } - return false; - } - throw new AssertionError(w1.boundKind()); - } - if (t2.tyKind() == TyKind.WILD_TY) { - WildTy w2 = (WildTy) t2; - switch (w2.boundKind()) { - case LOWER: - // T <= ? super S - return isSubtype(w2.bound(), t1, strict); - case UPPER: - // T <= ? extends S - return isSubtype(t1, w2.bound(), strict); - case NONE: - // T <= ? [extends Object] - return true; - } - throw new AssertionError(w2.boundKind()); - } - if (isSameType(t1, t2)) { - return true; - } - return false; - } - - @Override - public boolean isSubsignature(ExecutableType m1, ExecutableType m2) { - return isSubsignature((MethodTy) asTurbineType(m1), (MethodTy) asTurbineType(m2)); - } - - private boolean isSubsignature(MethodTy a, MethodTy b) { - return isSameSignature(a, b) || isSameSignature(a, (MethodTy) erasure(b)); - } - - private boolean isSameSignature(MethodTy a, MethodTy b) { - if (a.parameters().size() != b.parameters().size()) { - return false; - } - ImmutableMap<TyVarSymbol, Type> mapping = getMapping(a, b); - if (mapping == null) { - return false; - } - if (!sameTypeParameterBounds(a, b, mapping)) { - return false; - } - Iterator<Type> ax = a.parameters().iterator(); - // adapt the formal parameter types of 'b' to the type parameters of 'a' - Iterator<Type> bx = substAll(b.parameters(), mapping).iterator(); - while (ax.hasNext()) { - if (!isSameType(ax.next(), bx.next())) { - return false; - } - } - return true; - } - - @Override - public List<? extends TypeMirror> directSupertypes(TypeMirror m) { - return factory.asTypeMirrors(directSupertypes(asTurbineType(m))); - } - - public ImmutableList<Type> directSupertypes(Type t) { - switch (t.tyKind()) { - case CLASS_TY: - return directSupertypes((ClassTy) t); - case INTERSECTION_TY: - return ((IntersectionTy) t).bounds(); - case TY_VAR: - return getBounds(factory.getTyVarInfo(((TyVar) t).sym()).upperBound()); - case ARRAY_TY: - return directSupertypes((ArrayTy) t); - case PRIM_TY: - case VOID_TY: - case WILD_TY: - case ERROR_TY: - case NONE_TY: - return ImmutableList.of(); - case METHOD_TY: - break; - } - throw new IllegalArgumentException(t.tyKind().name()); - } - - private ImmutableList<Type> directSupertypes(ArrayTy t) { - Type elem = t.elementType(); - if (elem.tyKind() == TyKind.PRIM_TY || isObjectType(elem)) { - return ImmutableList.of( - IntersectionTy.create( - ImmutableList.of(ClassTy.OBJECT, ClassTy.SERIALIZABLE, ClassTy.CLONEABLE))); - } - ImmutableList<Type> ex = directSupertypes(elem); - return ImmutableList.of(ArrayTy.create(ex.iterator().next(), ImmutableList.of())); - } - - private ImmutableList<Type> directSupertypes(ClassTy t) { - if (t.sym().equals(ClassSymbol.OBJECT)) { - return ImmutableList.of(); - } - TypeBoundClass info = factory.getSymbol(t.sym()); - Map<TyVarSymbol, Type> mapping = getMapping(t); - boolean raw = mapping == null; - ImmutableList.Builder<Type> builder = ImmutableList.builder(); - if (info.superClassType() != null) { - builder.add(raw ? erasure(info.superClassType()) : subst(info.superClassType(), mapping)); - } else { - builder.add(ClassTy.OBJECT); - } - for (Type interfaceType : info.interfaceTypes()) { - builder.add(raw ? erasure(interfaceType) : subst(interfaceType, mapping)); - } - return builder.build(); - } - - @Override - public TypeMirror erasure(TypeMirror typeMirror) { - return factory.asTypeMirror(erasure(asTurbineType(typeMirror))); - } - - private Type erasure(Type type) { - return Erasure.erase( - type, - new Function<TyVarSymbol, TyVarInfo>() { - @Override - public TyVarInfo apply(TyVarSymbol input) { - return factory.getTyVarInfo(input); - } - }); - } - - @Override - public TypeElement boxedClass(PrimitiveType p) { - return factory.typeElement(boxedClass(((PrimTy) asTurbineType(p)).primkind())); - } - - static ClassSymbol boxedClass(TurbineConstantTypeKind kind) { - switch (kind) { - case CHAR: - return ClassSymbol.CHARACTER; - case SHORT: - return ClassSymbol.SHORT; - case INT: - return ClassSymbol.INTEGER; - case LONG: - return ClassSymbol.LONG; - case FLOAT: - return ClassSymbol.FLOAT; - case DOUBLE: - return ClassSymbol.DOUBLE; - case BOOLEAN: - return ClassSymbol.BOOLEAN; - case BYTE: - return ClassSymbol.BYTE; - case STRING: - case NULL: - break; - } - throw new AssertionError(kind); - } - - @Override - public PrimitiveType unboxedType(TypeMirror typeMirror) { - Type type = asTurbineType(typeMirror); - if (type.tyKind() != TyKind.CLASS_TY) { - throw new IllegalArgumentException(type.toString()); - } - TurbineConstantTypeKind unboxed = unboxedType((ClassTy) type); - if (unboxed == null) { - throw new IllegalArgumentException(type.toString()); - } - return (PrimitiveType) factory.asTypeMirror(PrimTy.create(unboxed, ImmutableList.of())); - } - - private static TurbineConstantTypeKind unboxedType(ClassTy classTy) { - switch (classTy.sym().binaryName()) { - case "java/lang/Boolean": - return TurbineConstantTypeKind.BOOLEAN; - case "java/lang/Byte": - return TurbineConstantTypeKind.BYTE; - case "java/lang/Short": - return TurbineConstantTypeKind.SHORT; - case "java/lang/Integer": - return TurbineConstantTypeKind.INT; - case "java/lang/Long": - return TurbineConstantTypeKind.LONG; - case "java/lang/Character": - return TurbineConstantTypeKind.CHAR; - case "java/lang/Float": - return TurbineConstantTypeKind.FLOAT; - case "java/lang/Double": - return TurbineConstantTypeKind.DOUBLE; - default: - return null; - } - } - - @Override - public TypeMirror capture(TypeMirror typeMirror) { - throw new UnsupportedOperationException(); - } - - @Override - public PrimitiveType getPrimitiveType(TypeKind kind) { - checkArgument(kind.isPrimitive(), "%s is not a primitive type", kind); - return (PrimitiveType) - factory.asTypeMirror(PrimTy.create(primitiveType(kind), ImmutableList.of())); - } - - private static TurbineConstantTypeKind primitiveType(TypeKind kind) { - switch (kind) { - case BOOLEAN: - return TurbineConstantTypeKind.BOOLEAN; - case BYTE: - return TurbineConstantTypeKind.BYTE; - case SHORT: - return TurbineConstantTypeKind.SHORT; - case INT: - return TurbineConstantTypeKind.INT; - case LONG: - return TurbineConstantTypeKind.LONG; - case CHAR: - return TurbineConstantTypeKind.CHAR; - case FLOAT: - return TurbineConstantTypeKind.FLOAT; - case DOUBLE: - return TurbineConstantTypeKind.DOUBLE; - default: - throw new IllegalArgumentException(kind + " is not a primitive type"); - } - } - - @Override - public NullType getNullType() { - return factory.nullType(); - } - - @Override - public NoType getNoType(TypeKind kind) { - switch (kind) { - case VOID: - return (NoType) factory.asTypeMirror(Type.VOID); - case NONE: - return factory.noType(); - default: - throw new IllegalArgumentException(kind.toString()); - } - } - - @Override - public ArrayType getArrayType(TypeMirror componentType) { - return (ArrayType) - factory.asTypeMirror(ArrayTy.create(asTurbineType(componentType), ImmutableList.of())); - } - - @Override - public WildcardType getWildcardType(TypeMirror extendsBound, TypeMirror superBound) { - WildTy type; - if (extendsBound != null) { - type = WildTy.WildUpperBoundedTy.create(asTurbineType(extendsBound), ImmutableList.of()); - } else if (superBound != null) { - type = WildTy.WildLowerBoundedTy.create(asTurbineType(superBound), ImmutableList.of()); - } else { - type = WildUnboundedTy.create(ImmutableList.of()); - } - return (WildcardType) factory.asTypeMirror(type); - } - - @Override - public DeclaredType getDeclaredType(TypeElement typeElem, TypeMirror... typeArgs) { - requireNonNull(typeElem); - ImmutableList.Builder<Type> args = ImmutableList.builder(); - for (TypeMirror t : typeArgs) { - args.add(asTurbineType(t)); - } - TurbineTypeElement element = (TurbineTypeElement) typeElem; - return (DeclaredType) - factory.asTypeMirror( - ClassTy.create( - ImmutableList.of( - SimpleClassTy.create(element.sym(), args.build(), ImmutableList.of())))); - } - - @Override - public DeclaredType getDeclaredType( - DeclaredType containing, TypeElement typeElem, TypeMirror... typeArgs) { - if (containing == null) { - return getDeclaredType(typeElem, typeArgs); - } - requireNonNull(typeElem); - ClassTy base = (ClassTy) asTurbineType(containing); - TurbineTypeElement element = (TurbineTypeElement) typeElem; - ImmutableList.Builder<Type> args = ImmutableList.builder(); - for (TypeMirror t : typeArgs) { - args.add(asTurbineType(t)); - } - return (DeclaredType) - factory.asTypeMirror( - ClassTy.create( - ImmutableList.<SimpleClassTy>builder() - .addAll(base.classes()) - .add(SimpleClassTy.create(element.sym(), args.build(), ImmutableList.of())) - .build())); - } - - private static ClassSymbol enclosingClass(Symbol symbol) { - switch (symbol.symKind()) { - case CLASS: - return (ClassSymbol) symbol; - case TY_PARAM: - return enclosingClass(((TyVarSymbol) symbol).owner()); - case METHOD: - return ((MethodSymbol) symbol).owner(); - case FIELD: - return ((FieldSymbol) symbol).owner(); - case PARAMETER: - return ((ParamSymbol) symbol).owner().owner(); - case MODULE: - case PACKAGE: - throw new IllegalArgumentException(symbol.symKind().toString()); - } - throw new AssertionError(symbol.symKind()); - } - - private static Type type(Element element) { - switch (element.getKind()) { - case TYPE_PARAMETER: - return TyVar.create(((TurbineTypeParameterElement) element).sym(), ImmutableList.of()); - case FIELD: - return ((TurbineFieldElement) element).info().type(); - case METHOD: - case CONSTRUCTOR: - return ((TurbineExecutableElement) element).info().asType(); - default: - throw new UnsupportedOperationException(element.toString()); - } - } - - /** - * Returns the {@link TypeMirror} of the given {@code element} as a member of {@code containing}, - * or else {@code null} if it is not a member. - * - * <p>e.g. given a class {@code MyStringList} that implements {@code List<String>}, the type of - * {@code List.add} would be {@code add(String)}. - */ - @Override - public TypeMirror asMemberOf(DeclaredType containing, Element element) { - ClassTy c = ((TurbineDeclaredType) containing).asTurbineType(); - ClassSymbol symbol = enclosingClass(((TurbineElement) element).sym()); - ImmutableList<ClassTy> path = factory.cha().search(c, enclosingClass(symbol)); - if (path.isEmpty()) { - return null; - } - Type type = type(element); - for (ClassTy ty : path) { - ImmutableMap<TyVarSymbol, Type> mapping = getMapping(ty); - if (mapping == null) { - type = erasure(type); - break; - } - type = subst(type, mapping); - } - return factory.asTypeMirror(type); - } -} diff --git a/java/com/google/turbine/tree/Pretty.java b/java/com/google/turbine/tree/Pretty.java index b693a42..2b9374e 100644 --- a/java/com/google/turbine/tree/Pretty.java +++ b/java/com/google/turbine/tree/Pretty.java @@ -501,6 +501,8 @@ public class Pretty implements Tree.Visitor<Void, Void> { case ACC_SYNTHETIC: case ACC_BRIDGE: break; + default: + throw new AssertionError(mod); } } } diff --git a/java/com/google/turbine/tree/Tree.java b/java/com/google/turbine/tree/Tree.java index d36c3ab..a20b106 100644 --- a/java/com/google/turbine/tree/Tree.java +++ b/java/com/google/turbine/tree/Tree.java @@ -661,7 +661,6 @@ public abstract class Tree { private final Tree ty; private final Ident name; private final Optional<Expression> init; - private final String javadoc; public VarDecl( int position, @@ -669,15 +668,13 @@ public abstract class Tree { ImmutableList<Anno> annos, Tree ty, Ident name, - Optional<Expression> init, - String javadoc) { + Optional<Expression> init) { super(position); this.mods = ImmutableSet.copyOf(mods); this.annos = annos; this.ty = ty; this.name = name; this.init = init; - this.javadoc = javadoc; } @Override @@ -709,14 +706,6 @@ public abstract class Tree { public Optional<Expression> init() { return init; } - - /** - * A javadoc comment, excluding the opening and closing delimiters but including all interior - * characters and whitespace. - */ - public String javadoc() { - return javadoc; - } } /** A JLS 8.4 method declaration. */ @@ -729,7 +718,6 @@ public abstract class Tree { private final ImmutableList<VarDecl> params; private final ImmutableList<ClassTy> exntys; private final Optional<Tree> defaultValue; - private final String javadoc; public MethDecl( int position, @@ -740,8 +728,7 @@ public abstract class Tree { Ident name, ImmutableList<VarDecl> params, ImmutableList<ClassTy> exntys, - Optional<Tree> defaultValue, - String javadoc) { + Optional<Tree> defaultValue) { super(position); this.mods = ImmutableSet.copyOf(mods); this.annos = annos; @@ -751,7 +738,6 @@ public abstract class Tree { this.params = params; this.exntys = exntys; this.defaultValue = defaultValue; - this.javadoc = javadoc; } @Override @@ -795,13 +781,6 @@ public abstract class Tree { public Optional<Tree> defaultValue() { return defaultValue; } - /** - * A javadoc comment, excluding the opening and closing delimiters but including all interior - * characters and whitespace. - */ - public String javadoc() { - return javadoc; - } } /** A JLS 9.7 annotation. */ @@ -873,7 +852,6 @@ public abstract class Tree { private final ImmutableList<ClassTy> impls; private final ImmutableList<Tree> members; private final TurbineTyKind tykind; - private final String javadoc; public TyDecl( int position, @@ -884,8 +862,7 @@ public abstract class Tree { Optional<ClassTy> xtnds, ImmutableList<ClassTy> impls, ImmutableList<Tree> members, - TurbineTyKind tykind, - String javadoc) { + TurbineTyKind tykind) { super(position); this.mods = ImmutableSet.copyOf(mods); this.annos = annos; @@ -895,7 +872,6 @@ public abstract class Tree { this.impls = impls; this.members = members; this.tykind = tykind; - this.javadoc = javadoc; } @Override @@ -939,13 +915,6 @@ public abstract class Tree { public TurbineTyKind tykind() { return tykind; } - /** - * A javadoc comment, excluding the opening and closing delimiters but including all interior - * characters and whitespace. - */ - public String javadoc() { - return javadoc; - } } /** A JLS 4.4. type variable declaration. */ diff --git a/java/com/google/turbine/type/AnnoInfo.java b/java/com/google/turbine/type/AnnoInfo.java index ff902b3..9c907aa 100644 --- a/java/com/google/turbine/type/AnnoInfo.java +++ b/java/com/google/turbine/type/AnnoInfo.java @@ -16,9 +16,6 @@ package com.google.turbine.type; -import static com.google.common.collect.Iterables.getOnlyElement; -import static java.util.Objects.requireNonNull; - import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.turbine.binder.sym.ClassSymbol; @@ -27,7 +24,6 @@ import com.google.turbine.model.Const; import com.google.turbine.tree.Tree; import com.google.turbine.tree.Tree.Anno; import com.google.turbine.tree.Tree.Expression; -import java.util.Map; import java.util.Objects; /** An annotation use. */ @@ -42,7 +38,7 @@ public class AnnoInfo { this.source = source; this.sym = sym; this.tree = tree; - this.values = requireNonNull(values); + this.values = values; } /** The annotation's source, for diagnostics. */ @@ -70,10 +66,6 @@ public class AnnoInfo { return sym; } - public Tree.Anno tree() { - return tree; - } - public AnnoInfo withValues(ImmutableMap<String, Const> values) { return new AnnoInfo(source, sym, tree, values); } @@ -91,27 +83,4 @@ public class AnnoInfo { AnnoInfo that = (AnnoInfo) obj; return sym.equals(that.sym) && values.equals(that.values); } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append('@').append(sym.binaryName().replace('/', '.').replace('$', '.')); - boolean first = true; - if (values != null && !values.isEmpty()) { - sb.append('('); - if (values.size() == 1 && values.containsKey("value")) { - sb.append(getOnlyElement(values.values())); - } else { - for (Map.Entry<String, Const> e : values.entrySet()) { - if (!first) { - sb.append(", "); - } - sb.append(e.getKey()).append('=').append(e.getValue()); - first = false; - } - } - sb.append(')'); - } - return sb.toString(); - } } diff --git a/java/com/google/turbine/type/Type.java b/java/com/google/turbine/type/Type.java index daba2ae..8950ec0 100644 --- a/java/com/google/turbine/type/Type.java +++ b/java/com/google/turbine/type/Type.java @@ -16,23 +16,14 @@ package com.google.turbine.type; -import static com.google.common.collect.Iterables.getLast; -import static java.util.Objects.requireNonNull; - import com.google.auto.value.AutoValue; -import com.google.auto.value.extension.memoized.Memoized; import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.turbine.binder.sym.ClassSymbol; import com.google.turbine.binder.sym.TyVarSymbol; import com.google.turbine.model.TurbineConstantTypeKind; -import com.google.turbine.tree.Tree; -import java.util.ArrayList; import java.util.Arrays; -import java.util.List; -import org.checkerframework.checker.nullness.qual.Nullable; /** JLS 4 types. */ public interface Type { @@ -57,11 +48,8 @@ public interface Type { WILD_TY, /** An intersection type. */ INTERSECTION_TY, - /** A method type. */ - METHOD_TY, - ERROR_TY, - NONE_TY, + ERROR_TY } /** The type kind. */ @@ -74,34 +62,9 @@ public interface Type { public TyKind tyKind() { return TyKind.VOID_TY; } - - @Override - public final String toString() { - return "void"; - } - }; - - /** The void type. */ - Type NONE = - new Type() { - @Override - public TyKind tyKind() { - return TyKind.NONE_TY; - } - - @Override - public final String toString() { - return "none"; - } }; - /** - * A class type. - * - * <p>Qualified types (e.g. {@code OuterClass<Foo>.InnerClass<Bar>}) are repesented as a list - * {@link SimpleClassTy}s (enclosing types first), each of which contains a {@link ClassSymbol} - * and an optional list of type arguments. - */ + /** A class type. */ @AutoValue abstract class ClassTy implements Type { @@ -114,17 +77,19 @@ public interface Type { /** The {@link ClassTy} for {@code java.lang.String}. */ public static final ClassTy STRING = asNonParametricClassTy(ClassSymbol.STRING); - public static final ClassTy CLONEABLE = asNonParametricClassTy(ClassSymbol.CLONEABLE); - public static final ClassTy SERIALIZABLE = asNonParametricClassTy(ClassSymbol.SERIALIZABLE); - /** Returns a {@link ClassTy} with no type arguments for the given {@link ClassSymbol}. */ public static ClassTy asNonParametricClassTy(ClassSymbol i) { - return ClassTy.create( - Arrays.asList(SimpleClassTy.create(i, ImmutableList.of(), ImmutableList.of()))); + return create(Arrays.asList(SimpleClassTy.create(i, ImmutableList.of(), ImmutableList.of()))); } public abstract ImmutableList<SimpleClassTy> classes(); + /** + * A class type. Qualified types are repesented as a list tuples, each of which contains a + * {@link ClassSymbol} and an optional list of type arguments. + * + * @param classes components of a qualified class type, possibly with type arguments. + */ public static ClassTy create(Iterable<SimpleClassTy> classes) { return new AutoValue_Type_ClassTy(ImmutableList.copyOf(classes)); } @@ -136,7 +101,7 @@ public interface Type { /** The class symbol. */ public ClassSymbol sym() { - return getLast(classes()).sym(); + return Iterables.getLast(classes()).sym(); } @Override @@ -144,15 +109,11 @@ public interface Type { StringBuilder sb = new StringBuilder(); boolean first = true; for (SimpleClassTy c : classes()) { - for (AnnoInfo anno : c.annos()) { - sb.append(anno); - sb.append(' '); - } if (!first) { sb.append('.'); sb.append(c.sym().binaryName().substring(c.sym().binaryName().lastIndexOf('$') + 1)); } else { - sb.append(c.sym().binaryName().replace('/', '.').replace('$', '.')); + sb.append(c.sym().binaryName()); } if (!c.targs().isEmpty()) { sb.append('<'); @@ -181,46 +142,6 @@ public interface Type { /** The type annotations. */ public abstract ImmutableList<AnnoInfo> annos(); - - @Memoized - @Override - public abstract int hashCode(); - } - - @Memoized - @Override - public int hashCode() { - return Iterables.getLast(classes()).hashCode(); - } - - @Override - public final boolean equals(Object obj) { - if (!(obj instanceof ClassTy)) { - return false; - } - ClassTy that = (ClassTy) obj; - int i = this.classes().size() - 1; - int j = that.classes().size() - 1; - for (; i >= 0 && j >= 0; i--, j--) { - if (!this.classes().get(i).equals(that.classes().get(j))) { - return false; - } - } - // don't rely on canonical form for simple class names - if (hasTargs(this.classes(), i) || hasTargs(that.classes(), j)) { - return false; - } - return true; - } - - private static boolean hasTargs(ImmutableList<SimpleClassTy> classes, int idx) { - for (; idx >= 0; idx--) { - SimpleClassTy simple = classes.get(idx); - if (!simple.targs().isEmpty() || !simple.annos().isEmpty()) { - return true; - } - } - return false; } } @@ -242,22 +163,6 @@ public interface Type { /** The type annotations. */ public abstract ImmutableList<AnnoInfo> annos(); - - @Override - public final String toString() { - StringBuilder sb = new StringBuilder(); - for (AnnoInfo anno : annos()) { - sb.append(anno); - sb.append(' '); - } - sb.append(elementType()); - sb.append("[]"); - return sb.toString(); - } - - @Memoized - @Override - public abstract int hashCode(); } /** A type variable. */ @@ -278,21 +183,11 @@ public interface Type { @Override public final String toString() { - StringBuilder sb = new StringBuilder(); - for (AnnoInfo anno : annos()) { - sb.append(anno); - sb.append(' '); - } - sb.append(sym().name()); - return sb.toString(); + return sym().owner() + "#" + sym().name(); } /** The type annotations. */ public abstract ImmutableList<AnnoInfo> annos(); - - @Memoized - @Override - public abstract int hashCode(); } /** A primitive type. */ @@ -313,21 +208,6 @@ public interface Type { /** The type annotations. */ public abstract ImmutableList<AnnoInfo> annos(); - - @Override - public final String toString() { - StringBuilder sb = new StringBuilder(); - for (AnnoInfo anno : annos()) { - sb.append(anno); - sb.append(' '); - } - sb.append(primkind()); - return sb.toString(); - } - - @Memoized - @Override - public abstract int hashCode(); } /** A wildcard type, valid only inside (possibly nested) type arguments. */ @@ -368,22 +248,6 @@ public interface Type { public BoundKind boundKind() { return BoundKind.UPPER; } - - @Override - public final String toString() { - StringBuilder sb = new StringBuilder(); - for (AnnoInfo anno : annotations()) { - sb.append(anno); - sb.append(' '); - } - sb.append("? extends "); - sb.append(bound()); - return sb.toString(); - } - - @Memoized - @Override - public abstract int hashCode(); } /** An lower-bounded wildcard type. */ @@ -402,22 +266,6 @@ public interface Type { public BoundKind boundKind() { return BoundKind.LOWER; } - - @Override - public final String toString() { - StringBuilder sb = new StringBuilder(); - for (AnnoInfo anno : annotations()) { - sb.append(anno); - sb.append(' '); - } - sb.append("? super "); - sb.append(bound()); - return sb.toString(); - } - - @Memoized - @Override - public abstract int hashCode(); } /** An unbounded wildcard type. */ @@ -437,21 +285,6 @@ public interface Type { public Type bound() { throw new IllegalStateException(); } - - @Override - public final String toString() { - StringBuilder sb = new StringBuilder(); - for (AnnoInfo anno : annotations()) { - sb.append(anno); - sb.append(' '); - } - sb.append('?'); - return sb.toString(); - } - - @Memoized - @Override - public abstract int hashCode(); } /** An intersection type. */ @@ -468,121 +301,18 @@ public interface Type { public TyKind tyKind() { return TyKind.INTERSECTION_TY; } - - @Memoized - @Override - public abstract int hashCode(); - - @Override - public final String toString() { - return Joiner.on('&').join(bounds()); - } - } - - /** A method type. */ - @AutoValue - abstract class MethodTy implements Type { - - public abstract ImmutableSet<TyVarSymbol> tyParams(); - - public abstract Type returnType(); - - /** The type of the receiver parameter (see JLS 8.4.1). */ - @Nullable - public abstract Type receiverType(); - - public abstract ImmutableList<Type> parameters(); - - public abstract ImmutableList<Type> thrown(); - - public static MethodTy create( - ImmutableSet<TyVarSymbol> tyParams, - Type returnType, - Type receiverType, - ImmutableList<Type> parameters, - ImmutableList<Type> thrown) { - return new AutoValue_Type_MethodTy(tyParams, returnType, receiverType, parameters, thrown); - } - - @Override - public TyKind tyKind() { - return TyKind.METHOD_TY; - } - - @Override - public final String toString() { - StringBuilder sb = new StringBuilder(); - if (!tyParams().isEmpty()) { - sb.append('<'); - Joiner.on(',').appendTo(sb, tyParams()); - sb.append('>'); - } - sb.append('('); - Joiner.on(',').appendTo(sb, parameters()); - sb.append(')'); - sb.append(returnType()); - return sb.toString(); - } - - @Memoized - @Override - public abstract int hashCode(); } /** An error type. */ - final class ErrorTy implements Type { - - private final String name; - - private ErrorTy(String name) { - this.name = requireNonNull(name); - } - - /** - * Best-effort syntactic context for use in diagnostics or by annotation processors. This may be - * a simple or qualified name; it is not a canonical qualified name. - */ - public String name() { - return name; - } - - public static ErrorTy create(Iterable<Tree.Ident> names) { - List<String> bits = new ArrayList<>(); - for (Tree.Ident ident : names) { - bits.add(ident.value()); - } - return create(Joiner.on('.').join(bits)); - } - - public static ErrorTy create(String name) { - return new ErrorTy(name); + @AutoValue + abstract class ErrorTy implements Type { + public static ErrorTy create() { + return new AutoValue_Type_ErrorTy(); } @Override public TyKind tyKind() { return TyKind.ERROR_TY; } - - @Override - public final String toString() { - return name(); - } - - @Override - public final int hashCode() { - return System.identityHashCode(this); - } - - @Override - public final boolean equals(Object other) { - // The name associated with an error type is context for use in diagnostics or by annotations - // processors. Two error types with the same name don't necessarily represent the same type. - - // TODO(cushon): should error types compare equal to themselves if they correspond to the same - // source location? Investigate storing the source position for this type, or replacing with - // `this == other` (and removing interning in ModelFactory). - - return false; - } } } diff --git a/java/com/google/turbine/types/Canonicalize.java b/java/com/google/turbine/types/Canonicalize.java index 22df069..ab73618 100644 --- a/java/com/google/turbine/types/Canonicalize.java +++ b/java/com/google/turbine/types/Canonicalize.java @@ -100,7 +100,6 @@ public class Canonicalize { case PRIM_TY: case VOID_TY: case TY_VAR: - case ERROR_TY: return type; case WILD_TY: return canonicalizeWildTy(base, (WildTy) type); @@ -119,9 +118,6 @@ public class Canonicalize { } private ClassTy canon(ClassSymbol base, ClassTy ty) { - if (ty.sym().equals(ClassSymbol.ERROR)) { - return ty; - } if (isRaw(ty)) { return Erasure.eraseClassTy(ty); } @@ -281,7 +277,7 @@ public class Canonicalize { } /** Instantiates a type argument using the given mapping. */ - private static Type instantiate(Map<TyVarSymbol, Type> mapping, Type type) { + private Type instantiate(Map<TyVarSymbol, Type> mapping, Type type) { if (type == null) { return null; } @@ -290,7 +286,6 @@ public class Canonicalize { return instantiateWildTy(mapping, (WildTy) type); case PRIM_TY: case VOID_TY: - case ERROR_TY: return type; case CLASS_TY: return instantiateClassTy(mapping, (ClassTy) type); @@ -309,7 +304,7 @@ public class Canonicalize { } } - private static Type instantiateWildTy(Map<TyVarSymbol, Type> mapping, WildTy type) { + private Type instantiateWildTy(Map<TyVarSymbol, Type> mapping, WildTy type) { switch (type.boundKind()) { case NONE: return type; @@ -319,11 +314,12 @@ public class Canonicalize { case LOWER: return Type.WildLowerBoundedTy.create( instantiate(mapping, type.bound()), type.annotations()); + default: + throw new AssertionError(type.boundKind()); } - throw new AssertionError(type.boundKind()); } - private static Type instantiateClassTy(Map<TyVarSymbol, Type> mapping, ClassTy type) { + private Type instantiateClassTy(Map<TyVarSymbol, Type> mapping, ClassTy type) { ImmutableList.Builder<SimpleClassTy> simples = ImmutableList.builder(); for (SimpleClassTy simple : type.classes()) { ImmutableList.Builder<Type> args = ImmutableList.builder(); @@ -340,7 +336,7 @@ public class Canonicalize { * reference, or else {@code null}. */ @Nullable - private static TyVarSymbol tyVarSym(Type type) { + private TyVarSymbol tyVarSym(Type type) { if (type.tyKind() == TyKind.TY_VAR) { return ((TyVar) type).sym(); } diff --git a/java/com/google/turbine/types/Erasure.java b/java/com/google/turbine/types/Erasure.java index 9042897..e2c7d8f 100644 --- a/java/com/google/turbine/types/Erasure.java +++ b/java/com/google/turbine/types/Erasure.java @@ -18,7 +18,6 @@ package com.google.turbine.types; import com.google.common.base.Function; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; import com.google.turbine.binder.bound.SourceTypeBoundClass; import com.google.turbine.binder.bound.TypeBoundClass.TyVarInfo; import com.google.turbine.binder.sym.TyVarSymbol; @@ -27,14 +26,15 @@ import com.google.turbine.type.Type.ArrayTy; import com.google.turbine.type.Type.ClassTy; import com.google.turbine.type.Type.ClassTy.SimpleClassTy; import com.google.turbine.type.Type.IntersectionTy; -import com.google.turbine.type.Type.MethodTy; import com.google.turbine.type.Type.TyVar; -import com.google.turbine.type.Type.WildTy; /** Generic type erasure. */ public class Erasure { public static Type erase(Type ty, Function<TyVarSymbol, SourceTypeBoundClass.TyVarInfo> tenv) { switch (ty.tyKind()) { + case PRIM_TY: + case VOID_TY: + return ty; case CLASS_TY: return eraseClassTy((Type.ClassTy) ty); case ARRAY_TY: @@ -43,37 +43,20 @@ public class Erasure { return eraseTyVar((TyVar) ty, tenv); case INTERSECTION_TY: return eraseIntersectionTy((Type.IntersectionTy) ty, tenv); - case WILD_TY: - return eraseWildTy((Type.WildTy) ty, tenv); - case METHOD_TY: - return erasureMethodTy((Type.MethodTy) ty, tenv); - case PRIM_TY: - case VOID_TY: - case ERROR_TY: - case NONE_TY: - return ty; - } - throw new AssertionError(ty.tyKind()); - } - - private static ImmutableList<Type> erase( - ImmutableList<Type> types, Function<TyVarSymbol, TyVarInfo> tenv) { - ImmutableList.Builder<Type> result = ImmutableList.builder(); - for (Type type : types) { - result.add(erase(type, tenv)); + default: + throw new AssertionError(ty.tyKind()); } - return result.build(); } private static Type eraseIntersectionTy( IntersectionTy ty, Function<TyVarSymbol, TyVarInfo> tenv) { - return ty.bounds().isEmpty() ? ClassTy.OBJECT : erase(ty.bounds().get(0), tenv); + return erase(ty.bounds().get(0), tenv); } private static Type eraseTyVar( TyVar ty, Function<TyVarSymbol, SourceTypeBoundClass.TyVarInfo> tenv) { SourceTypeBoundClass.TyVarInfo info = tenv.apply(ty.sym()); - return erase(info.upperBound(), tenv); + return erase(info.bound(), tenv); } private static Type.ArrayTy eraseArrayTy( @@ -92,24 +75,4 @@ public class Erasure { } return ClassTy.create(classes.build()); } - - private static Type eraseWildTy(WildTy ty, Function<TyVarSymbol, TyVarInfo> tenv) { - switch (ty.boundKind()) { - case NONE: - case LOWER: - return ClassTy.OBJECT; - case UPPER: - return erase(ty.bound(), tenv); - } - throw new AssertionError(ty.boundKind()); - } - - private static Type erasureMethodTy(MethodTy ty, Function<TyVarSymbol, TyVarInfo> tenv) { - return MethodTy.create( - /* tyParams= */ ImmutableSet.of(), - erase(ty.returnType(), tenv), - ty.receiverType() != null ? erase(ty.receiverType(), tenv) : null, - erase(ty.parameters(), tenv), - erase(ty.thrown(), tenv)); - } } diff --git a/javatests/com/google/turbine/binder/BinderErrorTest.java b/javatests/com/google/turbine/binder/BinderErrorTest.java index 15b54eb..5a4d97e 100644 --- a/javatests/com/google/turbine/binder/BinderErrorTest.java +++ b/javatests/com/google/turbine/binder/BinderErrorTest.java @@ -22,19 +22,11 @@ import static org.junit.Assert.fail; import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.turbine.binder.Processing.ProcessorInfo; import com.google.turbine.diag.TurbineError; import com.google.turbine.parse.Parser; import com.google.turbine.tree.Tree.CompUnit; import java.util.Arrays; import java.util.Optional; -import java.util.Set; -import javax.annotation.processing.AbstractProcessor; -import javax.annotation.processing.RoundEnvironment; -import javax.annotation.processing.SupportedAnnotationTypes; -import javax.lang.model.SourceVersion; -import javax.lang.model.element.TypeElement; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -267,7 +259,7 @@ public class BinderErrorTest { { "<>:2: error: java.lang.Object is not an annotation", // " @Object int x;", - " ^", + " ^", }, }, { @@ -279,7 +271,7 @@ public class BinderErrorTest { { "<>:2: error: java.lang.Deprecated is not @Repeatable", // " @Deprecated @Deprecated int x;", - " ^", + " ^", }, }, { @@ -291,7 +283,7 @@ public class BinderErrorTest { { "<>:2: error: could not resolve NoSuch.NoSuch", // " @NoSuch.NoSuch int x;", - " ^", + " ^", }, }, { @@ -425,9 +417,6 @@ public class BinderErrorTest { "}", }, { - "<>:1: error: cycle in class hierarchy: Cycle", - "class Cycle extends Cycle {", - " ^", "<>:2: error: could not resolve NoSuch", // " NoSuch f;", " ^", @@ -512,7 +501,7 @@ public class BinderErrorTest { " ^", "<>:3: error: could not resolve NoSuchAnno", "@NoSuchAnno", - "^", + " ^", }, }, { @@ -579,127 +568,7 @@ public class BinderErrorTest { "@One.A(b = {@One.NoSuch})", " ^", }, - }, - { - { - "public class Test {", // - " @interface Anno {", - " Class<?> value() default Object.class;", - " }", - " @Anno(NoSuch.class) int x;", - " @Anno(NoSuch.class) int y;", - "}", - }, - { - "<>:5: error: could not resolve NoSuch", - " @Anno(NoSuch.class) int x;", - " ^", - "<>:6: error: could not resolve NoSuch", - " @Anno(NoSuch.class) int y;", - " ^", - }, - }, - { - { - "public class Test {", // - " @A @B void f() {}", - "}", - }, - { - "<>:2: error: could not resolve A", - " @A @B void f() {}", - " ^", - "<>:2: error: could not resolve B", - " @A @B void f() {}", - " ^", - }, - }, - { - { - "public class Test {", // - " @A(\"bar\") void f() {}", - "}", - }, - { - "<>:2: error: could not resolve A", // - " @A(\"bar\") void f() {}", - " ^", - }, - }, - { - { - "@NoSuch", - "@interface A {", // - "}", - }, - { - "<>:1: error: could not resolve NoSuch", // - "@NoSuch", - "^", - }, - }, - { - { - "public class Test {", // - " @String @String int x;", - "}", - }, - { - "<>:2: error: java.lang.String is not an annotation", - " @String @String int x;", - " ^", - "<>:2: error: java.lang.String is not an annotation", - " @String @String int x;", - " ^", - }, - }, - { - { - "@interface Anno {", - " int value();", - "}", - "enum E {", - " ONE", - "}", - "@Anno(value = E.ONE)", - "interface Test {}", - }, - { - "<>:7: error: could not evaluate constant expression", // - "@Anno(value = E.ONE)", - " ^", - }, - }, - { - { - "class T extends T {}", - }, - { - "<>:1: error: cycle in class hierarchy: T", "class T extends T {}", " ^", - }, - }, - { - { - "class T implements T {}", - }, - { - "<>:1: error: cycle in class hierarchy: T", - "class T implements T {}", - " ^", - }, - }, - { - { - "class T {", // - " static final String s = \"a\" + + \"b\";", - "}", - }, - { - "<>:2: error: bad operand type String", - " static final String s = \"a\" + + \"b\";", - " ^", - }, - }, + } }; return Arrays.asList((Object[][]) testCases); } @@ -727,41 +596,6 @@ public class BinderErrorTest { } } - @SupportedAnnotationTypes("*") - static class HelloWorldProcessor extends AbstractProcessor { - - @Override - public SourceVersion getSupportedSourceVersion() { - return SourceVersion.latestSupported(); - } - - @Override - public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { - return false; - } - } - - // exercise error reporting with annotation enabled, which should be identical - @Test - public void testWithProcessors() throws Exception { - try { - Binder.bind( - ImmutableList.of(parseLines(source)), - ClassPathBinder.bindClasspath(ImmutableList.of()), - ProcessorInfo.create( - ImmutableList.of(new HelloWorldProcessor()), - /* loader= */ getClass().getClassLoader(), - /* options= */ ImmutableMap.of(), - SourceVersion.latestSupported()), - TURBINE_BOOTCLASSPATH, - /* moduleVersion=*/ Optional.empty()) - .units(); - fail(Joiner.on('\n').join(source)); - } catch (TurbineError e) { - assertThat(e).hasMessageThat().isEqualTo(lines(expected)); - } - } - private static CompUnit parseLines(String... lines) { return Parser.parse(lines(lines)); } diff --git a/javatests/com/google/turbine/binder/BinderTest.java b/javatests/com/google/turbine/binder/BinderTest.java index e238ee0..4b1e890 100644 --- a/javatests/com/google/turbine/binder/BinderTest.java +++ b/javatests/com/google/turbine/binder/BinderTest.java @@ -36,6 +36,8 @@ import com.google.turbine.tree.Tree; import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.jar.JarEntry; @@ -53,21 +55,22 @@ public class BinderTest { @Test public void hello() throws Exception { - ImmutableList<Tree.CompUnit> units = - ImmutableList.of( - parseLines( - "package a;", // - "public class A {", - " public class Inner1 extends b.B {", - " }", - " public class Inner2 extends A.Inner1 {", - " }", - "}"), - parseLines( - "package b;", // - "import a.A;", - "public class B extends A {", - "}")); + List<Tree.CompUnit> units = new ArrayList<>(); + units.add( + parseLines( + "package a;", // + "public class A {", + " public class Inner1 extends b.B {", + " }", + " public class Inner2 extends A.Inner1 {", + " }", + "}")); + units.add( + parseLines( + "package b;", // + "import a.A;", + "public class B extends A {", + "}")); ImmutableMap<ClassSymbol, SourceTypeBoundClass> bound = Binder.bind( @@ -100,19 +103,20 @@ public class BinderTest { @Test public void interfaces() throws Exception { - ImmutableList<Tree.CompUnit> units = - ImmutableList.of( - parseLines( - "package com.i;", // - "public interface I {", - " public class IInner {", - " }", - "}"), - parseLines( - "package b;", // - "class B implements com.i.I {", - " class BInner extends IInner {}", - "}")); + List<Tree.CompUnit> units = new ArrayList<>(); + units.add( + parseLines( + "package com.i;", // + "public interface I {", + " public class IInner {", + " }", + "}")); + units.add( + parseLines( + "package b;", // + "class B implements com.i.I {", + " class BInner extends IInner {}", + "}")); ImmutableMap<ClassSymbol, SourceTypeBoundClass> bound = Binder.bind( @@ -139,19 +143,20 @@ public class BinderTest { @Test public void imports() throws Exception { - ImmutableList<Tree.CompUnit> units = - ImmutableList.of( - parseLines( - "package com.test;", // - "public class Test {", - " public static class Inner {}", - "}"), - parseLines( - "package other;", // - "import com.test.Test.Inner;", - "import no.such.Class;", // imports are resolved lazily on-demand - "public class Foo extends Inner {", - "}")); + List<Tree.CompUnit> units = new ArrayList<>(); + units.add( + parseLines( + "package com.test;", // + "public class Test {", + " public static class Inner {}", + "}")); + units.add( + parseLines( + "package other;", // + "import com.test.Test.Inner;", + "import no.such.Class;", // imports are resolved lazily on-demand + "public class Foo extends Inner {", + "}")); ImmutableMap<ClassSymbol, SourceTypeBoundClass> bound = Binder.bind( @@ -167,20 +172,21 @@ public class BinderTest { @Test public void cycle() throws Exception { - ImmutableList<Tree.CompUnit> units = - ImmutableList.of( - parseLines( - "package a;", // - "import b.B;", - "public class A extends B.Inner {", - " class Inner {}", - "}"), - parseLines( - "package b;", // - "import a.A;", - "public class B extends A.Inner {", - " class Inner {}", - "}")); + List<Tree.CompUnit> units = new ArrayList<>(); + units.add( + parseLines( + "package a;", // + "import b.B;", + "public class A extends B.Inner {", + " class Inner {}", + "}")); + units.add( + parseLines( + "package b;", // + "import a.A;", + "public class B extends A.Inner {", + " class Inner {}", + "}")); try { Binder.bind( @@ -196,12 +202,12 @@ public class BinderTest { @Test public void annotationDeclaration() throws Exception { - ImmutableList<Tree.CompUnit> units = - ImmutableList.of( - parseLines( - "package com.test;", // - "public @interface Annotation {", - "}")); + List<Tree.CompUnit> units = new ArrayList<>(); + units.add( + parseLines( + "package com.test;", // + "public @interface Annotation {", + "}")); ImmutableMap<ClassSymbol, SourceTypeBoundClass> bound = Binder.bind( @@ -224,13 +230,13 @@ public class BinderTest { @Test public void helloBytecode() throws Exception { - ImmutableList<Tree.CompUnit> units = - ImmutableList.of( - parseLines( - "package a;", // - "import java.util.Map.Entry;", - "public class A implements Entry {", - "}")); + List<Tree.CompUnit> units = new ArrayList<>(); + units.add( + parseLines( + "package a;", // + "import java.util.Map.Entry;", + "public class A implements Entry {", + "}")); ImmutableMap<ClassSymbol, SourceTypeBoundClass> bound = Binder.bind( @@ -262,15 +268,15 @@ public class BinderTest { jos.write(lib.get("B")); } - ImmutableList<Tree.CompUnit> units = - ImmutableList.of( - parseLines( - "import java.lang.annotation.Target;", - "import java.lang.annotation.ElementType;", - "public class C implements B {", - " @Target(ElementType.TYPE_USE)", - " @interface A {};", - "}")); + List<Tree.CompUnit> units = new ArrayList<>(); + units.add( + parseLines( + "import java.lang.annotation.Target;", + "import java.lang.annotation.ElementType;", + "public class C implements B {", + " @Target(ElementType.TYPE_USE)", + " @interface A {};", + "}")); ImmutableMap<ClassSymbol, SourceTypeBoundClass> bound = Binder.bind( @@ -288,13 +294,13 @@ public class BinderTest { // (Error reporting is deferred to javac.) @Test public void invalidConst() throws Exception { - ImmutableList<Tree.CompUnit> units = - ImmutableList.of( - parseLines( - "package a;", // - "public class A {", - " public static final boolean b = true == 42;", - "}")); + List<Tree.CompUnit> units = new ArrayList<>(); + units.add( + parseLines( + "package a;", // + "public class A {", + " public static final boolean b = true == 42;", + "}")); ImmutableMap<ClassSymbol, SourceTypeBoundClass> bound = Binder.bind( diff --git a/javatests/com/google/turbine/binder/ClassPathBinderTest.java b/javatests/com/google/turbine/binder/ClassPathBinderTest.java index c11d814..3f41706 100644 --- a/javatests/com/google/turbine/binder/ClassPathBinderTest.java +++ b/javatests/com/google/turbine/binder/ClassPathBinderTest.java @@ -44,10 +44,7 @@ import com.google.turbine.type.AnnoInfo; import com.google.turbine.type.Type.ClassTy; import java.io.IOError; import java.io.IOException; -import java.nio.file.Files; import java.nio.file.Path; -import java.util.jar.JarEntry; -import java.util.jar.JarOutputStream; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -164,18 +161,4 @@ public class ClassPathBinderTest { assertThat(e).hasMessageThat().contains("NOT_A_JAR"); } } - - @Test - public void resources() throws Exception { - Path path = temporaryFolder.newFile("tmp.jar").toPath(); - try (JarOutputStream jos = new JarOutputStream(Files.newOutputStream(path))) { - jos.putNextEntry(new JarEntry("foo/bar/hello.txt")); - jos.write("hello".getBytes(UTF_8)); - jos.putNextEntry(new JarEntry("foo/bar/Baz.class")); - jos.write("goodbye".getBytes(UTF_8)); - } - ClassPath classPath = ClassPathBinder.bindClasspath(ImmutableList.of(path)); - assertThat(new String(classPath.resource("foo/bar/hello.txt").get(), UTF_8)).isEqualTo("hello"); - assertThat(classPath.resource("foo/bar/Baz.class")).isNull(); - } } diff --git a/javatests/com/google/turbine/binder/bytecode/BytecodeBoundClassTest.java b/javatests/com/google/turbine/binder/bytecode/BytecodeBoundClassTest.java index 3e841a5..2a0de48 100644 --- a/javatests/com/google/turbine/binder/bytecode/BytecodeBoundClassTest.java +++ b/javatests/com/google/turbine/binder/bytecode/BytecodeBoundClassTest.java @@ -22,14 +22,14 @@ import static com.google.common.truth.Truth.assertThat; import static com.google.turbine.testing.TestClassPaths.TURBINE_BOOTCLASSPATH; import static java.util.Objects.requireNonNull; -import com.google.common.collect.Iterables; +import com.google.common.collect.ImmutableMap; import com.google.common.io.ByteStreams; import com.google.turbine.binder.bound.TurbineClassValue; import com.google.turbine.binder.bound.TypeBoundClass; -import com.google.turbine.binder.bound.TypeBoundClass.FieldInfo; import com.google.turbine.binder.bound.TypeBoundClass.MethodInfo; import com.google.turbine.binder.env.CompoundEnv; import com.google.turbine.binder.env.Env; +import com.google.turbine.binder.env.SimpleEnv; import com.google.turbine.binder.sym.ClassSymbol; import com.google.turbine.type.Type; import com.google.turbine.type.Type.ClassTy; @@ -37,9 +37,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.Serializable; import java.io.UncheckedIOException; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -86,10 +84,6 @@ public class BytecodeBoundClassTest { <X, Y extends X, Z extends Throwable> X foo(@Deprecated X bar, Y baz) throws IOException, Z { return null; } - - void baz() throws IOException { - throw new IOException(); - } } @Test @@ -103,12 +97,6 @@ public class BytecodeBoundClassTest { assertThat(m.parameters().get(0).annotations()).hasSize(1); assertThat(m.parameters().get(0).name()).isEqualTo("bar"); assertThat(m.exceptions()).hasSize(2); - - MethodInfo b = - getBytecodeBoundClass(HasMethod.class).methods().stream() - .filter(x -> x.name().equals("baz")) - .collect(onlyElement()); - assertThat(b.exceptions()).hasSize(1); } @interface VoidAnno { @@ -128,53 +116,6 @@ public class BytecodeBoundClassTest { .isEqualTo(Type.TyKind.ARRAY_TY); } - static class HasField { - @Deprecated List<String> foo; - } - - @Test - public void fieldTypes() { - FieldInfo f = - getBytecodeBoundClass(HasField.class).fields().stream() - .filter(x -> x.name().equals("foo")) - .collect(onlyElement()); - - assertThat(Iterables.getLast(((ClassTy) f.type()).classes()).targs()).hasSize(1); - assertThat(f.annotations()).hasSize(1); - } - - interface Y { - Object f(); - } - - interface X extends Y { - String f(); - } - - @Test - public void covariantBridges() { - assertThat(getBytecodeBoundClass(X.class, Y.class).methods()).hasSize(1); - } - - interface A<T> { - void f(T t); - } - - interface B<T extends Number> extends A<T> { - @Override - void f(T t); - } - - interface C<T extends Integer> extends B<T> { - @Override - void f(T t); - } - - @Test - public void genericBridges() { - assertThat(getBytecodeBoundClass(C.class, B.class, A.class).methods()).hasSize(1); - } - private static byte[] toByteArrayOrDie(InputStream is) { try { return ByteStreams.toByteArray(is); @@ -194,29 +135,15 @@ public class BytecodeBoundClassTest { "test.jar"); } - private BytecodeBoundClass getBytecodeBoundClass(Class<?> clazz, Class<?>... classpath) { - Map<ClassSymbol, BytecodeBoundClass> map = new HashMap<>(); - Env<ClassSymbol, BytecodeBoundClass> env = - CompoundEnv.of(TURBINE_BOOTCLASSPATH.env()) + private BytecodeBoundClass getBytecodeBoundClass(Class<?> clazz) { + Env<ClassSymbol, BytecodeBoundClass> env = TURBINE_BOOTCLASSPATH.env(); + env = + CompoundEnv.of(env) .append( - new Env<ClassSymbol, BytecodeBoundClass>() { - @Override - public BytecodeBoundClass get(ClassSymbol sym) { - return map.get(sym); - } - }); - addClass(clazz, map, env); - addClass(BytecodeBoundClassTest.class, map, env); - for (Class<?> c : classpath) { - addClass(c, map, env); - } + new SimpleEnv<>( + ImmutableMap.of( + new ClassSymbol(BytecodeBoundClass.class.getName().replace('.', '/')), + getBytecodeBoundClass(env, BytecodeBoundClassTest.class)))); return getBytecodeBoundClass(env, clazz); } - - private void addClass( - Class<?> clazz, - Map<ClassSymbol, BytecodeBoundClass> map, - Env<ClassSymbol, BytecodeBoundClass> env) { - map.put(new ClassSymbol(clazz.getName().replace('.', '/')), getBytecodeBoundClass(env, clazz)); - } } diff --git a/javatests/com/google/turbine/bytecode/ClassReaderTest.java b/javatests/com/google/turbine/bytecode/ClassReaderTest.java index fb64541..dda29ac 100644 --- a/javatests/com/google/turbine/bytecode/ClassReaderTest.java +++ b/javatests/com/google/turbine/bytecode/ClassReaderTest.java @@ -35,7 +35,6 @@ import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.ModuleVisitor; import org.objectweb.asm.Opcodes; @@ -153,8 +152,7 @@ public class ClassReaderTest { "<X:Ljava/lang/Object;>Ljava/lang/Object;", "java/lang/Object", null); - FieldVisitor fv = cw.visitField(Opcodes.ACC_PUBLIC, "x", "I", null, null); - fv.visitAnnotation("Ljava/lang/Deprecated;", true); + cw.visitField(Opcodes.ACC_PUBLIC, "x", "I", null, null); cw.visitField( Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_STATIC, "y", @@ -175,9 +173,7 @@ public class ClassReaderTest { assertThat(x.descriptor()).isEqualTo("I"); assertThat(x.signature()).isNull(); assertThat(x.value()).isNull(); - assertThat(x.annotations()).hasSize(1); - ClassFile.AnnotationInfo annotation = Iterables.getOnlyElement(x.annotations()); - assertThat(annotation.typeName()).isEqualTo("Ljava/lang/Deprecated;"); + assertThat(x.annotations()).isEmpty(); ClassFile.FieldInfo y = classFile.fields().get(1); assertThat(y.access()) @@ -186,13 +182,12 @@ public class ClassReaderTest { assertThat(y.descriptor()).isEqualTo("I"); assertThat(y.value().constantTypeKind()).isEqualTo(TurbineConstantTypeKind.INT); assertThat(((Const.IntValue) y.value()).value()).isEqualTo(42); - assertThat(y.annotations()).isEmpty(); ClassFile.FieldInfo z = classFile.fields().get(2); assertThat(z.name()).isEqualTo("z"); assertThat(z.descriptor()).isEqualTo("Ljava/util/List;"); - assertThat(z.signature()).isEqualTo("Ljava/util/List<TX;>;"); - assertThat(z.annotations()).isEmpty(); + // don't bother reading signatures for fields; we only care about constants + assertThat(z.signature()).isNull(); } @Test diff --git a/javatests/com/google/turbine/bytecode/ClassWriterTest.java b/javatests/com/google/turbine/bytecode/ClassWriterTest.java index 71cf356..e544c15 100644 --- a/javatests/com/google/turbine/bytecode/ClassWriterTest.java +++ b/javatests/com/google/turbine/bytecode/ClassWriterTest.java @@ -17,7 +17,6 @@ package com.google.turbine.bytecode; import static com.google.common.truth.Truth.assertThat; -import static com.google.common.truth.Truth.assertWithMessage; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; @@ -85,7 +84,7 @@ public class ClassWriterTest { /* classes= */ null, fileManager.getJavaFileObjects(path)); - assertWithMessage(collector.getDiagnostics().toString()).that(task.call()).isTrue(); + assertThat(task.call()).named(collector.getDiagnostics().toString()).isTrue(); byte[] original = Files.readAllBytes(out.resolve("test/Test.class")); byte[] actual = ClassWriter.writeClass(ClassReader.read(null, original)); diff --git a/javatests/com/google/turbine/bytecode/sig/SigRegressionTest.java b/javatests/com/google/turbine/bytecode/sig/SigRegressionTest.java index 042bb80..a0f0774 100644 --- a/javatests/com/google/turbine/bytecode/sig/SigRegressionTest.java +++ b/javatests/com/google/turbine/bytecode/sig/SigRegressionTest.java @@ -102,6 +102,5 @@ public class SigRegressionTest { input = "LA<[-[Z>.I;"; sig = new SigParser(input).parseClassSig(); - assertThat(SigWriter.classSig(sig)).isEqualTo(input); } } diff --git a/javatests/com/google/turbine/deps/AbstractTransitiveTest.java b/javatests/com/google/turbine/deps/AbstractTransitiveTest.java index c5b68ff..4cb8adf 100644 --- a/javatests/com/google/turbine/deps/AbstractTransitiveTest.java +++ b/javatests/com/google/turbine/deps/AbstractTransitiveTest.java @@ -36,6 +36,7 @@ import java.nio.file.Path; import java.util.Arrays; import java.util.Enumeration; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.jar.JarEntry; import java.util.jar.JarFile; @@ -142,7 +143,7 @@ public abstract class AbstractTransitiveTest { // Explicitly use turbine; javac-turbine doesn't support direct-classpath compilations. Path libc = temporaryFolder.newFolder().toPath().resolve("out.jar"); - ImmutableList<String> sources = + List<String> sources = new SourceBuilder() .addSourceLines( "c/C.java", @@ -151,17 +152,18 @@ public abstract class AbstractTransitiveTest { " @Anno(x = 2) static final Inner i; // a.A$Inner ", " static final int X = CONST; // a.A#CONST", "}") - .build() - .stream() + .build().stream() .map(Path::toString) .collect(toImmutableList()); - Main.compile( - optionsWithBootclasspath() - .setSources(sources) - .setClassPath( - ImmutableList.of(libb).stream().map(Path::toString).collect(toImmutableList())) - .setOutput(libc.toString()) - .build()); + boolean ok = + Main.compile( + optionsWithBootclasspath() + .addSources(sources) + .addClassPathEntries( + ImmutableList.of(libb).stream().map(Path::toString).collect(toImmutableList())) + .setOutput(libc.toString()) + .build()); + assertThat(ok).isTrue(); assertThat(readJar(libc).keySet()) .containsExactly( diff --git a/javatests/com/google/turbine/deps/DependenciesTest.java b/javatests/com/google/turbine/deps/DependenciesTest.java index bc663cd..b1da209 100644 --- a/javatests/com/google/turbine/deps/DependenciesTest.java +++ b/javatests/com/google/turbine/deps/DependenciesTest.java @@ -22,6 +22,7 @@ import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Streams; import com.google.turbine.binder.Binder; import com.google.turbine.binder.Binder.BindingResult; import com.google.turbine.binder.ClassPathBinder; @@ -39,6 +40,7 @@ import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -86,7 +88,7 @@ public class DependenciesTest { static class DepsBuilder { List<Path> classpath; - ImmutableList.Builder<CompUnit> units = ImmutableList.builder(); + List<CompUnit> units = new ArrayList<>(); DepsBuilder setClasspath(Path... classpath) { this.classpath = ImmutableList.copyOf(classpath); @@ -101,7 +103,7 @@ public class DependenciesTest { DepsProto.Dependencies run() throws IOException { BindingResult bound = Binder.bind( - units.build(), + units, ClassPathBinder.bindClasspath(classpath), TestClassPaths.TURBINE_BOOTCLASSPATH, /* moduleVersion=*/ Optional.empty()); @@ -114,7 +116,7 @@ public class DependenciesTest { } private Map<Path, DepsProto.Dependency.Kind> depsMap(DepsProto.Dependencies deps) { - return deps.getDependencyList().stream() + return Streams.stream(deps.getDependencyList()) .collect(Collectors.toMap(d -> Paths.get(d.getPath()), DepsProto.Dependency::getKind)); } @@ -331,96 +333,6 @@ public class DependenciesTest { } } - @Test - public void annotations_recursive() throws Exception { - Path libA = libA(); - Path libB = libB(); - - DepsProto.Dependencies deps = - new DepsBuilder() - .setClasspath(libA, libB) - .addSourceLines( - "Test.java", // - "import a.A;", - "import b.B;", - "@A(B.class)", - "class Test {", - "}") - .run(); - assertThat(depsMap(deps)) - .containsExactly( - libA, DepsProto.Dependency.Kind.EXPLICIT, libB, DepsProto.Dependency.Kind.EXPLICIT); - } - - @Test - public void annotations_field() throws Exception { - Path libA = libA(); - Path libB = libB(); - DepsProto.Dependencies deps = - new DepsBuilder() - .setClasspath(libA, libB) - .addSourceLines( - "Test.java", // - "import a.A;", - "import b.B;", - "class Test {", - " @A(B.class)", - " int x;", - "}") - .run(); - assertThat(depsMap(deps)) - .containsExactly( - libA, DepsProto.Dependency.Kind.EXPLICIT, libB, DepsProto.Dependency.Kind.EXPLICIT); - } - - @Test - public void annotations_method() throws Exception { - Path libA = libA(); - Path libB = libB(); - DepsProto.Dependencies deps = - new DepsBuilder() - .setClasspath(libA, libB) - .addSourceLines( - "Test.java", // - "import a.A;", - "import b.B;", - "class Test {", - " @A(B.class)", - " void f() {}", - "}") - .run(); - assertThat(depsMap(deps)) - .containsExactly( - libA, DepsProto.Dependency.Kind.EXPLICIT, libB, DepsProto.Dependency.Kind.EXPLICIT); - } - - private Path libB() throws Exception { - return new LibraryBuilder() - .addSourceLines( - "b/B.java", - "package b;", - "import java.lang.annotation.Retention;", - "import static java.lang.annotation.RetentionPolicy.RUNTIME;", - "@Retention(RUNTIME)", - "public @interface B {", - "}") - .compileToJar("libb.jar"); - } - - private Path libA() throws Exception { - return new LibraryBuilder() - .addSourceLines( - "a/A.java", - "package a;", - "import java.lang.annotation.Retention;", - "import static java.lang.annotation.RetentionPolicy.RUNTIME;", - "@Retention(RUNTIME)", - "public @interface A {", - " Class<?> value() default Object.class;", - "}") - .compileToJar("liba.jar"); - } - void writeDeps(Path path, ImmutableMap<String, DepsProto.Dependency.Kind> deps) throws IOException { DepsProto.Dependencies.Builder builder = diff --git a/javatests/com/google/turbine/deps/TransitiveTest.java b/javatests/com/google/turbine/deps/TransitiveTest.java index 2c9f807..f8c5b50 100644 --- a/javatests/com/google/turbine/deps/TransitiveTest.java +++ b/javatests/com/google/turbine/deps/TransitiveTest.java @@ -17,6 +17,7 @@ package com.google.turbine.deps; import static com.google.common.collect.ImmutableList.toImmutableList; +import static com.google.common.truth.Truth.assertThat; import static com.google.turbine.testing.TestClassPaths.optionsWithBootclasspath; import com.google.common.collect.ImmutableList; @@ -33,12 +34,15 @@ public class TransitiveTest extends AbstractTransitiveTest { protected Path runTurbine(ImmutableList<Path> sources, ImmutableList<Path> classpath) throws IOException { Path out = temporaryFolder.newFolder().toPath().resolve("out.jar"); - Main.compile( - optionsWithBootclasspath() - .setSources(sources.stream().map(Path::toString).collect(toImmutableList())) - .setClassPath(classpath.stream().map(Path::toString).collect(toImmutableList())) - .setOutput(out.toString()) - .build()); + boolean ok = + Main.compile( + optionsWithBootclasspath() + .addSources(sources.stream().map(Path::toString).collect(toImmutableList())) + .addClassPathEntries( + classpath.stream().map(Path::toString).collect(toImmutableList())) + .setOutput(out.toString()) + .build()); + assertThat(ok).isTrue(); return out; } } diff --git a/javatests/com/google/turbine/lower/IntegrationTestSupport.java b/javatests/com/google/turbine/lower/IntegrationTestSupport.java index a03473d..680b073 100644 --- a/javatests/com/google/turbine/lower/IntegrationTestSupport.java +++ b/javatests/com/google/turbine/lower/IntegrationTestSupport.java @@ -16,13 +16,11 @@ package com.google.turbine.lower; -import static com.google.common.collect.ImmutableList.toImmutableList; +import static com.google.common.truth.Truth.assertThat; import static com.google.turbine.testing.TestClassPaths.TURBINE_BOOTCLASSPATH; import static java.nio.charset.StandardCharsets.UTF_8; -import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toCollection; import static java.util.stream.Collectors.toList; -import static org.junit.Assert.fail; import com.google.common.base.Joiner; import com.google.common.base.Splitter; @@ -31,13 +29,12 @@ import com.google.common.io.MoreFiles; import com.google.common.jimfs.Configuration; import com.google.common.jimfs.Jimfs; import com.google.turbine.binder.Binder; -import com.google.turbine.binder.Binder.BindingResult; import com.google.turbine.binder.ClassPath; import com.google.turbine.binder.ClassPathBinder; import com.google.turbine.diag.SourceFile; import com.google.turbine.parse.Parser; import com.google.turbine.testing.AsmUtils; -import com.google.turbine.tree.Tree.CompUnit; +import com.google.turbine.tree.Tree; import com.sun.source.util.JavacTask; import com.sun.tools.javac.api.JavacTool; import com.sun.tools.javac.file.JavacFileManager; @@ -103,11 +100,8 @@ public class IntegrationTestSupport { public static Map<String, byte[]> canonicalize(Map<String, byte[]> in) { List<ClassNode> classes = toClassNodes(in); - // drop local and anonymous classes - classes = - classes.stream() - .filter(n -> !isAnonymous(n) && !isLocal(n)) - .collect(toCollection(ArrayList::new)); + // drop anonymous classes + classes = classes.stream().filter(n -> !isAnonymous(n)).collect(toCollection(ArrayList::new)); // collect all inner classes attributes Map<String, InnerClassNode> infos = new HashMap<>(); @@ -129,10 +123,6 @@ public class IntegrationTestSupport { return toByteCode(classes); } - private static boolean isLocal(ClassNode n) { - return n.outerMethod != null; - } - private static boolean isAnonymous(ClassNode n) { // JVMS 4.7.6: if C is anonymous, the value of the inner_name_index item must be zero return n.innerClasses.stream().anyMatch(i -> i.name.equals(n.name) && i.innerName == null); @@ -446,41 +436,15 @@ public class IntegrationTestSupport { ClassPath bootClassPath, Optional<String> moduleVersion) throws IOException { - BindingResult bound = turbineAnalysis(input, classpath, bootClassPath, moduleVersion); - return Lower.lowerAll(bound.units(), bound.modules(), bound.classPathEnv()).bytes(); - } - - public static BindingResult turbineAnalysis( - Map<String, String> input, - ImmutableList<Path> classpath, - ClassPath bootClassPath, - Optional<String> moduleVersion) - throws IOException { - ImmutableList<CompUnit> units = + List<Tree.CompUnit> units = input.entrySet().stream() .map(e -> new SourceFile(e.getKey(), e.getValue())) .map(Parser::parse) - .collect(toImmutableList()); - - return Binder.bind( - units, ClassPathBinder.bindClasspath(classpath), bootClassPath, moduleVersion); - } - - public static JavacTask runJavacAnalysis( - Map<String, String> sources, Collection<Path> classpath, ImmutableList<String> options) - throws Exception { - return runJavacAnalysis(sources, classpath, options, new DiagnosticCollector<>()); - } + .collect(toList()); - public static JavacTask runJavacAnalysis( - Map<String, String> sources, - Collection<Path> classpath, - ImmutableList<String> options, - DiagnosticCollector<JavaFileObject> collector) - throws Exception { - FileSystem fs = Jimfs.newFileSystem(Configuration.unix()); - Path out = fs.getPath("out"); - return setupJavac(sources, classpath, options, collector, fs, out); + Binder.BindingResult bound = + Binder.bind(units, ClassPathBinder.bindClasspath(classpath), bootClassPath, moduleVersion); + return Lower.lowerAll(bound.units(), bound.modules(), bound.classPathEnv()).bytes(); } public static Map<String, byte[]> runJavac( @@ -493,46 +457,10 @@ public class IntegrationTestSupport { Map<String, String> sources, Collection<Path> classpath, ImmutableList<String> options) throws Exception { - DiagnosticCollector<JavaFileObject> collector = new DiagnosticCollector<>(); FileSystem fs = Jimfs.newFileSystem(Configuration.unix()); - Path out = fs.getPath("out"); - JavacTask task = setupJavac(sources, classpath, options, collector, fs, out); - - if (!task.call()) { - fail(collector.getDiagnostics().stream().map(d -> d.toString()).collect(joining("\n"))); - } - - List<Path> classes = new ArrayList<>(); - Files.walkFileTree( - out, - new SimpleFileVisitor<Path>() { - @Override - public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) - throws IOException { - if (path.getFileName().toString().endsWith(".class")) { - classes.add(path); - } - return FileVisitResult.CONTINUE; - } - }); - Map<String, byte[]> result = new LinkedHashMap<>(); - for (Path path : classes) { - String r = out.relativize(path).toString(); - result.put(r.substring(0, r.length() - ".class".length()), Files.readAllBytes(path)); - } - return result; - } - - private static JavacTask setupJavac( - Map<String, String> sources, - Collection<Path> classpath, - ImmutableList<String> options, - DiagnosticCollector<JavaFileObject> collector, - FileSystem fs, - Path out) - throws IOException { Path srcs = fs.getPath("srcs"); + Path out = fs.getPath("out"); Files.createDirectories(out); @@ -547,6 +475,7 @@ public class IntegrationTestSupport { } JavacTool compiler = JavacTool.create(); + DiagnosticCollector<JavaFileObject> collector = new DiagnosticCollector<>(); JavacFileManager fileManager = new JavacFileManager(new Context(), true, UTF_8); fileManager.setLocationFromPaths(StandardLocation.CLASS_OUTPUT, ImmutableList.of(out)); fileManager.setLocationFromPaths(StandardLocation.CLASS_PATH, classpath); @@ -558,13 +487,36 @@ public class IntegrationTestSupport { StandardLocation.locationFor("MODULE_SOURCE_PATH"), ImmutableList.of(srcs)); } - return compiler.getTask( - new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.err, UTF_8)), true), - fileManager, - collector, - options, - ImmutableList.of(), - fileManager.getJavaFileObjectsFromPaths(inputs)); + JavacTask task = + compiler.getTask( + new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.err, UTF_8)), true), + fileManager, + collector, + options, + ImmutableList.of(), + fileManager.getJavaFileObjectsFromPaths(inputs)); + + assertThat(task.call()).named(collector.getDiagnostics().toString()).isTrue(); + + List<Path> classes = new ArrayList<>(); + Files.walkFileTree( + out, + new SimpleFileVisitor<Path>() { + @Override + public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) + throws IOException { + if (path.getFileName().toString().endsWith(".class")) { + classes.add(path); + } + return FileVisitResult.CONTINUE; + } + }); + Map<String, byte[]> result = new LinkedHashMap<>(); + for (Path path : classes) { + String r = out.relativize(path).toString(); + result.put(r.substring(0, r.length() - ".class".length()), Files.readAllBytes(path)); + } + return result; } /** Normalizes and stringifies a collection of class files. */ @@ -583,17 +535,17 @@ public class IntegrationTestSupport { return sb.toString(); } - public static class TestInput { + static class TestInput { - public final Map<String, String> sources; - public final Map<String, String> classes; + final Map<String, String> sources; + final Map<String, String> classes; public TestInput(Map<String, String> sources, Map<String, String> classes) { this.sources = sources; this.classes = classes; } - public static TestInput parse(String text) { + static TestInput parse(String text) { Map<String, String> sources = new LinkedHashMap<>(); Map<String, String> classes = new LinkedHashMap<>(); String className = null; diff --git a/javatests/com/google/turbine/lower/LowerIntegrationTest.java b/javatests/com/google/turbine/lower/LowerIntegrationTest.java index 85c3450..f7e9c18 100644 --- a/javatests/com/google/turbine/lower/LowerIntegrationTest.java +++ b/javatests/com/google/turbine/lower/LowerIntegrationTest.java @@ -308,9 +308,6 @@ public class LowerIntegrationTest { "shadow_inherited.test", "static_final_boxed.test", "anno_void.test", - "tyanno_varargs.test", - "tyanno_inner.test", - "local.test", }; List<Object[]> tests = ImmutableList.copyOf(testCases).stream().map(x -> new Object[] {x}).collect(toList()); diff --git a/javatests/com/google/turbine/lower/LowerSignatureTest.java b/javatests/com/google/turbine/lower/LowerSignatureTest.java index 08bc46d..5ccbf01 100644 --- a/javatests/com/google/turbine/lower/LowerSignatureTest.java +++ b/javatests/com/google/turbine/lower/LowerSignatureTest.java @@ -83,7 +83,7 @@ public class LowerSignatureTest { assertThat(SigWriter.type(new LowerSignature().signature(type))) .isEqualTo("Ltest/Outer<Ljava/lang/Object;>.Inner<Ljava/lang/Object;>;"); // Type#toString is only for debugging - assertThat(type.toString()).isEqualTo("test.Outer<java.lang.Object>.Inner<java.lang.Object>"); + assertThat(type.toString()).isEqualTo("test/Outer<java/lang/Object>.Inner<java/lang/Object>"); } @Test diff --git a/javatests/com/google/turbine/lower/LowerTest.java b/javatests/com/google/turbine/lower/LowerTest.java index 8151e81..0de55c3 100644 --- a/javatests/com/google/turbine/lower/LowerTest.java +++ b/javatests/com/google/turbine/lower/LowerTest.java @@ -33,7 +33,6 @@ import com.google.turbine.binder.env.SimpleEnv; import com.google.turbine.binder.sym.ClassSymbol; import com.google.turbine.binder.sym.FieldSymbol; import com.google.turbine.binder.sym.MethodSymbol; -import com.google.turbine.binder.sym.ParamSymbol; import com.google.turbine.binder.sym.TyVarSymbol; import com.google.turbine.bytecode.ByteReader; import com.google.turbine.bytecode.ConstantPoolReader; @@ -105,13 +104,12 @@ public class LowerTest { new ClassSymbol("test/Test$Inner"), ImmutableList.of(), ImmutableList.of()))))), - /* lowerBound= */ null, ImmutableList.of())); int access = TurbineFlag.ACC_SUPER | TurbineFlag.ACC_PUBLIC; ImmutableList<SourceTypeBoundClass.MethodInfo> methods = ImmutableList.of( new SourceTypeBoundClass.MethodInfo( - new MethodSymbol(-1, new ClassSymbol("test/Test"), "f"), + new MethodSymbol(new ClassSymbol("test/Test"), "f"), ImmutableMap.of(), PrimTy.create(TurbineConstantTypeKind.INT, ImmutableList.of()), ImmutableList.of(), @@ -122,9 +120,9 @@ public class LowerTest { ImmutableList.of(), null), new SourceTypeBoundClass.MethodInfo( - new MethodSymbol(-1, new ClassSymbol("test/Test"), "g"), + new MethodSymbol(new ClassSymbol("test/Test"), "g"), ImmutableMap.of( - new TyVarSymbol(new MethodSymbol(-1, new ClassSymbol("test/Test"), "g"), "V"), + new TyVarSymbol(new MethodSymbol(new ClassSymbol("test/Test"), "g"), "V"), new SourceTypeBoundClass.TyVarInfo( IntersectionTy.create( ImmutableList.of( @@ -134,9 +132,8 @@ public class LowerTest { new ClassSymbol("java/lang/Runnable"), ImmutableList.of(), ImmutableList.of()))))), - /* lowerBound= */ null, ImmutableList.of()), - new TyVarSymbol(new MethodSymbol(-1, new ClassSymbol("test/Test"), "g"), "E"), + new TyVarSymbol(new MethodSymbol(new ClassSymbol("test/Test"), "g"), "E"), new SourceTypeBoundClass.TyVarInfo( IntersectionTy.create( ImmutableList.of( @@ -146,20 +143,17 @@ public class LowerTest { new ClassSymbol("java/lang/Error"), ImmutableList.of(), ImmutableList.of()))))), - /* lowerBound= */ null, ImmutableList.of())), Type.VOID, ImmutableList.of( new SourceTypeBoundClass.ParamInfo( - new ParamSymbol( - new MethodSymbol(-1, new ClassSymbol("test/Test"), "g"), "foo"), PrimTy.create(TurbineConstantTypeKind.INT, ImmutableList.of()), + "foo", ImmutableList.of(), 0)), ImmutableList.of( TyVar.create( - new TyVarSymbol( - new MethodSymbol(-1, new ClassSymbol("test/Test"), "g"), "E"), + new TyVarSymbol(new MethodSymbol(new ClassSymbol("test/Test"), "g"), "E"), ImmutableList.of())), TurbineFlag.ACC_PUBLIC, null, @@ -356,7 +350,7 @@ public class LowerTest { int typeRef, TypePath typePath, String desc, boolean visible) { path[0] = typePath; return null; - } + }; }; } }, @@ -610,10 +604,9 @@ public class LowerTest { assertThat(error) .hasMessageThat() .contains( - lines( - "Test.java:3: error: could not locate class file for A", - " I i;", - " ^")); + "Test.java:3: error: could not locate class file for A\n" + + " I i;\n" + + " ^"); } } @@ -647,6 +640,6 @@ public class LowerTest { } static String lines(String... lines) { - return Joiner.on(System.lineSeparator()).join(lines); + return Joiner.on("\n").join(lines); } } diff --git a/javatests/com/google/turbine/lower/testdata/local.test b/javatests/com/google/turbine/lower/testdata/local.test deleted file mode 100644 index fd6d4c5..0000000 --- a/javatests/com/google/turbine/lower/testdata/local.test +++ /dev/null @@ -1,8 +0,0 @@ -=== T.java === -class T { - Object f() { - class Local { - } - return new Local(); - } -}
\ No newline at end of file diff --git a/javatests/com/google/turbine/lower/testdata/tyanno_inner.test b/javatests/com/google/turbine/lower/testdata/tyanno_inner.test deleted file mode 100644 index d42b3a3..0000000 --- a/javatests/com/google/turbine/lower/testdata/tyanno_inner.test +++ /dev/null @@ -1,16 +0,0 @@ -%%% A.java %%% -import static java.lang.annotation.ElementType.TYPE_PARAMETER; - -import java.lang.annotation.Target; - -@interface A { - - @Target(TYPE_PARAMETER) - @interface I { - } -} - -=== T.java === -abstract class T<@A.I X> { - -} diff --git a/javatests/com/google/turbine/lower/testdata/tyanno_varargs.test b/javatests/com/google/turbine/lower/testdata/tyanno_varargs.test deleted file mode 100644 index 1fbc1e1..0000000 --- a/javatests/com/google/turbine/lower/testdata/tyanno_varargs.test +++ /dev/null @@ -1,12 +0,0 @@ -=== T.java === -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; - -import java.lang.annotation.Target; - -abstract class T { - @Target({PARAMETER, TYPE_USE}) - @interface A {} - - void f(boolean a, @A String b, Object @A... xs) {} -} diff --git a/javatests/com/google/turbine/main/MainTest.java b/javatests/com/google/turbine/main/MainTest.java index 5d47632..65f3167 100644 --- a/javatests/com/google/turbine/main/MainTest.java +++ b/javatests/com/google/turbine/main/MainTest.java @@ -17,29 +17,17 @@ package com.google.turbine.main; import static com.google.common.base.StandardSystemProperty.JAVA_CLASS_VERSION; -import static com.google.common.collect.ImmutableMap.toImmutableMap; import static com.google.common.truth.Truth.assertThat; -import static com.google.common.truth.Truth8.assertThat; -import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat; import static com.google.turbine.testing.TestClassPaths.optionsWithBootclasspath; import static java.nio.charset.StandardCharsets.UTF_8; import static org.junit.Assert.fail; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; import com.google.common.io.ByteStreams; import com.google.common.io.MoreFiles; -import com.google.protobuf.ExtensionRegistry; import com.google.turbine.diag.TurbineError; import com.google.turbine.options.TurbineOptions; -import com.google.turbine.proto.ManifestProto; -import java.io.BufferedInputStream; -import java.io.File; import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.UncheckedIOException; -import java.io.Writer; import java.nio.file.Files; import java.nio.file.Path; import java.time.LocalDateTime; @@ -47,27 +35,16 @@ import java.time.ZoneId; import java.util.Enumeration; import java.util.LinkedHashMap; import java.util.Map; -import java.util.Set; import java.util.jar.Attributes; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.JarOutputStream; import java.util.jar.Manifest; -import java.util.stream.Stream; -import javax.annotation.processing.AbstractProcessor; -import javax.annotation.processing.ProcessingEnvironment; -import javax.annotation.processing.RoundEnvironment; -import javax.annotation.processing.SupportedAnnotationTypes; -import javax.lang.model.SourceVersion; -import javax.lang.model.element.TypeElement; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; @RunWith(JUnit4.class) public class MainTest { @@ -107,11 +84,13 @@ public class MainTest { Path output = temporaryFolder.newFile("output.jar").toPath(); - Main.compile( - optionsWithBootclasspath() - .setSources(ImmutableList.of(src.toString())) - .setOutput(output.toString()) - .build()); + boolean ok = + Main.compile( + optionsWithBootclasspath() + .addSources(ImmutableList.of(src.toString())) + .setOutput(output.toString()) + .build()); + assertThat(ok).isTrue(); Map<String, byte[]> data = readJar(output); assertThat(data.keySet()).containsExactly("test/package-info.class"); @@ -127,11 +106,13 @@ public class MainTest { Path output = temporaryFolder.newFile("output.jar").toPath(); - Main.compile( - optionsWithBootclasspath() - .setSourceJars(ImmutableList.of(srcjar.toString())) - .setOutput(output.toString()) - .build()); + boolean ok = + Main.compile( + optionsWithBootclasspath() + .setSourceJars(ImmutableList.of(srcjar.toString())) + .setOutput(output.toString()) + .build()); + assertThat(ok).isTrue(); Map<String, byte[]> data = readJar(output); assertThat(data.keySet()).containsExactly("test/package-info.class"); @@ -169,13 +150,15 @@ public class MainTest { Path output = temporaryFolder.newFile("output.jar").toPath(); - Main.compile( - TurbineOptions.builder() - .setRelease("9") - .setSources(ImmutableList.of(src.toString())) - .setSourceJars(ImmutableList.of(srcjar.toString())) - .setOutput(output.toString()) - .build()); + boolean ok = + Main.compile( + TurbineOptions.builder() + .setRelease("9") + .addSources(ImmutableList.of(src.toString())) + .setSourceJars(ImmutableList.of(srcjar.toString())) + .setOutput(output.toString()) + .build()); + assertThat(ok).isTrue(); Map<String, byte[]> data = readJar(output); assertThat(data.keySet()) @@ -188,48 +171,26 @@ public class MainTest { MoreFiles.asCharSink(src, UTF_8).write("class Foo {}"); Path output = temporaryFolder.newFile("output.jar").toPath(); - Path gensrcOutput = temporaryFolder.newFile("gensrcOutput.jar").toPath(); - Main.compile( - optionsWithBootclasspath() - .setSources(ImmutableList.of(src.toString())) - .setTargetLabel("//foo:foo") - .setInjectingRuleKind("foo_library") - .setOutput(output.toString()) - .setGensrcOutput(gensrcOutput.toString()) - .build()); + boolean ok = + Main.compile( + optionsWithBootclasspath() + .addSources(ImmutableList.of(src.toString())) + .setTargetLabel("//foo:foo") + .setInjectingRuleKind("foo_library") + .setOutput(output.toString()) + .build()); + assertThat(ok).isTrue(); try (JarFile jarFile = new JarFile(output.toFile())) { - try (Stream<JarEntry> entries = jarFile.stream()) { - assertThat(entries.map(JarEntry::getName)) - .containsAtLeast("META-INF/", "META-INF/MANIFEST.MF"); - } Manifest manifest = jarFile.getManifest(); Attributes attributes = manifest.getMainAttributes(); - ImmutableMap<String, ?> entries = - attributes.entrySet().stream() - .collect(toImmutableMap(e -> e.getKey().toString(), Map.Entry::getValue)); - assertThat(entries) - .containsExactly( - "Created-By", "bazel", - "Manifest-Version", "1.0", - "Target-Label", "//foo:foo", - "Injecting-Rule-Kind", "foo_library"); + assertThat(attributes.getValue("Target-Label")).isEqualTo("//foo:foo"); + assertThat(attributes.getValue("Injecting-Rule-Kind")).isEqualTo("foo_library"); assertThat(jarFile.getEntry(JarFile.MANIFEST_NAME).getLastModifiedTime().toInstant()) .isEqualTo( LocalDateTime.of(2010, 1, 1, 0, 0, 0).atZone(ZoneId.systemDefault()).toInstant()); } - try (JarFile jarFile = new JarFile(gensrcOutput.toFile())) { - Manifest manifest = jarFile.getManifest(); - Attributes attributes = manifest.getMainAttributes(); - ImmutableMap<String, ?> entries = - attributes.entrySet().stream() - .collect(toImmutableMap(e -> e.getKey().toString(), Map.Entry::getValue)); - assertThat(entries) - .containsExactly( - "Created-By", "bazel", - "Manifest-Version", "1.0"); - } } @Test @@ -240,11 +201,13 @@ public class MainTest { Path output = temporaryFolder.newFile("output.jar").toPath(); - Main.compile( - TurbineOptions.builder() - .setSources(ImmutableList.of(src.toString())) - .setOutput(output.toString()) - .build()); + boolean ok = + Main.compile( + TurbineOptions.builder() + .addSources(ImmutableList.of(src.toString())) + .setOutput(output.toString()) + .build()); + assertThat(ok).isTrue(); Map<String, byte[]> data = readJar(output); assertThat(data.keySet()).containsExactly("java/lang/Object.class"); @@ -260,7 +223,7 @@ public class MainTest { try { Main.compile( TurbineOptions.builder() - .setSources(ImmutableList.of(src.toString())) + .addSources(ImmutableList.of(src.toString())) .setOutput(output.toString()) .build()); fail(); @@ -275,200 +238,10 @@ public class MainTest { MoreFiles.asCharSink(src, UTF_8).write("public class Test {}"); try { - Main.compile(optionsWithBootclasspath().setSources(ImmutableList.of(src.toString())).build()); + Main.compile(optionsWithBootclasspath().addSources(ImmutableList.of(src.toString())).build()); fail(); } catch (UsageException expected) { - assertThat(expected) - .hasMessageThat() - .contains("at least one of --output, --gensrc_output, or --resource_output is required"); - } - } - - @Test - public void noSources() throws IOException { - // Compilations with no sources (or source jars) are accepted, and create empty for requested - // outputs. This is helpful for the Bazel integration, which allows java_library rules to be - // declared without sources. - File gensrc = temporaryFolder.newFile("gensrc.jar"); - Main.compile(optionsWithBootclasspath().setGensrcOutput(gensrc.toString()).build()); - try (JarFile jarFile = new JarFile(gensrc); - Stream<JarEntry> entries = jarFile.stream()) { - assertThat(entries.map(JarEntry::getName)) - .containsExactly("META-INF/", "META-INF/MANIFEST.MF"); - } - } - - @SupportedAnnotationTypes("*") - public static class SourceGeneratingProcessor extends AbstractProcessor { - - @Override - public SourceVersion getSupportedSourceVersion() { - return SourceVersion.latestSupported(); - } - - private boolean first = true; - - @Override - public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { - if (first) { - try (Writer writer = processingEnv.getFiler().createSourceFile("g.Gen").openWriter()) { - writer.write("package g; class Gen {}"); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - first = false; - } - return false; - } - } - - @Test - public void testManifestProto() throws IOException { - Path src = temporaryFolder.newFile("Foo.java").toPath(); - MoreFiles.asCharSink(src, UTF_8).write("package f; @Deprecated class Foo {}"); - - Path output = temporaryFolder.newFile("output.jar").toPath(); - Path gensrcOutput = temporaryFolder.newFile("gensrcOutput.jar").toPath(); - Path manifestProtoOutput = temporaryFolder.newFile("manifest.proto").toPath(); - - Main.compile( - optionsWithBootclasspath() - .setSources(ImmutableList.of(src.toString())) - .setTargetLabel("//foo:foo") - .setInjectingRuleKind("foo_library") - .setOutput(output.toString()) - .setGensrcOutput(gensrcOutput.toString()) - .setOutputManifest(manifestProtoOutput.toString()) - .setProcessors(ImmutableList.of(SourceGeneratingProcessor.class.getName())) - .build()); - - assertThat(readManifestProto(manifestProtoOutput)) - .isEqualTo( - ManifestProto.Manifest.newBuilder() - .addCompilationUnit( - ManifestProto.CompilationUnit.newBuilder() - .setPkg("f") - .addTopLevel("Foo") - .setPath(src.toString()) - .setGeneratedByAnnotationProcessor(false) - .build()) - .addCompilationUnit( - ManifestProto.CompilationUnit.newBuilder() - .setPkg("g") - .addTopLevel("Gen") - .setPath("g/Gen.java") - .setGeneratedByAnnotationProcessor(true) - .build()) - .build()); - } - - private static ManifestProto.Manifest readManifestProto(Path manifestProtoOutput) - throws IOException { - ManifestProto.Manifest.Builder manifest = ManifestProto.Manifest.newBuilder(); - try (InputStream is = new BufferedInputStream(Files.newInputStream(manifestProtoOutput))) { - manifest.mergeFrom(is, ExtensionRegistry.getEmptyRegistry()); - } - return manifest.build(); - } - - @SupportedAnnotationTypes("*") - public static class CrashyProcessor extends AbstractProcessor { - - @Override - public SourceVersion getSupportedSourceVersion() { - return SourceVersion.latestSupported(); - } - - @Override - public synchronized void init(ProcessingEnvironment processingEnv) { - throw new AssertionError(); - } - - @Override - public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { - return false; - } - } - - @Test - public void noSourcesProcessing() throws IOException { - // Compilations with no sources shouldn't initialize annotation processors. - File gensrc = temporaryFolder.newFile("gensrc.jar"); - Main.compile( - optionsWithBootclasspath() - .setProcessors(ImmutableList.of(CrashyProcessor.class.getName())) - .setGensrcOutput(gensrc.toString()) - .build()); - try (JarFile jarFile = new JarFile(gensrc); - Stream<JarEntry> entries = jarFile.stream()) { - assertThat(entries.map(JarEntry::getName)) - .containsExactly("META-INF/", "META-INF/MANIFEST.MF"); - } - } - - @SupportedAnnotationTypes("*") - public static class ClassGeneratingProcessor extends AbstractProcessor { - - @Override - public SourceVersion getSupportedSourceVersion() { - return SourceVersion.latestSupported(); - } - - private boolean first = true; - - @Override - public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { - if (first) { - try (OutputStream outputStream = - processingEnv.getFiler().createClassFile("g.Gen").openOutputStream()) { - outputStream.write(dump()); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - first = false; - } - return false; - } - - public static byte[] dump() { - ClassWriter classWriter = new ClassWriter(0); - classWriter.visit( - Opcodes.V1_8, - Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER, - "g/Gen", - null, - "java/lang/Object", - null); - { - MethodVisitor methodVisitor = - classWriter.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null); - methodVisitor.visitCode(); - methodVisitor.visitVarInsn(Opcodes.ALOAD, 0); - methodVisitor.visitMethodInsn( - Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false); - methodVisitor.visitInsn(Opcodes.RETURN); - methodVisitor.visitMaxs(1, 1); - methodVisitor.visitEnd(); - } - classWriter.visitEnd(); - return classWriter.toByteArray(); - } - } - - @Test - public void classGeneration() throws IOException { - Path src = temporaryFolder.newFile("package-info.jar").toPath(); - MoreFiles.asCharSink(src, UTF_8).write("@Deprecated package test;"); - File resources = temporaryFolder.newFile("resources.jar"); - Main.compile( - optionsWithBootclasspath() - .setProcessors(ImmutableList.of(ClassGeneratingProcessor.class.getName())) - .setSources(ImmutableList.of(src.toString())) - .setResourceOutput(resources.toString()) - .build()); - try (JarFile jarFile = new JarFile(resources); - Stream<JarEntry> entries = jarFile.stream()) { - assertThat(entries.map(JarEntry::getName)).containsExactly("g/Gen.class"); + assertThat(expected).hasMessageThat().contains("--output is required"); } } } diff --git a/javatests/com/google/turbine/main/ReducedClasspathTest.java b/javatests/com/google/turbine/main/ReducedClasspathTest.java deleted file mode 100644 index d74c640..0000000 --- a/javatests/com/google/turbine/main/ReducedClasspathTest.java +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.main; - -import static com.google.common.truth.Truth.assertThat; -import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat; -import static com.google.turbine.testing.TestClassPaths.optionsWithBootclasspath; -import static java.nio.charset.StandardCharsets.UTF_8; -import static org.junit.Assert.fail; - -import com.google.common.base.Joiner; -import com.google.common.collect.ImmutableList; -import com.google.protobuf.ExtensionRegistry; -import com.google.turbine.diag.TurbineError; -import com.google.turbine.lower.IntegrationTestSupport; -import com.google.turbine.lower.IntegrationTestSupport.TestInput; -import com.google.turbine.main.Main.Result; -import com.google.turbine.options.TurbineOptions.ReducedClasspathMode; -import com.google.turbine.proto.DepsProto; -import com.google.turbine.proto.DepsProto.Dependency.Kind; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Map; -import java.util.jar.JarEntry; -import java.util.jar.JarOutputStream; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class ReducedClasspathTest { - - @Rule public final TemporaryFolder temporaryFolder = new TemporaryFolder(); - - private Path liba; - private Path libb; - private Path libc; - private Path libcJdeps; - - @Before - public void setup() throws Exception { - Map<String, byte[]> compiled = - IntegrationTestSupport.runJavac( - TestInput.parse( - String.join( - "\n", - ImmutableList.of( - "=== a/A.java ===", - "package a;", - "public class A {", - " public static class I {}", - "}", - "=== b/B.java ===", - "package b;", - "import a.A;", - "public class B extends A {}", - "=== c/C.java ===", - "package c;", - "import b.B;", - "public class C extends B {}"))) - .sources, - /* classpath= */ ImmutableList.of()); - - liba = createLibrary(compiled, "liba.jar", "a/A", "a/A$I"); - libb = createLibrary(compiled, "libb.jar", "b/B"); - libc = createLibrary(compiled, "libc.jar", "c/C"); - - libcJdeps = temporaryFolder.newFile("libc.jdeps").toPath(); - try (OutputStream os = new BufferedOutputStream(Files.newOutputStream(libcJdeps))) { - DepsProto.Dependencies.newBuilder() - .addDependency( - DepsProto.Dependency.newBuilder() - .setKind(Kind.EXPLICIT) - .setPath(libb.toString()) - .build()) - .build() - .writeTo(os); - } - } - - private Path createLibrary(Map<String, byte[]> compiled, String jarPath, String... classNames) - throws IOException { - Path lib = temporaryFolder.newFile(jarPath).toPath(); - try (JarOutputStream jos = new JarOutputStream(Files.newOutputStream(lib))) { - for (String className : classNames) { - jos.putNextEntry(new JarEntry(className + ".class")); - jos.write(compiled.get(className)); - } - } - return lib; - } - - @Test - public void succeedsWithoutFallingBack() throws Exception { - Path src = temporaryFolder.newFile("Test.java").toPath(); - Files.write( - src, - ImmutableList.of( - "import c.C;", // - "class Test extends C {", - "}"), - UTF_8); - - Path output = temporaryFolder.newFile("output.jar").toPath(); - - Result result = - Main.compile( - optionsWithBootclasspath() - .setOutput(output.toString()) - .setSources(ImmutableList.of(src.toString())) - .setReducedClasspathMode(ReducedClasspathMode.JAVABUILDER_REDUCED) - .setClassPath( - ImmutableList.of( - // ensure that the compilation succeeds without falling back by adding - // a jar to the transitive classpath that doesn't exist, which would cause - // the compilation to fail if it fell back - temporaryFolder.newFile("no.such.jar").toString(), - liba.toString(), - libb.toString(), - libc.toString())) - .setDirectJars(ImmutableList.of(libc.toString())) - .setDepsArtifacts(ImmutableList.of(libcJdeps.toString())) - .build()); - assertThat(result.transitiveClasspathFallback()).isFalse(); - } - - @Test - public void succeedsAfterFallingBack() throws Exception { - Path src = temporaryFolder.newFile("Test.java").toPath(); - Files.write( - src, - ImmutableList.of( - "import c.C;", // - "class Test extends C {", - " I i;", - "}"), - UTF_8); - - Path output = temporaryFolder.newFile("output.jar").toPath(); - - Result result = - Main.compile( - optionsWithBootclasspath() - .setOutput(output.toString()) - .setSources(ImmutableList.of(src.toString())) - .setReducedClasspathMode(ReducedClasspathMode.JAVABUILDER_REDUCED) - .setClassPath(ImmutableList.of(liba.toString(), libb.toString(), libc.toString())) - .setDirectJars(ImmutableList.of(libc.toString())) - .setDepsArtifacts(ImmutableList.of(libcJdeps.toString())) - .build()); - assertThat(result.transitiveClasspathFallback()).isTrue(); - assertThat(result.reducedClasspathLength()).isEqualTo(2); - assertThat(result.transitiveClasspathLength()).isEqualTo(3); - } - - @Test - public void bazelFallback() throws Exception { - Path src = temporaryFolder.newFile("Test.java").toPath(); - Files.write( - src, - ImmutableList.of( - "import c.C;", // - "class Test extends C {", - " I i;", - "}"), - UTF_8); - - Path output = temporaryFolder.newFile("output.jar").toPath(); - Path jdeps = temporaryFolder.newFile("output.jdeps").toPath(); - - Result result = - Main.compile( - optionsWithBootclasspath() - .setOutput(output.toString()) - .setTargetLabel("//java/com/google/foo") - .setOutputDeps(jdeps.toString()) - .setSources(ImmutableList.of(src.toString())) - .setReducedClasspathMode(ReducedClasspathMode.BAZEL_REDUCED) - .setClassPath(ImmutableList.of(libc.toString())) - .setReducedClasspathLength(1) - .setFullClasspathLength(3) - .build()); - assertThat(result.transitiveClasspathFallback()).isTrue(); - assertThat(result.reducedClasspathLength()).isEqualTo(1); - assertThat(result.transitiveClasspathLength()).isEqualTo(3); - DepsProto.Dependencies.Builder deps = DepsProto.Dependencies.newBuilder(); - try (InputStream is = new BufferedInputStream(Files.newInputStream(jdeps))) { - deps.mergeFrom(is, ExtensionRegistry.getEmptyRegistry()); - } - assertThat(deps.build()) - .isEqualTo( - DepsProto.Dependencies.newBuilder() - .setRequiresReducedClasspathFallback(true) - .setRuleLabel("//java/com/google/foo") - .build()); - } - - @Test - public void noFallbackWithoutDirectJarsAndJdeps() throws Exception { - Path src = temporaryFolder.newFile("Test.java").toPath(); - Files.write( - src, - ImmutableList.of( - "import c.C;", // - "class Test extends C {", - " I i;", - "}"), - UTF_8); - - Path output = temporaryFolder.newFile("output.jar").toPath(); - - try { - Main.compile( - optionsWithBootclasspath() - .setOutput(output.toString()) - .setSources(ImmutableList.of(src.toString())) - .setReducedClasspathMode(ReducedClasspathMode.JAVABUILDER_REDUCED) - .setClassPath(ImmutableList.of(libc.toString())) - .setDepsArtifacts(ImmutableList.of(libcJdeps.toString())) - .build()); - fail(); - } catch (TurbineError e) { - assertThat(e).hasMessageThat().contains("could not resolve I"); - } - } - - static String lines(String... lines) { - return Joiner.on(System.lineSeparator()).join(lines); - } -} diff --git a/javatests/com/google/turbine/model/ConstTest.java b/javatests/com/google/turbine/model/ConstTest.java index 984fd5a..a64d0bf 100644 --- a/javatests/com/google/turbine/model/ConstTest.java +++ b/javatests/com/google/turbine/model/ConstTest.java @@ -16,19 +16,12 @@ package com.google.turbine.model; -import static com.google.common.truth.Truth.assertThat; - import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.testing.EqualsTester; -import com.google.turbine.binder.bound.EnumConstantValue; -import com.google.turbine.binder.bound.TurbineAnnotationValue; +import com.google.turbine.binder.bound.AnnotationValue; import com.google.turbine.binder.bound.TurbineClassValue; import com.google.turbine.binder.sym.ClassSymbol; -import com.google.turbine.binder.sym.FieldSymbol; -import com.google.turbine.model.Const.ArrayInitValue; -import com.google.turbine.model.Const.IntValue; -import com.google.turbine.type.AnnoInfo; import com.google.turbine.type.Type.ClassTy; import com.google.turbine.type.Type.PrimTy; import org.junit.Test; @@ -69,31 +62,15 @@ public class ConstTest { new Const.ArrayInitValue( ImmutableList.of(new Const.IntValue(3), new Const.IntValue(4)))) .addEqualityGroup( - new TurbineAnnotationValue( - new AnnoInfo( - null, - new ClassSymbol("test/Anno"), - null, - ImmutableMap.of("value", new Const.IntValue(3)))), - new TurbineAnnotationValue( - new AnnoInfo( - null, - new ClassSymbol("test/Anno"), - null, - ImmutableMap.of("value", new Const.IntValue(3))))) + new AnnotationValue( + new ClassSymbol("test/Anno"), ImmutableMap.of("value", new Const.IntValue(3))), + new AnnotationValue( + new ClassSymbol("test/Anno"), ImmutableMap.of("value", new Const.IntValue(3)))) .addEqualityGroup( - new TurbineAnnotationValue( - new AnnoInfo( - null, - new ClassSymbol("test/Anno"), - null, - ImmutableMap.of("value", new Const.IntValue(4)))), - new TurbineAnnotationValue( - new AnnoInfo( - null, - new ClassSymbol("test/Anno"), - null, - ImmutableMap.of("value", new Const.IntValue(4))))) + new AnnotationValue( + new ClassSymbol("test/Anno"), ImmutableMap.of("value", new Const.IntValue(4))), + new AnnotationValue( + new ClassSymbol("test/Anno"), ImmutableMap.of("value", new Const.IntValue(4)))) .addEqualityGroup( new TurbineClassValue(ClassTy.asNonParametricClassTy(new ClassSymbol("test/Clazz"))), new TurbineClassValue(ClassTy.asNonParametricClassTy(new ClassSymbol("test/Clazz")))) @@ -105,37 +82,4 @@ public class ConstTest { new TurbineClassValue(PrimTy.create(TurbineConstantTypeKind.INT, ImmutableList.of()))) .testEquals(); } - - @Test - public void toStringTest() { - assertThat(new Const.CharValue('\t').toString()).isEqualTo("\'\\t\'"); - assertThat(new EnumConstantValue(new FieldSymbol(new ClassSymbol("Foo"), "CONST")).toString()) - .isEqualTo("CONST"); - assertThat(makeAnno(ImmutableMap.of())).isEqualTo("@p.Anno"); - assertThat(makeAnno(ImmutableMap.of("value", new IntValue(1)))).isEqualTo("@p.Anno(1)"); - assertThat(makeAnno(ImmutableMap.of("x", new IntValue(1)))).isEqualTo("@p.Anno(x=1)"); - assertThat( - makeAnno( - ImmutableMap.of("value", new ArrayInitValue(ImmutableList.of(new IntValue(1)))))) - .isEqualTo("@p.Anno({1})"); - assertThat( - makeAnno( - ImmutableMap.of( - "value", - new ArrayInitValue(ImmutableList.of(new IntValue(1), new IntValue(2)))))) - .isEqualTo("@p.Anno({1, 2})"); - assertThat( - makeAnno(ImmutableMap.of("xs", new ArrayInitValue(ImmutableList.of(new IntValue(1)))))) - .isEqualTo("@p.Anno(xs={1})"); - assertThat(makeAnno(ImmutableMap.of("x", new IntValue(1), "y", new IntValue(2)))) - .isEqualTo("@p.Anno(x=1, y=2)"); - assertThat(new Const.StringValue("\"").toString()).isEqualTo("\"\\\"\""); - assertThat(new Const.ByteValue((byte) 42).toString()).isEqualTo("(byte)0x2a"); - assertThat(new Const.ShortValue((short) 42).toString()).isEqualTo("42"); - } - - private static String makeAnno(ImmutableMap<String, Const> value) { - return new TurbineAnnotationValue(new AnnoInfo(null, new ClassSymbol("p/Anno"), null, value)) - .toString(); - } } diff --git a/javatests/com/google/turbine/options/TurbineOptionsTest.java b/javatests/com/google/turbine/options/TurbineOptionsTest.java index d4b468b..a5872d9 100644 --- a/javatests/com/google/turbine/options/TurbineOptionsTest.java +++ b/javatests/com/google/turbine/options/TurbineOptionsTest.java @@ -22,7 +22,6 @@ import static org.junit.Assert.fail; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; -import com.google.turbine.options.TurbineOptions.ReducedClasspathMode; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; @@ -96,7 +95,7 @@ public class TurbineOptionsTest { assertThat(options.outputDeps()).hasValue("out.jdeps"); assertThat(options.targetLabel()).hasValue("//java/com/google/test"); assertThat(options.injectingRuleKind()).hasValue("foo_library"); - assertThat(options.reducedClasspathMode()).isEqualTo(ReducedClasspathMode.NONE); + assertThat(options.shouldReduceClassPath()).isTrue(); } @Test @@ -262,22 +261,13 @@ public class TurbineOptionsTest { @Test public void javacopts() throws Exception { String[] lines = { - "--javacopts", - "--release", - "8", - "--", - "--sources", - "Test.java", - "--javacopts", - "--release", - "9", - "--", + "--javacopts", "--release", "9", "--", "--sources", "Test.java", }; TurbineOptions options = TurbineOptionsParser.parse(Iterables.concat(BASE_ARGS, Arrays.asList(lines))); - assertThat(options.javacOpts()).containsExactly("--release", "8", "--release", "9").inOrder(); + assertThat(options.javacOpts()).containsExactly("--release", "9").inOrder(); assertThat(options.sources()).containsExactly("Test.java"); } @@ -325,14 +315,20 @@ public class TurbineOptionsTest { } @Test - public void miscOutputs() throws Exception { - TurbineOptions options = - TurbineOptionsParser.parse( - Iterables.concat( - BASE_ARGS, - ImmutableList.of("--gensrc_output", "gensrc.jar", "--profile", "turbine.prof"))); - assertThat(options.gensrcOutput()).hasValue("gensrc.jar"); - assertThat(options.profile()).hasValue("turbine.prof"); + public void shouldReduceClasspath() throws Exception { + { + TurbineOptions options = + TurbineOptionsParser.parse( + Iterables.concat(BASE_ARGS, ImmutableList.of("--reduce_classpath"))); + assertThat(options.shouldReduceClassPath()).isTrue(); + } + + { + TurbineOptions options = + TurbineOptionsParser.parse( + Iterables.concat(BASE_ARGS, ImmutableList.of("--noreduce_classpath"))); + assertThat(options.shouldReduceClassPath()).isFalse(); + } } @Test @@ -354,23 +350,4 @@ public class TurbineOptionsTest { } catch (IllegalArgumentException expected) { } } - - @Test - public void builtinProcessors() throws Exception { - String[] lines = {"--builtin_processors", "BuiltinProcessor"}; - TurbineOptions options = - TurbineOptionsParser.parse(Iterables.concat(BASE_ARGS, Arrays.asList(lines))); - assertThat(options.builtinProcessors()).containsExactly("BuiltinProcessor"); - } - - @Test - public void reducedClasspathMode() throws Exception { - for (ReducedClasspathMode mode : ReducedClasspathMode.values()) { - TurbineOptions options = - TurbineOptionsParser.parse( - Iterables.concat( - BASE_ARGS, ImmutableList.of("--reduce_classpath_mode", mode.name()))); - assertThat(options.reducedClasspathMode()).isEqualTo(mode); - } - } } diff --git a/javatests/com/google/turbine/parse/CommentParserTest.java b/javatests/com/google/turbine/parse/CommentParserTest.java deleted file mode 100644 index a2f84d5..0000000 --- a/javatests/com/google/turbine/parse/CommentParserTest.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2016 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.parse; - -import static com.google.common.collect.ImmutableMap.toImmutableMap; -import static com.google.common.collect.Iterables.getOnlyElement; -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.base.Joiner; -import com.google.turbine.tree.Tree; -import com.google.turbine.tree.Tree.MethDecl; -import com.google.turbine.tree.Tree.TyDecl; -import com.google.turbine.tree.Tree.VarDecl; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class CommentParserTest { - - @Test - public void comments() { - Tree.CompUnit unit = - Parser.parse( - Joiner.on('\n') - .join( - "package p;", - "/** hello world */", - "class Test {", - " /**", - " * This is", - " * class A", - " */", - " class A {", - " /** This is a method */", - " void f() {}", - " /** This is a field */", - " int g;", - " }", - " /* This is not javadoc */", - " class B {}", - " /**", - " * This is", - " * class C", - " */", - " class C {}", - "}\n")); - TyDecl decl = getOnlyElement(unit.decls()); - assertThat(decl.javadoc()).isEqualTo(" hello world "); - assertThat( - decl.members().stream() - .map(Tree.TyDecl.class::cast) - .filter(c -> c.javadoc() != null) - .collect(toImmutableMap(c -> c.name().value(), c -> c.javadoc()))) - .containsExactly( - "A", "\n * This is\n * class A\n ", - "C", "\n * This is\n * class C\n "); - TyDecl a = (TyDecl) decl.members().get(0); - MethDecl f = (MethDecl) a.members().get(0); - assertThat(f.javadoc()).isEqualTo(" This is a method "); - VarDecl g = (VarDecl) a.members().get(1); - assertThat(g.javadoc()).isEqualTo(" This is a field "); - } -} diff --git a/javatests/com/google/turbine/parse/JavacLexer.java b/javatests/com/google/turbine/parse/JavacLexer.java index d8939f1..af82dbe 100644 --- a/javatests/com/google/turbine/parse/JavacLexer.java +++ b/javatests/com/google/turbine/parse/JavacLexer.java @@ -280,7 +280,8 @@ public class JavacLexer { case CHARLITERAL: return String.format( "CHAR_LITERAL(%s)", SourceCodeEscapers.javaCharEscaper().escape(token.stringVal())); + default: + return token.kind.toString(); } - return token.kind.toString(); } } diff --git a/javatests/com/google/turbine/parse/LexerTest.java b/javatests/com/google/turbine/parse/LexerTest.java index 8530d52..4867a22 100644 --- a/javatests/com/google/turbine/parse/LexerTest.java +++ b/javatests/com/google/turbine/parse/LexerTest.java @@ -40,6 +40,12 @@ public class LexerTest { } @Test + public void unterminated() { + assertThat(lex("/* foo")).containsExactly("EOF"); + assertThat(lex("\" foo")).containsExactly("EOF"); + } + + @Test public void boolLiteral() { lexerComparisonTest("0b0101__01010"); assertThat(lex("1 + 0b1000100101")) diff --git a/javatests/com/google/turbine/parse/ParseErrorTest.java b/javatests/com/google/turbine/parse/ParseErrorTest.java index 6a9ad11..49fb273 100644 --- a/javatests/com/google/turbine/parse/ParseErrorTest.java +++ b/javatests/com/google/turbine/parse/ParseErrorTest.java @@ -228,57 +228,6 @@ public class ParseErrorTest { } } - @Test - public void abruptMultivariableDeclaration() { - String input = "class T { int x,; }"; - try { - Parser.parse(input); - fail("expected parsing to fail"); - } catch (TurbineError e) { - assertThat(e) - .hasMessageThat() - .isEqualTo( - lines( - "<>:1: error: expected token <identifier>", // - "class T { int x,; }", - " ^")); - } - } - - @Test - public void invalidAnnotation() { - String input = "@Foo(x = @E [] x) class T {}"; - try { - Parser.parse(input); - fail("expected parsing to fail"); - } catch (TurbineError e) { - assertThat(e) - .hasMessageThat() - .isEqualTo( - lines( - "<>:1: error: invalid annotation argument", // - "@Foo(x = @E [] x) class T {}", - " ^")); - } - } - - @Test - public void unclosedComment() { - String input = "/** *\u001a/ class Test {}"; - try { - Parser.parse(input); - fail("expected parsing to fail"); - } catch (TurbineError e) { - assertThat(e) - .hasMessageThat() - .isEqualTo( - lines( - "<>:1: error: unclosed comment", // - "/** *\u001a/ class Test {}", - "^")); - } - } - private static String lines(String... lines) { return Joiner.on(System.lineSeparator()).join(lines); } diff --git a/javatests/com/google/turbine/parse/UnicodeEscapePreprocessorTest.java b/javatests/com/google/turbine/parse/UnicodeEscapePreprocessorTest.java index e3f7b63..2637091 100644 --- a/javatests/com/google/turbine/parse/UnicodeEscapePreprocessorTest.java +++ b/javatests/com/google/turbine/parse/UnicodeEscapePreprocessorTest.java @@ -16,13 +16,10 @@ package com.google.turbine.parse; -import static com.google.common.collect.Iterables.getOnlyElement; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.fail; import com.google.turbine.diag.SourceFile; -import com.google.turbine.diag.TurbineError; -import com.google.turbine.diag.TurbineError.ErrorKind; import java.util.ArrayList; import java.util.List; import org.junit.Test; @@ -60,15 +57,15 @@ public class UnicodeEscapePreprocessorTest { try { readAll("\\u00"); fail(); - } catch (TurbineError e) { - assertThat(getOnlyElement(e.diagnostics()).kind()).isEqualTo(ErrorKind.UNEXPECTED_EOF); + } catch (AssertionError e) { + assertThat(e).hasMessage("unexpected end of input"); } try { readAll("\\u"); fail(); - } catch (TurbineError e) { - assertThat(getOnlyElement(e.diagnostics()).kind()).isEqualTo(ErrorKind.UNEXPECTED_EOF); + } catch (AssertionError e) { + assertThat(e).hasMessage("unexpected end of input"); } } @@ -77,16 +74,6 @@ public class UnicodeEscapePreprocessorTest { assertThat(readAll("\\u005C\\\\u005C")).containsExactly('\\', '\\', '\\'); } - @Test - public void invalidEscape() { - try { - readAll("\\uUUUU"); - fail(); - } catch (TurbineError e) { - assertThat(getOnlyElement(e.diagnostics()).kind()).isEqualTo(ErrorKind.INVALID_UNICODE); - } - } - private List<Character> readAll(String input) { UnicodeEscapePreprocessor reader = new UnicodeEscapePreprocessor(new SourceFile(null, input)); List<Character> result = new ArrayList<>(); diff --git a/javatests/com/google/turbine/processing/AbstractTurbineTypesBiPredicateTest.java b/javatests/com/google/turbine/processing/AbstractTurbineTypesBiPredicateTest.java deleted file mode 100644 index 6ea6e72..0000000 --- a/javatests/com/google/turbine/processing/AbstractTurbineTypesBiPredicateTest.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import static com.google.common.truth.Truth.assertWithMessage; - -import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.Types; - -/** - * A combo test for {@link TurbineTypes} that compares the behaviour of bipredicates like {@link - * Types#isSubtype(TypeMirror, TypeMirror)} with javac's implementation. - */ -abstract class AbstractTurbineTypesBiPredicateTest extends AbstractTurbineTypesTest { - - final String testDescription; - final TypesBiFunctionInput javacInput; - final TypesBiFunctionInput turbineInput; - - public AbstractTurbineTypesBiPredicateTest( - String testDescription, TypesBiFunctionInput javacInput, TypesBiFunctionInput turbineInput) { - this.testDescription = testDescription; - this.javacInput = javacInput; - this.turbineInput = turbineInput; - } - - protected void test(String symbol, TypeBiPredicate predicate) { - assertWithMessage("%s = %s", javacInput.format(symbol), turbineInput.format(symbol)) - .that(turbineInput.apply(predicate)) - .isEqualTo(javacInput.apply(predicate)); - } -} diff --git a/javatests/com/google/turbine/processing/AbstractTurbineTypesTest.java b/javatests/com/google/turbine/processing/AbstractTurbineTypesTest.java deleted file mode 100644 index e6a59bf..0000000 --- a/javatests/com/google/turbine/processing/AbstractTurbineTypesTest.java +++ /dev/null @@ -1,527 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import static com.google.common.collect.ImmutableList.toImmutableList; -import static com.google.common.collect.ImmutableMap.toImmutableMap; -import static com.google.common.truth.Truth.assertThat; -import static com.google.common.truth.Truth.assertWithMessage; -import static java.nio.charset.StandardCharsets.UTF_8; -import static java.util.stream.Collectors.joining; - -import com.google.common.base.Joiner; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ListMultimap; -import com.google.common.collect.Lists; -import com.google.common.collect.Multimap; -import com.google.common.collect.MultimapBuilder; -import com.google.common.collect.Streams; -import com.google.turbine.binder.Binder; -import com.google.turbine.binder.Binder.BindingResult; -import com.google.turbine.binder.ClassPathBinder; -import com.google.turbine.binder.bound.TypeBoundClass; -import com.google.turbine.binder.env.CompoundEnv; -import com.google.turbine.binder.env.Env; -import com.google.turbine.binder.env.SimpleEnv; -import com.google.turbine.binder.sym.ClassSymbol; -import com.google.turbine.parse.Parser; -import com.google.turbine.testing.TestClassPaths; -import com.google.turbine.tree.Tree.CompUnit; -import com.sun.source.util.JavacTask; -import com.sun.tools.javac.api.JavacTool; -import com.sun.tools.javac.file.JavacFileManager; -import com.sun.tools.javac.util.Context; -import java.net.URI; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Deque; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.atomic.AtomicInteger; -import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.TypeParameterElement; -import javax.lang.model.element.VariableElement; -import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.type.TypeVariable; -import javax.lang.model.type.WildcardType; -import javax.lang.model.util.ElementScanner8; -import javax.lang.model.util.SimpleTypeVisitor8; -import javax.lang.model.util.Types; -import javax.tools.JavaFileManager; -import javax.tools.JavaFileObject.Kind; -import javax.tools.SimpleJavaFileObject; - -class AbstractTurbineTypesTest { - - protected static class TypeParameters { - protected final Types javacTypes; - protected final List<List<TypeMirror>> aGroups; - protected final Types turbineTypes; - protected final List<List<TypeMirror>> bGroups; - - private TypeParameters( - Types javacTypes, - List<List<TypeMirror>> aGroups, - Types turbineTypes, - List<List<TypeMirror>> bGroups) { - this.javacTypes = javacTypes; - this.aGroups = aGroups; - this.turbineTypes = turbineTypes; - this.bGroups = bGroups; - } - } - - protected interface TypeBiPredicate { - boolean apply(Types types, TypeMirror a, TypeMirror b); - } - - static class TypesBiFunctionInput { - final Types types; - final TypeMirror lhs; - final TypeMirror rhs; - - TypesBiFunctionInput(Types types, TypeMirror lhs, TypeMirror rhs) { - this.types = types; - this.lhs = lhs; - this.rhs = rhs; - } - - boolean apply(TypeBiPredicate predicate) { - return predicate.apply(types, lhs, rhs); - } - - String format(String symbol) { - return String.format("`%s` %s `%s`", lhs, symbol, rhs); - } - } - - protected static Iterable<Object[]> binaryParameters() throws Exception { - TypeParameters typeParameters = typeParameters(); - List<Object[]> params = new ArrayList<>(); - for (int i = 0; i < typeParameters.aGroups.size(); i++) { - List<TypeMirror> ax = typeParameters.aGroups.get(i); - List<TypeMirror> bx = typeParameters.bGroups.get(i); - Streams.zip( - Lists.cartesianProduct(ax, ax).stream(), - Lists.cartesianProduct(bx, bx).stream(), - (a, b) -> - new Object[] { - a.get(0) + " " + a.get(1), - new TypesBiFunctionInput(typeParameters.javacTypes, a.get(0), a.get(1)), - new TypesBiFunctionInput(typeParameters.turbineTypes, b.get(0), b.get(1)), - }) - .forEachOrdered(params::add); - } - return params; - } - - protected static Iterable<Object[]> unaryParameters() throws Exception { - TypeParameters typeParameters = typeParameters(); - List<Object[]> params = new ArrayList<>(); - for (int i = 0; i < typeParameters.aGroups.size(); i++) { - Streams.zip( - typeParameters.aGroups.get(i).stream(), - typeParameters.bGroups.get(i).stream(), - (a, b) -> - new Object[] { - a.toString(), typeParameters.javacTypes, a, typeParameters.turbineTypes, b, - }) - .forEachOrdered(params::add); - } - return params; - } - - protected static TypeParameters typeParameters() throws Exception { - String[][] types = { - // generics - { - "Object", - "String", - "Cloneable", - "Serializable", - "List", - "Set", - "ArrayList", - "Collection", - "List<Object>", - "List<Number>", - "List<Integer>", - "ArrayList<Object>", - "ArrayList<Number>", - "ArrayList<Integer>", - }, - // wildcards - { - "Object", - "String", - "Cloneable", - "Serializable", - "List", - "List<?>", - "List<Object>", - "List<Number>", - "List<Integer>", - "List<? extends Object>", - "List<? extends Number>", - "List<? extends Integer>", - "List<? super Object>", - "List<? super Number>", - "List<? super Integer>", - }, - // arrays - { - "Object", - "String", - "Cloneable", - "Serializable", - "List", - "Object[]", - "Number[]", - "List<Integer>[]", - "List<? extends Integer>[]", - "long[]", - "int[]", - "int[][]", - "Long[]", - "Integer[]", - "Integer[][]", - }, - // primitives - { - "Object", - "String", - "Cloneable", - "Serializable", - "List", - "int", - "char", - "byte", - "short", - "boolean", - "long", - "float", - "double", - "Integer", - "Character", - "Byte", - "Short", - "Boolean", - "Long", - "Float", - "Double", - }, - }; - List<String> files = new ArrayList<>(); - AtomicInteger idx = new AtomicInteger(); - for (String[] group : types) { - StringBuilder sb = new StringBuilder(); - Joiner.on('\n') - .appendTo( - sb, - "package p;", - "import java.util.*;", - "import java.io.*;", - String.format("abstract class Test%s {", idx.getAndIncrement()), - Streams.mapWithIndex( - Arrays.stream(group), (x, i) -> String.format(" %s f%d;\n", x, i)) - .collect(joining("\n")), - " abstract <T extends Serializable & List<T>> T f();", - " abstract <V extends List<V>> V g();", - " abstract <W extends ArrayList> W h();", - " abstract <X extends Serializable> X i();", - "}"); - String content = sb.toString(); - files.add(content); - } - // type hierarchies - files.add( - Joiner.on('\n') - .join( - "import java.util.*;", - "class Hierarchy {", // - " static class A<T> {", - " class I {}", - " }", - " static class D<T> extends A<T[]> {}", - " static class E<T> extends A<T> {", - " class J extends I {}", - " }", - " static class F<T> extends A {}", - " static class G<T> extends A<List<T>> {}", - " A rawA;", - " A<Object[]> a1;", - " A<Number[]> a2;", - " A<Integer[]> a3;", - " A<? super Object> a4;", - " A<? super Number> a5;", - " A<? super Integer> a6;", - " A<? extends Object> a7;", - " A<? extends Number> a8;", - " A<? extends Integer> a9;", - " A<List<Integer>> a10;", - " D<Object> d1;", - " D<Number> d2;", - " D<Integer> d3;", - " A<Object>.I i1;", - " A<Number>.I i2;", - " A<Integer>.I i3;", - " E<Object>.J j1;", - " E<Number>.J j2;", - " E<Integer>.J j3;", - " F<Integer> f1;", - " F<Number> f2;", - " F<Object> f3;", - " G<Integer> g1;", - " G<Number> g2;", - "}")); - // methods - files.add( - Joiner.on('\n') - .join( - "import java.io.*;", - "class Methods {", - " void f() {}", - " void g() {}", - " void f(int x) {}", - " void f(int x, int y) {}", - " abstract static class I {", - " abstract int f();", - " abstract void g() throws IOException;", - " abstract <T> void h();", - " abstract <T extends String> T i(T s);", - " }", - " abstract static class J {", - " abstract long f();", - " abstract void g();", - " abstract <T> void h();", - " abstract <T extends Number> T i(T s);", - " }", - " class K {", - " void f(K this, int x) {}", - " void g(K this) {}", - " <T extends Enum<T> & Serializable> void h(T t) {}", - " }", - " class L {", - " void f(int x) {}", - " void g() {}", - " <E extends Enum<E> & Serializable> void h(E t) {}", - " }", - "}", - "class M<T extends Enum<T> & Serializable> {", - " void h(T t) {}", - "}")); - - Context context = new Context(); - JavaFileManager fileManager = new JavacFileManager(context, true, UTF_8); - idx.set(0); - ImmutableList<SimpleJavaFileObject> compilationUnits = - files.stream() - .map( - x -> - new SimpleJavaFileObject( - URI.create("file://test" + idx.getAndIncrement() + ".java"), Kind.SOURCE) { - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) { - return x; - } - }) - .collect(toImmutableList()); - JavacTask task = - JavacTool.create() - .getTask( - /* out= */ null, - fileManager, - /* diagnosticListener= */ null, - /* options= */ ImmutableList.of(), - /* classes= */ ImmutableList.of(), - compilationUnits); - - Types javacTypes = task.getTypes(); - ImmutableMap<String, Element> javacElements = - Streams.stream(task.analyze()) - .collect(toImmutableMap(e -> e.getSimpleName().toString(), x -> x)); - - ImmutableList<CompUnit> units = files.stream().map(Parser::parse).collect(toImmutableList()); - BindingResult bound = - Binder.bind( - units, - ClassPathBinder.bindClasspath(ImmutableList.of()), - TestClassPaths.TURBINE_BOOTCLASSPATH, - Optional.empty()); - Env<ClassSymbol, TypeBoundClass> env = - CompoundEnv.<ClassSymbol, TypeBoundClass>of(bound.classPathEnv()) - .append(new SimpleEnv<>(bound.units())); - ModelFactory factory = new ModelFactory(env, ClassLoader.getSystemClassLoader(), bound.tli()); - Types turbineTypes = new TurbineTypes(factory); - ImmutableMap<String, Element> turbineElements = - bound.units().keySet().stream() - .filter(x -> !x.binaryName().contains("$")) // only top level classes - .collect(toImmutableMap(x -> x.simpleName(), factory::element)); - - assertThat(javacElements.keySet()).containsExactlyElementsIn(turbineElements.keySet()); - - List<List<TypeMirror>> aGroups = new ArrayList<>(); - List<List<TypeMirror>> bGroups = new ArrayList<>(); - for (String name : javacElements.keySet()) { - - List<TypeMirror> aGroup = new ArrayList<>(); - List<TypeMirror> bGroup = new ArrayList<>(); - - ListMultimap<String, TypeMirror> javacInputs = - MultimapBuilder.linkedHashKeys().arrayListValues().build(); - javacElements - .get(name) - .getEnclosedElements() - .forEach(e -> getTypes(javacTypes, e, javacInputs)); - - ListMultimap<String, TypeMirror> turbineInputs = - MultimapBuilder.linkedHashKeys().arrayListValues().build(); - turbineElements - .get(name) - .getEnclosedElements() - .forEach(e -> getTypes(turbineTypes, e, turbineInputs)); - - assertThat(turbineInputs.keySet()).containsExactlyElementsIn(javacInputs.keySet()); - - for (String key : javacInputs.keySet()) { - List<TypeMirror> a = javacInputs.get(key); - List<TypeMirror> b = turbineInputs.get(key); - assertWithMessage(key) - .that(b.stream().map(x -> x.getKind() + " " + x).collect(toImmutableList())) - .containsExactlyElementsIn( - a.stream().map(x -> x.getKind() + " " + x).collect(toImmutableList())) - .inOrder(); - aGroup.addAll(a); - bGroup.addAll(b); - } - aGroups.add(aGroup); - bGroups.add(bGroup); - } - return new TypeParameters(javacTypes, aGroups, turbineTypes, bGroups); - } - - /** - * Discover all types contained in the given element, keyed by their immediate enclosing element. - */ - private static void getTypes( - Types typeUtils, Element element, Multimap<String, TypeMirror> types) { - element.accept( - new ElementScanner8<Void, Void>() { - - /** - * Returns an element name qualified by all enclosing elements, to allow comparison - * between javac and turbine's implementation to group related types. - */ - String key(Element e) { - Deque<String> flat = new ArrayDeque<>(); - while (e != null) { - flat.addFirst(e.getSimpleName().toString()); - if (e.getKind() == ElementKind.PACKAGE) { - break; - } - e = e.getEnclosingElement(); - } - return Joiner.on('.').join(flat); - } - - void addType(Element e, TypeMirror t) { - if (t != null) { - types.put(key(e), t); - t.accept( - new SimpleTypeVisitor8<Void, Void>() { - @Override - public Void visitDeclared(DeclaredType t, Void aVoid) { - for (TypeMirror a : t.getTypeArguments()) { - a.accept(this, null); - } - return null; - } - - @Override - public Void visitWildcard(WildcardType t, Void aVoid) { - types.put(key(e), t); - return null; - } - - @Override - public Void visitTypeVariable(TypeVariable t, Void aVoid) { - if (t.getUpperBound() != null) { - types.put(key(e), t.getUpperBound()); - } - return null; - } - }, - null); - } - } - - void addType(Element e, List<? extends TypeMirror> types) { - for (TypeMirror type : types) { - addType(e, type); - } - } - - @Override - public Void visitVariable(VariableElement e, Void unused) { - if (e.getSimpleName().toString().contains("this$")) { - // enclosing instance parameters - return null; - } - addType(e, e.asType()); - return super.visitVariable(e, null); - } - - @Override - public Void visitType(TypeElement e, Void unused) { - addType(e, e.asType()); - return super.visitType(e, null); - } - - @Override - public Void visitExecutable(ExecutableElement e, Void unused) { - scan(e.getTypeParameters(), null); - scan(e.getParameters(), null); - addType(e, e.asType()); - addType(e, e.getReturnType()); - TypeMirror receiverType = e.getReceiverType(); - if (receiverType == null) { - // work around a javac bug in JDK < 14, see: - // https://bugs.openjdk.java.net/browse/JDK-8222369 - receiverType = typeUtils.getNoType(TypeKind.NONE); - } - addType(e, receiverType); - addType(e, e.getThrownTypes()); - return null; - } - - @Override - public Void visitTypeParameter(TypeParameterElement e, Void unused) { - addType(e, e.asType()); - addType(e, e.getBounds()); - return null; - } - }, - null); - } -} diff --git a/javatests/com/google/turbine/processing/ProcessingIntegrationTest.java b/javatests/com/google/turbine/processing/ProcessingIntegrationTest.java deleted file mode 100644 index ed5af6a..0000000 --- a/javatests/com/google/turbine/processing/ProcessingIntegrationTest.java +++ /dev/null @@ -1,346 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import static com.google.common.collect.ImmutableList.toImmutableList; -import static com.google.common.collect.MoreCollectors.onlyElement; -import static com.google.common.truth.Truth.assertThat; -import static java.nio.charset.StandardCharsets.UTF_8; -import static java.util.stream.Collectors.joining; -import static org.junit.Assert.fail; - -import com.google.common.base.Joiner; -import com.google.common.base.Splitter; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.turbine.binder.Binder; -import com.google.turbine.binder.Binder.BindingResult; -import com.google.turbine.binder.ClassPathBinder; -import com.google.turbine.binder.Processing; -import com.google.turbine.binder.Processing.ProcessorInfo; -import com.google.turbine.diag.SourceFile; -import com.google.turbine.diag.TurbineError; -import com.google.turbine.lower.IntegrationTestSupport; -import com.google.turbine.parse.Parser; -import com.google.turbine.testing.TestClassPaths; -import com.google.turbine.tree.Tree; -import java.io.IOException; -import java.io.PrintWriter; -import java.io.UncheckedIOException; -import java.io.Writer; -import java.util.Optional; -import java.util.Set; -import javax.annotation.processing.AbstractProcessor; -import javax.annotation.processing.RoundEnvironment; -import javax.annotation.processing.SupportedAnnotationTypes; -import javax.lang.model.SourceVersion; -import javax.lang.model.element.TypeElement; -import javax.tools.Diagnostic; -import javax.tools.JavaFileObject; -import javax.tools.StandardLocation; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class ProcessingIntegrationTest { - - @SupportedAnnotationTypes("*") - public static class CrashingProcessor extends AbstractProcessor { - - @Override - public SourceVersion getSupportedSourceVersion() { - return SourceVersion.latestSupported(); - } - - @Override - public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { - throw new RuntimeException("crash!"); - } - } - - private static final IntegrationTestSupport.TestInput SOURCES = - IntegrationTestSupport.TestInput.parse( - Joiner.on('\n') - .join( - "=== Test.java ===", // - "@Deprecated", - "class Test extends NoSuch {", - "}")); - - @Test - public void crash() throws IOException { - ImmutableList<Tree.CompUnit> units = - SOURCES.sources.entrySet().stream() - .map(e -> new SourceFile(e.getKey(), e.getValue())) - .map(Parser::parse) - .collect(toImmutableList()); - try { - Binder.bind( - units, - ClassPathBinder.bindClasspath(ImmutableList.of()), - Processing.ProcessorInfo.create( - ImmutableList.of(new CrashingProcessor()), - getClass().getClassLoader(), - ImmutableMap.of(), - SourceVersion.latestSupported()), - TestClassPaths.TURBINE_BOOTCLASSPATH, - Optional.empty()); - fail(); - } catch (TurbineError e) { - assertThat(e.diagnostics()).hasSize(2); - assertThat(e.diagnostics().get(0).message()).contains("could not resolve NoSuch"); - assertThat(e.diagnostics().get(1).message()).contains("crash!"); - } - } - - @SupportedAnnotationTypes("*") - public static class WarningProcessor extends AbstractProcessor { - - @Override - public SourceVersion getSupportedSourceVersion() { - return SourceVersion.latestSupported(); - } - - private boolean first = true; - - @Override - public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { - if (first) { - processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, "proc warning"); - try { - JavaFileObject file = processingEnv.getFiler().createSourceFile("Gen.java"); - try (Writer writer = file.openWriter()) { - writer.write("class Gen {}"); - } - } catch (IOException e) { - throw new UncheckedIOException(e); - } - first = false; - } - if (roundEnv.processingOver()) { - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "proc error"); - } - return false; - } - } - - @Test - public void warnings() throws IOException { - ImmutableList<Tree.CompUnit> units = - IntegrationTestSupport.TestInput.parse( - Joiner.on('\n') - .join( - "=== Test.java ===", // - "@Deprecated", - "class Test {", - "}")) - .sources - .entrySet() - .stream() - .map(e -> new SourceFile(e.getKey(), e.getValue())) - .map(Parser::parse) - .collect(toImmutableList()); - try { - Binder.bind( - units, - ClassPathBinder.bindClasspath(ImmutableList.of()), - Processing.ProcessorInfo.create( - ImmutableList.of(new WarningProcessor()), - getClass().getClassLoader(), - ImmutableMap.of(), - SourceVersion.latestSupported()), - TestClassPaths.TURBINE_BOOTCLASSPATH, - Optional.empty()); - fail(); - } catch (TurbineError e) { - ImmutableList<String> diags = - e.diagnostics().stream().map(d -> d.message()).collect(toImmutableList()); - assertThat(diags).hasSize(2); - assertThat(diags.get(0)).contains("proc warning"); - assertThat(diags.get(1)).contains("proc error"); - } - } - - @SupportedAnnotationTypes("*") - public static class ResourceProcessor extends AbstractProcessor { - - @Override - public SourceVersion getSupportedSourceVersion() { - return SourceVersion.latestSupported(); - } - - private boolean first = true; - - @Override - public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { - if (first) { - try { - try (Writer writer = processingEnv.getFiler().createSourceFile("Gen").openWriter()) { - writer.write("class Gen {}"); - } - try (Writer writer = - processingEnv - .getFiler() - .createResource(StandardLocation.SOURCE_OUTPUT, "", "source.txt") - .openWriter()) { - writer.write("hello source output"); - } - try (Writer writer = - processingEnv - .getFiler() - .createResource(StandardLocation.CLASS_OUTPUT, "", "class.txt") - .openWriter()) { - writer.write("hello class output"); - } - } catch (IOException e) { - throw new UncheckedIOException(e); - } - first = false; - } - return false; - } - } - - @Test - public void resources() throws IOException { - ImmutableList<Tree.CompUnit> units = - IntegrationTestSupport.TestInput.parse( - Joiner.on('\n') - .join( - "=== Test.java ===", // - "@Deprecated", - "class Test {", - "}")) - .sources - .entrySet() - .stream() - .map(e -> new SourceFile(e.getKey(), e.getValue())) - .map(Parser::parse) - .collect(toImmutableList()); - BindingResult bound = - Binder.bind( - units, - ClassPathBinder.bindClasspath(ImmutableList.of()), - ProcessorInfo.create( - ImmutableList.of(new ResourceProcessor()), - getClass().getClassLoader(), - ImmutableMap.of(), - SourceVersion.latestSupported()), - TestClassPaths.TURBINE_BOOTCLASSPATH, - Optional.empty()); - - assertThat(bound.generatedSources().keySet()).containsExactly("Gen.java", "source.txt"); - assertThat(bound.generatedClasses().keySet()).containsExactly("class.txt"); - - assertThat(bound.generatedSources().get("source.txt").source()) - .isEqualTo("hello source output"); - assertThat(new String(bound.generatedClasses().get("class.txt"), UTF_8)) - .isEqualTo("hello class output"); - } - - @Test - public void getAllAnnotations() throws IOException { - ImmutableList<Tree.CompUnit> units = - IntegrationTestSupport.TestInput.parse( - Joiner.on('\n') - .join( - "=== A.java ===", // - "import java.lang.annotation.Inherited;", - "@Inherited", - "@interface A {}", - "=== B.java ===", // - "@interface B {}", - "=== One.java ===", // - "@A @B class One {}", - "=== Two.java ===", // - "class Two extends One {}")) - .sources - .entrySet() - .stream() - .map(e -> new SourceFile(e.getKey(), e.getValue())) - .map(Parser::parse) - .collect(toImmutableList()); - BindingResult bound = - Binder.bind( - units, - ClassPathBinder.bindClasspath(ImmutableList.of()), - ProcessorInfo.create( - ImmutableList.of(new ElementsAnnotatedWithProcessor()), - getClass().getClassLoader(), - ImmutableMap.of(), - SourceVersion.latestSupported()), - TestClassPaths.TURBINE_BOOTCLASSPATH, - Optional.empty()); - - assertThat( - Splitter.on(System.lineSeparator()) - .omitEmptyStrings() - .split( - new String( - bound.generatedClasses().entrySet().stream() - .filter(s -> s.getKey().equals("output.txt")) - .collect(onlyElement()) - .getValue(), - UTF_8))) - .containsExactly("A: One, Two", "B: One"); - } - - @SupportedAnnotationTypes("*") - private static class ElementsAnnotatedWithProcessor extends AbstractProcessor { - - @Override - public SourceVersion getSupportedSourceVersion() { - return SourceVersion.latestSupported(); - } - - private boolean first = true; - - @Override - public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { - if (first) { - try (PrintWriter writer = - new PrintWriter( - processingEnv - .getFiler() - .createResource(StandardLocation.CLASS_OUTPUT, "", "output.txt") - .openWriter(), - /* autoFlush= */ true)) { - printAnnotatedElements(roundEnv, writer, "A"); - printAnnotatedElements(roundEnv, writer, "B"); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - first = false; - } - return false; - } - - private void printAnnotatedElements( - RoundEnvironment roundEnv, PrintWriter writer, String annotation) { - writer.println( - annotation - + ": " - + roundEnv - .getElementsAnnotatedWith( - processingEnv.getElementUtils().getTypeElement(annotation)) - .stream() - .map(e -> e.getSimpleName().toString()) - .collect(joining(", "))); - } - } -} diff --git a/javatests/com/google/turbine/processing/TurbineAnnotationMirrorTest.java b/javatests/com/google/turbine/processing/TurbineAnnotationMirrorTest.java deleted file mode 100644 index a049860..0000000 --- a/javatests/com/google/turbine/processing/TurbineAnnotationMirrorTest.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import static com.google.common.collect.ImmutableList.toImmutableList; -import static com.google.common.collect.ImmutableMap.toImmutableMap; -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.base.Joiner; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ListMultimap; -import com.google.common.collect.MultimapBuilder; -import com.google.common.collect.Multimaps; -import com.google.turbine.binder.Binder; -import com.google.turbine.binder.bound.TypeBoundClass; -import com.google.turbine.binder.env.CompoundEnv; -import com.google.turbine.binder.env.Env; -import com.google.turbine.binder.env.SimpleEnv; -import com.google.turbine.binder.sym.ClassSymbol; -import com.google.turbine.lower.IntegrationTestSupport; -import com.google.turbine.lower.IntegrationTestSupport.TestInput; -import com.google.turbine.processing.TurbineElement.TurbineTypeElement; -import com.google.turbine.testing.TestClassPaths; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.stream.Stream; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.AnnotationValue; -import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.AbstractAnnotationValueVisitor8; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class TurbineAnnotationMirrorTest { - - private AnnotationMirror getAnnotation( - List<? extends AnnotationMirror> annotationMirrors, String name) { - return annotationMirrors.stream() - .filter(x -> x.getAnnotationType().asElement().getSimpleName().contentEquals(name)) - .findFirst() - .get(); - } - - private ImmutableMap<String, Object> values(AnnotationMirror a) { - return values(a.getElementValues()); - } - - /** - * Returns a map from the name of annotation elements to their values, see also {@link - * #getValue(AnnotationValue)}. - */ - private ImmutableMap<String, Object> values( - Map<? extends ExecutableElement, ? extends AnnotationValue> values) { - return values.entrySet().stream() - .collect( - toImmutableMap( - e -> e.getKey().getSimpleName().toString(), e -> getValue(e.getValue()))); - } - - /** - * Returns the given annotation value as an Object (for primitives), or a list (for arrays), or - * strings (for compound annotations, enums, and class literals). - */ - static Object getValue(AnnotationValue value) { - return value.accept( - new AbstractAnnotationValueVisitor8<Object, Void>() { - @Override - public Object visitBoolean(boolean b, Void unused) { - return b; - } - - @Override - public Object visitByte(byte b, Void unused) { - return b; - } - - @Override - public Object visitChar(char c, Void unused) { - return c; - } - - @Override - public Object visitDouble(double d, Void unused) { - return d; - } - - @Override - public Object visitFloat(float f, Void unused) { - return f; - } - - @Override - public Object visitInt(int i, Void unused) { - return i; - } - - @Override - public Object visitLong(long i, Void unused) { - return i; - } - - @Override - public Object visitShort(short s, Void unused) { - return s; - } - - @Override - public Object visitString(String s, Void unused) { - return s; - } - - @Override - public Object visitType(TypeMirror t, Void unused) { - return value.toString(); - } - - @Override - public Object visitEnumConstant(VariableElement c, Void unused) { - return value.toString(); - } - - @Override - public Object visitAnnotation(AnnotationMirror a, Void unused) { - return value.toString(); - } - - @Override - public Object visitArray(List<? extends AnnotationValue> vals, Void unused) { - return vals.stream().map(v -> v.accept(this, null)).collect(toImmutableList()); - } - }, - null); - } - - private static Stream<String> typeAnnotationNames(Element e) { - return e.asType().getAnnotationMirrors().stream() - .map(anno -> anno.getAnnotationType().asElement().getSimpleName().toString()); - } - - @Test - public void test() throws Exception { - TestInput input = - TestInput.parse( - Joiner.on('\n') - .join( - "=== Test.java ===", - "import java.lang.annotation.ElementType;", - "import java.lang.annotation.Retention;", - "import java.lang.annotation.RetentionPolicy;", - "import java.lang.annotation.Target;", - "import java.util.Map;", - "import java.util.Map.Entry;", - "@Retention(RetentionPolicy.RUNTIME)", - "@interface A {", - " int x() default 0;", - " int y() default 1;", - " int[] z() default {};", - "}", - "@interface B {", - " Class<?> c() default String.class;", - " ElementType e() default ElementType.TYPE_USE;", - " A f() default @A;", - "}", - "@Retention(RetentionPolicy.RUNTIME)", - "@Target(ElementType.TYPE_USE)", - "@interface T {}", - "@Target(ElementType.TYPE_USE)", - "@interface V {}", - "", - "@A(y = 42, z = {43})", - "@B", - "class Test {", - " class I {}", - " @T Test. @V I f;", - " Map. @T Entry g;", - " @T Entry h;", - "}", - "")); - - Binder.BindingResult bound = - IntegrationTestSupport.turbineAnalysis( - input.sources, - ImmutableList.of(), - TestClassPaths.TURBINE_BOOTCLASSPATH, - Optional.empty()); - - Env<ClassSymbol, TypeBoundClass> env = - CompoundEnv.<ClassSymbol, TypeBoundClass>of(bound.classPathEnv()) - .append(new SimpleEnv<>(bound.units())); - ModelFactory factory = new ModelFactory(env, ClassLoader.getSystemClassLoader(), bound.tli()); - TurbineTypes turbineTypes = new TurbineTypes(factory); - TurbineElements turbineElements = new TurbineElements(factory, turbineTypes); - - TurbineTypeElement te = factory.typeElement(new ClassSymbol("Test")); - - AnnotationMirror a = getAnnotation(te.getAnnotationMirrors(), "A"); - ((TypeElement) a.getAnnotationType().asElement()).getQualifiedName().contentEquals("A"); - assertThat(values(a)).containsExactly("y", 42, "z", ImmutableList.of(43)); - assertThat(values(turbineElements.getElementValuesWithDefaults(a))) - .containsExactly( - "x", 0, - "y", 42, - "z", ImmutableList.of(43)); - - AnnotationMirror b = getAnnotation(te.getAnnotationMirrors(), "B"); - assertThat(values(turbineElements.getElementValuesWithDefaults(b))) - .containsExactly( - "c", "java.lang.String.class", - "e", "java.lang.annotation.ElementType.TYPE_USE", - "f", "@A"); - - ListMultimap<String, String> fieldTypeAnnotations = - te.getEnclosedElements().stream() - .filter(e -> e.getKind().equals(ElementKind.FIELD)) - .collect( - Multimaps.flatteningToMultimap( - e -> e.getSimpleName().toString(), - e -> typeAnnotationNames(e), - MultimapBuilder.linkedHashKeys().arrayListValues()::build)); - assertThat(fieldTypeAnnotations) - .containsExactly( - "f", "V", - "g", "T", - "h", "T"); - } -} diff --git a/javatests/com/google/turbine/processing/TurbineAnnotationProxyTest.java b/javatests/com/google/turbine/processing/TurbineAnnotationProxyTest.java deleted file mode 100644 index d339700..0000000 --- a/javatests/com/google/turbine/processing/TurbineAnnotationProxyTest.java +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import static com.google.common.collect.ImmutableList.toImmutableList; -import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.fail; - -import com.google.common.base.Joiner; -import com.google.common.collect.ImmutableList; -import com.google.common.io.ByteStreams; -import com.google.common.primitives.Ints; -import com.google.common.testing.EqualsTester; -import com.google.turbine.binder.Binder; -import com.google.turbine.binder.ClassPathBinder; -import com.google.turbine.binder.bound.TypeBoundClass; -import com.google.turbine.binder.env.CompoundEnv; -import com.google.turbine.binder.env.Env; -import com.google.turbine.binder.env.SimpleEnv; -import com.google.turbine.binder.sym.ClassSymbol; -import com.google.turbine.diag.SourceFile; -import com.google.turbine.lower.IntegrationTestSupport.TestInput; -import com.google.turbine.parse.Parser; -import com.google.turbine.processing.TurbineElement.TurbineTypeElement; -import com.google.turbine.testing.TestClassPaths; -import com.google.turbine.tree.Tree.CompUnit; -import java.io.IOException; -import java.io.InputStream; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Repeatable; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Arrays; -import java.util.Optional; -import java.util.jar.JarEntry; -import java.util.jar.JarOutputStream; -import javax.lang.model.element.TypeElement; -import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.MirroredTypeException; -import javax.lang.model.type.MirroredTypesException; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class TurbineAnnotationProxyTest { - - @Rule public final TemporaryFolder temporaryFolder = new TemporaryFolder(); - - @Retention(RetentionPolicy.RUNTIME) - public @interface A { - B b() default @B(-1); - - ElementType e() default ElementType.PACKAGE; - - int[] xs() default {}; - - Class<?> c() default String.class; - - Class<?>[] cx() default {}; - } - - @Retention(RetentionPolicy.RUNTIME) - @Inherited - public @interface B { - int value(); - } - - @Retention(RetentionPolicy.RUNTIME) - public @interface C {} - - @Retention(RetentionPolicy.RUNTIME) - public @interface RS { - R[] value() default {}; - } - - @Repeatable(RS.class) - @Retention(RetentionPolicy.RUNTIME) - public @interface R { - int value() default 1; - } - - @A - static class I {} - - @Test - public void test() throws IOException { - - Path lib = temporaryFolder.newFile("lib.jar").toPath(); - try (JarOutputStream jos = new JarOutputStream(Files.newOutputStream(lib))) { - addClass(jos, TurbineAnnotationProxyTest.class); - addClass(jos, A.class); - addClass(jos, B.class); - addClass(jos, C.class); - addClass(jos, R.class); - } - - TestInput input = - TestInput.parse( - Joiner.on('\n') - .join( - "=== Super.java ===", - "import " + B.class.getCanonicalName() + ";", - "import " + C.class.getCanonicalName() + ";", - "@B(42)", - "@C", - "class Super {}", - "=== Test.java ===", - "import " + A.class.getCanonicalName() + ";", - "import " + R.class.getCanonicalName() + ";", - "@A(xs = {1,2,3}, cx = {Integer.class, Long.class})", - "@R(1)", - "@R(2)", - "@R(3)", - "class Test extends Super {}", - "")); - - ImmutableList<CompUnit> units = - input.sources.entrySet().stream() - .map(e -> new SourceFile(e.getKey(), e.getValue())) - .map(Parser::parse) - .collect(toImmutableList()); - - Binder.BindingResult bound = - Binder.bind( - units, - ClassPathBinder.bindClasspath(ImmutableList.of(lib)), - TestClassPaths.TURBINE_BOOTCLASSPATH, - Optional.empty()); - - Env<ClassSymbol, TypeBoundClass> env = - CompoundEnv.<ClassSymbol, TypeBoundClass>of(bound.classPathEnv()) - .append(new SimpleEnv<>(bound.units())); - ModelFactory factory = new ModelFactory(env, ClassLoader.getSystemClassLoader(), bound.tli()); - TurbineTypeElement te = factory.typeElement(new ClassSymbol("Test")); - - A a = te.getAnnotation(A.class); - B b = te.getAnnotation(B.class); - assertThat(te.getAnnotation(C.class)).isNull(); - - assertThat(a.b().value()).isEqualTo(-1); - assertThat(a.e()).isEqualTo(ElementType.PACKAGE); - try { - a.c(); - fail(); - } catch (MirroredTypeException e) { - assertThat(e.getTypeMirror().getKind()).isEqualTo(TypeKind.DECLARED); - assertThat(getQualifiedName(e.getTypeMirror())).contains("java.lang.String"); - } - try { - a.cx(); - fail(); - } catch (MirroredTypesException e) { - assertThat( - e.getTypeMirrors().stream().map(m -> getQualifiedName(m)).collect(toImmutableList())) - .containsExactly("java.lang.Integer", "java.lang.Long"); - } - assertThat(Ints.asList(a.xs())).containsExactly(1, 2, 3).inOrder(); - assertThat(a.annotationType()).isEqualTo(A.class); - - assertThat(b.value()).isEqualTo(42); - - RS container = te.getAnnotation(RS.class); - assertThat(container.value()).hasLength(3); - R[] rs = te.getAnnotationsByType(R.class); - assertThat(rs).hasLength(3); - assertThat(Arrays.toString(rs)) - .isEqualTo( - String.format( - "[@%s(1), @%s(2), @%s(3)]", - R.class.getCanonicalName(), - R.class.getCanonicalName(), - R.class.getCanonicalName())); - - new EqualsTester() - .addEqualityGroup(a, te.getAnnotation(A.class)) - .addEqualityGroup(b, te.getAnnotation(B.class)) - .addEqualityGroup(rs[0]) - .addEqualityGroup(rs[1]) - .addEqualityGroup(rs[2]) - .addEqualityGroup(container) - .addEqualityGroup(I.class.getAnnotation(A.class)) - .addEqualityGroup("unrelated") - .testEquals(); - } - - private static void addClass(JarOutputStream jos, Class<?> clazz) throws IOException { - String entryPath = clazz.getName().replace('.', '/') + ".class"; - jos.putNextEntry(new JarEntry(entryPath)); - try (InputStream is = clazz.getClassLoader().getResourceAsStream(entryPath)) { - ByteStreams.copy(is, jos); - } - } - - private static String getQualifiedName(TypeMirror typeMirror) { - return ((TypeElement) ((DeclaredType) typeMirror).asElement()).getQualifiedName().toString(); - } -} diff --git a/javatests/com/google/turbine/processing/TurbineElementTest.java b/javatests/com/google/turbine/processing/TurbineElementTest.java deleted file mode 100644 index 0b3448f..0000000 --- a/javatests/com/google/turbine/processing/TurbineElementTest.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import static com.google.common.collect.ImmutableList.toImmutableList; -import static com.google.common.collect.Iterables.getOnlyElement; -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.collect.MoreCollectors; -import com.google.common.testing.EqualsTester; -import com.google.turbine.binder.sym.ClassSymbol; -import com.google.turbine.binder.sym.FieldSymbol; -import com.google.turbine.binder.sym.PackageSymbol; -import com.google.turbine.testing.TestClassPaths; -import com.google.turbine.type.Type.ClassTy; -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.TypeElement; -import javax.lang.model.element.TypeParameterElement; -import javax.lang.model.element.VariableElement; -import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class TurbineElementTest { - - private final ModelFactory factory = - new ModelFactory( - TestClassPaths.TURBINE_BOOTCLASSPATH.env(), - ClassLoader.getSystemClassLoader(), - TestClassPaths.TURBINE_BOOTCLASSPATH.index()); - - @Test - public void typeElement() { - TypeElement e = factory.typeElement(new ClassSymbol("java/util/Map$Entry")); - TypeElement m = (TypeElement) e.getEnclosingElement(); - TypeMirror t = e.asType(); - - assertThat(e.getSimpleName().toString()).isEqualTo("Entry"); - assertThat(e.getQualifiedName().toString()).isEqualTo("java.util.Map.Entry"); - assertThat(e.toString()).isEqualTo("java.util.Map.Entry"); - assertThat(e.asType().toString()).isEqualTo("java.util.Map.Entry<K,V>"); - assertThat(e.getKind()).isEqualTo(ElementKind.INTERFACE); - assertThat(e.getNestingKind()).isEqualTo(NestingKind.MEMBER); - assertThat(e.getModifiers()) - .containsExactly(Modifier.PUBLIC, Modifier.ABSTRACT, Modifier.STATIC); - - assertThat(m.getSimpleName().toString()).isEqualTo("Map"); - assertThat(m.getSuperclass().getKind()).isEqualTo(TypeKind.NONE); - assertThat(m.getQualifiedName().toString()).isEqualTo("java.util.Map"); - assertThat(m.toString()).isEqualTo("java.util.Map"); - assertThat(m.asType().toString()).isEqualTo("java.util.Map<K,V>"); - assertThat(m.getNestingKind()).isEqualTo(NestingKind.TOP_LEVEL); - assertThat(m.getSuperclass().getKind()).isEqualTo(TypeKind.NONE); - assertThat(m.getEnclosingElement().getKind()).isEqualTo(ElementKind.PACKAGE); - - assertThat(t.getKind()).isEqualTo(TypeKind.DECLARED); - } - - @Test - public void superClass() { - TypeElement e = factory.typeElement(new ClassSymbol("java/util/HashMap")); - assertThat( - ((TypeElement) ((DeclaredType) e.getSuperclass()).asElement()) - .getQualifiedName() - .toString()) - .isEqualTo("java.util.AbstractMap"); - - e = factory.typeElement(new ClassSymbol("java/lang/annotation/ElementType")); - assertThat( - ((TypeElement) ((DeclaredType) e.getSuperclass()).asElement()) - .getQualifiedName() - .toString()) - .isEqualTo("java.lang.Enum"); - } - - @Test - public void interfaces() { - TypeElement e = factory.typeElement(new ClassSymbol("java/util/HashMap")); - assertThat( - e.getInterfaces().stream() - .map( - i -> - ((TypeElement) ((DeclaredType) i).asElement()) - .getQualifiedName() - .toString()) - .collect(toImmutableList())) - .contains("java.util.Map"); - } - - @Test - public void typeParameters() { - TypeElement e = factory.typeElement(new ClassSymbol("java/util/HashMap")); - assertThat(e.getTypeParameters().stream().map(Object::toString).collect(toImmutableList())) - .containsExactly("K", "V"); - for (TypeParameterElement t : e.getTypeParameters()) { - assertThat(t.getGenericElement()).isEqualTo(e); - assertThat(t.getEnclosingElement()).isEqualTo(e); - assertThat(t.getBounds()).containsExactly(factory.asTypeMirror(ClassTy.OBJECT)); - } - } - - @Test - public void enclosed() { - assertThat( - factory.typeElement(new ClassSymbol("java/lang/Integer")).getEnclosedElements().stream() - .map(e -> e.getKind() + " " + e) - .collect(toImmutableList())) - .containsAtLeast("METHOD parseInt(java.lang.String)", "FIELD MAX_VALUE"); - } - - @Test - public void equals() { - new EqualsTester() - .addEqualityGroup( - factory.typeElement(new ClassSymbol("java/util/List")), - factory.typeElement(new ClassSymbol("java/util/List"))) - .addEqualityGroup(factory.typeElement(new ClassSymbol("java/util/ArrayList"))) - .addEqualityGroup( - factory.typeElement(new ClassSymbol("java/util/Map")).getTypeParameters().get(0), - factory.typeElement(new ClassSymbol("java/util/Map")).getTypeParameters().get(0)) - .addEqualityGroup( - factory.typeElement(new ClassSymbol("java/util/ArrayList")).getTypeParameters().get(0)) - .addEqualityGroup( - factory.fieldElement( - new FieldSymbol(new ClassSymbol("java/util/ArrayList"), "elementData")), - factory.fieldElement( - new FieldSymbol(new ClassSymbol("java/util/ArrayList"), "elementData"))) - .addEqualityGroup( - factory.fieldElement( - new FieldSymbol(new ClassSymbol("java/util/ArrayList"), "serialVersionUID"))) - .addEqualityGroup( - ((ExecutableElement) - factory - .typeElement(new ClassSymbol("java/util/ArrayList")) - .getEnclosedElements() - .stream() - .filter( - e -> - e.getKind().equals(ElementKind.METHOD) - && e.getSimpleName().contentEquals("add")) - .skip(1) - .findFirst() - .get()) - .getParameters() - .get(0)) - .addEqualityGroup( - factory - .typeElement(new ClassSymbol("java/util/ArrayList")) - .getEnclosedElements() - .stream() - .filter(e -> e.getKind().equals(ElementKind.METHOD)) - .skip(1) - .findFirst() - .get()) - .addEqualityGroup( - factory - .typeElement(new ClassSymbol("java/util/ArrayList")) - .getEnclosedElements() - .stream() - .filter(e -> e.getKind().equals(ElementKind.METHOD)) - .findFirst() - .get(), - factory - .typeElement(new ClassSymbol("java/util/ArrayList")) - .getEnclosedElements() - .stream() - .filter(e -> e.getKind().equals(ElementKind.METHOD)) - .findFirst() - .get()) - .addEqualityGroup( - factory.packageElement(new PackageSymbol("java/util")), - factory.typeElement(new ClassSymbol("java/util/ArrayList")).getEnclosingElement()) - .addEqualityGroup(factory.packageElement(new PackageSymbol("java/lang"))) - .testEquals(); - } - - @Test - public void noElement() { - PackageElement p = factory.packageElement(new PackageSymbol("java/lang")); - assertThat(p.getEnclosingElement()).isNull(); - } - - @Test - public void objectSuper() { - assertThat(factory.typeElement(new ClassSymbol("java/lang/Object")).getSuperclass().getKind()) - .isEqualTo(TypeKind.NONE); - } - - @Test - public void typeKind() { - assertThat(factory.typeElement(new ClassSymbol("java/lang/annotation/Target")).getKind()) - .isEqualTo(ElementKind.ANNOTATION_TYPE); - assertThat(factory.typeElement(new ClassSymbol("java/lang/annotation/ElementType")).getKind()) - .isEqualTo(ElementKind.ENUM); - } - - @Test - public void parameter() { - ExecutableElement equals = - (ExecutableElement) - factory.typeElement(new ClassSymbol("java/lang/Object")).getEnclosedElements().stream() - .filter(e -> e.getSimpleName().contentEquals("equals")) - .collect(MoreCollectors.onlyElement()); - VariableElement parameter = getOnlyElement(equals.getParameters()); - assertThat(parameter.getKind()).isEqualTo(ElementKind.PARAMETER); - assertThat(parameter.asType().toString()).isEqualTo("java.lang.Object"); - assertThat(parameter.getModifiers()).isEmpty(); - assertThat(parameter.getEnclosedElements()).isEmpty(); - assertThat(parameter.getSimpleName().toString()).isNotEmpty(); - assertThat(parameter.getConstantValue()).isNull(); - } -} diff --git a/javatests/com/google/turbine/processing/TurbineElementsGetAllMembersTest.java b/javatests/com/google/turbine/processing/TurbineElementsGetAllMembersTest.java deleted file mode 100644 index 11dedbf..0000000 --- a/javatests/com/google/turbine/processing/TurbineElementsGetAllMembersTest.java +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import static com.google.common.collect.ImmutableList.toImmutableList; -import static com.google.common.truth.Truth.assertThat; -import static java.util.Objects.requireNonNull; - -import com.google.common.base.Joiner; -import com.google.common.collect.ImmutableList; -import com.google.turbine.binder.Binder; -import com.google.turbine.binder.ClassPathBinder; -import com.google.turbine.binder.bound.TypeBoundClass; -import com.google.turbine.binder.env.CompoundEnv; -import com.google.turbine.binder.env.Env; -import com.google.turbine.binder.env.SimpleEnv; -import com.google.turbine.binder.sym.ClassSymbol; -import com.google.turbine.diag.SourceFile; -import com.google.turbine.lower.IntegrationTestSupport; -import com.google.turbine.lower.IntegrationTestSupport.TestInput; -import com.google.turbine.parse.Parser; -import com.google.turbine.testing.TestClassPaths; -import com.google.turbine.tree.Tree.CompUnit; -import com.sun.source.util.JavacTask; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Optional; -import javax.lang.model.element.Element; -import javax.lang.model.util.Elements; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameters; - -@RunWith(Parameterized.class) -public class TurbineElementsGetAllMembersTest { - - @Parameters - public static Iterable<Object[]> parameters() { - // An array of test inputs. Each element is an array of lines of sources to compile. - String[][] inputs = { - { - "=== Test.java ===", // - "class Test {", - "}", - }, - { - "=== A.java ===", - "interface A {", - " Integer f();", - "}", - "=== B.java ===", - "interface B {", - " Integer f();", - "}", - "=== Test.java ===", // - "class Test implements A, B {", - " Integer f() {", - " return 42;", - " }", - "}", - }, - { - "=== I.java ===", - "abstract class I {", - " abstract Integer f();", - "}", - "=== J.java ===", - "interface J extends I {", - " default Integer f() {", - " return 42;", - " }", - "}", - "=== Test.java ===", // - "class Test extends I implements J {", - "}", - }, - { - "=== I.java ===", - "interface I {", - " Integer f();", - "}", - "=== J.java ===", - "interface J extends I {", - " default Integer f() {", - " return 42;", - " }", - "}", - "=== Test.java ===", // - "class Test implements J, I {", - "}", - }, - { - "=== p/A.java ===", - "package p;", - "public class A {", - " public boolean f() {", - " return true;", - " }", - "}", - "=== p/B.java ===", - "package p;", - "public interface B {", - " public boolean f();", - "}", - "=== Test.java ===", // - "import p.*;", - "class Test extends A implements B {", - "}", - }, - { - "=== p/A.java ===", - "package p;", - "public class A {", - " public boolean f() {", - " return true;", - " }", - "}", - "=== p/B.java ===", - "package p;", - "public interface B {", - " public boolean f();", - "}", - "=== Middle.java ===", // - "import p.*;", - "public abstract class Middle extends A implements B {", - "}", - "=== Test.java ===", // - "class Test extends Middle {", - "}", - }, - { - "=== A.java ===", - "interface A {", - " Integer f();", - "}", - "=== B.java ===", - "interface B {", - " Number f();", - "}", - "=== Test.java ===", // - "abstract class Test implements A, B {", - "}", - }, - { - "=== A.java ===", - "interface A {", - " Integer f();", - "}", - "=== B.java ===", - "interface B {", - " Integer f();", - "}", - "=== Test.java ===", // - "abstract class Test implements A, B {", - "}", - }, - { - "=== I.java ===", - "interface I {", - " int x;", - "}", - "=== J.java ===", - "interface J {", - " int x;", - "}", - "=== B.java ===", - "class B {", - " int x;", - "}", - "=== C.java ===", - "class C extends B {", - " static int x;", - "}", - "=== Test.java ===", - "class Test extends C implements I, J {", - " int x;", - "}", - }, - { - "=== one/A.java ===", - "public class A {", - " int a;", - "}", - "=== two/B.java ===", - "public class B extends A {", - " int b;", - " private int c;", - " protected int d;", - "}", - "=== Test.java ===", - "public class Test extends B {", - " int x;", - "}", - }, - { - "=== A.java ===", - "interface A {", - " class I {}", - "}", - "=== B.java ===", - "interface B {", - " class J {}", - "}", - "=== Test.java ===", // - "abstract class Test implements A, B {", - "}", - }, - { - "=== A.java ===", - "import java.util.List;", - "interface A<T> {", - " List<? extends T> f();", - "}", - "=== Test.java ===", - "import java.util.List;", - "class Test<T extends Number> implements A<T> {", - " public List<? extends T> f() {", - " return null;", - " }", - "}", - }, - }; - return Arrays.stream(inputs) - .map(input -> TestInput.parse(Joiner.on('\n').join(input))) - .map(x -> new Object[] {x}) - .collect(toImmutableList()); - } - - private final TestInput input; - - public TurbineElementsGetAllMembersTest(TestInput input) { - this.input = input; - } - - // Compile the test inputs with javac and turbine, and assert that getAllMembers returns the - // same elements under each implementation. - @Test - public void test() throws Exception { - JavacTask javacTask = - IntegrationTestSupport.runJavacAnalysis( - input.sources, ImmutableList.of(), ImmutableList.of()); - Elements javacElements = javacTask.getElements(); - List<? extends Element> javacMembers = - javacElements.getAllMembers(requireNonNull(javacElements.getTypeElement("Test"))); - - ImmutableList<CompUnit> units = - input.sources.entrySet().stream() - .map(e -> new SourceFile(e.getKey(), e.getValue())) - .map(Parser::parse) - .collect(toImmutableList()); - - Binder.BindingResult bound = - Binder.bind( - units, - ClassPathBinder.bindClasspath(ImmutableList.of()), - TestClassPaths.TURBINE_BOOTCLASSPATH, - Optional.empty()); - - Env<ClassSymbol, TypeBoundClass> env = - CompoundEnv.<ClassSymbol, TypeBoundClass>of(bound.classPathEnv()) - .append(new SimpleEnv<>(bound.units())); - ModelFactory factory = new ModelFactory(env, ClassLoader.getSystemClassLoader(), bound.tli()); - TurbineTypes turbineTypes = new TurbineTypes(factory); - TurbineElements turbineElements = new TurbineElements(factory, turbineTypes); - List<? extends Element> turbineMembers = - turbineElements.getAllMembers(factory.typeElement(new ClassSymbol("Test"))); - - assertThat(formatElements(turbineMembers)) - .containsExactlyElementsIn(formatElements(javacMembers)); - } - - private static ImmutableList<String> formatElements(Collection<? extends Element> elements) { - return elements.stream() - .map(e -> String.format("%s %s.%s %s", e.getKind(), e.getEnclosingElement(), e, e.asType())) - .collect(toImmutableList()); - } -} diff --git a/javatests/com/google/turbine/processing/TurbineElementsTest.java b/javatests/com/google/turbine/processing/TurbineElementsTest.java deleted file mode 100644 index 770e6f6..0000000 --- a/javatests/com/google/turbine/processing/TurbineElementsTest.java +++ /dev/null @@ -1,353 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import static com.google.common.collect.ImmutableList.toImmutableList; -import static com.google.common.collect.Iterables.getOnlyElement; -import static com.google.common.collect.MoreCollectors.onlyElement; -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.base.Joiner; -import com.google.common.collect.ImmutableList; -import com.google.common.testing.EqualsTester; -import com.google.turbine.binder.Binder.BindingResult; -import com.google.turbine.binder.bound.TypeBoundClass; -import com.google.turbine.binder.env.CompoundEnv; -import com.google.turbine.binder.env.Env; -import com.google.turbine.binder.env.SimpleEnv; -import com.google.turbine.binder.sym.ClassSymbol; -import com.google.turbine.lower.IntegrationTestSupport; -import com.google.turbine.testing.TestClassPaths; -import com.sun.source.util.JavacTask; -import java.io.StringWriter; -import java.util.Arrays; -import java.util.List; -import java.util.Optional; -import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Name; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; -import javax.lang.model.util.Elements; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class TurbineElementsTest { - - private static final IntegrationTestSupport.TestInput SOURCES = - IntegrationTestSupport.TestInput.parse( - Joiner.on('\n') - .join( - "=== Test.java ===", - "@Deprecated", - "@A class Test extends One {}", - "=== One.java ===", - "/** javadoc", - " * for", - " * one", - " */", - "@B class One extends Two {", - " /** method javadoc */", - " void f() {}", - " /** field javadoc */", - " int x;", - "}", - "=== Two.java ===", - "/** javadoc", - " for", - " two with extra *", - " */", - "@C(1) class Two extends Three {}", - "=== Three.java ===", - "@C(2) class Three extends Four {}", - "=== Four.java ===", - "@D class Four {}", - "=== Annotations.java ===", - "import java.lang.annotation.Inherited;", - "@interface A {}", - "@interface B {}", - "@Inherited", - "@interface C {", - " int value() default 42;", - "}", - "@Inherited", - "@interface D {}", - "=== com/pkg/P.java ===", - "package com.pkg;", - "@interface P {}", - "=== com/pkg/package-info.java ===", - "@P", - "package com.pkg;", - "=== Const.java ===", - "class Const {", - " static final int X = 1867;", - "}", - "=== com/pkg/empty/package-info.java ===", - "@P", - "package com.pkg.empty;", - "import com.pkg.P;", - "=== com/pkg/A.java ===", - "package com.pkg;", - "class A {", - " class I {}", - "}", - "=== com/pkg/B.java ===", - "package com.pkg;", - "class B {}")); - - Elements javacElements; - ModelFactory factory; - TurbineElements turbineElements; - - @Before - public void setup() throws Exception { - JavacTask task = - IntegrationTestSupport.runJavacAnalysis( - SOURCES.sources, ImmutableList.of(), ImmutableList.of()); - task.analyze(); - javacElements = task.getElements(); - - BindingResult bound = - IntegrationTestSupport.turbineAnalysis( - SOURCES.sources, - ImmutableList.of(), - TestClassPaths.TURBINE_BOOTCLASSPATH, - Optional.empty()); - Env<ClassSymbol, TypeBoundClass> env = - CompoundEnv.<ClassSymbol, TypeBoundClass>of(bound.classPathEnv()) - .append(new SimpleEnv<>(bound.units())); - factory = new ModelFactory(env, TurbineElementsTest.class.getClassLoader(), bound.tli()); - TurbineTypes turbineTypes = new TurbineTypes(factory); - turbineElements = new TurbineElements(factory, turbineTypes); - } - - @Test - public void constants() { - for (Object value : - Arrays.asList( - Short.valueOf((short) 1), - Short.MIN_VALUE, - Short.MAX_VALUE, - Byte.valueOf((byte) 1), - Byte.MIN_VALUE, - Byte.MAX_VALUE, - Integer.valueOf(1), - Integer.MIN_VALUE, - Integer.MAX_VALUE, - Long.valueOf(1), - Long.MIN_VALUE, - Long.MAX_VALUE, - Float.valueOf(1), - Float.NaN, - Double.NEGATIVE_INFINITY, - Double.POSITIVE_INFINITY, - Float.MAX_VALUE, - Float.MIN_VALUE, - Double.valueOf(1), - Double.NaN, - Double.NEGATIVE_INFINITY, - Double.POSITIVE_INFINITY, - Double.MAX_VALUE, - Double.MIN_VALUE, - 'a', - '\n', - "hello", - "\"hello\n\"")) { - assertThat(turbineElements.getConstantExpression(value)) - .isEqualTo(javacElements.getConstantExpression(value)); - } - } - - @Test - public void getName() { - Name n = turbineElements.getName("hello"); - assertThat(n.contentEquals("hello")).isTrue(); - assertThat(n.contentEquals("goodbye")).isFalse(); - - assertThat(n.toString()).isEqualTo("hello"); - assertThat(n.toString()) - .isEqualTo(new String(new char[] {'h', 'e', 'l', 'l', 'o'})); // defeat interning - - assertThat(n.length()).isEqualTo(5); - - new EqualsTester() - .addEqualityGroup(turbineElements.getName("hello"), turbineElements.getName("hello")) - .addEqualityGroup(turbineElements.getName("goodbye")) - .testEquals(); - } - - @Test - public void getAllAnnotationMirrors() { - assertThat( - toStrings( - turbineElements.getAllAnnotationMirrors( - factory.typeElement(new ClassSymbol("Test"))))) - .containsExactly("@java.lang.Deprecated", "@A", "@C(1)", "@D"); - } - - @Test - public void getTypeElement() { - for (String name : Arrays.asList("java.util.Map", "java.util.Map.Entry")) { - assertThat(turbineElements.getTypeElement(name).getQualifiedName().toString()) - .isEqualTo(name); - } - assertThat(turbineElements.getTypeElement("NoSuch")).isNull(); - assertThat(turbineElements.getTypeElement("java.lang.Object.NoSuch")).isNull(); - assertThat(turbineElements.getTypeElement("java.lang.NoSuch")).isNull(); - assertThat(turbineElements.getTypeElement("java.lang.Integer.MAX_VALUE")).isNull(); - } - - private static ImmutableList<String> toStrings(List<?> inputs) { - return inputs.stream().map(String::valueOf).collect(toImmutableList()); - } - - @Test - public void isDeprecated() { - assertThat(turbineElements.isDeprecated(turbineElements.getTypeElement("java.lang.Object"))) - .isFalse(); - assertThat(turbineElements.isDeprecated(turbineElements.getTypeElement("One"))).isFalse(); - assertThat(turbineElements.isDeprecated(turbineElements.getTypeElement("Test"))).isTrue(); - } - - @Test - public void getBinaryName() { - assertThat( - turbineElements - .getBinaryName(turbineElements.getTypeElement("java.util.Map.Entry")) - .toString()) - .isEqualTo("java.util.Map$Entry"); - } - - @Test - public void methodDefaultTest() { - assertThat( - ((ExecutableElement) - getOnlyElement(turbineElements.getTypeElement("C").getEnclosedElements())) - .getDefaultValue() - .getValue()) - .isEqualTo(42); - } - - @Test - public void constantFieldTest() { - assertThat( - ((VariableElement) - turbineElements.getTypeElement("Const").getEnclosedElements().stream() - .filter(x -> x.getKind().equals(ElementKind.FIELD)) - .collect(onlyElement())) - .getConstantValue()) - .isEqualTo(1867); - } - - @Test - public void packageElement() { - assertThat( - toStrings( - turbineElements.getAllAnnotationMirrors( - turbineElements.getPackageElement("com.pkg")))) - .containsExactly("@com.pkg.P"); - assertThat( - turbineElements.getAllAnnotationMirrors(turbineElements.getPackageElement("java.lang"))) - .isEmpty(); - assertThat(turbineElements.getPackageElement("com.google.no.such.pkg")).isNull(); - } - - @Test - public void packageMembers() { - assertThat( - turbineElements.getPackageElement("com.pkg").getEnclosedElements().stream() - .map(e -> ((TypeElement) e).getQualifiedName().toString()) - .collect(toImmutableList())) - .containsExactly("com.pkg.P", "com.pkg.A", "com.pkg.B"); - assertThat(turbineElements.getPackageElement("com.pkg.empty").getEnclosedElements()).isEmpty(); - } - - @Test - public void noElement() { - Element e = factory.noElement("com.google.Foo"); - assertThat(e.getKind()).isEqualTo(ElementKind.CLASS); - assertThat(e.getSimpleName().toString()).isEqualTo("Foo"); - assertThat(e.getEnclosingElement().toString()).isEqualTo("com.google"); - assertThat(e.getEnclosingElement().getKind()).isEqualTo(ElementKind.PACKAGE); - - e = factory.noElement("Foo"); - assertThat(e.getSimpleName().toString()).isEqualTo("Foo"); - assertThat(e.getEnclosingElement().toString()).isEmpty(); - assertThat(e.getEnclosingElement().getKind()).isEqualTo(ElementKind.PACKAGE); - } - - @Test - public void javadoc() { - TypeElement e = turbineElements.getTypeElement("One"); - assertThat(turbineElements.getDocComment(e)) - .isEqualTo( - " javadoc\n" // - + " for\n" - + " one\n" - + ""); - - assertThat( - turbineElements.getDocComment( - e.getEnclosedElements().stream() - .filter(x -> x.getKind().equals(ElementKind.FIELD)) - .collect(onlyElement()))) - .isEqualTo(" field javadoc "); - - assertThat( - turbineElements.getDocComment( - e.getEnclosedElements().stream() - .filter(x -> x.getKind().equals(ElementKind.METHOD)) - .collect(onlyElement()))) - .isEqualTo(" method javadoc "); - - e = turbineElements.getTypeElement("Two"); - assertThat(turbineElements.getDocComment(e)) - .isEqualTo( - " javadoc\n" // - + "for\n" - + "two with extra *\n" - + ""); - } - - @Test - public void syntheticParameters() { - assertThat( - ((ExecutableElement) - getOnlyElement( - turbineElements.getTypeElement("com.pkg.A.I").getEnclosedElements())) - .getParameters()) - .isEmpty(); - } - - @Test - public void printElements() { - StringWriter w = new StringWriter(); - turbineElements.printElements( - w, - turbineElements.getTypeElement("com.pkg.A"), - turbineElements.getTypeElement("com.pkg.A.I")); - assertThat(w.toString()).isEqualTo(lines("com.pkg.A", "com.pkg.A.I")); - } - - private String lines(String... lines) { - return Joiner.on(System.lineSeparator()).join(lines) + System.lineSeparator(); - } -} diff --git a/javatests/com/google/turbine/processing/TurbineFilerTest.java b/javatests/com/google/turbine/processing/TurbineFilerTest.java deleted file mode 100644 index 40b78ea..0000000 --- a/javatests/com/google/turbine/processing/TurbineFilerTest.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import static com.google.common.collect.Iterables.getOnlyElement; -import static com.google.common.truth.Truth.assertThat; -import static java.nio.charset.StandardCharsets.UTF_8; -import static org.junit.Assert.fail; - -import com.google.common.base.Function; -import com.google.common.base.Supplier; -import com.google.common.io.ByteStreams; -import com.google.common.io.CharStreams; -import com.google.turbine.diag.SourceFile; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.OutputStream; -import java.io.Writer; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import javax.annotation.processing.FilerException; -import javax.lang.model.element.Element; -import javax.tools.FileObject; -import javax.tools.JavaFileObject; -import javax.tools.StandardLocation; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class TurbineFilerTest { - - private final Set<String> seen = new HashSet<>(); - private TurbineFiler filer; - - @Before - public void setup() { - Function<String, Supplier<byte[]>> classpath = - new Function<String, Supplier<byte[]>>() { - @Nullable - @Override - public Supplier<byte[]> apply(String input) { - return null; - } - }; - this.filer = new TurbineFiler(seen, classpath, TurbineFilerTest.class.getClassLoader()); - } - - @Test - public void hello() throws IOException { - JavaFileObject sourceFile = filer.createSourceFile("com.foo.Bar", (Element[]) null); - try (OutputStream os = sourceFile.openOutputStream()) { - os.write("hello".getBytes(UTF_8)); - } - assertThat(sourceFile.getLastModified()).isEqualTo(0); - - JavaFileObject classFile = filer.createClassFile("com.foo.Baz", (Element[]) null); - try (OutputStream os = classFile.openOutputStream()) { - os.write("goodbye".getBytes(UTF_8)); - } - assertThat(classFile.getLastModified()).isEqualTo(0); - - Collection<SourceFile> roundSources = filer.finishRound(); - assertThat(roundSources).hasSize(1); - assertThat(filer.generatedSources()).hasSize(1); - assertThat(filer.generatedClasses()).hasSize(1); - - SourceFile source = getOnlyElement(roundSources); - assertThat(source.path()).isEqualTo("com/foo/Bar.java"); - assertThat(source.source()).isEqualTo("hello"); - - Map.Entry<String, byte[]> clazz = getOnlyElement(filer.generatedClasses().entrySet()); - assertThat(clazz.getKey()).isEqualTo("com/foo/Baz.class"); - assertThat(new String(clazz.getValue(), UTF_8)).isEqualTo("goodbye"); - } - - @Test - public void existing() throws IOException { - seen.add("com/foo/Bar.java"); - seen.add("com/foo/Baz.class"); - - try { - filer.createSourceFile("com.foo.Bar", (Element[]) null); - fail(); - } catch (FilerException expected) { - } - filer.createSourceFile("com.foo.Baz", (Element[]) null); - - filer.createClassFile("com.foo.Bar", (Element[]) null); - try { - filer.createClassFile("com.foo.Baz", (Element[]) null); - fail(); - } catch (FilerException expected) { - } - } - - @Test - public void get() throws IOException { - for (StandardLocation location : - Arrays.asList( - StandardLocation.CLASS_OUTPUT, - StandardLocation.SOURCE_OUTPUT, - StandardLocation.ANNOTATION_PROCESSOR_PATH, - StandardLocation.CLASS_PATH)) { - try { - filer.getResource(location, "", "NoSuch"); - fail(); - } catch (FileNotFoundException expected) { - } - } - } - - @Test - public void sourceOutput() throws IOException { - JavaFileObject classFile = filer.createSourceFile("com.foo.Bar", (Element[]) null); - try (Writer writer = classFile.openWriter()) { - writer.write("hello"); - } - filer.finishRound(); - - FileObject output = filer.getResource(StandardLocation.SOURCE_OUTPUT, "com.foo", "Bar.java"); - assertThat(new String(ByteStreams.toByteArray(output.openInputStream()), UTF_8)) - .isEqualTo("hello"); - assertThat(output.getCharContent(false).toString()).isEqualTo("hello"); - assertThat(CharStreams.toString(output.openReader(true))).isEqualTo("hello"); - } - - @Test - public void classOutput() throws IOException { - JavaFileObject classFile = filer.createClassFile("com.foo.Baz", (Element[]) null); - try (OutputStream os = classFile.openOutputStream()) { - os.write("goodbye".getBytes(UTF_8)); - } - filer.finishRound(); - - FileObject output = filer.getResource(StandardLocation.CLASS_OUTPUT, "com.foo", "Baz.class"); - assertThat(new String(ByteStreams.toByteArray(output.openInputStream()), UTF_8)) - .isEqualTo("goodbye"); - assertThat(output.getCharContent(false).toString()).isEqualTo("goodbye"); - assertThat(CharStreams.toString(output.openReader(true))).isEqualTo("goodbye"); - } - - @Test - public void classpathResources() throws IOException { - FileObject resource = - filer.getResource(StandardLocation.ANNOTATION_PROCESSOR_PATH, "META-INF", "MANIFEST.MF"); - - assertThat(new String(ByteStreams.toByteArray(resource.openInputStream()), UTF_8)) - .contains("Manifest-Version:"); - assertThat(CharStreams.toString(resource.openReader(true))).contains("Manifest-Version:"); - assertThat(resource.getCharContent(false).toString()).contains("Manifest-Version:"); - } -} diff --git a/javatests/com/google/turbine/processing/TurbineMessagerTest.java b/javatests/com/google/turbine/processing/TurbineMessagerTest.java deleted file mode 100644 index c1e6401..0000000 --- a/javatests/com/google/turbine/processing/TurbineMessagerTest.java +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import static com.google.common.collect.ImmutableList.toImmutableList; -import static com.google.common.truth.Truth.assertThat; -import static java.util.Comparator.comparing; - -import com.google.common.base.Joiner; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.turbine.binder.Binder; -import com.google.turbine.binder.ClassPathBinder; -import com.google.turbine.binder.Processing; -import com.google.turbine.diag.SourceFile; -import com.google.turbine.diag.TurbineDiagnostic; -import com.google.turbine.diag.TurbineError; -import com.google.turbine.lower.IntegrationTestSupport; -import com.google.turbine.parse.Parser; -import com.google.turbine.testing.TestClassPaths; -import com.google.turbine.tree.Tree; -import com.sun.source.util.JavacTask; -import java.nio.file.Paths; -import java.util.Collection; -import java.util.List; -import java.util.Locale; -import java.util.Optional; -import java.util.Set; -import javax.annotation.processing.AbstractProcessor; -import javax.annotation.processing.RoundEnvironment; -import javax.annotation.processing.SupportedAnnotationTypes; -import javax.lang.model.SourceVersion; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.AnnotationValue; -import javax.lang.model.element.Element; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.TypeElement; -import javax.lang.model.util.ElementScanner8; -import javax.lang.model.util.SimpleAnnotationValueVisitor8; -import javax.tools.Diagnostic; -import javax.tools.DiagnosticCollector; -import javax.tools.JavaFileObject; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class TurbineMessagerTest { - - private static final IntegrationTestSupport.TestInput SOURCES = - IntegrationTestSupport.TestInput.parse( - Joiner.on('\n') - .join( - "=== Test.java ===", - "@A class Test {", - " @A @B void f() {}", - " @B int x;", - "}", - "=== One.java ===", - "class One<U, V> {", - " @A void f(@B int x, @C int y) {}", - " <X, Y> void g(X x) {}", - "}", - "=== Two.java ===", - "class Two {", - " @D(value = 1) int x1;", - " @D(1) int x2;", - " @E(1) int x3;", - " @E({1, 2}) int x4;", - " @E(value = {1, 2}, y = 3) int x5;", - " @E(y = 0, value = {1, 2}) int x6;", - "}", - "=== Annotations.java ===", - "@interface A {}", - "@interface B {}", - "@interface C {}", - "@interface D {", - " int value() default 0;", - "}", - "@interface E {", - " int[] value() default {};", - " int y() default 0;", - "}")); - - /** - * Tests {@link TurbineMessager} by logging a message at each {@link Element}, {@link - * AnnotationMirror}, and {@link AnnotationValue}. - */ - @SupportedAnnotationTypes("*") - public static class DiagnosticTesterProcessor extends AbstractProcessor { - @Override - public SourceVersion getSupportedSourceVersion() { - return SourceVersion.latestSupported(); - } - - @Override - public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { - for (Element e : roundEnv.getRootElements()) { - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, String.valueOf(e)); - e.accept( - new ElementScanner8<Void, Void>() { - @Override - public Void scan(Element e, Void unused) { - processingEnv - .getMessager() - .printMessage(Diagnostic.Kind.ERROR, String.valueOf(e), e); - for (AnnotationMirror a : e.getAnnotationMirrors()) { - processingEnv - .getMessager() - .printMessage(Diagnostic.Kind.ERROR, String.format("%s %s", e, a), e, a); - for (AnnotationValue av : a.getElementValues().values()) { - processAnnotation(e, a, av); - } - } - return null; - } - - private void processAnnotation(Element e, AnnotationMirror a, AnnotationValue av) { - processingEnv - .getMessager() - .printMessage( - Diagnostic.Kind.ERROR, String.format("%s %s %s", e, a, av), e, a, av); - av.accept( - new SimpleAnnotationValueVisitor8<Void, Void>() { - @Override - public Void visitAnnotation(AnnotationMirror a, Void unused) { - visitAnnotationValues(a.getElementValues().values()); - return null; - } - - @Override - public Void visitArray(List<? extends AnnotationValue> vals, Void unused) { - visitAnnotationValues(vals); - return null; - } - - private void visitAnnotationValues( - Collection<? extends AnnotationValue> values) { - for (AnnotationValue av : values) { - processAnnotation(e, a, av); - } - } - }, - null); - } - - @Override - public Void visitExecutable(ExecutableElement e, Void unused) { - scan(e.getTypeParameters(), null); - return super.visitExecutable(e, unused); - } - - @Override - public Void visitType(TypeElement e, Void unused) { - scan(e.getTypeParameters(), null); - return super.visitType(e, unused); - } - }, - null); - } - return false; - } - } - - @Test - public void test() throws Exception { - - // Processes the test sources with the DiagnosticTesterProcessor under both javac and turbine, - // and asserts that the diagnostics have the same source path, line, and column under each. - - DiagnosticCollector<JavaFileObject> collector = new DiagnosticCollector<>(); - JavacTask task = - IntegrationTestSupport.runJavacAnalysis( - SOURCES.sources, ImmutableList.of(), ImmutableList.of(), collector); - task.setProcessors(ImmutableList.of(new DiagnosticTesterProcessor())); - task.call(); - ImmutableList<String> javacDiagnostics = - collector.getDiagnostics().stream() - // sort the diagnostics for nicer test failure messages - .sorted( - comparing(TurbineMessagerTest::shortPath) - .thenComparing(Diagnostic::getLineNumber) - .thenComparing(Diagnostic::getColumnNumber)) - .map(TurbineMessagerTest::formatDiagnostic) - .collect(toImmutableList()); - - ImmutableList<String> turbineDiagnostics; - ImmutableList<Tree.CompUnit> units = - SOURCES.sources.entrySet().stream() - .map(e -> new SourceFile(e.getKey(), e.getValue())) - .map(Parser::parse) - .collect(toImmutableList()); - try { - Binder.bind( - units, - ClassPathBinder.bindClasspath(ImmutableList.of()), - Processing.ProcessorInfo.create( - ImmutableList.of(new DiagnosticTesterProcessor()), - getClass().getClassLoader(), - ImmutableMap.of(), - SourceVersion.latestSupported()), - TestClassPaths.TURBINE_BOOTCLASSPATH, - Optional.empty()); - throw new AssertionError(); - } catch (TurbineError e) { - turbineDiagnostics = - e.diagnostics().stream() - .sorted( - comparing(TurbineDiagnostic::path) - .thenComparing(TurbineDiagnostic::line) - .thenComparing(TurbineDiagnostic::column)) - .map(TurbineMessagerTest::formatDiagnostic) - .collect(toImmutableList()); - } - - assertThat(turbineDiagnostics).containsExactlyElementsIn(javacDiagnostics).inOrder(); - } - - private static String formatDiagnostic(TurbineDiagnostic d) { - return String.format("%s:%s:%s %s", d.path(), d.line(), d.column(), d.message()); - } - - private static String formatDiagnostic(Diagnostic<? extends JavaFileObject> d) { - return String.format( - "%s:%s:%s %s", - shortPath(d), d.getLineNumber(), d.getColumnNumber(), d.getMessage(Locale.ENGLISH)); - } - - private static String shortPath(Diagnostic<? extends JavaFileObject> d) { - return d.getSource() != null - ? Paths.get(d.getSource().getName()).getFileName().toString() - : "<>"; - } -} diff --git a/javatests/com/google/turbine/processing/TurbineNameTest.java b/javatests/com/google/turbine/processing/TurbineNameTest.java deleted file mode 100644 index f67fc82..0000000 --- a/javatests/com/google/turbine/processing/TurbineNameTest.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class TurbineNameTest { - - @Test - public void equals() { - new EqualsTester() - .addEqualityGroup( - new TurbineName("hello"), new TurbineName("hello"), new TurbineName("hello")) - .addEqualityGroup(new TurbineName("is")) - .addEqualityGroup(new TurbineName("there")) - .addEqualityGroup(new TurbineName("anybody")) - .addEqualityGroup(new TurbineName("in")) - .testEquals(); - } - - @Test - public void asd() { - assertThat(new TurbineName("hello").contentEquals("hello")).isTrue(); - assertThat(new TurbineName("hello").contentEquals("goodbye")).isFalse(); - - assertThat(new TurbineName("hello").length()).isEqualTo(5); - - assertThat(new TurbineName("hello").charAt(0)).isEqualTo('h'); - - assertThat(new TurbineName("hello").subSequence(1, 4).toString()).isEqualTo("ell"); - - assertThat(new TurbineName("hello").toString()).isEqualTo("hello"); - } -} diff --git a/javatests/com/google/turbine/processing/TurbineTypeMirrorTest.java b/javatests/com/google/turbine/processing/TurbineTypeMirrorTest.java deleted file mode 100644 index bf08f89..0000000 --- a/javatests/com/google/turbine/processing/TurbineTypeMirrorTest.java +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import static com.google.common.collect.MoreCollectors.onlyElement; -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Iterables; -import com.google.common.testing.EqualsTester; -import com.google.turbine.binder.sym.ClassSymbol; -import com.google.turbine.binder.sym.PackageSymbol; -import com.google.turbine.binder.sym.TyVarSymbol; -import com.google.turbine.model.TurbineConstantTypeKind; -import com.google.turbine.testing.TestClassPaths; -import com.google.turbine.type.Type; -import com.google.turbine.type.Type.PrimTy; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.TypeElement; -import javax.lang.model.type.ArrayType; -import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.ExecutableType; -import javax.lang.model.type.IntersectionType; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.type.TypeVariable; -import javax.lang.model.type.WildcardType; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class TurbineTypeMirrorTest { - - private final ModelFactory factory = - new ModelFactory( - TestClassPaths.TURBINE_BOOTCLASSPATH.env(), - ClassLoader.getSystemClassLoader(), - TestClassPaths.TURBINE_BOOTCLASSPATH.index()); - - @Test - public void primitiveTypes() { - for (TypeKind kind : TypeKind.values()) { - if (!kind.isPrimitive()) { - continue; - } - TurbineConstantTypeKind turbineKind = TurbineConstantTypeKind.valueOf(kind.name()); - TypeMirror type = factory.asTypeMirror(PrimTy.create(turbineKind, ImmutableList.of())); - assertThat(type.getKind()).isEqualTo(kind); - } - } - - @Test - public void equals() { - new EqualsTester() - .addEqualityGroup( - factory.asTypeMirror( - Type.ClassTy.create( - ImmutableList.of( - Type.ClassTy.SimpleClassTy.create( - new ClassSymbol("java/util/Map"), - ImmutableList.of(), - ImmutableList.of()), - Type.ClassTy.SimpleClassTy.create( - new ClassSymbol("java/util/Map$Entry"), - ImmutableList.of(Type.ClassTy.STRING, Type.ClassTy.STRING), - ImmutableList.of()))))) - .addEqualityGroup( - factory.asTypeMirror( - Type.ClassTy.create( - ImmutableList.of( - Type.ClassTy.SimpleClassTy.create( - new ClassSymbol("java/util/Map$Entry"), - ImmutableList.of(Type.ClassTy.STRING, Type.ClassTy.OBJECT), - ImmutableList.of()))))) - .addEqualityGroup( - factory.asTypeMirror( - Type.ClassTy.asNonParametricClassTy(new ClassSymbol("java/util/Map$Entry")))) - .addEqualityGroup( - factory.asTypeMirror(PrimTy.create(TurbineConstantTypeKind.LONG, ImmutableList.of())), - factory.asTypeMirror(PrimTy.create(TurbineConstantTypeKind.LONG, ImmutableList.of()))) - .addEqualityGroup( - factory.asTypeMirror(PrimTy.create(TurbineConstantTypeKind.INT, ImmutableList.of()))) - .addEqualityGroup( - factory.asTypeMirror( - Type.WildLowerBoundedTy.create( - Type.ClassTy.asNonParametricClassTy(new ClassSymbol("java/lang/Integer")), - ImmutableList.of()))) - .addEqualityGroup( - factory.asTypeMirror( - Type.WildUpperBoundedTy.create( - Type.ClassTy.asNonParametricClassTy(new ClassSymbol("java/lang/Integer")), - ImmutableList.of()))) - .addEqualityGroup(factory.asTypeMirror(Type.WildUnboundedTy.create(ImmutableList.of()))) - .addEqualityGroup( - factory.asTypeMirror( - Type.ArrayTy.create( - PrimTy.create(TurbineConstantTypeKind.LONG, ImmutableList.of()), - ImmutableList.of()))) - .addEqualityGroup(factory.packageType(new PackageSymbol("java/lang"))) - .addEqualityGroup( - factory.asTypeMirror( - Type.TyVar.create( - new TyVarSymbol(new ClassSymbol("java/util/List"), "V"), ImmutableList.of()))) - .addEqualityGroup( - factory.asTypeMirror( - Type.IntersectionTy.create( - ImmutableList.of( - Type.ClassTy.asNonParametricClassTy( - new ClassSymbol("java/io/Serializable")), - Type.ClassTy.asNonParametricClassTy( - new ClassSymbol("java/lang/Cloneable")))))) - .addEqualityGroup(factory.noType()) - .testEquals(); - } - - @Test - public void roundTrip() { - DeclaredType te = - (DeclaredType) - factory.asTypeMirror( - Type.ClassTy.create( - ImmutableList.of( - Type.ClassTy.SimpleClassTy.create( - new ClassSymbol("java/util/List"), - ImmutableList.of( - Type.ClassTy.asNonParametricClassTy( - new ClassSymbol("java/lang/String"))), - ImmutableList.of())))); - assertThat(te.asElement().asType()).isNotEqualTo(te); - assertThat(te.asElement().asType()) - .isEqualTo( - factory.asTypeMirror( - Type.ClassTy.create( - ImmutableList.of( - Type.ClassTy.SimpleClassTy.create( - new ClassSymbol("java/util/List"), - ImmutableList.of( - Type.TyVar.create( - new TyVarSymbol(new ClassSymbol("java/util/List"), "E"), - ImmutableList.of())), - ImmutableList.of()))))); - } - - @Test - public void wildTy() { - WildcardType lower = - (WildcardType) - factory.asTypeMirror( - Type.WildLowerBoundedTy.create( - Type.ClassTy.asNonParametricClassTy(new ClassSymbol("java/lang/Integer")), - ImmutableList.of())); - WildcardType upper = - (WildcardType) - factory.asTypeMirror( - Type.WildUpperBoundedTy.create( - Type.ClassTy.asNonParametricClassTy(new ClassSymbol("java/lang/Long")), - ImmutableList.of())); - WildcardType unbound = - (WildcardType) factory.asTypeMirror(Type.WildUnboundedTy.create(ImmutableList.of())); - - assertThat(lower.getKind()).isEqualTo(TypeKind.WILDCARD); - assertThat(lower.getExtendsBound()).isNull(); - assertThat(lower.getSuperBound().getKind()).isEqualTo(TypeKind.DECLARED); - - assertThat(upper.getKind()).isEqualTo(TypeKind.WILDCARD); - assertThat(upper.getExtendsBound().getKind()).isEqualTo(TypeKind.DECLARED); - assertThat(upper.getSuperBound()).isNull(); - - assertThat(unbound.getKind()).isEqualTo(TypeKind.WILDCARD); - assertThat(unbound.getExtendsBound()).isNull(); - assertThat(unbound.getSuperBound()).isNull(); - } - - @Test - public void intersection() { - IntersectionType t = - (IntersectionType) - factory.asTypeMirror( - Type.IntersectionTy.create( - ImmutableList.of( - Type.ClassTy.asNonParametricClassTy( - new ClassSymbol("java/io/Serializable")), - Type.ClassTy.asNonParametricClassTy( - new ClassSymbol("java/lang/Cloneable"))))); - - assertThat(t.getKind()).isEqualTo(TypeKind.INTERSECTION); - assertThat(t.getBounds()) - .containsExactlyElementsIn( - factory.asTypeMirrors( - ImmutableList.of( - Type.ClassTy.asNonParametricClassTy(new ClassSymbol("java/lang/Object")), - Type.ClassTy.asNonParametricClassTy(new ClassSymbol("java/io/Serializable")), - Type.ClassTy.asNonParametricClassTy(new ClassSymbol("java/lang/Cloneable"))))); - } - - @Test - public void tyVar() { - TypeVariable t = - (TypeVariable) - Iterables.getOnlyElement( - factory - .typeElement(new ClassSymbol("java/util/Collections")) - .getEnclosedElements() - .stream() - .filter(e -> e.getSimpleName().contentEquals("sort")) - .filter(ExecutableElement.class::isInstance) - .map(ExecutableElement.class::cast) - .filter(e -> e.getParameters().size() == 1) - .findFirst() - .get() - .getTypeParameters()) - .asType(); - assertThat(t.getKind()).isEqualTo(TypeKind.TYPEVAR); - assertThat(t.getLowerBound().getKind()).isEqualTo(TypeKind.NONE); - assertThat(t.getUpperBound().toString()).isEqualTo("java.lang.Comparable<? super T>"); - } - - @Test - public void arrayType() { - ArrayType t = - (ArrayType) - factory.asTypeMirror( - Type.ArrayTy.create( - PrimTy.create(TurbineConstantTypeKind.LONG, ImmutableList.of()), - ImmutableList.of())); - assertThat(t.getKind()).isEqualTo(TypeKind.ARRAY); - assertThat(t.getComponentType().getKind()).isEqualTo(TypeKind.LONG); - } - - @Test - public void declared() { - DeclaredType a = - (DeclaredType) - factory.asTypeMirror( - Type.ClassTy.create( - ImmutableList.of( - Type.ClassTy.SimpleClassTy.create( - new ClassSymbol("java/util/Map"), - ImmutableList.of(), - ImmutableList.of()), - Type.ClassTy.SimpleClassTy.create( - new ClassSymbol("java/util/Map$Entry"), - ImmutableList.of(Type.ClassTy.STRING, Type.ClassTy.STRING), - ImmutableList.of())))); - DeclaredType b = - (DeclaredType) - factory.asTypeMirror( - Type.ClassTy.asNonParametricClassTy(new ClassSymbol("java/util/Map$Entry"))); - - assertThat(a.getEnclosingType().getKind()).isEqualTo(TypeKind.NONE); - assertThat(b.getEnclosingType().getKind()).isEqualTo(TypeKind.NONE); - } - - @Test - public void method() { - ExecutableType type = - (ExecutableType) - ((TypeElement) factory.typeElement(new ClassSymbol("java/util/Collections"))) - .getEnclosedElements().stream() - .filter(e -> e.getSimpleName().contentEquals("replaceAll")) - .collect(onlyElement()) - .asType(); - assertThat(type.getTypeVariables()).hasSize(1); - assertThat(type.toString()).isEqualTo("<T>(java.util.List<T>,T,T)boolean"); - } -} diff --git a/javatests/com/google/turbine/processing/TurbineTypesContainsTest.java b/javatests/com/google/turbine/processing/TurbineTypesContainsTest.java deleted file mode 100644 index e9e411f..0000000 --- a/javatests/com/google/turbine/processing/TurbineTypesContainsTest.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import static com.google.common.truth.TruthJUnit.assume; - -import javax.lang.model.type.TypeKind; -import javax.lang.model.util.Types; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameters; - -@RunWith(Parameterized.class) -public class TurbineTypesContainsTest extends AbstractTurbineTypesBiPredicateTest { - - @Parameters(name = "{index}: {0}") - public static Iterable<Object[]> parameters() throws Exception { - return binaryParameters(); - } - - public TurbineTypesContainsTest( - String name, TypesBiFunctionInput javacInput, TypesBiFunctionInput turbineInput) { - super(name, javacInput, turbineInput); - } - - @Test - public void contains() { - // crashes javac - assume().that(javacInput.lhs.getKind()).isNotEqualTo(TypeKind.NONE); - assume().that(javacInput.rhs.getKind()).isNotEqualTo(TypeKind.NONE); - - // crashes javac - assume().that(javacInput.lhs.getKind()).isNotEqualTo(TypeKind.EXECUTABLE); - assume().that(javacInput.rhs.getKind()).isNotEqualTo(TypeKind.EXECUTABLE); - - test("<=", Types::contains); - } -} diff --git a/javatests/com/google/turbine/processing/TurbineTypesFactoryTest.java b/javatests/com/google/turbine/processing/TurbineTypesFactoryTest.java deleted file mode 100644 index 0f9e6a6..0000000 --- a/javatests/com/google/turbine/processing/TurbineTypesFactoryTest.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.fail; - -import com.google.common.base.Joiner; -import com.google.common.collect.ImmutableList; -import com.google.turbine.binder.Binder.BindingResult; -import com.google.turbine.binder.bound.TypeBoundClass; -import com.google.turbine.binder.env.CompoundEnv; -import com.google.turbine.binder.env.Env; -import com.google.turbine.binder.env.SimpleEnv; -import com.google.turbine.binder.sym.ClassSymbol; -import com.google.turbine.lower.IntegrationTestSupport; -import com.google.turbine.testing.TestClassPaths; -import com.google.turbine.type.Type.ArrayTy; -import com.google.turbine.type.Type.ClassTy; -import com.google.turbine.type.Type.ClassTy.SimpleClassTy; -import com.google.turbine.type.Type.WildLowerBoundedTy; -import com.google.turbine.type.Type.WildUnboundedTy; -import com.google.turbine.type.Type.WildUpperBoundedTy; -import java.util.Optional; -import javax.lang.model.type.PrimitiveType; -import javax.lang.model.type.TypeKind; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class TurbineTypesFactoryTest { - - private static final IntegrationTestSupport.TestInput SOURCES = - IntegrationTestSupport.TestInput.parse( - Joiner.on('\n') - .join( - "=== Test.java ===", // - "class Test {", - " class I {}", - "}")); - - ModelFactory factory; - TurbineElements turbineElements; - TurbineTypes turbineTypes; - - @Before - public void setup() throws Exception { - - BindingResult bound = - IntegrationTestSupport.turbineAnalysis( - SOURCES.sources, - ImmutableList.of(), - TestClassPaths.TURBINE_BOOTCLASSPATH, - Optional.empty()); - Env<ClassSymbol, TypeBoundClass> env = - CompoundEnv.<ClassSymbol, TypeBoundClass>of(bound.classPathEnv()) - .append(new SimpleEnv<>(bound.units())); - factory = new ModelFactory(env, getClass().getClassLoader(), bound.tli()); - turbineTypes = new TurbineTypes(factory); - turbineElements = new TurbineElements(factory, turbineTypes); - } - - @Test - public void primitiveTypes() { - for (TypeKind kind : TypeKind.values()) { - if (kind.isPrimitive()) { - PrimitiveType type = turbineTypes.getPrimitiveType(kind); - assertThat(type.getKind()).isEqualTo(kind); - } else { - try { - turbineTypes.getPrimitiveType(kind); - fail(); - } catch (IllegalArgumentException expected) { - } - } - } - } - - @Test - public void arrayType() { - assertThat( - turbineTypes.isSameType( - turbineTypes.getArrayType( - turbineTypes.erasure(turbineElements.getTypeElement("java.util.Map").asType())), - factory.asTypeMirror( - ArrayTy.create( - ClassTy.asNonParametricClassTy(new ClassSymbol("java/util/Map")), - ImmutableList.of())))) - .isTrue(); - } - - @Test - public void wildcardType() { - // wildcard types don't compare equal with isSameType, so compare their string representations - assertThat(turbineTypes.getWildcardType(null, null).toString()) - .isEqualTo(factory.asTypeMirror(WildUnboundedTy.create(ImmutableList.of())).toString()); - assertThat( - turbineTypes - .getWildcardType(turbineElements.getTypeElement("java.lang.String").asType(), null) - .toString()) - .isEqualTo( - factory - .asTypeMirror(WildUpperBoundedTy.create(ClassTy.STRING, ImmutableList.of())) - .toString()); - assertThat( - turbineTypes - .getWildcardType(null, turbineElements.getTypeElement("java.lang.String").asType()) - .toString()) - .isEqualTo( - factory - .asTypeMirror(WildLowerBoundedTy.create(ClassTy.STRING, ImmutableList.of())) - .toString()); - } - - @Test - public void declaredType() { - assertThat( - turbineTypes.isSameType( - turbineTypes.getDeclaredType( - turbineElements.getTypeElement("java.util.Map"), - turbineElements.getTypeElement("java.lang.String").asType(), - turbineElements.getTypeElement("java.lang.Integer").asType()), - factory.asTypeMirror( - ClassTy.create( - ImmutableList.of( - SimpleClassTy.create( - new ClassSymbol("java/util/Map"), - ImmutableList.of( - ClassTy.STRING, - ClassTy.asNonParametricClassTy(ClassSymbol.INTEGER)), - ImmutableList.of())))))) - .isTrue(); - assertThat( - turbineTypes.isSameType( - turbineTypes.getDeclaredType( - turbineTypes.getDeclaredType(turbineElements.getTypeElement("Test")), - turbineElements.getTypeElement("Test.I")), - factory.asTypeMirror( - ClassTy.create( - ImmutableList.of( - SimpleClassTy.create( - new ClassSymbol("Test"), ImmutableList.of(), ImmutableList.of()), - SimpleClassTy.create( - new ClassSymbol("Test$I"), - ImmutableList.of(), - ImmutableList.of())))))) - .isTrue(); - } - - @Test - public void noType() { - assertThat(turbineTypes.getNoType(TypeKind.VOID).getKind()).isEqualTo(TypeKind.VOID); - assertThat(turbineTypes.getNoType(TypeKind.NONE).getKind()).isEqualTo(TypeKind.NONE); - try { - turbineTypes.getNoType(TypeKind.DECLARED); - fail(); - } catch (IllegalArgumentException expected) { - } - } - - @Test - public void nullType() { - assertThat(turbineTypes.getNullType().getKind()).isEqualTo(TypeKind.NULL); - } -} diff --git a/javatests/com/google/turbine/processing/TurbineTypesIsAssignableTest.java b/javatests/com/google/turbine/processing/TurbineTypesIsAssignableTest.java deleted file mode 100644 index 75b93b0..0000000 --- a/javatests/com/google/turbine/processing/TurbineTypesIsAssignableTest.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import static com.google.common.truth.TruthJUnit.assume; - -import javax.lang.model.type.TypeKind; -import javax.lang.model.util.Types; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameters; - -@RunWith(Parameterized.class) -public class TurbineTypesIsAssignableTest extends AbstractTurbineTypesBiPredicateTest { - - @Parameters(name = "{index}: {0}") - public static Iterable<Object[]> parameters() throws Exception { - return binaryParameters(); - } - - public TurbineTypesIsAssignableTest( - String testDescription, TypesBiFunctionInput javacInput, TypesBiFunctionInput turbineInput) { - super(testDescription, javacInput, turbineInput); - } - - @Test - public void isAssignable() { - // see JDK-8039198 - assume().that(javacInput.lhs.getKind()).isNotEqualTo(TypeKind.WILDCARD); - assume().that(javacInput.rhs.getKind()).isNotEqualTo(TypeKind.WILDCARD); - - // crashes javac - assume().that(javacInput.lhs.getKind()).isNotEqualTo(TypeKind.NONE); - assume().that(javacInput.rhs.getKind()).isNotEqualTo(TypeKind.NONE); - - // crashes javac - assume().that(javacInput.lhs.getKind()).isNotEqualTo(TypeKind.EXECUTABLE); - assume().that(javacInput.rhs.getKind()).isNotEqualTo(TypeKind.EXECUTABLE); - - test("isAssignable", Types::isAssignable); - } -} diff --git a/javatests/com/google/turbine/processing/TurbineTypesIsSameTypeTest.java b/javatests/com/google/turbine/processing/TurbineTypesIsSameTypeTest.java deleted file mode 100644 index ef45991..0000000 --- a/javatests/com/google/turbine/processing/TurbineTypesIsSameTypeTest.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import javax.lang.model.util.Types; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameters; - -@RunWith(Parameterized.class) -public class TurbineTypesIsSameTypeTest extends AbstractTurbineTypesBiPredicateTest { - - @Parameters(name = "{index}: {0}") - public static Iterable<Object[]> parameters() throws Exception { - return binaryParameters(); - } - - public TurbineTypesIsSameTypeTest( - String testDescription, TypesBiFunctionInput javacInput, TypesBiFunctionInput turbineInput) { - super(testDescription, javacInput, turbineInput); - } - - @Test - public void isSameType() { - test("isSameType", Types::isSameType); - } -} diff --git a/javatests/com/google/turbine/processing/TurbineTypesIsSubsignatureTest.java b/javatests/com/google/turbine/processing/TurbineTypesIsSubsignatureTest.java deleted file mode 100644 index 5f315da..0000000 --- a/javatests/com/google/turbine/processing/TurbineTypesIsSubsignatureTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import static com.google.common.truth.TruthJUnit.assume; - -import javax.lang.model.type.ExecutableType; -import javax.lang.model.type.TypeKind; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameters; - -@RunWith(Parameterized.class) -public class TurbineTypesIsSubsignatureTest extends AbstractTurbineTypesBiPredicateTest { - - @Parameters(name = "{index}: {0}") - public static Iterable<Object[]> parameters() throws Exception { - return binaryParameters(); - } - - public TurbineTypesIsSubsignatureTest( - String testDescription, TypesBiFunctionInput javacInput, TypesBiFunctionInput turbineInput) { - super(testDescription, javacInput, turbineInput); - } - - @Test - public void isSubsignature() { - assume().that(javacInput.lhs.getKind()).isEqualTo(TypeKind.EXECUTABLE); - assume().that(javacInput.rhs.getKind()).isEqualTo(TypeKind.EXECUTABLE); - - test( - "isSubsignature", - (types, x, y) -> types.isSubsignature((ExecutableType) x, (ExecutableType) y)); - } -} diff --git a/javatests/com/google/turbine/processing/TurbineTypesIsSubtypeTest.java b/javatests/com/google/turbine/processing/TurbineTypesIsSubtypeTest.java deleted file mode 100644 index 8370126..0000000 --- a/javatests/com/google/turbine/processing/TurbineTypesIsSubtypeTest.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import static com.google.common.truth.TruthJUnit.assume; - -import javax.lang.model.type.TypeKind; -import javax.lang.model.util.Types; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameters; - -@RunWith(Parameterized.class) -public class TurbineTypesIsSubtypeTest extends AbstractTurbineTypesBiPredicateTest { - - @Parameters(name = "{index}: {0}") - public static Iterable<Object[]> parameters() throws Exception { - return binaryParameters(); - } - - public TurbineTypesIsSubtypeTest( - String testDescription, TypesBiFunctionInput javacInput, TypesBiFunctionInput turbineInput) { - super(testDescription, javacInput, turbineInput); - } - - @Test - public void isSubtype() { - // see JDK-8039198 - assume().that(javacInput.lhs.getKind()).isNotEqualTo(TypeKind.WILDCARD); - assume().that(javacInput.rhs.getKind()).isNotEqualTo(TypeKind.WILDCARD); - - // crashes javac - assume().that(javacInput.lhs.getKind()).isNotEqualTo(TypeKind.NONE); - assume().that(javacInput.rhs.getKind()).isNotEqualTo(TypeKind.NONE); - - // crashes javac - assume().that(javacInput.lhs.getKind()).isNotEqualTo(TypeKind.EXECUTABLE); - assume().that(javacInput.rhs.getKind()).isNotEqualTo(TypeKind.EXECUTABLE); - - test("<:", Types::isSubtype); - } -} diff --git a/javatests/com/google/turbine/processing/TurbineTypesUnaryTest.java b/javatests/com/google/turbine/processing/TurbineTypesUnaryTest.java deleted file mode 100644 index eb5ee6c..0000000 --- a/javatests/com/google/turbine/processing/TurbineTypesUnaryTest.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.processing; - -import static com.google.common.truth.Truth.assertWithMessage; -import static com.google.common.truth.TruthJUnit.assume; -import static org.junit.Assert.fail; - -import com.google.common.base.Joiner; -import com.google.common.collect.ImmutableSet; -import javax.lang.model.type.PrimitiveType; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.Types; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameters; - -@RunWith(Parameterized.class) -public class TurbineTypesUnaryTest extends AbstractTurbineTypesTest { - - @Parameters(name = "{index}: {0}") - public static Iterable<Object[]> parameters() throws Exception { - return unaryParameters(); - } - - final String testDescription; - final Types javacTypes; - final TypeMirror javacA; - final Types turbineTypes; - final TypeMirror turbineA; - - public TurbineTypesUnaryTest( - String testDescription, - Types javacTypes, - TypeMirror javacA, - Types turbineTypes, - TypeMirror turbineA) { - this.testDescription = testDescription; - this.javacTypes = javacTypes; - this.javacA = javacA; - this.turbineTypes = turbineTypes; - this.turbineA = turbineA; - } - - @Test - public void unboxedType() { - IllegalArgumentException thrown = null; - String expectedType = null; - try { - expectedType = javacTypes.unboxedType(javacA).toString(); - } catch (IllegalArgumentException e) { - thrown = e; - } - if (thrown != null) { - try { - turbineTypes.unboxedType(turbineA).toString(); - fail(String.format("expected unboxedType(`%s`) to throw", turbineA)); - } catch (IllegalArgumentException expected) { - // expected - } - } else { - String actual = turbineTypes.unboxedType(turbineA).toString(); - assertWithMessage("unboxedClass(`%s`) = unboxedClass(`%s`)", javacA, turbineA) - .that(actual) - .isEqualTo(expectedType); - } - } - - @Test - public void boxedClass() { - assume().that(javacA).isInstanceOf(PrimitiveType.class); - assume().that(turbineA).isInstanceOf(PrimitiveType.class); - - String expected = javacTypes.boxedClass((PrimitiveType) javacA).toString(); - String actual = turbineTypes.boxedClass((PrimitiveType) turbineA).toString(); - assertWithMessage("boxedClass(`%s`) = boxedClass(`%s`)", javacA, turbineA) - .that(actual) - .isEqualTo(expected); - } - - @Test - public void erasure() { - String expected = javacTypes.erasure(javacA).toString(); - String actual = turbineTypes.erasure(turbineA).toString(); - assertWithMessage("erasure(`%s`) = erasure(`%s`)", javacA, turbineA) - .that(actual) - .isEqualTo(expected); - } - - private static final ImmutableSet<TypeKind> UNSUPPORTED_BY_DIRECT_SUPERTYPES = - ImmutableSet.of(TypeKind.EXECUTABLE, TypeKind.PACKAGE); - - @Test - public void directSupertypes() { - assume().that(UNSUPPORTED_BY_DIRECT_SUPERTYPES).doesNotContain(javacA.getKind()); - - String expected = Joiner.on(", ").join(javacTypes.directSupertypes(javacA)); - String actual = Joiner.on(", ").join(turbineTypes.directSupertypes(turbineA)); - assertWithMessage("directSupertypes(`%s`) = directSupertypes(`%s`)", javacA, turbineA) - .that(actual) - .isEqualTo(expected); - } - - @Test - public void directSupertypesThrows() { - assume().that(UNSUPPORTED_BY_DIRECT_SUPERTYPES).contains(javacA.getKind()); - - try { - javacTypes.directSupertypes(turbineA); - fail(); - } catch (IllegalArgumentException expected) { - } - try { - turbineTypes.directSupertypes(turbineA); - fail(); - } catch (IllegalArgumentException expected) { - } - } - - @Test - public void asElement() { - // TODO(cushon): this looks like a javac bug - assume().that(javacA.getKind()).isNotEqualTo(TypeKind.INTERSECTION); - - String expected = String.valueOf(javacTypes.asElement(javacA)); - String actual = String.valueOf(turbineTypes.asElement(turbineA)); - assertWithMessage("asElement(`%s`) = asElement(`%s`)", javacA, turbineA) - .that(actual) - .isEqualTo(expected); - } -} diff --git a/javatests/com/google/turbine/testing/TestClassPaths.java b/javatests/com/google/turbine/testing/TestClassPaths.java index 93be916..bf38913 100644 --- a/javatests/com/google/turbine/testing/TestClassPaths.java +++ b/javatests/com/google/turbine/testing/TestClassPaths.java @@ -67,7 +67,7 @@ public class TestClassPaths { public static TurbineOptions.Builder optionsWithBootclasspath() { TurbineOptions.Builder options = TurbineOptions.builder(); if (!BOOTCLASSPATH.isEmpty()) { - options.setBootClassPath( + options.addBootClassPathEntries( BOOTCLASSPATH.stream().map(Path::toString).collect(toImmutableList())); } else { options.setRelease("8"); diff --git a/javatests/com/google/turbine/type/TypeTest.java b/javatests/com/google/turbine/type/TypeTest.java deleted file mode 100644 index be3eb9c..0000000 --- a/javatests/com/google/turbine/type/TypeTest.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2019 Google Inc. All Rights Reserved. - * - * 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 com.google.turbine.type; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.collect.ImmutableList; -import com.google.common.testing.EqualsTester; -import com.google.turbine.binder.sym.ClassSymbol; -import com.google.turbine.tree.Tree.Ident; -import com.google.turbine.type.Type.ClassTy; -import com.google.turbine.type.Type.ClassTy.SimpleClassTy; -import com.google.turbine.type.Type.ErrorTy; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class TypeTest { - - @Test - public void equals() { - new EqualsTester() - .addEqualityGroup( - ClassTy.create( - ImmutableList.of( - SimpleClassTy.create( - new ClassSymbol("java/util/Map"), ImmutableList.of(), ImmutableList.of()), - SimpleClassTy.create( - new ClassSymbol("java/util/Map$Entry"), - ImmutableList.of(ClassTy.STRING, ClassTy.STRING), - ImmutableList.of())))) - .addEqualityGroup( - SimpleClassTy.create( - new ClassSymbol("java/util/Map$Entry"), - ImmutableList.of(ClassTy.STRING, ClassTy.OBJECT), - ImmutableList.of())) - .addEqualityGroup(ClassTy.asNonParametricClassTy(new ClassSymbol("java/util/Map$Entry"))) - .testEquals(); - } - - private static final int NO_POSITION = -1; - - @Test - public void error() { - assertThat( - ErrorTy.create( - ImmutableList.of( - new Ident(NO_POSITION, "com"), - new Ident(NO_POSITION, "foo"), - new Ident(NO_POSITION, "Bar"))) - .name()) - .isEqualTo("com.foo.Bar"); - } -} diff --git a/javatests/com/google/turbine/zip/ZipTest.java b/javatests/com/google/turbine/zip/ZipTest.java index bfc9cdf..67dcfe7 100644 --- a/javatests/com/google/turbine/zip/ZipTest.java +++ b/javatests/com/google/turbine/zip/ZipTest.java @@ -165,7 +165,7 @@ public class ZipTest { actual(path); fail(); } catch (ZipException e) { - assertThat(e).hasMessageThat().isEqualTo("zip file comment length was 33, expected 17"); + assertThat(e).hasMessage("zip file comment length was 33, expected 17"); } } } @@ -74,19 +74,13 @@ <dependency> <groupId>com.google.truth</groupId> <artifactId>truth</artifactId> - <version>1.0</version> - <scope>test</scope> - </dependency> - <dependency> - <groupId>com.google.truth.extensions</groupId> - <artifactId>truth-proto-extension</artifactId> - <version>1.0</version> + <version>0.42</version> <scope>test</scope> </dependency> <dependency> <groupId>com.google.truth.extensions</groupId> <artifactId>truth-java8-extension</artifactId> - <version>1.0</version> + <version>0.42</version> <scope>test</scope> </dependency> <dependency> diff --git a/proto/deps.proto b/proto/deps.proto index e93cc95..27013a2 100644 --- a/proto/deps.proto +++ b/proto/deps.proto @@ -20,6 +20,7 @@ option java_package = "com.google.turbine.proto"; option java_outer_classname = "DepsProto"; message Dependency { + enum Kind { // Dependency used explicitly in the source. EXPLICIT = 0; @@ -48,9 +49,4 @@ message Dependencies { // Whether the action was successful; even when compilation fails, partial // dependency information can be useful. optional bool success = 3; - - // If the Java action was started with a reduced classpath and an error - // occurred suggesting that it should be rerun with the full classpath, this - // will be true. - optional bool requires_reduced_classpath_fallback = 5; } diff --git a/proto/manifest.proto b/proto/manifest.proto deleted file mode 100644 index 20e85ef..0000000 --- a/proto/manifest.proto +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2020 Google Inc. All Rights Reserved. -// -// 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. - -// Definitions for dependency reports. - -syntax = "proto2"; - -option java_package = "com.google.turbine.proto"; -option java_outer_classname = "ManifestProto"; - -// Information about a single compilation unit (.java file) -message CompilationUnit { - // The path to the compilation unit - optional string path = 1; - - // The package of the source file - optional string pkg = 2; - - // Whether the source was generated by an annotation processor - optional bool generated_by_annotation_processor = 3; - - // The list of top-level types in the compilation unit - repeated string top_level = 4; -} - -// Top-level message found in .manifest artifacts -message Manifest { - repeated CompilationUnit compilation_unit = 1; -}
\ No newline at end of file |