1/* 2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 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 */ 25package jdk.jshell; 26 27import static com.sun.tools.javac.code.Flags.COMPOUND; 28import static com.sun.tools.javac.code.Kinds.Kind.PCK; 29import com.sun.tools.javac.code.Printer; 30import com.sun.tools.javac.code.Symbol; 31import com.sun.tools.javac.code.Symbol.ClassSymbol; 32import com.sun.tools.javac.code.Symbol.PackageSymbol; 33import com.sun.tools.javac.code.Type; 34import com.sun.tools.javac.code.Type.ClassType; 35import com.sun.tools.javac.util.JavacMessages; 36import java.util.Locale; 37import java.util.function.BinaryOperator; 38 39/** 40 * Print types in source form. 41 */ 42class TypePrinter extends Printer { 43 44 private static final String OBJECT = "Object"; 45 46 private final JavacMessages messages; 47 private final BinaryOperator<String> fullClassNameAndPackageToClass; 48 49 TypePrinter(JavacMessages messages, BinaryOperator<String> fullClassNameAndPackageToClass) { 50 this.messages = messages; 51 this.fullClassNameAndPackageToClass = fullClassNameAndPackageToClass; 52 } 53 54 String toString(Type t) { 55 return visit(t, Locale.getDefault()); 56 } 57 58 @Override 59 protected String localize(Locale locale, String key, Object... args) { 60 return messages.getLocalizedString(locale, key, args); 61 } 62 63 @Override 64 protected String capturedVarId(Type.CapturedType t, Locale locale) { 65 throw new InternalError("should never call this"); 66 } 67 68 @Override 69 public String visitCapturedType(Type.CapturedType t, Locale locale) { 70 return visit(t.wildcard, locale); 71 } 72 73 @Override 74 public String visitType(Type t, Locale locale) { 75 String s = (t.tsym == null || t.tsym.name == null) 76 ? OBJECT // none 77 : t.tsym.name.toString(); 78 return s; 79 } 80 81 /** 82 * Converts a class name into a (possibly localized) string. Anonymous inner 83 * classes get converted into a localized string. 84 * 85 * @param t the type of the class whose name is to be rendered 86 * @param longform if set, the class' fullname is displayed - if unset the 87 * short name is chosen (w/o package) 88 * @param locale the locale in which the string is to be rendered 89 * @return localized string representation 90 */ 91 @Override 92 protected String className(ClassType t, boolean longform, Locale locale) { 93 Symbol sym = t.tsym; 94 if (sym.name.length() == 0 && (sym.flags() & COMPOUND) != 0) { 95 return OBJECT; 96 } else if (sym.name.length() == 0) { 97 // Anonymous 98 String s; 99 ClassType norm = (ClassType) t.tsym.type; 100 if (norm == null) { 101 s = OBJECT; 102 } else if (norm.interfaces_field != null && norm.interfaces_field.nonEmpty()) { 103 s = visit(norm.interfaces_field.head, locale); 104 } else { 105 s = visit(norm.supertype_field, locale); 106 } 107 return s; 108 } else if (longform) { 109 String pkg = ""; 110 for (Symbol psym = sym; psym != null; psym = psym.owner) { 111 if (psym.kind == PCK) { 112 pkg = psym.getQualifiedName().toString(); 113 break; 114 } 115 } 116 return fullClassNameAndPackageToClass.apply( 117 sym.getQualifiedName().toString(), 118 pkg 119 ); 120 } else { 121 return sym.name.toString(); 122 } 123 } 124 125 @Override 126 public String visitClassSymbol(ClassSymbol sym, Locale locale) { 127 return sym.name.isEmpty() 128 ? sym.flatname.toString() // Anonymous 129 : sym.fullname.toString(); 130 } 131 132 @Override 133 public String visitPackageSymbol(PackageSymbol s, Locale locale) { 134 return s.isUnnamed() 135 ? "" // Unnamed package 136 : s.fullname.toString(); 137 } 138 139} 140