1/* 2 * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24import com.sun.source.tree.AnnotationTree; 25import com.sun.source.tree.CompilationUnitTree; 26import com.sun.source.util.JavacTask; 27import com.sun.source.util.TreeScanner; 28import com.sun.source.util.Trees; 29import com.sun.tools.javac.api.JavacTool; 30import com.sun.tools.javac.file.JavacFileManager; 31import com.sun.tools.javac.util.Assert; 32import java.io.File; 33import java.io.IOException; 34import java.net.URI; 35import java.net.URISyntaxException; 36import java.util.ArrayList; 37import java.util.Arrays; 38import java.util.Collections; 39import java.util.Comparator; 40import java.util.List; 41import java.util.Set; 42import javax.annotation.processing.AbstractProcessor; 43import javax.annotation.processing.RoundEnvironment; 44import javax.annotation.processing.SupportedAnnotationTypes; 45import javax.lang.model.element.TypeElement; 46import javax.tools.Diagnostic; 47import javax.tools.DiagnosticListener; 48import javax.tools.FileObject; 49import javax.tools.ForwardingJavaFileManager; 50import javax.tools.JavaFileManager; 51import javax.tools.JavaFileObject; 52import javax.tools.SimpleJavaFileObject; 53 54@SupportedAnnotationTypes("*") 55public class Processor extends AbstractProcessor { 56 57 @Override 58 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { 59 throw new IllegalStateException("Should not be invoked."); 60 } 61 62 public static void main(String... args) throws IOException, URISyntaxException { 63 if (args.length != 1) throw new IllegalStateException("Must provide class name!"); 64 String testContent = null; 65 List<File> sourcePath = new ArrayList<>(); 66 for (String sourcePaths : System.getProperty("test.src.path").split(":")) { 67 sourcePath.add(new File(sourcePaths)); 68 } 69 JavacFileManager fm = JavacTool.create().getStandardFileManager(null, null, null); 70 for (File sp : sourcePath) { 71 File inp = new File(sp, args[0]); 72 73 if (inp.canRead()) { 74 testContent = fm.getJavaFileObject(inp.toPath()).getCharContent(true).toString(); 75 } 76 } 77 if (testContent == null) throw new IllegalStateException(); 78 DiagnosticListener<JavaFileObject> devNull = new DiagnosticListener<JavaFileObject>() { 79 @Override public void report(Diagnostic<? extends JavaFileObject> diagnostic) { } 80 }; 81 JavaFileObject testFile = new TestFO(new URI("mem://" + args[0]), testContent); 82 JavacTask task = JavacTool.create().getTask(null, 83 new TestFM(fm), 84 devNull, 85 Arrays.asList("-Xjcov"), 86 null, 87 Arrays.asList(testFile)); 88 final Trees trees = Trees.instance(task); 89 final CompilationUnitTree cut = task.parse().iterator().next(); 90 task.analyze(); 91 92 final List<int[]> annotations = new ArrayList<>(); 93 94 new TreeScanner<Void, Void>() { 95 @Override 96 public Void visitAnnotation(AnnotationTree node, Void p) { 97 int endPos = (int) trees.getSourcePositions().getEndPosition(cut, node); 98 99 Assert.check(endPos >= 0); 100 101 annotations.add(new int[] {(int) trees.getSourcePositions().getStartPosition(cut, node), endPos}); 102 return super.visitAnnotation(node, p); 103 } 104 }.scan(cut.getTypeDecls().get(0), null); 105 106 Collections.sort(annotations, new Comparator<int[]>() { 107 @Override public int compare(int[] o1, int[] o2) { 108 return o2[0] - o1[0]; 109 } 110 }); 111 112 for (final int[] annotation : annotations) { 113 StringBuilder updatedContent = new StringBuilder(); 114 int last = testContent.length(); 115 116 for (int[] toRemove : annotations) { 117 if (toRemove == annotation) continue; 118 updatedContent.insert(0, testContent.substring(toRemove[1], last)); 119 last = toRemove[0]; 120 } 121 122 updatedContent.insert(0, testContent.substring(0, last)); 123 124 JavaFileObject updatedFile = new TestFO(new URI("mem://" + args[0]), updatedContent.toString()); 125 JavacTask testTask = JavacTool.create().getTask(null, 126 new TestFM(fm), 127 devNull, 128 Arrays.asList("-processor", "Processor"), 129 null, 130 Arrays.asList(updatedFile)); 131 132 try { 133 testTask.analyze(); 134 } catch (Throwable e) { 135 System.out.println("error while processing:"); 136 System.out.println(updatedContent); 137 throw e; 138 } 139 } 140 } 141 142 private static final class TestFO extends SimpleJavaFileObject { 143 private final String content; 144 public TestFO(URI uri, String content) { 145 super(uri, Kind.SOURCE); 146 this.content = content; 147 } 148 149 @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { 150 return content; 151 } 152 153 @Override public boolean isNameCompatible(String simpleName, Kind kind) { 154 return true; 155 } 156 } 157 158 private static final class TestFM extends ForwardingJavaFileManager<JavaFileManager> { 159 160 public TestFM(JavaFileManager fileManager) { 161 super(fileManager); 162 } 163 164 @Override 165 public boolean isSameFile(FileObject a, FileObject b) { 166 return a.equals(b); 167 } 168 169 } 170} 171