• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019 Google Inc. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.turbine.processing;
18 
19 import static com.google.common.collect.ImmutableList.toImmutableList;
20 import static com.google.common.truth.Truth.assertThat;
21 import static java.util.Objects.requireNonNull;
22 
23 import com.google.common.base.Joiner;
24 import com.google.common.collect.ImmutableList;
25 import com.google.turbine.binder.Binder;
26 import com.google.turbine.binder.ClassPathBinder;
27 import com.google.turbine.binder.bound.TypeBoundClass;
28 import com.google.turbine.binder.env.CompoundEnv;
29 import com.google.turbine.binder.env.Env;
30 import com.google.turbine.binder.env.SimpleEnv;
31 import com.google.turbine.binder.sym.ClassSymbol;
32 import com.google.turbine.diag.SourceFile;
33 import com.google.turbine.lower.IntegrationTestSupport;
34 import com.google.turbine.lower.IntegrationTestSupport.TestInput;
35 import com.google.turbine.parse.Parser;
36 import com.google.turbine.testing.TestClassPaths;
37 import com.google.turbine.tree.Tree.CompUnit;
38 import com.sun.source.util.JavacTask;
39 import java.util.Arrays;
40 import java.util.Collection;
41 import java.util.List;
42 import java.util.Optional;
43 import javax.lang.model.element.Element;
44 import javax.lang.model.util.Elements;
45 import org.junit.Test;
46 import org.junit.runner.RunWith;
47 import org.junit.runners.Parameterized;
48 import org.junit.runners.Parameterized.Parameters;
49 
50 @RunWith(Parameterized.class)
51 public class TurbineElementsGetAllMembersTest {
52 
53   @Parameters
parameters()54   public static Iterable<Object[]> parameters() {
55     // An array of test inputs. Each element is an array of lines of sources to compile.
56     String[][] inputs = {
57       {
58         "=== Test.java ===", //
59         "class Test {",
60         "}",
61       },
62       {
63         "=== A.java ===",
64         "interface A {",
65         "  Integer f();",
66         "}",
67         "=== B.java ===",
68         "interface B {",
69         "  Integer f();",
70         "}",
71         "=== Test.java ===", //
72         "class Test implements A, B {",
73         "  Integer f() {",
74         "    return 42;",
75         "  }",
76         "}",
77       },
78       {
79         "=== I.java ===",
80         "abstract class I {",
81         "  abstract Integer f();",
82         "}",
83         "=== J.java ===",
84         "interface J extends I {",
85         "  default Integer f() {",
86         "    return 42;",
87         "  }",
88         "}",
89         "=== Test.java ===", //
90         "class Test extends I implements J {",
91         "}",
92       },
93       {
94         "=== I.java ===",
95         "interface I {",
96         "  Integer f();",
97         "}",
98         "=== J.java ===",
99         "interface J extends I {",
100         "  default Integer f() {",
101         "    return 42;",
102         "  }",
103         "}",
104         "=== Test.java ===", //
105         "class Test implements J, I {",
106         "}",
107       },
108       {
109         "=== p/A.java ===",
110         "package p;",
111         "public class A {",
112         "  public boolean f() {",
113         "    return true;",
114         "  }",
115         "}",
116         "=== p/B.java ===",
117         "package p;",
118         "public interface B {",
119         "  public boolean f();",
120         "}",
121         "=== Test.java ===", //
122         "import p.*;",
123         "class Test extends A implements B {",
124         "}",
125       },
126       {
127         "=== p/A.java ===",
128         "package p;",
129         "public class A {",
130         "  public boolean f() {",
131         "    return true;",
132         "  }",
133         "}",
134         "=== p/B.java ===",
135         "package p;",
136         "public interface B {",
137         "  public boolean f();",
138         "}",
139         "=== Middle.java ===", //
140         "import p.*;",
141         "public abstract class Middle extends A implements B {",
142         "}",
143         "=== Test.java ===", //
144         "class Test extends Middle {",
145         "}",
146       },
147       {
148         "=== A.java ===",
149         "interface A {",
150         "  Integer f();",
151         "}",
152         "=== B.java ===",
153         "interface B {",
154         "  Number f();",
155         "}",
156         "=== Test.java ===", //
157         "abstract class Test implements A, B {",
158         "}",
159       },
160       {
161         "=== A.java ===",
162         "interface A {",
163         "  Integer f();",
164         "}",
165         "=== B.java ===",
166         "interface B {",
167         "  Integer f();",
168         "}",
169         "=== Test.java ===", //
170         "abstract class Test implements A, B {",
171         "}",
172       },
173       {
174         "=== I.java ===",
175         "interface I {",
176         "  int x;",
177         "}",
178         "=== J.java ===",
179         "interface J {",
180         "  int x;",
181         "}",
182         "=== B.java ===",
183         "class B {",
184         "  int x;",
185         "}",
186         "=== C.java ===",
187         "class C extends B {",
188         "  static int x;",
189         "}",
190         "=== Test.java ===",
191         "class Test extends C implements I, J {",
192         "  int x;",
193         "}",
194       },
195       {
196         "=== one/A.java ===",
197         "public class A {",
198         "  int a;",
199         "}",
200         "=== two/B.java ===",
201         "public class B extends A {",
202         "  int b;",
203         "  private int c;",
204         "  protected int d;",
205         "}",
206         "=== Test.java ===",
207         "public class Test extends B {",
208         "  int x;",
209         "}",
210       },
211       {
212         "=== A.java ===",
213         "interface A {",
214         "  class I {}",
215         "}",
216         "=== B.java ===",
217         "interface B {",
218         "  class J {}",
219         "}",
220         "=== Test.java ===", //
221         "abstract class Test implements A, B {",
222         "}",
223       },
224       {
225         "=== A.java ===",
226         "import java.util.List;",
227         "interface A<T> {",
228         "  List<? extends T> f();",
229         "}",
230         "=== Test.java ===",
231         "import java.util.List;",
232         "class Test<T extends Number> implements A<T> {",
233         "  public List<? extends T> f() {",
234         "    return null;",
235         "  }",
236         "}",
237       },
238     };
239     return Arrays.stream(inputs)
240         .map(input -> TestInput.parse(Joiner.on('\n').join(input)))
241         .map(x -> new Object[] {x})
242         .collect(toImmutableList());
243   }
244 
245   private final TestInput input;
246 
TurbineElementsGetAllMembersTest(TestInput input)247   public TurbineElementsGetAllMembersTest(TestInput input) {
248     this.input = input;
249   }
250 
251   // Compile the test inputs with javac and turbine, and assert that getAllMembers returns the
252   // same elements under each implementation.
253   @Test
test()254   public void test() throws Exception {
255     JavacTask javacTask =
256         IntegrationTestSupport.runJavacAnalysis(
257             input.sources, ImmutableList.of(), ImmutableList.of());
258     Elements javacElements = javacTask.getElements();
259     List<? extends Element> javacMembers =
260         javacElements.getAllMembers(requireNonNull(javacElements.getTypeElement("Test")));
261 
262     ImmutableList<CompUnit> units =
263         input.sources.entrySet().stream()
264             .map(e -> new SourceFile(e.getKey(), e.getValue()))
265             .map(Parser::parse)
266             .collect(toImmutableList());
267 
268     Binder.BindingResult bound =
269         Binder.bind(
270             units,
271             ClassPathBinder.bindClasspath(ImmutableList.of()),
272             TestClassPaths.TURBINE_BOOTCLASSPATH,
273             Optional.empty());
274 
275     Env<ClassSymbol, TypeBoundClass> env =
276         CompoundEnv.<ClassSymbol, TypeBoundClass>of(bound.classPathEnv())
277             .append(new SimpleEnv<>(bound.units()));
278     ModelFactory factory = new ModelFactory(env, ClassLoader.getSystemClassLoader(), bound.tli());
279     TurbineTypes turbineTypes = new TurbineTypes(factory);
280     TurbineElements turbineElements = new TurbineElements(factory, turbineTypes);
281     List<? extends Element> turbineMembers =
282         turbineElements.getAllMembers(factory.typeElement(new ClassSymbol("Test")));
283 
284     assertThat(formatElements(turbineMembers))
285         .containsExactlyElementsIn(formatElements(javacMembers));
286   }
287 
formatElements(Collection<? extends Element> elements)288   private static ImmutableList<String> formatElements(Collection<? extends Element> elements) {
289     return elements.stream()
290         .map(e -> String.format("%s %s.%s %s", e.getKind(), e.getEnclosingElement(), e, e.asType()))
291         .collect(toImmutableList());
292   }
293 }
294