8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.tools.sjavac.comp;
27
28 import javax.lang.model.element.Element;
29 import java.util.Arrays;
30 import java.util.Comparator;
31 import java.util.HashMap;
32 import java.util.HashSet;
33 import java.util.Map;
34 import java.util.Set;
35
36 import com.sun.tools.javac.code.Symbol.ClassSymbol;
37 import com.sun.tools.javac.util.Assert;
38 import com.sun.tools.javac.util.Context;
39 import com.sun.tools.javac.util.Log;
40 import com.sun.tools.javac.util.Name;
41
42 /** Utility class containing dependency information between packages
43 * and the pubapi for a package.
44 *
45 * <p><b>This is NOT part of any supported API.
46 * If you write code that depends on this, you do so at your own risk.
47 * This code and its internal interfaces are subject to change or
48 * deletion without notice.</b>
49 */
50 public class Dependencies {
51 protected static final Context.Key<Dependencies> dependenciesKey = new Context.Key<>();
52
53 // The log to be used for error reporting.
54 protected Log log;
55 // Map from package name to packages that the package depends upon.
56 protected Map<Name,Set<Name>> deps;
57 // This is the set of all packages that are supplied
58 // through the java files at the command line.
59 protected Set<Name> explicitPackages;
60
61 // Map from a package name to its public api.
62 // Will the Name encode the module in the future?
63 // If not, this will have to change to map from Module+Name to public api.
64 protected Map<Name,StringBuffer> publicApiPerClass;
65
66 public static Dependencies instance(Context context) {
67 Dependencies instance = context.get(dependenciesKey);
68 if (instance == null)
69 instance = new Dependencies(context);
70 return instance;
71 }
72
73 private Dependencies(Context context) {
74 context.put(dependenciesKey, this);
75 log = Log.instance(context);
76 deps = new HashMap<>();
77 explicitPackages = new HashSet<>();
78 publicApiPerClass = new HashMap<>();
79 }
80
81 /**
82 * Fetch the set of dependencies that are relevant to the compile
83 * that has just been performed. I.e. we are only interested in
84 * dependencies for classes that were explicitly compiled.
85 * @return
86 */
87 public Map<String,Set<String>> getDependencies() {
88 Map<String,Set<String>> new_deps = new HashMap<>();
89 if (explicitPackages == null) return new_deps;
90 for (Name pkg : explicitPackages) {
91 Set<Name> set = deps.get(pkg);
92 if (set != null) {
93 Set<String> new_set = new_deps.get(pkg.toString());
94 if (new_set == null) {
95 new_set = new HashSet<>();
96 // Modules beware....
97 new_deps.put(":"+pkg.toString(), new_set);
98 }
99 for (Name d : set) {
100 new_set.add(":"+d.toString());
101 }
102 }
103 }
104 return new_deps;
105 }
106
107 static class CompareNames implements Comparator<Name> {
108 public int compare(Name a, Name b) {
109 return a.toString().compareTo(b.toString());
110 }
111
112 }
113
114 /**
115 * Convert the map from class names to their pubapi to a map
116 * from package names to their pubapi (which is the sorted concatenation
117 * of all the class pubapis)
118 */
119 public Map<String,String> getPubapis() {
120 Map<String,String> publicApiPerPackage = new HashMap<>();
121 if (publicApiPerClass == null) return publicApiPerPackage;
122 Name[] keys = publicApiPerClass.keySet().toArray(new Name[0]);
123 Arrays.sort(keys, new CompareNames());
124 StringBuffer newPublicApi = new StringBuffer();
125 int i=0;
126 String prevPkg = "";
127 for (Name k : keys) {
128 String cn = k.toString();
129 String pn = "";
130 int dp = cn.lastIndexOf('.');
131 if (dp != -1) {
132 pn = cn.substring(0,dp);
133 }
134 if (!pn.equals(prevPkg)) {
135 if (!prevPkg.equals("")) {
136 // Add default module name ":"
137 publicApiPerPackage.put(":"+prevPkg, newPublicApi.toString());
138 }
139 newPublicApi = new StringBuffer();
140 prevPkg = pn;
141 }
142 newPublicApi.append(publicApiPerClass.get(k));
143 i++;
144 }
145 if (!prevPkg.equals(""))
146 publicApiPerPackage.put(":"+prevPkg, newPublicApi.toString());
147 return publicApiPerPackage;
148 }
149
150 /**
151 * Visit the api of a class and construct a pubapi string and
152 * store it into the pubapi_perclass map.
153 */
154 public void visitPubapi(Element e) {
155 Name n = ((ClassSymbol)e).fullname;
156 Name p = ((ClassSymbol)e).packge().fullname;
157 StringBuffer sb = publicApiPerClass.get(n);
158 Assert.check(sb == null);
159 sb = new StringBuffer();
160 PubapiVisitor v = new PubapiVisitor(sb);
161 v.visit(e);
162 if (sb.length()>0) {
163 publicApiPerClass.put(n, sb);
164 }
165 explicitPackages.add(p);
166 }
167
168 /**
169 * Collect a dependency. curr_pkg is marked as depending on dep_pkg.
170 */
171 public void collect(Name currPkg, Name depPkg) {
172 if (!currPkg.equals(depPkg)) {
173 Set<Name> theset = deps.get(currPkg);
174 if (theset==null) {
175 theset = new HashSet<>();
176 deps.put(currPkg, theset);
177 }
178 theset.add(depPkg);
179 }
180 }
181 }
|
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.tools.sjavac.comp;
27
28 import java.util.Collection;
29 import java.util.Collections;
30 import java.util.HashMap;
31 import java.util.Map;
32 import java.util.Set;
33 import java.util.stream.Collectors;
34
35 import javax.lang.model.element.Element;
36 import javax.tools.JavaFileManager.Location;
37 import javax.tools.JavaFileObject;
38 import javax.tools.StandardLocation;
39
40 import com.sun.tools.javac.code.Symbol.ClassSymbol;
41 import com.sun.tools.javac.code.Symbol.TypeSymbol;
42 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
43 import com.sun.tools.javac.util.Context;
44 import com.sun.tools.javac.util.Log;
45 import com.sun.tools.sjavac.Util;
46 import com.sun.tools.sjavac.pubapi.PubApi;
47
48 /** Utility class containing dependency information between packages
49 * and the pubapi for a package.
50 *
51 * <p><b>This is NOT part of any supported API.
52 * If you write code that depends on this, you do so at your own risk.
53 * This code and its internal interfaces are subject to change or
54 * deletion without notice.</b>
55 */
56 public class Dependencies {
57 protected static final Context.Key<Dependencies> dependenciesKey = new Context.Key<>();
58
59 // The log to be used for error reporting.
60 protected Log log;
61
62 // CompilationUnit -> Fully qualified type -> set of dependencies
63 protected Map<JCCompilationUnit, Map<String, Set<TypeSymbol>>> deps = new HashMap<>();
64
65 // CompilationUnit -> Fully qualified type -> set of dependencies
66 protected Map<JCCompilationUnit, Map<String, Set<TypeSymbol>>> cpDeps = new HashMap<>();
67
68 // Map from a class name to its public api.
69 // Will the Name encode the module in the future?
70 // If not, this will have to change to map from Module+Name to public api.
71 protected Map<ClassSymbol, PubApi> publicApiPerClass = new HashMap<>();
72
73 public static Dependencies instance(Context context) {
74 Dependencies instance = context.get(dependenciesKey);
75 if (instance == null)
76 instance = new Dependencies(context);
77 return instance;
78 }
79
80 private Dependencies(Context context) {
81 context.put(dependenciesKey, this);
82 log = Log.instance(context);
83 }
84
85 /**
86 * Convert the map from class names to their pubapi to a map
87 * from package names to their pubapi.
88 */
89 public Map<String, PubApi> getPubapis(Collection<JavaFileObject> explicitJFOs, boolean explicits) {
90
91 // Maps ":java.lang" to a package level pub api (with only types on top level)
92 Map<String, PubApi> result = new HashMap<>();
93 for (ClassSymbol cs : publicApiPerClass.keySet()) {
94
95 boolean amongExplicits = explicitJFOs.contains(cs.sourcefile);
96 if (explicits != amongExplicits)
97 continue;
98
99 String pkg = ":" + cs.packge().fullname;
100 PubApi currentPubApi = result.getOrDefault(pkg, new PubApi());
101 result.put(pkg, PubApi.mergeTypes(currentPubApi, publicApiPerClass.get(cs)));
102 }
103
104 return result;
105 }
106
107 /**
108 * Visit the api of a class and construct a pubapi and
109 * store it into the pubapi_perclass map.
110 */
111 @SuppressWarnings("deprecation")
112 public void visitPubapi(Element e) {
113
114 // Skip anonymous classes for now
115 if (e == null)
116 return;
117
118 PubapiVisitor v = new PubapiVisitor();
119 v.visit(e);
120 publicApiPerClass.put((ClassSymbol) e, v.getCollectedPubApi());
121 }
122
123 public void collect(Location loc, JCCompilationUnit cu, String from, TypeSymbol toSym) {
124
125 Map<JCCompilationUnit, Map<String, Set<TypeSymbol>>> depsMap;
126
127 // TODO: Just because it's not CLASS_PATH doesn't mean it's to-be-compiled path
128 depsMap = loc == StandardLocation.CLASS_PATH ? cpDeps : deps;
129
130 if (!depsMap.containsKey(cu))
131 depsMap.put(cu, new HashMap<>());
132 Map<String, Set<TypeSymbol>> map = depsMap.get(cu);
133 map.merge(from, Collections.singleton(toSym), Util::union);
134 }
135
136 // Package -> Type [from] -> Set of Type [to]
137 public Map<String, Map<String, Set<String>>> getDependencies(Collection<JavaFileObject> explicits) {
138 return getTypeDependenciesHelper(explicits, deps);
139 }
140 public Map<String, Map<String, Set<String>>> getCpDependencies(Collection<JavaFileObject> explicits) {
141 return getTypeDependenciesHelper(explicits, cpDeps);
142 }
143 public Map<String, Map<String, Set<String>>> getTypeDependenciesHelper(Collection<JavaFileObject> explicits,
144 Map<JCCompilationUnit, Map<String, Set<TypeSymbol>>> depsMap) {
145 Map<String, Map<String, Set<String>>> result = new HashMap<>();
146 for (JCCompilationUnit cu : depsMap.keySet()) {
147
148 if (!explicits.contains(cu.sourcefile))
149 continue;
150
151 // Dependencies to add to package entry
152 Map<String, Set<TypeSymbol>> src = depsMap.getOrDefault(cu, Collections.emptyMap());
153
154 // Sjavac does currently not handle default packages.
155 if (cu.getPackage() == null)
156 continue;
157
158 String key = ":" + cu.getPackage().packge.fullname.toString();
159
160 // Find (or create) destination
161 Map<String, Set<String>> dst;
162 if (result.containsKey(key))
163 dst = result.get(key);
164 else
165 result.put(key, dst = new HashMap<>());
166
167 for (String fqFrom : src.keySet()) {
168 dst.put(fqFrom, src.get(fqFrom)
169 .stream()
170 .map(ts -> ts.type.tsym.flatName().toString())
171 .collect(Collectors.toSet()));
172 }
173 }
174 return result;
175 }
176
177 }
|