/*
 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.tools.jdeprscan;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

Utility class for pretty-printing various bits of API syntax.
/** * Utility class for pretty-printing various bits of API syntax. */
public class Pretty {
Converts deprecation information into an @Deprecated annotation. The output is minimized: an empty since string is omitted, a forRemoval value of false is omitted; and if both are omitted, the trailing parentheses are also omitted.
Params:
  • since – the since value
  • forRemoval – the forRemoval value
Returns:string containing an annotation
/** * Converts deprecation information into an {@code @Deprecated} annotation. * The output is minimized: an empty since string is omitted, a forRemoval * value of false is omitted; and if both are omitted, the trailing parentheses * are also omitted. * * @param since the since value * @param forRemoval the forRemoval value * @return string containing an annotation */
static String depr(String since, boolean forRemoval) { String d = "@Deprecated"; if (since.isEmpty() && !forRemoval) { return d; } StringBuilder sb = new StringBuilder(d).append('('); if (!since.isEmpty()) { sb.append("since=\"") .append(since.replace("\"", "\\\"")) .append('"'); } if (forRemoval) { if (!since.isEmpty()) { sb.append(", "); } sb.append("forRemoval=true"); } sb.append(')'); return sb.toString(); }
Converts a slash-$ style name into a dot-separated name.
Params:
  • n – the input name
Returns:the result name
/** * Converts a slash-$ style name into a dot-separated name. * * @param n the input name * @return the result name */
static String unslashify(String n) { return n.replace("/", ".") .replace("$", "."); }
Converts a type descriptor to a readable string.
Params:
  • desc – the input descriptor
Returns:the result string
/** * Converts a type descriptor to a readable string. * * @param desc the input descriptor * @return the result string */
static String desc(String desc) { return desc(desc, new int[] { 0 }); }
Converts one type descriptor to a readable string, starting from position pos_inout[0], and updating it to the location following the descriptor just parsed. A type descriptor mostly corresponds to a FieldType in JVMS 4.3.2. It can be one of a BaseType (a single character denoting a primitive, plus void), an object type ("Lname;"), or an array type (one more more '[' followed by a base or object type).
Params:
  • desc – a string possibly containing several descriptors
  • pos_inout – on input, the start position; on return, the position following the just-parsed descriptor
Returns:the result string
/** * Converts one type descriptor to a readable string, starting * from position {@code pos_inout[0]}, and updating it to the * location following the descriptor just parsed. A type descriptor * mostly corresponds to a FieldType in JVMS 4.3.2. It can be one of a * BaseType (a single character denoting a primitive, plus void), * an object type ("Lname;"), or an array type (one more more '[' followed * by a base or object type). * * @param desc a string possibly containing several descriptors * @param pos_inout on input, the start position; on return, the position * following the just-parsed descriptor * @return the result string */
static String desc(String desc, int[] pos_inout) { int dims = 0; int pos = pos_inout[0]; final int len = desc.length(); while (pos < len && desc.charAt(pos) == '[') { pos++; dims++; } String name; if (pos >= len) { return null; } char c = desc.charAt(pos++); switch (c) { case 'Z': name = "boolean"; break; case 'B': name = "byte"; break; case 'S': name = "short"; break; case 'C': name = "char"; break; case 'I': name = "int"; break; case 'J': name = "long"; break; case 'F': name = "float"; break; case 'D': name = "double"; break; case 'V': name = "void"; break; case 'L': int semi = desc.indexOf(';', pos); if (semi == -1) { return null; } name = unslashify(desc.substring(pos, semi)); pos = semi + 1; break; default: return null; } StringBuilder sb = new StringBuilder(name); for (int i = 0; i < dims; i++) { sb.append("[]"); } pos_inout[0] = pos; return sb.toString(); }
Converts a series of type descriptors into a comma-separated, readable string. This is used for the parameter types of a method descriptor.
Params:
  • types – the parameter types
Returns:the readable string
/** * Converts a series of type descriptors into a comma-separated, * readable string. This is used for the parameter types of a * method descriptor. * * @param types the parameter types * @return the readable string */
static String parms(String types) { int[] pos = new int[] { 0 }; StringBuilder sb = new StringBuilder(); boolean first = true; String t; while ((t = desc(types, pos)) != null) { if (first) { first = false; } else { sb.append(','); } sb.append(t); } return sb.toString(); }
Pattern for matching a method descriptor. Match results can be retrieved from named capture groups as follows: "name(params)return".
/** * Pattern for matching a method descriptor. Match results can * be retrieved from named capture groups as follows: "name(params)return". */
static final Pattern DESC_PAT = Pattern.compile("(?<name>.*)\\((?<args>.*)\\)(?<return>.*)");
Pretty-prints the data contained in the given DeprData object.
Params:
  • dd – the deprecation data object
Returns:the formatted string
/** * Pretty-prints the data contained in the given DeprData object. * * @param dd the deprecation data object * @return the formatted string */
public static String print(DeprData dd) { StringBuilder sb = new StringBuilder(); sb.append(depr(dd.since, dd.forRemoval)) .append(' '); switch (dd.kind) { case ANNOTATION_TYPE: sb.append("@interface "); sb.append(unslashify(dd.typeName)); break; case CLASS: sb.append("class "); sb.append(unslashify(dd.typeName)); break; case ENUM: sb.append("enum "); sb.append(unslashify(dd.typeName)); break; case INTERFACE: sb.append("interface "); sb.append(unslashify(dd.typeName)); break; case ENUM_CONSTANT: case FIELD: sb.append(unslashify(dd.typeName)) .append('.') .append(dd.nameSig); break; case CONSTRUCTOR: Matcher cons = DESC_PAT.matcher(dd.nameSig); sb.append(unslashify(dd.typeName)); if (cons.matches()) { sb.append('(') .append(parms(cons.group("args"))) .append(')'); } else { sb.append('.') .append(dd.nameSig); } break; case METHOD: Matcher meth = DESC_PAT.matcher(dd.nameSig); if (meth.matches()) { sb.append(desc(meth.group("return"))) .append(' ') .append(unslashify(dd.typeName)) .append('.') .append(meth.group("name")) .append('(') .append(parms(meth.group("args"))) .append(')'); } else { sb.append(unslashify(dd.typeName)) .append('.') .append(dd.nameSig); } break; } return sb.toString(); } }