ApiExtraction.java revision 3573:c4a18ee691c4
1275970Scy/* 2275970Scy * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. 3275970Scy * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4275970Scy * 5275970Scy * This code is free software; you can redistribute it and/or modify it 6275970Scy * under the terms of the GNU General Public License version 2 only, as 7275970Scy * published by the Free Software Foundation. 8275970Scy * 9275970Scy * This code is distributed in the hope that it will be useful, but WITHOUT 10275970Scy * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11275970Scy * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12275970Scy * version 2 for more details (a copy is included in the LICENSE file that 13275970Scy * accompanied this code). 14275970Scy * 15275970Scy * You should have received a copy of the GNU General Public License version 16275970Scy * 2 along with this work; if not, write to the Free Software Foundation, 17275970Scy * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18275970Scy * 19275970Scy * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20275970Scy * or visit www.oracle.com if you need additional information or have any 21275970Scy * questions. 22275970Scy */ 23275970Scy 24275970Scy/* 25275970Scy * @test 26275970Scy * @bug 8054717 27275970Scy * @summary Make sure extraction of non-private APIs work as expected. 28275970Scy * @library /tools/lib 29275970Scy * @modules jdk.compiler/com.sun.tools.javac.api 30275970Scy * jdk.compiler/com.sun.tools.javac.main 31275970Scy * jdk.compiler/com.sun.tools.sjavac 32275970Scy * jdk.compiler/com.sun.tools.sjavac.options 33275970Scy * jdk.compiler/com.sun.tools.sjavac.pubapi 34275970Scy * @build Wrapper toolbox.ToolBox toolbox.JavacTask 35275970Scy * @run main Wrapper ApiExtraction 36275970Scy */ 37275970Scy 38275970Scyimport static java.util.Arrays.asList; 39275970Scyimport static java.util.Collections.emptyList; 40275970Scyimport static javax.lang.model.element.Modifier.FINAL; 41275970Scyimport static javax.lang.model.element.Modifier.PROTECTED; 42275970Scyimport static javax.lang.model.element.Modifier.PUBLIC; 43275970Scyimport static javax.lang.model.element.Modifier.STATIC; 44275970Scy 45275970Scyimport java.io.IOException; 46275970Scyimport java.util.HashSet; 47275970Scyimport java.util.List; 48275970Scyimport java.util.Set; 49275970Scy 50275970Scyimport javax.lang.model.type.TypeKind; 51275970Scy 52275970Scyimport com.sun.tools.sjavac.PubApiExtractor; 53275970Scyimport com.sun.tools.sjavac.options.Options; 54275970Scyimport com.sun.tools.sjavac.pubapi.PrimitiveTypeDesc; 55275970Scyimport com.sun.tools.sjavac.pubapi.PubApi; 56275970Scyimport com.sun.tools.sjavac.pubapi.PubMethod; 57275970Scyimport com.sun.tools.sjavac.pubapi.PubType; 58275970Scyimport com.sun.tools.sjavac.pubapi.PubVar; 59275970Scyimport com.sun.tools.sjavac.pubapi.ReferenceTypeDesc; 60275970Scy 61275970Scyimport toolbox.JavacTask; 62275970Scyimport toolbox.ToolBox; 63275970Scy 64275970Scypublic class ApiExtraction { 65275970Scy public static void main(String[] args) throws IOException { 66275970Scy 67275970Scy String testSrc = String.join("\n", 68275970Scy "import java.util.*;", 69275970Scy "public final class TestClass extends Thread {", 70275970Scy 71275970Scy // Fields with various combination of modifiers 72275970Scy " private String s1 = \"str 1\";", 73275970Scy " public String s2 = \"str 2\";", 74275970Scy " protected final String s3 = \"str 3\";", 75275970Scy " static String s4 = \"str 4\";", 76275970Scy 77275970Scy // Methods with various combinations of types and modifiers 78275970Scy " protected void m1() {}", 79275970Scy " public static Map<Integer, List<String>> m2() {", 80275970Scy " return null;", 81275970Scy " }", 82275970Scy " final void m3(Set<Map<Integer, Map<String, String>>> s) {}", 83275970Scy 84275970Scy // Some inner classes 85275970Scy " static class DummyInner1 implements Runnable {", 86275970Scy " protected int field;", 87275970Scy " public void run() {}", 88275970Scy " }", 89275970Scy " final class DummyInner2 { }", 90275970Scy "}"); 91275970Scy 92275970Scy // Create class file to extract API from 93275970Scy new JavacTask(new ToolBox()).sources(testSrc).run(); 94275970Scy 95275970Scy // Extract PubApi 96275970Scy Options options = Options.parseArgs("-d", "bin", "--state-dir=bin", "-cp", "."); 97275970Scy PubApiExtractor pubApiExtr = new PubApiExtractor(options); 98275970Scy PubApi actualApi = pubApiExtr.getPubApi("TestClass"); 99275970Scy pubApiExtr.close(); 100275970Scy 101275970Scy // Validate result 102275970Scy PubApi expectedApi = getExpectedPubApi(); 103275970Scy if (!expectedApi.equals(actualApi)) { 104275970Scy List<String> diffs = expectedApi.diff(actualApi); 105275970Scy System.out.println(diffs.size() + " differences found."); 106275970Scy for (String diff : diffs) { 107275970Scy System.out.println(diff); 108275970Scy } 109275970Scy throw new AssertionError("Actual API differs from expected API."); 110275970Scy } 111275970Scy } 112275970Scy 113275970Scy private static PubApi getExpectedPubApi() { 114275970Scy 115275970Scy ReferenceTypeDesc string = new ReferenceTypeDesc("java.lang.String"); 116275970Scy 117275970Scy // Fields 118275970Scy // (s1 is private and therefore not included) 119275970Scy PubVar s2 = new PubVar(setOf(PUBLIC), string, "s2", null); 120275970Scy PubVar s4 = new PubVar(setOf(STATIC), string, "s4", null); 121275970Scy PubVar s3 = new PubVar(setOf(PROTECTED, FINAL), string, "s3", 122275970Scy "\"\\u0073\\u0074\\u0072\\u0020\\u0033\""); 123275970Scy 124275970Scy // Methods 125275970Scy PubMethod init = new PubMethod(setOf(PUBLIC), 126275970Scy emptyList(), 127275970Scy new PrimitiveTypeDesc(TypeKind.VOID), 128275970Scy "<init>", 129275970Scy emptyList(), 130275970Scy emptyList()); 131275970Scy 132275970Scy PubMethod clinit = new PubMethod(setOf(STATIC), 133275970Scy emptyList(), 134275970Scy new PrimitiveTypeDesc(TypeKind.VOID), 135275970Scy "<clinit>", 136275970Scy emptyList(), 137275970Scy emptyList()); 138275970Scy 139275970Scy PubMethod m1 = new PubMethod(setOf(PROTECTED), 140275970Scy emptyList(), 141275970Scy new PrimitiveTypeDesc(TypeKind.VOID), 142275970Scy "m1", 143275970Scy emptyList(), 144275970Scy emptyList()); 145275970Scy 146275970Scy PubMethod m2 = new PubMethod(setOf(PUBLIC, STATIC), 147275970Scy emptyList(), 148275970Scy new ReferenceTypeDesc("java.util.Map"), 149275970Scy "m2", 150275970Scy emptyList(), 151275970Scy emptyList()); 152275970Scy 153275970Scy PubMethod m3 = new PubMethod(setOf(FINAL), 154275970Scy emptyList(), 155275970Scy new PrimitiveTypeDesc(TypeKind.VOID), 156275970Scy "m3", 157275970Scy asList(new ReferenceTypeDesc("java.util.Set")), 158275970Scy emptyList()); 159275970Scy 160275970Scy // Complete class 161275970Scy PubType testClass = new PubType(setOf(PUBLIC, FINAL), 162275970Scy "TestClass", 163275970Scy new PubApi(asList(getDummyInner1(), getDummyInner2()), 164275970Scy asList(s2, s3, s4), 165275970Scy asList(init, clinit, m1, m2, m3))); 166275970Scy 167275970Scy // Wrap in "package level" PubApi 168275970Scy return new PubApi(asList(testClass), emptyList(), emptyList()); 169275970Scy } 170275970Scy 171275970Scy private static PubType getDummyInner1() { 172275970Scy PubMethod init = new PubMethod(setOf(), 173275970Scy emptyList(), 174275970Scy new PrimitiveTypeDesc(TypeKind.VOID), 175275970Scy "<init>", 176275970Scy emptyList(), 177275970Scy emptyList()); 178275970Scy 179275970Scy PubMethod run = new PubMethod(setOf(PUBLIC), 180275970Scy emptyList(), 181275970Scy new PrimitiveTypeDesc(TypeKind.VOID), 182275970Scy "run", 183275970Scy emptyList(), 184275970Scy emptyList()); 185275970Scy 186275970Scy PubVar field = new PubVar(setOf(PROTECTED), 187275970Scy new PrimitiveTypeDesc(TypeKind.INT), 188275970Scy "field", 189275970Scy null); 190275970Scy 191275970Scy return new PubType(setOf(STATIC), 192275970Scy "TestClass$DummyInner1", 193275970Scy new PubApi(emptyList(), 194275970Scy asList(field), 195275970Scy asList(init, run))); 196275970Scy } 197275970Scy 198275970Scy private static PubType getDummyInner2() { 199275970Scy PubMethod init = new PubMethod(setOf(), 200275970Scy emptyList(), 201275970Scy new PrimitiveTypeDesc(TypeKind.VOID), 202275970Scy "<init>", 203275970Scy emptyList(), 204275970Scy emptyList()); 205275970Scy 206275970Scy return new PubType(setOf(FINAL), 207275970Scy "TestClass$DummyInner2", 208275970Scy new PubApi(emptyList(), 209275970Scy emptyList(), 210275970Scy asList(init))); 211275970Scy } 212275970Scy 213275970Scy @SafeVarargs 214275970Scy private static <T> Set<T> setOf(T... elements) { 215275970Scy return new HashSet<>(asList(elements)); 216275970Scy } 217275970Scy} 218275970Scy