Skip to content

Commit ea81dbb

Browse files
committed
Merge pull request google#36 from gk5885/compilation-rule
Add the compilation rule…
2 parents c1f7c59 + 31eb503 commit ea81dbb

File tree

3 files changed

+226
-9
lines changed

3 files changed

+226
-9
lines changed

src/main/java/com/google/testing/compile/Compilation.java

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,17 @@
1818
import static com.google.common.base.Charsets.UTF_8;
1919
import static javax.tools.JavaFileObject.Kind.SOURCE;
2020

21+
import com.google.common.base.Function;
22+
import com.google.common.base.Objects;
23+
import com.google.common.collect.ImmutableList;
24+
import com.google.common.collect.ImmutableListMultimap;
25+
import com.google.common.collect.ImmutableSet;
26+
import com.google.common.collect.Multimaps;
27+
28+
import com.sun.source.tree.CompilationUnitTree;
29+
import com.sun.source.util.JavacTask;
30+
import com.sun.tools.javac.api.JavacTool;
31+
2132
import java.io.IOException;
2233
import java.util.List;
2334
import java.util.Locale;
@@ -30,15 +41,6 @@
3041
import javax.tools.JavaFileObject;
3142
import javax.tools.ToolProvider;
3243

33-
import com.google.common.base.Function;
34-
import com.google.common.collect.ImmutableList;
35-
import com.google.common.collect.ImmutableListMultimap;
36-
import com.google.common.collect.ImmutableSet;
37-
import com.google.common.collect.Multimaps;
38-
import com.sun.source.tree.CompilationUnitTree;
39-
import com.sun.source.util.JavacTask;
40-
import com.sun.tools.javac.api.JavacTool;
41-
4244
/**
4345
* Utilities for performing compilation with {@code javac}.
4446
*
@@ -150,5 +152,13 @@ ImmutableListMultimap<JavaFileObject.Kind, JavaFileObject> generatedFilesByKind(
150152
ImmutableList<JavaFileObject> generatedSources() {
151153
return generatedFilesByKind.get(SOURCE);
152154
}
155+
156+
@Override
157+
public String toString() {
158+
return Objects.toStringHelper(this)
159+
.add("successful", successful)
160+
.add("diagnostics", diagnosticsByKind)
161+
.toString();
162+
}
153163
}
154164
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*
2+
* Copyright (C) 2014 Google, Inc.
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+
package com.google.testing.compile;
17+
18+
import static com.google.common.base.Preconditions.checkState;
19+
20+
import com.google.common.collect.ImmutableList;
21+
import com.google.common.collect.ImmutableSet;
22+
import com.google.testing.compile.Compilation.Result;
23+
24+
import org.junit.Rule;
25+
import org.junit.rules.TestRule;
26+
import org.junit.runner.Description;
27+
import org.junit.runners.JUnit4;
28+
import org.junit.runners.model.Statement;
29+
30+
import java.util.Set;
31+
import java.util.concurrent.atomic.AtomicReference;
32+
33+
import javax.annotation.processing.AbstractProcessor;
34+
import javax.annotation.processing.ProcessingEnvironment;
35+
import javax.annotation.processing.RoundEnvironment;
36+
import javax.lang.model.SourceVersion;
37+
import javax.lang.model.element.TypeElement;
38+
import javax.lang.model.util.Elements;
39+
import javax.lang.model.util.Types;
40+
41+
/**
42+
* A {@link JUnit4} {@link Rule} that executes tests such that a instances of {@link Elements} and
43+
* {@link Types} are available during execution.
44+
*
45+
* <p>To use this rule in a test, just add the following field: <pre> {@code
46+
* @Rule public CompilationRule compilationRule = new CompilationRule();}
47+
*
48+
* @author Gregory Kick
49+
*/
50+
public final class CompilationRule implements TestRule {
51+
private Elements elements;
52+
private Types types;
53+
54+
@Override
55+
public Statement apply(final Statement base, Description description) {
56+
return new Statement() {
57+
@Override public void evaluate() throws Throwable {
58+
final AtomicReference<Throwable> thrown = new AtomicReference<Throwable>();
59+
Result result = Compilation.compile(ImmutableList.of(new AbstractProcessor() {
60+
@Override
61+
public SourceVersion getSupportedSourceVersion() {
62+
return SourceVersion.latest();
63+
}
64+
65+
@Override
66+
public Set<String> getSupportedAnnotationTypes() {
67+
return ImmutableSet.of("*");
68+
}
69+
70+
@Override
71+
public synchronized void init(ProcessingEnvironment processingEnv) {
72+
super.init(processingEnv);
73+
elements = processingEnv.getElementUtils();
74+
types = processingEnv.getTypeUtils();
75+
}
76+
77+
@Override
78+
public boolean process(Set<? extends TypeElement> annotations,
79+
RoundEnvironment roundEnv) {
80+
// just run the test on the last round after compilation is over
81+
if (roundEnv.processingOver()) {
82+
try {
83+
base.evaluate();
84+
} catch (Throwable e) {
85+
thrown.set(e);
86+
}
87+
}
88+
return false;
89+
}
90+
}),
91+
// just compile _something_
92+
ImmutableList.of(JavaFileObjects.forSourceLines("Dummy", "final class Dummy {}")));
93+
checkState(result.successful(), result);
94+
Throwable t = thrown.get();
95+
if (t != null) {
96+
throw t;
97+
}
98+
}
99+
};
100+
}
101+
102+
/**
103+
* Returns the {@link Elements} instance associated with the current execution of the rule.
104+
*
105+
* @throws IllegalStateException if this method is invoked outside the execution of the rule.
106+
*/
107+
public Elements getElements() {
108+
checkState(elements != null, "Not running within the rule");
109+
return elements;
110+
}
111+
112+
/**
113+
* Returns the {@link Types} instance associated with the current execution of the rule.
114+
*
115+
* @throws IllegalStateException if this method is invoked outside the execution of the rule.
116+
*/
117+
public Types getTypes() {
118+
checkState(elements != null, "Not running within the rule");
119+
return types;
120+
}
121+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
* Copyright (C) 2014 Google, Inc.
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+
package com.google.testing.compile;
17+
18+
import static org.truth0.Truth.ASSERT;
19+
20+
import org.junit.Before;
21+
import org.junit.Rule;
22+
import org.junit.Test;
23+
import org.junit.runner.RunWith;
24+
import org.junit.runners.JUnit4;
25+
26+
import java.util.ArrayList;
27+
import java.util.List;
28+
import java.util.concurrent.atomic.AtomicInteger;
29+
30+
import javax.lang.model.element.Element;
31+
import javax.lang.model.element.TypeElement;
32+
import javax.lang.model.type.DeclaredType;
33+
import javax.lang.model.type.TypeMirror;
34+
import javax.lang.model.util.Elements;
35+
import javax.lang.model.util.Types;
36+
37+
/**
38+
* Tests the {@link CompilationRule} by applying it to this test.
39+
*/
40+
@RunWith(JUnit4.class)
41+
public class CompilationRuleTest {
42+
@Rule public CompilationRule compilationRule = new CompilationRule();
43+
44+
private final AtomicInteger executions = new AtomicInteger();
45+
46+
@Test public void testMethodsExecuteExactlyOnce() {
47+
ASSERT.that(executions.getAndIncrement()).is(0);
48+
}
49+
50+
@Before /* we also make sure that getElements works in a @Before method */
51+
@Test public void getElements() {
52+
ASSERT.that(compilationRule.getElements()).isNotNull();
53+
}
54+
55+
@Before /* we also make sure that getTypes works in a @Before method */
56+
@Test public void getTypes() {
57+
ASSERT.that(compilationRule.getTypes()).isNotNull();
58+
}
59+
60+
/**
61+
* Do some non-trivial operation with {@link Element} instances because they stop working after
62+
* compilation stops.
63+
*/
64+
@Test public void elementsAreValidAndWorking() {
65+
Elements elements = compilationRule.getElements();
66+
TypeElement stringElement = elements.getTypeElement(String.class.getName());
67+
ASSERT.that(stringElement.getEnclosingElement())
68+
.isEqualTo(elements.getPackageElement("java.lang"));
69+
}
70+
71+
/**
72+
* Do some non-trivial operation with {@link TypeMirror} instances because they stop working after
73+
* compilation stops.
74+
*/
75+
@Test public void typeMirrorsAreValidAndWorking() {
76+
Elements elements = compilationRule.getElements();
77+
Types types = compilationRule.getTypes();
78+
DeclaredType arrayListOfString = types.getDeclaredType(
79+
elements.getTypeElement(ArrayList.class.getName()),
80+
elements.getTypeElement(String.class.getName()).asType());
81+
DeclaredType listOfExtendsObjectType = types.getDeclaredType(
82+
elements.getTypeElement(List.class.getName()),
83+
types.getWildcardType(elements.getTypeElement(Object.class.getName()).asType(), null));
84+
ASSERT.that(types.isAssignable(arrayListOfString, listOfExtendsObjectType)).isTrue();
85+
}
86+
}

0 commit comments

Comments
 (0)