Path: blob/master/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/Pretty.java
41161 views
/*1* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package com.sun.tools.jdeprscan;2627import java.util.regex.Matcher;28import java.util.regex.Pattern;2930/**31* Utility class for pretty-printing various bits of API syntax.32*/33public class Pretty {34/**35* Converts deprecation information into an {@code @Deprecated} annotation.36* The output is minimized: an empty since string is omitted, a forRemoval37* value of false is omitted; and if both are omitted, the trailing parentheses38* are also omitted.39*40* @param since the since value41* @param forRemoval the forRemoval value42* @return string containing an annotation43*/44static String depr(String since, boolean forRemoval) {45String d = "@Deprecated";4647if (since.isEmpty() && !forRemoval) {48return d;49}5051StringBuilder sb = new StringBuilder(d).append('(');5253if (!since.isEmpty()) {54sb.append("since=\"")55.append(since.replace("\"", "\\\""))56.append('"');57}5859if (forRemoval) {60if (!since.isEmpty()) {61sb.append(", ");62}63sb.append("forRemoval=true");64}6566sb.append(')');6768return sb.toString();69}7071/**72* Converts a slash-$ style name into a dot-separated name.73*74* @param n the input name75* @return the result name76*/77static String unslashify(String n) {78return n.replace("/", ".")79.replace("$", ".");80}8182/**83* Converts a type descriptor to a readable string.84*85* @param desc the input descriptor86* @return the result string87*/88static String desc(String desc) {89return desc(desc, new int[] { 0 });90}9192/**93* Converts one type descriptor to a readable string, starting94* from position {@code pos_inout[0]}, and updating it to the95* location following the descriptor just parsed. A type descriptor96* mostly corresponds to a FieldType in JVMS 4.3.2. It can be one of a97* BaseType (a single character denoting a primitive, plus void),98* an object type ("Lname;"), or an array type (one more more '[' followed99* by a base or object type).100*101* @param desc a string possibly containing several descriptors102* @param pos_inout on input, the start position; on return, the position103* following the just-parsed descriptor104* @return the result string105*/106static String desc(String desc, int[] pos_inout) {107int dims = 0;108int pos = pos_inout[0];109final int len = desc.length();110111while (pos < len && desc.charAt(pos) == '[') {112pos++;113dims++;114}115116String name;117118if (pos >= len) {119return null;120}121122char c = desc.charAt(pos++);123switch (c) {124case 'Z':125name = "boolean";126break;127case 'B':128name = "byte";129break;130case 'S':131name = "short";132break;133case 'C':134name = "char";135break;136case 'I':137name = "int";138break;139case 'J':140name = "long";141break;142case 'F':143name = "float";144break;145case 'D':146name = "double";147break;148case 'V':149name = "void";150break;151case 'L':152int semi = desc.indexOf(';', pos);153if (semi == -1) {154return null;155}156name = unslashify(desc.substring(pos, semi));157pos = semi + 1;158break;159default:160return null;161}162163StringBuilder sb = new StringBuilder(name);164for (int i = 0; i < dims; i++) {165sb.append("[]");166}167pos_inout[0] = pos;168return sb.toString();169}170171/**172* Converts a series of type descriptors into a comma-separated,173* readable string. This is used for the parameter types of a174* method descriptor.175*176* @param types the parameter types177* @return the readable string178*/179static String parms(String types) {180int[] pos = new int[] { 0 };181StringBuilder sb = new StringBuilder();182183boolean first = true;184185String t;186187while ((t = desc(types, pos)) != null) {188if (first) {189first = false;190} else {191sb.append(',');192}193sb.append(t);194}195196return sb.toString();197}198199/**200* Pattern for matching a method descriptor. Match results can201* be retrieved from named capture groups as follows: "name(params)return".202*/203static final Pattern DESC_PAT = Pattern.compile("(?<name>.*)\\((?<args>.*)\\)(?<return>.*)");204205/**206* Pretty-prints the data contained in the given DeprData object.207*208* @param dd the deprecation data object209* @return the formatted string210*/211public static String print(DeprData dd) {212StringBuilder sb = new StringBuilder();213sb.append(depr(dd.since, dd.forRemoval))214.append(' ');215216switch (dd.kind) {217case ANNOTATION_TYPE:218sb.append("@interface ");219sb.append(unslashify(dd.typeName));220break;221case CLASS:222sb.append("class ");223sb.append(unslashify(dd.typeName));224break;225case ENUM:226sb.append("enum ");227sb.append(unslashify(dd.typeName));228break;229case INTERFACE:230sb.append("interface ");231sb.append(unslashify(dd.typeName));232break;233234case ENUM_CONSTANT:235case FIELD:236sb.append(unslashify(dd.typeName))237.append('.')238.append(dd.nameSig);239break;240case CONSTRUCTOR:241Matcher cons = DESC_PAT.matcher(dd.nameSig);242sb.append(unslashify(dd.typeName));243if (cons.matches()) {244sb.append('(')245.append(parms(cons.group("args")))246.append(')');247} else {248sb.append('.')249.append(dd.nameSig);250}251break;252case METHOD:253Matcher meth = DESC_PAT.matcher(dd.nameSig);254if (meth.matches()) {255sb.append(desc(meth.group("return")))256.append(' ')257.append(unslashify(dd.typeName))258.append('.')259.append(meth.group("name"))260.append('(')261.append(parms(meth.group("args")))262.append(')');263} else {264sb.append(unslashify(dd.typeName))265.append('.')266.append(dd.nameSig);267}268break;269}270271return sb.toString();272}273}274275276