/* * Copyright 2017 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.errorprone; 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.Locale.ENGLISH; import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; import com.google.common.jimfs.Configuration; import com.google.common.jimfs.Jimfs; 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.io.IOException; import java.nio.file.FileSystem; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import javax.tools.Diagnostic; import javax.tools.DiagnosticCollector; import javax.tools.JavaFileObject; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; /** {@link ErrorProneJavacPlugin}Test */ @RunWith(JUnit4.class) public class ErrorProneJavacPluginTest { @Rule public final TemporaryFolder temporaryFolder = new TemporaryFolder(); @Test public void hello() throws IOException { FileSystem fileSystem = Jimfs.newFileSystem(Configuration.unix()); Path source = fileSystem.getPath("Test.java"); Files.write( source, ImmutableList.of( "import java.util.HashSet;", "import java.util.Set;", "class Test {", " public static void main(String[] args) {", " Set<Short> s = new HashSet<>();", " for (short i = 0; i < 100; i++) {", " s.add(i);", " s.remove(i - 1);", " }", " System.out.println(s.size());", " }", "}"), UTF_8); JavacFileManager fileManager = new JavacFileManager(new Context(), false, UTF_8); DiagnosticCollector<JavaFileObject> diagnosticCollector = new DiagnosticCollector<>(); JavacTask task = JavacTool.create() .getTask( null, fileManager, diagnosticCollector, ImmutableList.of("-Xplugin:ErrorProne"), ImmutableList.of(), fileManager.getJavaFileObjects(source)); assertThat(task.call()).isFalse(); Diagnostic<? extends JavaFileObject> diagnostic = diagnosticCollector .getDiagnostics() .stream() .filter(d -> d.getKind() == Diagnostic.Kind.ERROR) .collect(onlyElement()); assertThat(diagnostic.getMessage(ENGLISH)).contains("[CollectionIncompatibleType]"); } @Test public void applyFixes() throws IOException { Path tmp = temporaryFolder.newFolder().toPath(); Path fileA = tmp.resolve("A.java"); Path fileB = tmp.resolve("B.java"); Files.write( fileA, ImmutableList.of( "class A implements Runnable {", // " public void run() {}", "}"), UTF_8); Files.write( fileB, ImmutableList.of( "class B implements Runnable {", // " public void run() {}", "}"), UTF_8); JavacFileManager fileManager = new JavacFileManager(new Context(), false, UTF_8); DiagnosticCollector<JavaFileObject> diagnosticCollector = new DiagnosticCollector<>(); JavacTask task = JavacTool.create() .getTask( null, fileManager, diagnosticCollector, ImmutableList.of( "-Xplugin:ErrorProne" + " -XepPatchChecks:MissingOverride -XepPatchLocation:IN_PLACE"), ImmutableList.of(), fileManager.getJavaFileObjects(fileA, fileB)); assertThat(task.call()) .named(Joiner.on('\n').join(diagnosticCollector.getDiagnostics())) .isTrue(); assertThat(Files.readAllLines(fileA, UTF_8)) .containsExactly( "class A implements Runnable {", // " @Override public void run() {}", "}") .inOrder(); assertThat(Files.readAllLines(fileB, UTF_8)) .containsExactly( "class B implements Runnable {", // " @Override public void run() {}", "}") .inOrder(); } @Test public void applyToPatchFile() throws IOException { Path tmp = temporaryFolder.newFolder().toPath(); Path patchDir = temporaryFolder.newFolder().toPath(); Files.createDirectories(patchDir); Path patchFile = patchDir.resolve("error-prone.patch"); // verify that any existing content in the patch file is deleted Files.write(patchFile, ImmutableList.of("--- C.java", "--- D.java"), UTF_8); Path fileA = tmp.resolve("A.java"); Path fileB = tmp.resolve("B.java"); Files.write( fileA, ImmutableList.of( "class A implements Runnable {", // " public void run() {}", "}"), UTF_8); Files.write( fileB, ImmutableList.of( "class B implements Runnable {", // " public void run() {}", "}"), UTF_8); JavacFileManager fileManager = new JavacFileManager(new Context(), false, UTF_8); DiagnosticCollector<JavaFileObject> diagnosticCollector = new DiagnosticCollector<>(); JavacTask task = JavacTool.create() .getTask( null, fileManager, diagnosticCollector, ImmutableList.of( "-Xplugin:ErrorProne" + " -XepPatchChecks:MissingOverride -XepPatchLocation:" + patchDir.toString()), ImmutableList.of(), fileManager.getJavaFileObjects(fileA, fileB)); assertThat(task.call()) .named(Joiner.on('\n').join(diagnosticCollector.getDiagnostics())) .isTrue(); assertThat( Files.readAllLines(patchFile, UTF_8) .stream() .filter(l -> l.startsWith("--- ")) .map(l -> Paths.get(l.substring("--- ".length())).getFileName().toString()) .collect(toImmutableList())) .containsExactly("A.java", "B.java"); } }