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.Iterator;
29 import java.util.List;
30 import javax.lang.model.element.Modifier;
31 import javax.lang.model.element.ExecutableElement;
32 import javax.lang.model.element.TypeElement;
33 import javax.lang.model.element.VariableElement;
34 import javax.lang.model.type.TypeMirror;
35 import javax.lang.model.util.ElementScanner9;
36
37 import com.sun.tools.javac.util.DefinedBy;
38 import com.sun.tools.javac.util.DefinedBy.Api;
39
40 /** Utility class that constructs a textual representation
41 * of the public api of a class.
42 *
43 * <p><b>This is NOT part of any supported API.
44 * If you write code that depends on this, you do so at your own risk.
45 * This code and its internal interfaces are subject to change or
46 * deletion without notice.</b>
47 */
48 public class PubapiVisitor extends ElementScanner9<Void, Void> {
49
50 StringBuffer sb;
51 // Important that it is 1! Part of protocol over wire, silly yes.
52 // Fix please.
53 int indent = 1;
54
55 public PubapiVisitor(StringBuffer sb) {
56 this.sb = sb;
57 }
58
59 String depth(int l) {
60 return " ".substring(0, l);
61 }
62
63 @Override @DefinedBy(Api.LANGUAGE_MODEL)
64 public Void visitType(TypeElement e, Void p) {
65 if (e.getModifiers().contains(Modifier.PUBLIC)
66 || e.getModifiers().contains(Modifier.PROTECTED))
67 {
68 sb.append(depth(indent) + "TYPE " + e.getQualifiedName() + "\n");
69 indent += 2;
70 Void v = super.visitType(e, p);
71 indent -= 2;
72 return v;
73 }
74 return null;
75 }
76
77 @Override @DefinedBy(Api.LANGUAGE_MODEL)
78 public Void visitVariable(VariableElement e, Void p) {
79 if (e.getModifiers().contains(Modifier.PUBLIC)
80 || e.getModifiers().contains(Modifier.PROTECTED)) {
81 sb.append(depth(indent)).append("VAR ")
82 .append(makeVariableString(e)).append("\n");
83 }
84 // Safe to not recurse here, because the only thing
85 // to visit here is the constructor of a variable declaration.
86 // If it happens to contain an anonymous inner class (which it might)
87 // then this class is never visible outside of the package anyway, so
88 // we are allowed to ignore it here.
89 return null;
90 }
91
92 @Override @DefinedBy(Api.LANGUAGE_MODEL)
93 public Void visitExecutable(ExecutableElement e, Void p) {
94 if (e.getModifiers().contains(Modifier.PUBLIC)
95 || e.getModifiers().contains(Modifier.PROTECTED)) {
96 sb.append(depth(indent)).append("METHOD ")
97 .append(makeMethodString(e)).append("\n");
98 }
99 return null;
100 }
101
102 /**
103 * Creates a String representation of a method element with everything
104 * necessary to track all public aspects of it in an API.
105 * @param e Element to create String for.
106 * @return String representation of element.
107 */
108 protected String makeMethodString(ExecutableElement e) {
109 StringBuilder result = new StringBuilder();
110 for (Modifier modifier : e.getModifiers()) {
111 result.append(modifier.toString());
112 result.append(" ");
113 }
114 result.append(e.getReturnType().toString());
115 result.append(" ");
116 result.append(e.toString());
117
118 List<? extends TypeMirror> thrownTypes = e.getThrownTypes();
119 if (!thrownTypes.isEmpty()) {
120 result.append(" throws ");
121 for (Iterator<? extends TypeMirror> iterator = thrownTypes
122 .iterator(); iterator.hasNext();) {
123 TypeMirror typeMirror = iterator.next();
124 result.append(typeMirror.toString());
125 if (iterator.hasNext()) {
126 result.append(", ");
127 }
128 }
129 }
130 return result.toString();
131 }
132
133 /**
134 * Creates a String representation of a variable element with everything
135 * necessary to track all public aspects of it in an API.
136 * @param e Element to create String for.
137 * @return String representation of element.
138 */
139 protected String makeVariableString(VariableElement e) {
140 StringBuilder result = new StringBuilder();
141 for (Modifier modifier : e.getModifiers()) {
142 result.append(modifier.toString());
143 result.append(" ");
144 }
145 result.append(e.asType().toString());
146 result.append(" ");
147 result.append(e.toString());
148 Object value = e.getConstantValue();
149 if (value != null) {
150 result.append(" = ");
151 if (e.asType().toString().equals("char")) {
152 int v = (int)value.toString().charAt(0);
153 result.append("'\\u"+Integer.toString(v,16)+"'");
154 } else {
155 result.append(value.toString());
156 }
157 }
158 return result.toString();
159 }
160 }
|
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 static javax.lang.model.element.Modifier.PRIVATE;
29
30 import java.util.List;
31 import java.util.stream.Collectors;
32
33 import javax.lang.model.element.Element;
34 import javax.lang.model.element.ExecutableElement;
35 import javax.lang.model.element.TypeElement;
36 import javax.lang.model.element.TypeParameterElement;
37 import javax.lang.model.element.VariableElement;
38 import javax.lang.model.type.TypeMirror;
39 import javax.lang.model.util.ElementScanner9;
40
41 import com.sun.tools.javac.util.DefinedBy;
42 import com.sun.tools.javac.util.DefinedBy.Api;
43 import com.sun.tools.sjavac.pubapi.PubApi;
44 import com.sun.tools.sjavac.pubapi.PubApiTypeParam;
45 import com.sun.tools.sjavac.pubapi.PubMethod;
46 import com.sun.tools.sjavac.pubapi.PubType;
47 import com.sun.tools.sjavac.pubapi.PubVar;
48 import com.sun.tools.sjavac.pubapi.TypeDesc;
49
50 /** Utility class that constructs a textual representation
51 * of the public api of a class.
52 *
53 * <p><b>This is NOT part of any supported API.
54 * If you write code that depends on this, you do so at your own risk.
55 * This code and its internal interfaces are subject to change or
56 * deletion without notice.</b>
57 */
58 public class PubapiVisitor extends ElementScanner9<Void, Void> {
59
60 private PubApi collectedApi = new PubApi();
61
62 private boolean isNonPrivate(Element e) {
63 return !e.getModifiers().contains(PRIVATE);
64 }
65
66 @Override @DefinedBy(Api.LANGUAGE_MODEL)
67 public Void visitType(TypeElement e, Void p) {
68 if (isNonPrivate(e)) {
69 PubApi prevApi = collectedApi;
70 collectedApi = new PubApi();
71 super.visitType(e, p);
72 PubType t = new PubType(e.getModifiers(),
73 e.getQualifiedName().toString(),
74 collectedApi);
75 prevApi.types.put(t.fqName, t);
76 collectedApi = prevApi;
77 }
78 return null;
79 }
80
81 private static String encodeChar(int c) {
82 return String.format("\\u%04x", c);
83 }
84
85 @Override @DefinedBy(Api.LANGUAGE_MODEL)
86 public Void visitVariable(VariableElement e, Void p) {
87 if (isNonPrivate(e)) {
88 Object constVal = e.getConstantValue();
89 String constValStr = null;
90 // TODO: This doesn't seem to be entirely accurate. What if I change
91 // from, say, 0 to 0L? (And the field is public final static so that
92 // it could get inlined.)
93 if (constVal != null) {
94 if (e.asType().toString().equals("char")) {
95 // What type is 'value'? Is it already a char?
96 char c = constVal.toString().charAt(0);
97 constValStr = "'" + encodeChar(c) + "'";
98 } else {
99 constValStr = constVal.toString()
100 .chars()
101 .mapToObj(PubapiVisitor::encodeChar)
102 .collect(Collectors.joining("", "\"", "\""));
103 }
104 }
105
106 PubVar v = new PubVar(e.getModifiers(),
107 TypeDesc.fromType(e.asType()),
108 e.toString(),
109 constValStr);
110 collectedApi.variables.put(v.identifier, v);
111 }
112
113 // Safe to not recurse here, because the only thing
114 // to visit here is the constructor of a variable declaration.
115 // If it happens to contain an anonymous inner class (which it might)
116 // then this class is never visible outside of the package anyway, so
117 // we are allowed to ignore it here.
118 return null;
119 }
120
121 @Override @DefinedBy(Api.LANGUAGE_MODEL)
122 public Void visitExecutable(ExecutableElement e, Void p) {
123 if (isNonPrivate(e)) {
124 PubMethod m = new PubMethod(e.getModifiers(),
125 getTypeParameters(e.getTypeParameters()),
126 TypeDesc.fromType(e.getReturnType()),
127 e.getSimpleName().toString(),
128 getTypeDescs(getParamTypes(e)),
129 getTypeDescs(e.getThrownTypes()));
130 collectedApi.methods.put(m.asSignatureString(), m);
131 }
132 return null;
133 }
134
135 private List<PubApiTypeParam> getTypeParameters(List<? extends TypeParameterElement> elements) {
136 return elements.stream()
137 .map(e -> new PubApiTypeParam(e.getSimpleName().toString(), getTypeDescs(e.getBounds())))
138 .collect(Collectors.toList());
139 }
140
141 private List<TypeMirror> getParamTypes(ExecutableElement e) {
142 return e.getParameters()
143 .stream()
144 .map(VariableElement::asType)
145 .collect(Collectors.toList());
146 }
147
148 private List<TypeDesc> getTypeDescs(List<? extends TypeMirror> list) {
149 return list.stream()
150 .map(TypeDesc::fromType)
151 .collect(Collectors.toList());
152 }
153
154 public PubApi getCollectedPubApi() {
155 return collectedApi;
156 }
157 }
|