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