1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Wed Apr 27 01:34:52 2016 +0800 1.3 @@ -0,0 +1,2963 @@ 1.4 +/* 1.5 + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Oracle designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Oracle in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.25 + * or visit www.oracle.com if you need additional information or have any 1.26 + * questions. 1.27 + */ 1.28 + 1.29 +package com.sun.tools.javac.jvm; 1.30 + 1.31 +import java.io.*; 1.32 +import java.net.URI; 1.33 +import java.net.URISyntaxException; 1.34 +import java.nio.CharBuffer; 1.35 +import java.util.Arrays; 1.36 +import java.util.EnumSet; 1.37 +import java.util.HashMap; 1.38 +import java.util.HashSet; 1.39 +import java.util.Map; 1.40 +import java.util.Set; 1.41 +import javax.lang.model.SourceVersion; 1.42 +import javax.tools.JavaFileObject; 1.43 +import javax.tools.JavaFileManager; 1.44 +import javax.tools.JavaFileManager.Location; 1.45 +import javax.tools.StandardJavaFileManager; 1.46 + 1.47 +import static javax.tools.StandardLocation.*; 1.48 + 1.49 +import com.sun.tools.javac.comp.Annotate; 1.50 +import com.sun.tools.javac.code.*; 1.51 +import com.sun.tools.javac.code.Lint.LintCategory; 1.52 +import com.sun.tools.javac.code.Type.*; 1.53 +import com.sun.tools.javac.code.Symbol.*; 1.54 +import com.sun.tools.javac.code.Symtab; 1.55 +import com.sun.tools.javac.file.BaseFileObject; 1.56 +import com.sun.tools.javac.util.*; 1.57 +import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 1.58 + 1.59 +import static com.sun.tools.javac.code.Flags.*; 1.60 +import static com.sun.tools.javac.code.Kinds.*; 1.61 +import static com.sun.tools.javac.code.TypeTag.CLASS; 1.62 +import static com.sun.tools.javac.code.TypeTag.TYPEVAR; 1.63 +import static com.sun.tools.javac.jvm.ClassFile.*; 1.64 +import static com.sun.tools.javac.jvm.ClassFile.Version.*; 1.65 + 1.66 +import static com.sun.tools.javac.main.Option.*; 1.67 + 1.68 +/** This class provides operations to read a classfile into an internal 1.69 + * representation. The internal representation is anchored in a 1.70 + * ClassSymbol which contains in its scope symbol representations 1.71 + * for all other definitions in the classfile. Top-level Classes themselves 1.72 + * appear as members of the scopes of PackageSymbols. 1.73 + * 1.74 + * <p><b>This is NOT part of any supported API. 1.75 + * If you write code that depends on this, you do so at your own risk. 1.76 + * This code and its internal interfaces are subject to change or 1.77 + * deletion without notice.</b> 1.78 + */ 1.79 +public class ClassReader { 1.80 + /** The context key for the class reader. */ 1.81 + protected static final Context.Key<ClassReader> classReaderKey = 1.82 + new Context.Key<ClassReader>(); 1.83 + 1.84 + public static final int INITIAL_BUFFER_SIZE = 0x0fff0; 1.85 + 1.86 + Annotate annotate; 1.87 + 1.88 + /** Switch: verbose output. 1.89 + */ 1.90 + boolean verbose; 1.91 + 1.92 + /** Switch: check class file for correct minor version, unrecognized 1.93 + * attributes. 1.94 + */ 1.95 + boolean checkClassFile; 1.96 + 1.97 + /** Switch: read constant pool and code sections. This switch is initially 1.98 + * set to false but can be turned on from outside. 1.99 + */ 1.100 + public boolean readAllOfClassFile = false; 1.101 + 1.102 + /** Switch: read GJ signature information. 1.103 + */ 1.104 + boolean allowGenerics; 1.105 + 1.106 + /** Switch: read varargs attribute. 1.107 + */ 1.108 + boolean allowVarargs; 1.109 + 1.110 + /** Switch: allow annotations. 1.111 + */ 1.112 + boolean allowAnnotations; 1.113 + 1.114 + /** Switch: allow simplified varargs. 1.115 + */ 1.116 + boolean allowSimplifiedVarargs; 1.117 + 1.118 + /** Lint option: warn about classfile issues 1.119 + */ 1.120 + boolean lintClassfile; 1.121 + 1.122 + /** Switch: preserve parameter names from the variable table. 1.123 + */ 1.124 + public boolean saveParameterNames; 1.125 + 1.126 + /** 1.127 + * Switch: cache completion failures unless -XDdev is used 1.128 + */ 1.129 + private boolean cacheCompletionFailure; 1.130 + 1.131 + /** 1.132 + * Switch: prefer source files instead of newer when both source 1.133 + * and class are available 1.134 + **/ 1.135 + public boolean preferSource; 1.136 + 1.137 + /** 1.138 + * The currently selected profile. 1.139 + */ 1.140 + public final Profile profile; 1.141 + 1.142 + /** The log to use for verbose output 1.143 + */ 1.144 + final Log log; 1.145 + 1.146 + /** The symbol table. */ 1.147 + Symtab syms; 1.148 + 1.149 + Types types; 1.150 + 1.151 + /** The name table. */ 1.152 + final Names names; 1.153 + 1.154 + /** Force a completion failure on this name 1.155 + */ 1.156 + final Name completionFailureName; 1.157 + 1.158 + /** Access to files 1.159 + */ 1.160 + private final JavaFileManager fileManager; 1.161 + 1.162 + /** Factory for diagnostics 1.163 + */ 1.164 + JCDiagnostic.Factory diagFactory; 1.165 + 1.166 + /** Can be reassigned from outside: 1.167 + * the completer to be used for ".java" files. If this remains unassigned 1.168 + * ".java" files will not be loaded. 1.169 + */ 1.170 + public SourceCompleter sourceCompleter = null; 1.171 + 1.172 + /** A hashtable containing the encountered top-level and member classes, 1.173 + * indexed by flat names. The table does not contain local classes. 1.174 + */ 1.175 + private Map<Name,ClassSymbol> classes; 1.176 + 1.177 + /** A hashtable containing the encountered packages. 1.178 + */ 1.179 + private Map<Name, PackageSymbol> packages; 1.180 + 1.181 + /** The current scope where type variables are entered. 1.182 + */ 1.183 + protected Scope typevars; 1.184 + 1.185 + /** The path name of the class file currently being read. 1.186 + */ 1.187 + protected JavaFileObject currentClassFile = null; 1.188 + 1.189 + /** The class or method currently being read. 1.190 + */ 1.191 + protected Symbol currentOwner = null; 1.192 + 1.193 + /** The buffer containing the currently read class file. 1.194 + */ 1.195 + byte[] buf = new byte[INITIAL_BUFFER_SIZE]; 1.196 + 1.197 + /** The current input pointer. 1.198 + */ 1.199 + protected int bp; 1.200 + 1.201 + /** The objects of the constant pool. 1.202 + */ 1.203 + Object[] poolObj; 1.204 + 1.205 + /** For every constant pool entry, an index into buf where the 1.206 + * defining section of the entry is found. 1.207 + */ 1.208 + int[] poolIdx; 1.209 + 1.210 + /** The major version number of the class file being read. */ 1.211 + int majorVersion; 1.212 + /** The minor version number of the class file being read. */ 1.213 + int minorVersion; 1.214 + 1.215 + /** A table to hold the constant pool indices for method parameter 1.216 + * names, as given in LocalVariableTable attributes. 1.217 + */ 1.218 + int[] parameterNameIndices; 1.219 + 1.220 + /** 1.221 + * Whether or not any parameter names have been found. 1.222 + */ 1.223 + boolean haveParameterNameIndices; 1.224 + 1.225 + /** Set this to false every time we start reading a method 1.226 + * and are saving parameter names. Set it to true when we see 1.227 + * MethodParameters, if it's set when we see a LocalVariableTable, 1.228 + * then we ignore the parameter names from the LVT. 1.229 + */ 1.230 + boolean sawMethodParameters; 1.231 + 1.232 + /** 1.233 + * The set of attribute names for which warnings have been generated for the current class 1.234 + */ 1.235 + Set<Name> warnedAttrs = new HashSet<Name>(); 1.236 + 1.237 + /** 1.238 + * Completer that delegates to the complete-method of this class. 1.239 + */ 1.240 + private final Completer thisCompleter = new Completer() { 1.241 + @Override 1.242 + public void complete(Symbol sym) throws CompletionFailure { 1.243 + ClassReader.this.complete(sym); 1.244 + } 1.245 + }; 1.246 + 1.247 + 1.248 + /** Get the ClassReader instance for this invocation. */ 1.249 + public static ClassReader instance(Context context) { 1.250 + ClassReader instance = context.get(classReaderKey); 1.251 + if (instance == null) 1.252 + instance = new ClassReader(context, true); 1.253 + return instance; 1.254 + } 1.255 + 1.256 + /** Initialize classes and packages, treating this as the definitive classreader. */ 1.257 + public void init(Symtab syms) { 1.258 + init(syms, true); 1.259 + } 1.260 + 1.261 + /** Initialize classes and packages, optionally treating this as 1.262 + * the definitive classreader. 1.263 + */ 1.264 + private void init(Symtab syms, boolean definitive) { 1.265 + if (classes != null) return; 1.266 + 1.267 + if (definitive) { 1.268 + Assert.check(packages == null || packages == syms.packages); 1.269 + packages = syms.packages; 1.270 + Assert.check(classes == null || classes == syms.classes); 1.271 + classes = syms.classes; 1.272 + } else { 1.273 + packages = new HashMap<Name, PackageSymbol>(); 1.274 + classes = new HashMap<Name, ClassSymbol>(); 1.275 + } 1.276 + 1.277 + packages.put(names.empty, syms.rootPackage); 1.278 + syms.rootPackage.completer = thisCompleter; 1.279 + syms.unnamedPackage.completer = thisCompleter; 1.280 + } 1.281 + 1.282 + /** Construct a new class reader, optionally treated as the 1.283 + * definitive classreader for this invocation. 1.284 + */ 1.285 + protected ClassReader(Context context, boolean definitive) { 1.286 + if (definitive) context.put(classReaderKey, this); 1.287 + 1.288 + names = Names.instance(context); 1.289 + syms = Symtab.instance(context); 1.290 + types = Types.instance(context); 1.291 + fileManager = context.get(JavaFileManager.class); 1.292 + if (fileManager == null) 1.293 + throw new AssertionError("FileManager initialization error"); 1.294 + diagFactory = JCDiagnostic.Factory.instance(context); 1.295 + 1.296 + init(syms, definitive); 1.297 + log = Log.instance(context); 1.298 + 1.299 + Options options = Options.instance(context); 1.300 + annotate = Annotate.instance(context); 1.301 + verbose = options.isSet(VERBOSE); 1.302 + checkClassFile = options.isSet("-checkclassfile"); 1.303 + 1.304 + Source source = Source.instance(context); 1.305 + allowGenerics = source.allowGenerics(); 1.306 + allowVarargs = source.allowVarargs(); 1.307 + allowAnnotations = source.allowAnnotations(); 1.308 + allowSimplifiedVarargs = source.allowSimplifiedVarargs(); 1.309 + 1.310 + saveParameterNames = options.isSet("save-parameter-names"); 1.311 + cacheCompletionFailure = options.isUnset("dev"); 1.312 + preferSource = "source".equals(options.get("-Xprefer")); 1.313 + 1.314 + profile = Profile.instance(context); 1.315 + 1.316 + completionFailureName = 1.317 + options.isSet("failcomplete") 1.318 + ? names.fromString(options.get("failcomplete")) 1.319 + : null; 1.320 + 1.321 + typevars = new Scope(syms.noSymbol); 1.322 + 1.323 + lintClassfile = Lint.instance(context).isEnabled(LintCategory.CLASSFILE); 1.324 + 1.325 + initAttributeReaders(); 1.326 + } 1.327 + 1.328 + /** Add member to class unless it is synthetic. 1.329 + */ 1.330 + private void enterMember(ClassSymbol c, Symbol sym) { 1.331 + // Synthetic members are not entered -- reason lost to history (optimization?). 1.332 + // Lambda methods must be entered because they may have inner classes (which reference them) 1.333 + if ((sym.flags_field & (SYNTHETIC|BRIDGE)) != SYNTHETIC || sym.name.startsWith(names.lambda)) 1.334 + c.members_field.enter(sym); 1.335 + } 1.336 + 1.337 +/************************************************************************ 1.338 + * Error Diagnoses 1.339 + ***********************************************************************/ 1.340 + 1.341 + 1.342 + public class BadClassFile extends CompletionFailure { 1.343 + private static final long serialVersionUID = 0; 1.344 + 1.345 + public BadClassFile(TypeSymbol sym, JavaFileObject file, JCDiagnostic diag) { 1.346 + super(sym, createBadClassFileDiagnostic(file, diag)); 1.347 + } 1.348 + } 1.349 + // where 1.350 + private JCDiagnostic createBadClassFileDiagnostic(JavaFileObject file, JCDiagnostic diag) { 1.351 + String key = (file.getKind() == JavaFileObject.Kind.SOURCE 1.352 + ? "bad.source.file.header" : "bad.class.file.header"); 1.353 + return diagFactory.fragment(key, file, diag); 1.354 + } 1.355 + 1.356 + public BadClassFile badClassFile(String key, Object... args) { 1.357 + return new BadClassFile ( 1.358 + currentOwner.enclClass(), 1.359 + currentClassFile, 1.360 + diagFactory.fragment(key, args)); 1.361 + } 1.362 + 1.363 +/************************************************************************ 1.364 + * Buffer Access 1.365 + ***********************************************************************/ 1.366 + 1.367 + /** Read a character. 1.368 + */ 1.369 + char nextChar() { 1.370 + return (char)(((buf[bp++] & 0xFF) << 8) + (buf[bp++] & 0xFF)); 1.371 + } 1.372 + 1.373 + /** Read a byte. 1.374 + */ 1.375 + int nextByte() { 1.376 + return buf[bp++] & 0xFF; 1.377 + } 1.378 + 1.379 + /** Read an integer. 1.380 + */ 1.381 + int nextInt() { 1.382 + return 1.383 + ((buf[bp++] & 0xFF) << 24) + 1.384 + ((buf[bp++] & 0xFF) << 16) + 1.385 + ((buf[bp++] & 0xFF) << 8) + 1.386 + (buf[bp++] & 0xFF); 1.387 + } 1.388 + 1.389 + /** Extract a character at position bp from buf. 1.390 + */ 1.391 + char getChar(int bp) { 1.392 + return 1.393 + (char)(((buf[bp] & 0xFF) << 8) + (buf[bp+1] & 0xFF)); 1.394 + } 1.395 + 1.396 + /** Extract an integer at position bp from buf. 1.397 + */ 1.398 + int getInt(int bp) { 1.399 + return 1.400 + ((buf[bp] & 0xFF) << 24) + 1.401 + ((buf[bp+1] & 0xFF) << 16) + 1.402 + ((buf[bp+2] & 0xFF) << 8) + 1.403 + (buf[bp+3] & 0xFF); 1.404 + } 1.405 + 1.406 + 1.407 + /** Extract a long integer at position bp from buf. 1.408 + */ 1.409 + long getLong(int bp) { 1.410 + DataInputStream bufin = 1.411 + new DataInputStream(new ByteArrayInputStream(buf, bp, 8)); 1.412 + try { 1.413 + return bufin.readLong(); 1.414 + } catch (IOException e) { 1.415 + throw new AssertionError(e); 1.416 + } 1.417 + } 1.418 + 1.419 + /** Extract a float at position bp from buf. 1.420 + */ 1.421 + float getFloat(int bp) { 1.422 + DataInputStream bufin = 1.423 + new DataInputStream(new ByteArrayInputStream(buf, bp, 4)); 1.424 + try { 1.425 + return bufin.readFloat(); 1.426 + } catch (IOException e) { 1.427 + throw new AssertionError(e); 1.428 + } 1.429 + } 1.430 + 1.431 + /** Extract a double at position bp from buf. 1.432 + */ 1.433 + double getDouble(int bp) { 1.434 + DataInputStream bufin = 1.435 + new DataInputStream(new ByteArrayInputStream(buf, bp, 8)); 1.436 + try { 1.437 + return bufin.readDouble(); 1.438 + } catch (IOException e) { 1.439 + throw new AssertionError(e); 1.440 + } 1.441 + } 1.442 + 1.443 +/************************************************************************ 1.444 + * Constant Pool Access 1.445 + ***********************************************************************/ 1.446 + 1.447 + /** Index all constant pool entries, writing their start addresses into 1.448 + * poolIdx. 1.449 + */ 1.450 + void indexPool() { 1.451 + poolIdx = new int[nextChar()]; 1.452 + poolObj = new Object[poolIdx.length]; 1.453 + int i = 1; 1.454 + while (i < poolIdx.length) { 1.455 + poolIdx[i++] = bp; 1.456 + byte tag = buf[bp++]; 1.457 + switch (tag) { 1.458 + case CONSTANT_Utf8: case CONSTANT_Unicode: { 1.459 + int len = nextChar(); 1.460 + bp = bp + len; 1.461 + break; 1.462 + } 1.463 + case CONSTANT_Class: 1.464 + case CONSTANT_String: 1.465 + case CONSTANT_MethodType: 1.466 + bp = bp + 2; 1.467 + break; 1.468 + case CONSTANT_MethodHandle: 1.469 + bp = bp + 3; 1.470 + break; 1.471 + case CONSTANT_Fieldref: 1.472 + case CONSTANT_Methodref: 1.473 + case CONSTANT_InterfaceMethodref: 1.474 + case CONSTANT_NameandType: 1.475 + case CONSTANT_Integer: 1.476 + case CONSTANT_Float: 1.477 + case CONSTANT_InvokeDynamic: 1.478 + bp = bp + 4; 1.479 + break; 1.480 + case CONSTANT_Long: 1.481 + case CONSTANT_Double: 1.482 + bp = bp + 8; 1.483 + i++; 1.484 + break; 1.485 + default: 1.486 + throw badClassFile("bad.const.pool.tag.at", 1.487 + Byte.toString(tag), 1.488 + Integer.toString(bp -1)); 1.489 + } 1.490 + } 1.491 + } 1.492 + 1.493 + /** Read constant pool entry at start address i, use pool as a cache. 1.494 + */ 1.495 + Object readPool(int i) { 1.496 + Object result = poolObj[i]; 1.497 + if (result != null) return result; 1.498 + 1.499 + int index = poolIdx[i]; 1.500 + if (index == 0) return null; 1.501 + 1.502 + byte tag = buf[index]; 1.503 + switch (tag) { 1.504 + case CONSTANT_Utf8: 1.505 + poolObj[i] = names.fromUtf(buf, index + 3, getChar(index + 1)); 1.506 + break; 1.507 + case CONSTANT_Unicode: 1.508 + throw badClassFile("unicode.str.not.supported"); 1.509 + case CONSTANT_Class: 1.510 + poolObj[i] = readClassOrType(getChar(index + 1)); 1.511 + break; 1.512 + case CONSTANT_String: 1.513 + // FIXME: (footprint) do not use toString here 1.514 + poolObj[i] = readName(getChar(index + 1)).toString(); 1.515 + break; 1.516 + case CONSTANT_Fieldref: { 1.517 + ClassSymbol owner = readClassSymbol(getChar(index + 1)); 1.518 + NameAndType nt = readNameAndType(getChar(index + 3)); 1.519 + poolObj[i] = new VarSymbol(0, nt.name, nt.uniqueType.type, owner); 1.520 + break; 1.521 + } 1.522 + case CONSTANT_Methodref: 1.523 + case CONSTANT_InterfaceMethodref: { 1.524 + ClassSymbol owner = readClassSymbol(getChar(index + 1)); 1.525 + NameAndType nt = readNameAndType(getChar(index + 3)); 1.526 + poolObj[i] = new MethodSymbol(0, nt.name, nt.uniqueType.type, owner); 1.527 + break; 1.528 + } 1.529 + case CONSTANT_NameandType: 1.530 + poolObj[i] = new NameAndType( 1.531 + readName(getChar(index + 1)), 1.532 + readType(getChar(index + 3)), types); 1.533 + break; 1.534 + case CONSTANT_Integer: 1.535 + poolObj[i] = getInt(index + 1); 1.536 + break; 1.537 + case CONSTANT_Float: 1.538 + poolObj[i] = new Float(getFloat(index + 1)); 1.539 + break; 1.540 + case CONSTANT_Long: 1.541 + poolObj[i] = new Long(getLong(index + 1)); 1.542 + break; 1.543 + case CONSTANT_Double: 1.544 + poolObj[i] = new Double(getDouble(index + 1)); 1.545 + break; 1.546 + case CONSTANT_MethodHandle: 1.547 + skipBytes(4); 1.548 + break; 1.549 + case CONSTANT_MethodType: 1.550 + skipBytes(3); 1.551 + break; 1.552 + case CONSTANT_InvokeDynamic: 1.553 + skipBytes(5); 1.554 + break; 1.555 + default: 1.556 + throw badClassFile("bad.const.pool.tag", Byte.toString(tag)); 1.557 + } 1.558 + return poolObj[i]; 1.559 + } 1.560 + 1.561 + /** Read signature and convert to type. 1.562 + */ 1.563 + Type readType(int i) { 1.564 + int index = poolIdx[i]; 1.565 + return sigToType(buf, index + 3, getChar(index + 1)); 1.566 + } 1.567 + 1.568 + /** If name is an array type or class signature, return the 1.569 + * corresponding type; otherwise return a ClassSymbol with given name. 1.570 + */ 1.571 + Object readClassOrType(int i) { 1.572 + int index = poolIdx[i]; 1.573 + int len = getChar(index + 1); 1.574 + int start = index + 3; 1.575 + Assert.check(buf[start] == '[' || buf[start + len - 1] != ';'); 1.576 + // by the above assertion, the following test can be 1.577 + // simplified to (buf[start] == '[') 1.578 + return (buf[start] == '[' || buf[start + len - 1] == ';') 1.579 + ? (Object)sigToType(buf, start, len) 1.580 + : (Object)enterClass(names.fromUtf(internalize(buf, start, 1.581 + len))); 1.582 + } 1.583 + 1.584 + /** Read signature and convert to type parameters. 1.585 + */ 1.586 + List<Type> readTypeParams(int i) { 1.587 + int index = poolIdx[i]; 1.588 + return sigToTypeParams(buf, index + 3, getChar(index + 1)); 1.589 + } 1.590 + 1.591 + /** Read class entry. 1.592 + */ 1.593 + ClassSymbol readClassSymbol(int i) { 1.594 + Object obj = readPool(i); 1.595 + if (obj != null && !(obj instanceof ClassSymbol)) 1.596 + throw badClassFile("bad.const.pool.entry", 1.597 + currentClassFile.toString(), 1.598 + "CONSTANT_Class_info", i); 1.599 + return (ClassSymbol)obj; 1.600 + } 1.601 + 1.602 + /** Read name. 1.603 + */ 1.604 + Name readName(int i) { 1.605 + Object obj = readPool(i); 1.606 + if (obj != null && !(obj instanceof Name)) 1.607 + throw badClassFile("bad.const.pool.entry", 1.608 + currentClassFile.toString(), 1.609 + "CONSTANT_Utf8_info or CONSTANT_String_info", i); 1.610 + return (Name)obj; 1.611 + } 1.612 + 1.613 + /** Read name and type. 1.614 + */ 1.615 + NameAndType readNameAndType(int i) { 1.616 + Object obj = readPool(i); 1.617 + if (obj != null && !(obj instanceof NameAndType)) 1.618 + throw badClassFile("bad.const.pool.entry", 1.619 + currentClassFile.toString(), 1.620 + "CONSTANT_NameAndType_info", i); 1.621 + return (NameAndType)obj; 1.622 + } 1.623 + 1.624 +/************************************************************************ 1.625 + * Reading Types 1.626 + ***********************************************************************/ 1.627 + 1.628 + /** The unread portion of the currently read type is 1.629 + * signature[sigp..siglimit-1]. 1.630 + */ 1.631 + byte[] signature; 1.632 + int sigp; 1.633 + int siglimit; 1.634 + boolean sigEnterPhase = false; 1.635 + 1.636 + /** Convert signature to type, where signature is a byte array segment. 1.637 + */ 1.638 + Type sigToType(byte[] sig, int offset, int len) { 1.639 + signature = sig; 1.640 + sigp = offset; 1.641 + siglimit = offset + len; 1.642 + return sigToType(); 1.643 + } 1.644 + 1.645 + /** Convert signature to type, where signature is implicit. 1.646 + */ 1.647 + Type sigToType() { 1.648 + switch ((char) signature[sigp]) { 1.649 + case 'T': 1.650 + sigp++; 1.651 + int start = sigp; 1.652 + while (signature[sigp] != ';') sigp++; 1.653 + sigp++; 1.654 + return sigEnterPhase 1.655 + ? Type.noType 1.656 + : findTypeVar(names.fromUtf(signature, start, sigp - 1 - start)); 1.657 + case '+': { 1.658 + sigp++; 1.659 + Type t = sigToType(); 1.660 + return new WildcardType(t, BoundKind.EXTENDS, 1.661 + syms.boundClass); 1.662 + } 1.663 + case '*': 1.664 + sigp++; 1.665 + return new WildcardType(syms.objectType, BoundKind.UNBOUND, 1.666 + syms.boundClass); 1.667 + case '-': { 1.668 + sigp++; 1.669 + Type t = sigToType(); 1.670 + return new WildcardType(t, BoundKind.SUPER, 1.671 + syms.boundClass); 1.672 + } 1.673 + case 'B': 1.674 + sigp++; 1.675 + return syms.byteType; 1.676 + case 'C': 1.677 + sigp++; 1.678 + return syms.charType; 1.679 + case 'D': 1.680 + sigp++; 1.681 + return syms.doubleType; 1.682 + case 'F': 1.683 + sigp++; 1.684 + return syms.floatType; 1.685 + case 'I': 1.686 + sigp++; 1.687 + return syms.intType; 1.688 + case 'J': 1.689 + sigp++; 1.690 + return syms.longType; 1.691 + case 'L': 1.692 + { 1.693 + // int oldsigp = sigp; 1.694 + Type t = classSigToType(); 1.695 + if (sigp < siglimit && signature[sigp] == '.') 1.696 + throw badClassFile("deprecated inner class signature syntax " + 1.697 + "(please recompile from source)"); 1.698 + /* 1.699 + System.err.println(" decoded " + 1.700 + new String(signature, oldsigp, sigp-oldsigp) + 1.701 + " => " + t + " outer " + t.outer()); 1.702 + */ 1.703 + return t; 1.704 + } 1.705 + case 'S': 1.706 + sigp++; 1.707 + return syms.shortType; 1.708 + case 'V': 1.709 + sigp++; 1.710 + return syms.voidType; 1.711 + case 'Z': 1.712 + sigp++; 1.713 + return syms.booleanType; 1.714 + case '[': 1.715 + sigp++; 1.716 + return new ArrayType(sigToType(), syms.arrayClass); 1.717 + case '(': 1.718 + sigp++; 1.719 + List<Type> argtypes = sigToTypes(')'); 1.720 + Type restype = sigToType(); 1.721 + List<Type> thrown = List.nil(); 1.722 + while (signature[sigp] == '^') { 1.723 + sigp++; 1.724 + thrown = thrown.prepend(sigToType()); 1.725 + } 1.726 + // if there is a typevar in the throws clause we should state it. 1.727 + for (List<Type> l = thrown; l.nonEmpty(); l = l.tail) { 1.728 + if (l.head.hasTag(TYPEVAR)) { 1.729 + l.head.tsym.flags_field |= THROWS; 1.730 + } 1.731 + } 1.732 + return new MethodType(argtypes, 1.733 + restype, 1.734 + thrown.reverse(), 1.735 + syms.methodClass); 1.736 + case '<': 1.737 + typevars = typevars.dup(currentOwner); 1.738 + Type poly = new ForAll(sigToTypeParams(), sigToType()); 1.739 + typevars = typevars.leave(); 1.740 + return poly; 1.741 + default: 1.742 + throw badClassFile("bad.signature", 1.743 + Convert.utf2string(signature, sigp, 10)); 1.744 + } 1.745 + } 1.746 + 1.747 + byte[] signatureBuffer = new byte[0]; 1.748 + int sbp = 0; 1.749 + /** Convert class signature to type, where signature is implicit. 1.750 + */ 1.751 + Type classSigToType() { 1.752 + if (signature[sigp] != 'L') 1.753 + throw badClassFile("bad.class.signature", 1.754 + Convert.utf2string(signature, sigp, 10)); 1.755 + sigp++; 1.756 + Type outer = Type.noType; 1.757 + int startSbp = sbp; 1.758 + 1.759 + while (true) { 1.760 + final byte c = signature[sigp++]; 1.761 + switch (c) { 1.762 + 1.763 + case ';': { // end 1.764 + ClassSymbol t = enterClass(names.fromUtf(signatureBuffer, 1.765 + startSbp, 1.766 + sbp - startSbp)); 1.767 + 1.768 + try { 1.769 + return (outer == Type.noType) ? 1.770 + t.erasure(types) : 1.771 + new ClassType(outer, List.<Type>nil(), t); 1.772 + } finally { 1.773 + sbp = startSbp; 1.774 + } 1.775 + } 1.776 + 1.777 + case '<': // generic arguments 1.778 + ClassSymbol t = enterClass(names.fromUtf(signatureBuffer, 1.779 + startSbp, 1.780 + sbp - startSbp)); 1.781 + outer = new ClassType(outer, sigToTypes('>'), t) { 1.782 + boolean completed = false; 1.783 + @Override 1.784 + public Type getEnclosingType() { 1.785 + if (!completed) { 1.786 + completed = true; 1.787 + tsym.complete(); 1.788 + Type enclosingType = tsym.type.getEnclosingType(); 1.789 + if (enclosingType != Type.noType) { 1.790 + List<Type> typeArgs = 1.791 + super.getEnclosingType().allparams(); 1.792 + List<Type> typeParams = 1.793 + enclosingType.allparams(); 1.794 + if (typeParams.length() != typeArgs.length()) { 1.795 + // no "rare" types 1.796 + super.setEnclosingType(types.erasure(enclosingType)); 1.797 + } else { 1.798 + super.setEnclosingType(types.subst(enclosingType, 1.799 + typeParams, 1.800 + typeArgs)); 1.801 + } 1.802 + } else { 1.803 + super.setEnclosingType(Type.noType); 1.804 + } 1.805 + } 1.806 + return super.getEnclosingType(); 1.807 + } 1.808 + @Override 1.809 + public void setEnclosingType(Type outer) { 1.810 + throw new UnsupportedOperationException(); 1.811 + } 1.812 + }; 1.813 + switch (signature[sigp++]) { 1.814 + case ';': 1.815 + if (sigp < signature.length && signature[sigp] == '.') { 1.816 + // support old-style GJC signatures 1.817 + // The signature produced was 1.818 + // Lfoo/Outer<Lfoo/X;>;.Lfoo/Outer$Inner<Lfoo/Y;>; 1.819 + // rather than say 1.820 + // Lfoo/Outer<Lfoo/X;>.Inner<Lfoo/Y;>; 1.821 + // so we skip past ".Lfoo/Outer$" 1.822 + sigp += (sbp - startSbp) + // "foo/Outer" 1.823 + 3; // ".L" and "$" 1.824 + signatureBuffer[sbp++] = (byte)'$'; 1.825 + break; 1.826 + } else { 1.827 + sbp = startSbp; 1.828 + return outer; 1.829 + } 1.830 + case '.': 1.831 + signatureBuffer[sbp++] = (byte)'$'; 1.832 + break; 1.833 + default: 1.834 + throw new AssertionError(signature[sigp-1]); 1.835 + } 1.836 + continue; 1.837 + 1.838 + case '.': 1.839 + //we have seen an enclosing non-generic class 1.840 + if (outer != Type.noType) { 1.841 + t = enterClass(names.fromUtf(signatureBuffer, 1.842 + startSbp, 1.843 + sbp - startSbp)); 1.844 + outer = new ClassType(outer, List.<Type>nil(), t); 1.845 + } 1.846 + signatureBuffer[sbp++] = (byte)'$'; 1.847 + continue; 1.848 + case '/': 1.849 + signatureBuffer[sbp++] = (byte)'.'; 1.850 + continue; 1.851 + default: 1.852 + signatureBuffer[sbp++] = c; 1.853 + continue; 1.854 + } 1.855 + } 1.856 + } 1.857 + 1.858 + /** Convert (implicit) signature to list of types 1.859 + * until `terminator' is encountered. 1.860 + */ 1.861 + List<Type> sigToTypes(char terminator) { 1.862 + List<Type> head = List.of(null); 1.863 + List<Type> tail = head; 1.864 + while (signature[sigp] != terminator) 1.865 + tail = tail.setTail(List.of(sigToType())); 1.866 + sigp++; 1.867 + return head.tail; 1.868 + } 1.869 + 1.870 + /** Convert signature to type parameters, where signature is a byte 1.871 + * array segment. 1.872 + */ 1.873 + List<Type> sigToTypeParams(byte[] sig, int offset, int len) { 1.874 + signature = sig; 1.875 + sigp = offset; 1.876 + siglimit = offset + len; 1.877 + return sigToTypeParams(); 1.878 + } 1.879 + 1.880 + /** Convert signature to type parameters, where signature is implicit. 1.881 + */ 1.882 + List<Type> sigToTypeParams() { 1.883 + List<Type> tvars = List.nil(); 1.884 + if (signature[sigp] == '<') { 1.885 + sigp++; 1.886 + int start = sigp; 1.887 + sigEnterPhase = true; 1.888 + while (signature[sigp] != '>') 1.889 + tvars = tvars.prepend(sigToTypeParam()); 1.890 + sigEnterPhase = false; 1.891 + sigp = start; 1.892 + while (signature[sigp] != '>') 1.893 + sigToTypeParam(); 1.894 + sigp++; 1.895 + } 1.896 + return tvars.reverse(); 1.897 + } 1.898 + 1.899 + /** Convert (implicit) signature to type parameter. 1.900 + */ 1.901 + Type sigToTypeParam() { 1.902 + int start = sigp; 1.903 + while (signature[sigp] != ':') sigp++; 1.904 + Name name = names.fromUtf(signature, start, sigp - start); 1.905 + TypeVar tvar; 1.906 + if (sigEnterPhase) { 1.907 + tvar = new TypeVar(name, currentOwner, syms.botType); 1.908 + typevars.enter(tvar.tsym); 1.909 + } else { 1.910 + tvar = (TypeVar)findTypeVar(name); 1.911 + } 1.912 + List<Type> bounds = List.nil(); 1.913 + boolean allInterfaces = false; 1.914 + if (signature[sigp] == ':' && signature[sigp+1] == ':') { 1.915 + sigp++; 1.916 + allInterfaces = true; 1.917 + } 1.918 + while (signature[sigp] == ':') { 1.919 + sigp++; 1.920 + bounds = bounds.prepend(sigToType()); 1.921 + } 1.922 + if (!sigEnterPhase) { 1.923 + types.setBounds(tvar, bounds.reverse(), allInterfaces); 1.924 + } 1.925 + return tvar; 1.926 + } 1.927 + 1.928 + /** Find type variable with given name in `typevars' scope. 1.929 + */ 1.930 + Type findTypeVar(Name name) { 1.931 + Scope.Entry e = typevars.lookup(name); 1.932 + if (e.scope != null) { 1.933 + return e.sym.type; 1.934 + } else { 1.935 + if (readingClassAttr) { 1.936 + // While reading the class attribute, the supertypes 1.937 + // might refer to a type variable from an enclosing element 1.938 + // (method or class). 1.939 + // If the type variable is defined in the enclosing class, 1.940 + // we can actually find it in 1.941 + // currentOwner.owner.type.getTypeArguments() 1.942 + // However, until we have read the enclosing method attribute 1.943 + // we don't know for sure if this owner is correct. It could 1.944 + // be a method and there is no way to tell before reading the 1.945 + // enclosing method attribute. 1.946 + TypeVar t = new TypeVar(name, currentOwner, syms.botType); 1.947 + missingTypeVariables = missingTypeVariables.prepend(t); 1.948 + // System.err.println("Missing type var " + name); 1.949 + return t; 1.950 + } 1.951 + throw badClassFile("undecl.type.var", name); 1.952 + } 1.953 + } 1.954 + 1.955 +/************************************************************************ 1.956 + * Reading Attributes 1.957 + ***********************************************************************/ 1.958 + 1.959 + protected enum AttributeKind { CLASS, MEMBER }; 1.960 + protected abstract class AttributeReader { 1.961 + protected AttributeReader(Name name, ClassFile.Version version, Set<AttributeKind> kinds) { 1.962 + this.name = name; 1.963 + this.version = version; 1.964 + this.kinds = kinds; 1.965 + } 1.966 + 1.967 + protected boolean accepts(AttributeKind kind) { 1.968 + if (kinds.contains(kind)) { 1.969 + if (majorVersion > version.major || (majorVersion == version.major && minorVersion >= version.minor)) 1.970 + return true; 1.971 + 1.972 + if (lintClassfile && !warnedAttrs.contains(name)) { 1.973 + JavaFileObject prev = log.useSource(currentClassFile); 1.974 + try { 1.975 + log.warning(LintCategory.CLASSFILE, (DiagnosticPosition) null, "future.attr", 1.976 + name, version.major, version.minor, majorVersion, minorVersion); 1.977 + } finally { 1.978 + log.useSource(prev); 1.979 + } 1.980 + warnedAttrs.add(name); 1.981 + } 1.982 + } 1.983 + return false; 1.984 + } 1.985 + 1.986 + protected abstract void read(Symbol sym, int attrLen); 1.987 + 1.988 + protected final Name name; 1.989 + protected final ClassFile.Version version; 1.990 + protected final Set<AttributeKind> kinds; 1.991 + } 1.992 + 1.993 + protected Set<AttributeKind> CLASS_ATTRIBUTE = 1.994 + EnumSet.of(AttributeKind.CLASS); 1.995 + protected Set<AttributeKind> MEMBER_ATTRIBUTE = 1.996 + EnumSet.of(AttributeKind.MEMBER); 1.997 + protected Set<AttributeKind> CLASS_OR_MEMBER_ATTRIBUTE = 1.998 + EnumSet.of(AttributeKind.CLASS, AttributeKind.MEMBER); 1.999 + 1.1000 + protected Map<Name, AttributeReader> attributeReaders = new HashMap<Name, AttributeReader>(); 1.1001 + 1.1002 + private void initAttributeReaders() { 1.1003 + AttributeReader[] readers = { 1.1004 + // v45.3 attributes 1.1005 + 1.1006 + new AttributeReader(names.Code, V45_3, MEMBER_ATTRIBUTE) { 1.1007 + protected void read(Symbol sym, int attrLen) { 1.1008 + if (readAllOfClassFile || saveParameterNames) 1.1009 + ((MethodSymbol)sym).code = readCode(sym); 1.1010 + else 1.1011 + bp = bp + attrLen; 1.1012 + } 1.1013 + }, 1.1014 + 1.1015 + new AttributeReader(names.ConstantValue, V45_3, MEMBER_ATTRIBUTE) { 1.1016 + protected void read(Symbol sym, int attrLen) { 1.1017 + Object v = readPool(nextChar()); 1.1018 + // Ignore ConstantValue attribute if field not final. 1.1019 + if ((sym.flags() & FINAL) != 0) 1.1020 + ((VarSymbol) sym).setData(v); 1.1021 + } 1.1022 + }, 1.1023 + 1.1024 + new AttributeReader(names.Deprecated, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) { 1.1025 + protected void read(Symbol sym, int attrLen) { 1.1026 + sym.flags_field |= DEPRECATED; 1.1027 + } 1.1028 + }, 1.1029 + 1.1030 + new AttributeReader(names.Exceptions, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) { 1.1031 + protected void read(Symbol sym, int attrLen) { 1.1032 + int nexceptions = nextChar(); 1.1033 + List<Type> thrown = List.nil(); 1.1034 + for (int j = 0; j < nexceptions; j++) 1.1035 + thrown = thrown.prepend(readClassSymbol(nextChar()).type); 1.1036 + if (sym.type.getThrownTypes().isEmpty()) 1.1037 + sym.type.asMethodType().thrown = thrown.reverse(); 1.1038 + } 1.1039 + }, 1.1040 + 1.1041 + new AttributeReader(names.InnerClasses, V45_3, CLASS_ATTRIBUTE) { 1.1042 + protected void read(Symbol sym, int attrLen) { 1.1043 + ClassSymbol c = (ClassSymbol) sym; 1.1044 + readInnerClasses(c); 1.1045 + } 1.1046 + }, 1.1047 + 1.1048 + new AttributeReader(names.LocalVariableTable, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) { 1.1049 + protected void read(Symbol sym, int attrLen) { 1.1050 + int newbp = bp + attrLen; 1.1051 + if (saveParameterNames && !sawMethodParameters) { 1.1052 + // Pick up parameter names from the variable table. 1.1053 + // Parameter names are not explicitly identified as such, 1.1054 + // but all parameter name entries in the LocalVariableTable 1.1055 + // have a start_pc of 0. Therefore, we record the name 1.1056 + // indicies of all slots with a start_pc of zero in the 1.1057 + // parameterNameIndicies array. 1.1058 + // Note that this implicitly honors the JVMS spec that 1.1059 + // there may be more than one LocalVariableTable, and that 1.1060 + // there is no specified ordering for the entries. 1.1061 + int numEntries = nextChar(); 1.1062 + for (int i = 0; i < numEntries; i++) { 1.1063 + int start_pc = nextChar(); 1.1064 + int length = nextChar(); 1.1065 + int nameIndex = nextChar(); 1.1066 + int sigIndex = nextChar(); 1.1067 + int register = nextChar(); 1.1068 + if (start_pc == 0) { 1.1069 + // ensure array large enough 1.1070 + if (register >= parameterNameIndices.length) { 1.1071 + int newSize = Math.max(register, parameterNameIndices.length + 8); 1.1072 + parameterNameIndices = 1.1073 + Arrays.copyOf(parameterNameIndices, newSize); 1.1074 + } 1.1075 + parameterNameIndices[register] = nameIndex; 1.1076 + haveParameterNameIndices = true; 1.1077 + } 1.1078 + } 1.1079 + } 1.1080 + bp = newbp; 1.1081 + } 1.1082 + }, 1.1083 + 1.1084 + new AttributeReader(names.MethodParameters, V52, MEMBER_ATTRIBUTE) { 1.1085 + protected void read(Symbol sym, int attrlen) { 1.1086 + int newbp = bp + attrlen; 1.1087 + if (saveParameterNames) { 1.1088 + sawMethodParameters = true; 1.1089 + int numEntries = nextByte(); 1.1090 + parameterNameIndices = new int[numEntries]; 1.1091 + haveParameterNameIndices = true; 1.1092 + for (int i = 0; i < numEntries; i++) { 1.1093 + int nameIndex = nextChar(); 1.1094 + int flags = nextChar(); 1.1095 + parameterNameIndices[i] = nameIndex; 1.1096 + } 1.1097 + } 1.1098 + bp = newbp; 1.1099 + } 1.1100 + }, 1.1101 + 1.1102 + 1.1103 + new AttributeReader(names.SourceFile, V45_3, CLASS_ATTRIBUTE) { 1.1104 + protected void read(Symbol sym, int attrLen) { 1.1105 + ClassSymbol c = (ClassSymbol) sym; 1.1106 + Name n = readName(nextChar()); 1.1107 + c.sourcefile = new SourceFileObject(n, c.flatname); 1.1108 + // If the class is a toplevel class, originating from a Java source file, 1.1109 + // but the class name does not match the file name, then it is 1.1110 + // an auxiliary class. 1.1111 + String sn = n.toString(); 1.1112 + if (c.owner.kind == Kinds.PCK && 1.1113 + sn.endsWith(".java") && 1.1114 + !sn.equals(c.name.toString()+".java")) { 1.1115 + c.flags_field |= AUXILIARY; 1.1116 + } 1.1117 + } 1.1118 + }, 1.1119 + 1.1120 + new AttributeReader(names.Synthetic, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) { 1.1121 + protected void read(Symbol sym, int attrLen) { 1.1122 + // bridge methods are visible when generics not enabled 1.1123 + if (allowGenerics || (sym.flags_field & BRIDGE) == 0) 1.1124 + sym.flags_field |= SYNTHETIC; 1.1125 + } 1.1126 + }, 1.1127 + 1.1128 + // standard v49 attributes 1.1129 + 1.1130 + new AttributeReader(names.EnclosingMethod, V49, CLASS_ATTRIBUTE) { 1.1131 + protected void read(Symbol sym, int attrLen) { 1.1132 + int newbp = bp + attrLen; 1.1133 + readEnclosingMethodAttr(sym); 1.1134 + bp = newbp; 1.1135 + } 1.1136 + }, 1.1137 + 1.1138 + new AttributeReader(names.Signature, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1.1139 + @Override 1.1140 + protected boolean accepts(AttributeKind kind) { 1.1141 + return super.accepts(kind) && allowGenerics; 1.1142 + } 1.1143 + 1.1144 + protected void read(Symbol sym, int attrLen) { 1.1145 + if (sym.kind == TYP) { 1.1146 + ClassSymbol c = (ClassSymbol) sym; 1.1147 + readingClassAttr = true; 1.1148 + try { 1.1149 + ClassType ct1 = (ClassType)c.type; 1.1150 + Assert.check(c == currentOwner); 1.1151 + ct1.typarams_field = readTypeParams(nextChar()); 1.1152 + ct1.supertype_field = sigToType(); 1.1153 + ListBuffer<Type> is = new ListBuffer<Type>(); 1.1154 + while (sigp != siglimit) is.append(sigToType()); 1.1155 + ct1.interfaces_field = is.toList(); 1.1156 + } finally { 1.1157 + readingClassAttr = false; 1.1158 + } 1.1159 + } else { 1.1160 + List<Type> thrown = sym.type.getThrownTypes(); 1.1161 + sym.type = readType(nextChar()); 1.1162 + //- System.err.println(" # " + sym.type); 1.1163 + if (sym.kind == MTH && sym.type.getThrownTypes().isEmpty()) 1.1164 + sym.type.asMethodType().thrown = thrown; 1.1165 + 1.1166 + } 1.1167 + } 1.1168 + }, 1.1169 + 1.1170 + // v49 annotation attributes 1.1171 + 1.1172 + new AttributeReader(names.AnnotationDefault, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1.1173 + protected void read(Symbol sym, int attrLen) { 1.1174 + attachAnnotationDefault(sym); 1.1175 + } 1.1176 + }, 1.1177 + 1.1178 + new AttributeReader(names.RuntimeInvisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1.1179 + protected void read(Symbol sym, int attrLen) { 1.1180 + attachAnnotations(sym); 1.1181 + } 1.1182 + }, 1.1183 + 1.1184 + new AttributeReader(names.RuntimeInvisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1.1185 + protected void read(Symbol sym, int attrLen) { 1.1186 + attachParameterAnnotations(sym); 1.1187 + } 1.1188 + }, 1.1189 + 1.1190 + new AttributeReader(names.RuntimeVisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1.1191 + protected void read(Symbol sym, int attrLen) { 1.1192 + attachAnnotations(sym); 1.1193 + } 1.1194 + }, 1.1195 + 1.1196 + new AttributeReader(names.RuntimeVisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1.1197 + protected void read(Symbol sym, int attrLen) { 1.1198 + attachParameterAnnotations(sym); 1.1199 + } 1.1200 + }, 1.1201 + 1.1202 + // additional "legacy" v49 attributes, superceded by flags 1.1203 + 1.1204 + new AttributeReader(names.Annotation, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1.1205 + protected void read(Symbol sym, int attrLen) { 1.1206 + if (allowAnnotations) 1.1207 + sym.flags_field |= ANNOTATION; 1.1208 + } 1.1209 + }, 1.1210 + 1.1211 + new AttributeReader(names.Bridge, V49, MEMBER_ATTRIBUTE) { 1.1212 + protected void read(Symbol sym, int attrLen) { 1.1213 + sym.flags_field |= BRIDGE; 1.1214 + if (!allowGenerics) 1.1215 + sym.flags_field &= ~SYNTHETIC; 1.1216 + } 1.1217 + }, 1.1218 + 1.1219 + new AttributeReader(names.Enum, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1.1220 + protected void read(Symbol sym, int attrLen) { 1.1221 + sym.flags_field |= ENUM; 1.1222 + } 1.1223 + }, 1.1224 + 1.1225 + new AttributeReader(names.Varargs, V49, CLASS_OR_MEMBER_ATTRIBUTE) { 1.1226 + protected void read(Symbol sym, int attrLen) { 1.1227 + if (allowVarargs) 1.1228 + sym.flags_field |= VARARGS; 1.1229 + } 1.1230 + }, 1.1231 + 1.1232 + new AttributeReader(names.RuntimeVisibleTypeAnnotations, V52, CLASS_OR_MEMBER_ATTRIBUTE) { 1.1233 + protected void read(Symbol sym, int attrLen) { 1.1234 + attachTypeAnnotations(sym); 1.1235 + } 1.1236 + }, 1.1237 + 1.1238 + new AttributeReader(names.RuntimeInvisibleTypeAnnotations, V52, CLASS_OR_MEMBER_ATTRIBUTE) { 1.1239 + protected void read(Symbol sym, int attrLen) { 1.1240 + attachTypeAnnotations(sym); 1.1241 + } 1.1242 + }, 1.1243 + 1.1244 + 1.1245 + // The following attributes for a Code attribute are not currently handled 1.1246 + // StackMapTable 1.1247 + // SourceDebugExtension 1.1248 + // LineNumberTable 1.1249 + // LocalVariableTypeTable 1.1250 + }; 1.1251 + 1.1252 + for (AttributeReader r: readers) 1.1253 + attributeReaders.put(r.name, r); 1.1254 + } 1.1255 + 1.1256 + /** Report unrecognized attribute. 1.1257 + */ 1.1258 + void unrecognized(Name attrName) { 1.1259 + if (checkClassFile) 1.1260 + printCCF("ccf.unrecognized.attribute", attrName); 1.1261 + } 1.1262 + 1.1263 + 1.1264 + 1.1265 + protected void readEnclosingMethodAttr(Symbol sym) { 1.1266 + // sym is a nested class with an "Enclosing Method" attribute 1.1267 + // remove sym from it's current owners scope and place it in 1.1268 + // the scope specified by the attribute 1.1269 + sym.owner.members().remove(sym); 1.1270 + ClassSymbol self = (ClassSymbol)sym; 1.1271 + ClassSymbol c = readClassSymbol(nextChar()); 1.1272 + NameAndType nt = readNameAndType(nextChar()); 1.1273 + 1.1274 + if (c.members_field == null) 1.1275 + throw badClassFile("bad.enclosing.class", self, c); 1.1276 + 1.1277 + MethodSymbol m = findMethod(nt, c.members_field, self.flags()); 1.1278 + if (nt != null && m == null) 1.1279 + throw badClassFile("bad.enclosing.method", self); 1.1280 + 1.1281 + self.name = simpleBinaryName(self.flatname, c.flatname) ; 1.1282 + self.owner = m != null ? m : c; 1.1283 + if (self.name.isEmpty()) 1.1284 + self.fullname = names.empty; 1.1285 + else 1.1286 + self.fullname = ClassSymbol.formFullName(self.name, self.owner); 1.1287 + 1.1288 + if (m != null) { 1.1289 + ((ClassType)sym.type).setEnclosingType(m.type); 1.1290 + } else if ((self.flags_field & STATIC) == 0) { 1.1291 + ((ClassType)sym.type).setEnclosingType(c.type); 1.1292 + } else { 1.1293 + ((ClassType)sym.type).setEnclosingType(Type.noType); 1.1294 + } 1.1295 + enterTypevars(self); 1.1296 + if (!missingTypeVariables.isEmpty()) { 1.1297 + ListBuffer<Type> typeVars = new ListBuffer<Type>(); 1.1298 + for (Type typevar : missingTypeVariables) { 1.1299 + typeVars.append(findTypeVar(typevar.tsym.name)); 1.1300 + } 1.1301 + foundTypeVariables = typeVars.toList(); 1.1302 + } else { 1.1303 + foundTypeVariables = List.nil(); 1.1304 + } 1.1305 + } 1.1306 + 1.1307 + // See java.lang.Class 1.1308 + private Name simpleBinaryName(Name self, Name enclosing) { 1.1309 + String simpleBinaryName = self.toString().substring(enclosing.toString().length()); 1.1310 + if (simpleBinaryName.length() < 1 || simpleBinaryName.charAt(0) != '$') 1.1311 + throw badClassFile("bad.enclosing.method", self); 1.1312 + int index = 1; 1.1313 + while (index < simpleBinaryName.length() && 1.1314 + isAsciiDigit(simpleBinaryName.charAt(index))) 1.1315 + index++; 1.1316 + return names.fromString(simpleBinaryName.substring(index)); 1.1317 + } 1.1318 + 1.1319 + private MethodSymbol findMethod(NameAndType nt, Scope scope, long flags) { 1.1320 + if (nt == null) 1.1321 + return null; 1.1322 + 1.1323 + MethodType type = nt.uniqueType.type.asMethodType(); 1.1324 + 1.1325 + for (Scope.Entry e = scope.lookup(nt.name); e.scope != null; e = e.next()) 1.1326 + if (e.sym.kind == MTH && isSameBinaryType(e.sym.type.asMethodType(), type)) 1.1327 + return (MethodSymbol)e.sym; 1.1328 + 1.1329 + if (nt.name != names.init) 1.1330 + // not a constructor 1.1331 + return null; 1.1332 + if ((flags & INTERFACE) != 0) 1.1333 + // no enclosing instance 1.1334 + return null; 1.1335 + if (nt.uniqueType.type.getParameterTypes().isEmpty()) 1.1336 + // no parameters 1.1337 + return null; 1.1338 + 1.1339 + // A constructor of an inner class. 1.1340 + // Remove the first argument (the enclosing instance) 1.1341 + nt.setType(new MethodType(nt.uniqueType.type.getParameterTypes().tail, 1.1342 + nt.uniqueType.type.getReturnType(), 1.1343 + nt.uniqueType.type.getThrownTypes(), 1.1344 + syms.methodClass)); 1.1345 + // Try searching again 1.1346 + return findMethod(nt, scope, flags); 1.1347 + } 1.1348 + 1.1349 + /** Similar to Types.isSameType but avoids completion */ 1.1350 + private boolean isSameBinaryType(MethodType mt1, MethodType mt2) { 1.1351 + List<Type> types1 = types.erasure(mt1.getParameterTypes()) 1.1352 + .prepend(types.erasure(mt1.getReturnType())); 1.1353 + List<Type> types2 = mt2.getParameterTypes().prepend(mt2.getReturnType()); 1.1354 + while (!types1.isEmpty() && !types2.isEmpty()) { 1.1355 + if (types1.head.tsym != types2.head.tsym) 1.1356 + return false; 1.1357 + types1 = types1.tail; 1.1358 + types2 = types2.tail; 1.1359 + } 1.1360 + return types1.isEmpty() && types2.isEmpty(); 1.1361 + } 1.1362 + 1.1363 + /** 1.1364 + * Character.isDigit answers <tt>true</tt> to some non-ascii 1.1365 + * digits. This one does not. <b>copied from java.lang.Class</b> 1.1366 + */ 1.1367 + private static boolean isAsciiDigit(char c) { 1.1368 + return '0' <= c && c <= '9'; 1.1369 + } 1.1370 + 1.1371 + /** Read member attributes. 1.1372 + */ 1.1373 + void readMemberAttrs(Symbol sym) { 1.1374 + readAttrs(sym, AttributeKind.MEMBER); 1.1375 + } 1.1376 + 1.1377 + void readAttrs(Symbol sym, AttributeKind kind) { 1.1378 + char ac = nextChar(); 1.1379 + for (int i = 0; i < ac; i++) { 1.1380 + Name attrName = readName(nextChar()); 1.1381 + int attrLen = nextInt(); 1.1382 + AttributeReader r = attributeReaders.get(attrName); 1.1383 + if (r != null && r.accepts(kind)) 1.1384 + r.read(sym, attrLen); 1.1385 + else { 1.1386 + unrecognized(attrName); 1.1387 + bp = bp + attrLen; 1.1388 + } 1.1389 + } 1.1390 + } 1.1391 + 1.1392 + private boolean readingClassAttr = false; 1.1393 + private List<Type> missingTypeVariables = List.nil(); 1.1394 + private List<Type> foundTypeVariables = List.nil(); 1.1395 + 1.1396 + /** Read class attributes. 1.1397 + */ 1.1398 + void readClassAttrs(ClassSymbol c) { 1.1399 + readAttrs(c, AttributeKind.CLASS); 1.1400 + } 1.1401 + 1.1402 + /** Read code block. 1.1403 + */ 1.1404 + Code readCode(Symbol owner) { 1.1405 + nextChar(); // max_stack 1.1406 + nextChar(); // max_locals 1.1407 + final int code_length = nextInt(); 1.1408 + bp += code_length; 1.1409 + final char exception_table_length = nextChar(); 1.1410 + bp += exception_table_length * 8; 1.1411 + readMemberAttrs(owner); 1.1412 + return null; 1.1413 + } 1.1414 + 1.1415 +/************************************************************************ 1.1416 + * Reading Java-language annotations 1.1417 + ***********************************************************************/ 1.1418 + 1.1419 + /** Attach annotations. 1.1420 + */ 1.1421 + void attachAnnotations(final Symbol sym) { 1.1422 + int numAttributes = nextChar(); 1.1423 + if (numAttributes != 0) { 1.1424 + ListBuffer<CompoundAnnotationProxy> proxies = 1.1425 + new ListBuffer<CompoundAnnotationProxy>(); 1.1426 + for (int i = 0; i<numAttributes; i++) { 1.1427 + CompoundAnnotationProxy proxy = readCompoundAnnotation(); 1.1428 + if (proxy.type.tsym == syms.proprietaryType.tsym) 1.1429 + sym.flags_field |= PROPRIETARY; 1.1430 + else if (proxy.type.tsym == syms.profileType.tsym) { 1.1431 + if (profile != Profile.DEFAULT) { 1.1432 + for (Pair<Name,Attribute> v: proxy.values) { 1.1433 + if (v.fst == names.value && v.snd instanceof Attribute.Constant) { 1.1434 + Attribute.Constant c = (Attribute.Constant) v.snd; 1.1435 + if (c.type == syms.intType && ((Integer) c.value) > profile.value) { 1.1436 + sym.flags_field |= NOT_IN_PROFILE; 1.1437 + } 1.1438 + } 1.1439 + } 1.1440 + } 1.1441 + } else 1.1442 + proxies.append(proxy); 1.1443 + } 1.1444 + annotate.normal(new AnnotationCompleter(sym, proxies.toList())); 1.1445 + } 1.1446 + } 1.1447 + 1.1448 + /** Attach parameter annotations. 1.1449 + */ 1.1450 + void attachParameterAnnotations(final Symbol method) { 1.1451 + final MethodSymbol meth = (MethodSymbol)method; 1.1452 + int numParameters = buf[bp++] & 0xFF; 1.1453 + List<VarSymbol> parameters = meth.params(); 1.1454 + int pnum = 0; 1.1455 + while (parameters.tail != null) { 1.1456 + attachAnnotations(parameters.head); 1.1457 + parameters = parameters.tail; 1.1458 + pnum++; 1.1459 + } 1.1460 + if (pnum != numParameters) { 1.1461 + throw badClassFile("bad.runtime.invisible.param.annotations", meth); 1.1462 + } 1.1463 + } 1.1464 + 1.1465 + void attachTypeAnnotations(final Symbol sym) { 1.1466 + int numAttributes = nextChar(); 1.1467 + if (numAttributes != 0) { 1.1468 + ListBuffer<TypeAnnotationProxy> proxies = new ListBuffer<>(); 1.1469 + for (int i = 0; i < numAttributes; i++) 1.1470 + proxies.append(readTypeAnnotation()); 1.1471 + annotate.normal(new TypeAnnotationCompleter(sym, proxies.toList())); 1.1472 + } 1.1473 + } 1.1474 + 1.1475 + /** Attach the default value for an annotation element. 1.1476 + */ 1.1477 + void attachAnnotationDefault(final Symbol sym) { 1.1478 + final MethodSymbol meth = (MethodSymbol)sym; // only on methods 1.1479 + final Attribute value = readAttributeValue(); 1.1480 + 1.1481 + // The default value is set later during annotation. It might 1.1482 + // be the case that the Symbol sym is annotated _after_ the 1.1483 + // repeating instances that depend on this default value, 1.1484 + // because of this we set an interim value that tells us this 1.1485 + // element (most likely) has a default. 1.1486 + // 1.1487 + // Set interim value for now, reset just before we do this 1.1488 + // properly at annotate time. 1.1489 + meth.defaultValue = value; 1.1490 + annotate.normal(new AnnotationDefaultCompleter(meth, value)); 1.1491 + } 1.1492 + 1.1493 + Type readTypeOrClassSymbol(int i) { 1.1494 + // support preliminary jsr175-format class files 1.1495 + if (buf[poolIdx[i]] == CONSTANT_Class) 1.1496 + return readClassSymbol(i).type; 1.1497 + return readType(i); 1.1498 + } 1.1499 + Type readEnumType(int i) { 1.1500 + // support preliminary jsr175-format class files 1.1501 + int index = poolIdx[i]; 1.1502 + int length = getChar(index + 1); 1.1503 + if (buf[index + length + 2] != ';') 1.1504 + return enterClass(readName(i)).type; 1.1505 + return readType(i); 1.1506 + } 1.1507 + 1.1508 + CompoundAnnotationProxy readCompoundAnnotation() { 1.1509 + Type t = readTypeOrClassSymbol(nextChar()); 1.1510 + int numFields = nextChar(); 1.1511 + ListBuffer<Pair<Name,Attribute>> pairs = 1.1512 + new ListBuffer<Pair<Name,Attribute>>(); 1.1513 + for (int i=0; i<numFields; i++) { 1.1514 + Name name = readName(nextChar()); 1.1515 + Attribute value = readAttributeValue(); 1.1516 + pairs.append(new Pair<Name,Attribute>(name, value)); 1.1517 + } 1.1518 + return new CompoundAnnotationProxy(t, pairs.toList()); 1.1519 + } 1.1520 + 1.1521 + TypeAnnotationProxy readTypeAnnotation() { 1.1522 + TypeAnnotationPosition position = readPosition(); 1.1523 + CompoundAnnotationProxy proxy = readCompoundAnnotation(); 1.1524 + 1.1525 + return new TypeAnnotationProxy(proxy, position); 1.1526 + } 1.1527 + 1.1528 + TypeAnnotationPosition readPosition() { 1.1529 + int tag = nextByte(); // TargetType tag is a byte 1.1530 + 1.1531 + if (!TargetType.isValidTargetTypeValue(tag)) 1.1532 + throw this.badClassFile("bad.type.annotation.value", String.format("0x%02X", tag)); 1.1533 + 1.1534 + TypeAnnotationPosition position = new TypeAnnotationPosition(); 1.1535 + TargetType type = TargetType.fromTargetTypeValue(tag); 1.1536 + 1.1537 + position.type = type; 1.1538 + 1.1539 + switch (type) { 1.1540 + // instanceof 1.1541 + case INSTANCEOF: 1.1542 + // new expression 1.1543 + case NEW: 1.1544 + // constructor/method reference receiver 1.1545 + case CONSTRUCTOR_REFERENCE: 1.1546 + case METHOD_REFERENCE: 1.1547 + position.offset = nextChar(); 1.1548 + break; 1.1549 + // local variable 1.1550 + case LOCAL_VARIABLE: 1.1551 + // resource variable 1.1552 + case RESOURCE_VARIABLE: 1.1553 + int table_length = nextChar(); 1.1554 + position.lvarOffset = new int[table_length]; 1.1555 + position.lvarLength = new int[table_length]; 1.1556 + position.lvarIndex = new int[table_length]; 1.1557 + 1.1558 + for (int i = 0; i < table_length; ++i) { 1.1559 + position.lvarOffset[i] = nextChar(); 1.1560 + position.lvarLength[i] = nextChar(); 1.1561 + position.lvarIndex[i] = nextChar(); 1.1562 + } 1.1563 + break; 1.1564 + // exception parameter 1.1565 + case EXCEPTION_PARAMETER: 1.1566 + position.exception_index = nextChar(); 1.1567 + break; 1.1568 + // method receiver 1.1569 + case METHOD_RECEIVER: 1.1570 + // Do nothing 1.1571 + break; 1.1572 + // type parameter 1.1573 + case CLASS_TYPE_PARAMETER: 1.1574 + case METHOD_TYPE_PARAMETER: 1.1575 + position.parameter_index = nextByte(); 1.1576 + break; 1.1577 + // type parameter bound 1.1578 + case CLASS_TYPE_PARAMETER_BOUND: 1.1579 + case METHOD_TYPE_PARAMETER_BOUND: 1.1580 + position.parameter_index = nextByte(); 1.1581 + position.bound_index = nextByte(); 1.1582 + break; 1.1583 + // class extends or implements clause 1.1584 + case CLASS_EXTENDS: 1.1585 + position.type_index = nextChar(); 1.1586 + break; 1.1587 + // throws 1.1588 + case THROWS: 1.1589 + position.type_index = nextChar(); 1.1590 + break; 1.1591 + // method parameter 1.1592 + case METHOD_FORMAL_PARAMETER: 1.1593 + position.parameter_index = nextByte(); 1.1594 + break; 1.1595 + // type cast 1.1596 + case CAST: 1.1597 + // method/constructor/reference type argument 1.1598 + case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: 1.1599 + case METHOD_INVOCATION_TYPE_ARGUMENT: 1.1600 + case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: 1.1601 + case METHOD_REFERENCE_TYPE_ARGUMENT: 1.1602 + position.offset = nextChar(); 1.1603 + position.type_index = nextByte(); 1.1604 + break; 1.1605 + // We don't need to worry about these 1.1606 + case METHOD_RETURN: 1.1607 + case FIELD: 1.1608 + break; 1.1609 + case UNKNOWN: 1.1610 + throw new AssertionError("jvm.ClassReader: UNKNOWN target type should never occur!"); 1.1611 + default: 1.1612 + throw new AssertionError("jvm.ClassReader: Unknown target type for position: " + position); 1.1613 + } 1.1614 + 1.1615 + { // See whether there is location info and read it 1.1616 + int len = nextByte(); 1.1617 + ListBuffer<Integer> loc = new ListBuffer<>(); 1.1618 + for (int i = 0; i < len * TypeAnnotationPosition.TypePathEntry.bytesPerEntry; ++i) 1.1619 + loc = loc.append(nextByte()); 1.1620 + position.location = TypeAnnotationPosition.getTypePathFromBinary(loc.toList()); 1.1621 + } 1.1622 + 1.1623 + return position; 1.1624 + } 1.1625 + 1.1626 + Attribute readAttributeValue() { 1.1627 + char c = (char) buf[bp++]; 1.1628 + switch (c) { 1.1629 + case 'B': 1.1630 + return new Attribute.Constant(syms.byteType, readPool(nextChar())); 1.1631 + case 'C': 1.1632 + return new Attribute.Constant(syms.charType, readPool(nextChar())); 1.1633 + case 'D': 1.1634 + return new Attribute.Constant(syms.doubleType, readPool(nextChar())); 1.1635 + case 'F': 1.1636 + return new Attribute.Constant(syms.floatType, readPool(nextChar())); 1.1637 + case 'I': 1.1638 + return new Attribute.Constant(syms.intType, readPool(nextChar())); 1.1639 + case 'J': 1.1640 + return new Attribute.Constant(syms.longType, readPool(nextChar())); 1.1641 + case 'S': 1.1642 + return new Attribute.Constant(syms.shortType, readPool(nextChar())); 1.1643 + case 'Z': 1.1644 + return new Attribute.Constant(syms.booleanType, readPool(nextChar())); 1.1645 + case 's': 1.1646 + return new Attribute.Constant(syms.stringType, readPool(nextChar()).toString()); 1.1647 + case 'e': 1.1648 + return new EnumAttributeProxy(readEnumType(nextChar()), readName(nextChar())); 1.1649 + case 'c': 1.1650 + return new Attribute.Class(types, readTypeOrClassSymbol(nextChar())); 1.1651 + case '[': { 1.1652 + int n = nextChar(); 1.1653 + ListBuffer<Attribute> l = new ListBuffer<Attribute>(); 1.1654 + for (int i=0; i<n; i++) 1.1655 + l.append(readAttributeValue()); 1.1656 + return new ArrayAttributeProxy(l.toList()); 1.1657 + } 1.1658 + case '@': 1.1659 + return readCompoundAnnotation(); 1.1660 + default: 1.1661 + throw new AssertionError("unknown annotation tag '" + c + "'"); 1.1662 + } 1.1663 + } 1.1664 + 1.1665 + interface ProxyVisitor extends Attribute.Visitor { 1.1666 + void visitEnumAttributeProxy(EnumAttributeProxy proxy); 1.1667 + void visitArrayAttributeProxy(ArrayAttributeProxy proxy); 1.1668 + void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy); 1.1669 + } 1.1670 + 1.1671 + static class EnumAttributeProxy extends Attribute { 1.1672 + Type enumType; 1.1673 + Name enumerator; 1.1674 + public EnumAttributeProxy(Type enumType, Name enumerator) { 1.1675 + super(null); 1.1676 + this.enumType = enumType; 1.1677 + this.enumerator = enumerator; 1.1678 + } 1.1679 + public void accept(Visitor v) { ((ProxyVisitor)v).visitEnumAttributeProxy(this); } 1.1680 + @Override 1.1681 + public String toString() { 1.1682 + return "/*proxy enum*/" + enumType + "." + enumerator; 1.1683 + } 1.1684 + } 1.1685 + 1.1686 + static class ArrayAttributeProxy extends Attribute { 1.1687 + List<Attribute> values; 1.1688 + ArrayAttributeProxy(List<Attribute> values) { 1.1689 + super(null); 1.1690 + this.values = values; 1.1691 + } 1.1692 + public void accept(Visitor v) { ((ProxyVisitor)v).visitArrayAttributeProxy(this); } 1.1693 + @Override 1.1694 + public String toString() { 1.1695 + return "{" + values + "}"; 1.1696 + } 1.1697 + } 1.1698 + 1.1699 + /** A temporary proxy representing a compound attribute. 1.1700 + */ 1.1701 + static class CompoundAnnotationProxy extends Attribute { 1.1702 + final List<Pair<Name,Attribute>> values; 1.1703 + public CompoundAnnotationProxy(Type type, 1.1704 + List<Pair<Name,Attribute>> values) { 1.1705 + super(type); 1.1706 + this.values = values; 1.1707 + } 1.1708 + public void accept(Visitor v) { ((ProxyVisitor)v).visitCompoundAnnotationProxy(this); } 1.1709 + @Override 1.1710 + public String toString() { 1.1711 + StringBuilder buf = new StringBuilder(); 1.1712 + buf.append("@"); 1.1713 + buf.append(type.tsym.getQualifiedName()); 1.1714 + buf.append("/*proxy*/{"); 1.1715 + boolean first = true; 1.1716 + for (List<Pair<Name,Attribute>> v = values; 1.1717 + v.nonEmpty(); v = v.tail) { 1.1718 + Pair<Name,Attribute> value = v.head; 1.1719 + if (!first) buf.append(","); 1.1720 + first = false; 1.1721 + buf.append(value.fst); 1.1722 + buf.append("="); 1.1723 + buf.append(value.snd); 1.1724 + } 1.1725 + buf.append("}"); 1.1726 + return buf.toString(); 1.1727 + } 1.1728 + } 1.1729 + 1.1730 + /** A temporary proxy representing a type annotation. 1.1731 + */ 1.1732 + static class TypeAnnotationProxy { 1.1733 + final CompoundAnnotationProxy compound; 1.1734 + final TypeAnnotationPosition position; 1.1735 + public TypeAnnotationProxy(CompoundAnnotationProxy compound, 1.1736 + TypeAnnotationPosition position) { 1.1737 + this.compound = compound; 1.1738 + this.position = position; 1.1739 + } 1.1740 + } 1.1741 + 1.1742 + class AnnotationDeproxy implements ProxyVisitor { 1.1743 + private ClassSymbol requestingOwner = currentOwner.kind == MTH 1.1744 + ? currentOwner.enclClass() : (ClassSymbol)currentOwner; 1.1745 + 1.1746 + List<Attribute.Compound> deproxyCompoundList(List<CompoundAnnotationProxy> pl) { 1.1747 + // also must fill in types!!!! 1.1748 + ListBuffer<Attribute.Compound> buf = 1.1749 + new ListBuffer<Attribute.Compound>(); 1.1750 + for (List<CompoundAnnotationProxy> l = pl; l.nonEmpty(); l=l.tail) { 1.1751 + buf.append(deproxyCompound(l.head)); 1.1752 + } 1.1753 + return buf.toList(); 1.1754 + } 1.1755 + 1.1756 + Attribute.Compound deproxyCompound(CompoundAnnotationProxy a) { 1.1757 + ListBuffer<Pair<Symbol.MethodSymbol,Attribute>> buf = 1.1758 + new ListBuffer<Pair<Symbol.MethodSymbol,Attribute>>(); 1.1759 + for (List<Pair<Name,Attribute>> l = a.values; 1.1760 + l.nonEmpty(); 1.1761 + l = l.tail) { 1.1762 + MethodSymbol meth = findAccessMethod(a.type, l.head.fst); 1.1763 + buf.append(new Pair<Symbol.MethodSymbol,Attribute> 1.1764 + (meth, deproxy(meth.type.getReturnType(), l.head.snd))); 1.1765 + } 1.1766 + return new Attribute.Compound(a.type, buf.toList()); 1.1767 + } 1.1768 + 1.1769 + MethodSymbol findAccessMethod(Type container, Name name) { 1.1770 + CompletionFailure failure = null; 1.1771 + try { 1.1772 + for (Scope.Entry e = container.tsym.members().lookup(name); 1.1773 + e.scope != null; 1.1774 + e = e.next()) { 1.1775 + Symbol sym = e.sym; 1.1776 + if (sym.kind == MTH && sym.type.getParameterTypes().length() == 0) 1.1777 + return (MethodSymbol) sym; 1.1778 + } 1.1779 + } catch (CompletionFailure ex) { 1.1780 + failure = ex; 1.1781 + } 1.1782 + // The method wasn't found: emit a warning and recover 1.1783 + JavaFileObject prevSource = log.useSource(requestingOwner.classfile); 1.1784 + try { 1.1785 + if (failure == null) { 1.1786 + log.warning("annotation.method.not.found", 1.1787 + container, 1.1788 + name); 1.1789 + } else { 1.1790 + log.warning("annotation.method.not.found.reason", 1.1791 + container, 1.1792 + name, 1.1793 + failure.getDetailValue());//diagnostic, if present 1.1794 + } 1.1795 + } finally { 1.1796 + log.useSource(prevSource); 1.1797 + } 1.1798 + // Construct a new method type and symbol. Use bottom 1.1799 + // type (typeof null) as return type because this type is 1.1800 + // a subtype of all reference types and can be converted 1.1801 + // to primitive types by unboxing. 1.1802 + MethodType mt = new MethodType(List.<Type>nil(), 1.1803 + syms.botType, 1.1804 + List.<Type>nil(), 1.1805 + syms.methodClass); 1.1806 + return new MethodSymbol(PUBLIC | ABSTRACT, name, mt, container.tsym); 1.1807 + } 1.1808 + 1.1809 + Attribute result; 1.1810 + Type type; 1.1811 + Attribute deproxy(Type t, Attribute a) { 1.1812 + Type oldType = type; 1.1813 + try { 1.1814 + type = t; 1.1815 + a.accept(this); 1.1816 + return result; 1.1817 + } finally { 1.1818 + type = oldType; 1.1819 + } 1.1820 + } 1.1821 + 1.1822 + // implement Attribute.Visitor below 1.1823 + 1.1824 + public void visitConstant(Attribute.Constant value) { 1.1825 + // assert value.type == type; 1.1826 + result = value; 1.1827 + } 1.1828 + 1.1829 + public void visitClass(Attribute.Class clazz) { 1.1830 + result = clazz; 1.1831 + } 1.1832 + 1.1833 + public void visitEnum(Attribute.Enum e) { 1.1834 + throw new AssertionError(); // shouldn't happen 1.1835 + } 1.1836 + 1.1837 + public void visitCompound(Attribute.Compound compound) { 1.1838 + throw new AssertionError(); // shouldn't happen 1.1839 + } 1.1840 + 1.1841 + public void visitArray(Attribute.Array array) { 1.1842 + throw new AssertionError(); // shouldn't happen 1.1843 + } 1.1844 + 1.1845 + public void visitError(Attribute.Error e) { 1.1846 + throw new AssertionError(); // shouldn't happen 1.1847 + } 1.1848 + 1.1849 + public void visitEnumAttributeProxy(EnumAttributeProxy proxy) { 1.1850 + // type.tsym.flatName() should == proxy.enumFlatName 1.1851 + TypeSymbol enumTypeSym = proxy.enumType.tsym; 1.1852 + VarSymbol enumerator = null; 1.1853 + CompletionFailure failure = null; 1.1854 + try { 1.1855 + for (Scope.Entry e = enumTypeSym.members().lookup(proxy.enumerator); 1.1856 + e.scope != null; 1.1857 + e = e.next()) { 1.1858 + if (e.sym.kind == VAR) { 1.1859 + enumerator = (VarSymbol)e.sym; 1.1860 + break; 1.1861 + } 1.1862 + } 1.1863 + } 1.1864 + catch (CompletionFailure ex) { 1.1865 + failure = ex; 1.1866 + } 1.1867 + if (enumerator == null) { 1.1868 + if (failure != null) { 1.1869 + log.warning("unknown.enum.constant.reason", 1.1870 + currentClassFile, enumTypeSym, proxy.enumerator, 1.1871 + failure.getDiagnostic()); 1.1872 + } else { 1.1873 + log.warning("unknown.enum.constant", 1.1874 + currentClassFile, enumTypeSym, proxy.enumerator); 1.1875 + } 1.1876 + result = new Attribute.Enum(enumTypeSym.type, 1.1877 + new VarSymbol(0, proxy.enumerator, syms.botType, enumTypeSym)); 1.1878 + } else { 1.1879 + result = new Attribute.Enum(enumTypeSym.type, enumerator); 1.1880 + } 1.1881 + } 1.1882 + 1.1883 + public void visitArrayAttributeProxy(ArrayAttributeProxy proxy) { 1.1884 + int length = proxy.values.length(); 1.1885 + Attribute[] ats = new Attribute[length]; 1.1886 + Type elemtype = types.elemtype(type); 1.1887 + int i = 0; 1.1888 + for (List<Attribute> p = proxy.values; p.nonEmpty(); p = p.tail) { 1.1889 + ats[i++] = deproxy(elemtype, p.head); 1.1890 + } 1.1891 + result = new Attribute.Array(type, ats); 1.1892 + } 1.1893 + 1.1894 + public void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy) { 1.1895 + result = deproxyCompound(proxy); 1.1896 + } 1.1897 + } 1.1898 + 1.1899 + class AnnotationDefaultCompleter extends AnnotationDeproxy implements Annotate.Worker { 1.1900 + final MethodSymbol sym; 1.1901 + final Attribute value; 1.1902 + final JavaFileObject classFile = currentClassFile; 1.1903 + @Override 1.1904 + public String toString() { 1.1905 + return " ClassReader store default for " + sym.owner + "." + sym + " is " + value; 1.1906 + } 1.1907 + AnnotationDefaultCompleter(MethodSymbol sym, Attribute value) { 1.1908 + this.sym = sym; 1.1909 + this.value = value; 1.1910 + } 1.1911 + // implement Annotate.Worker.run() 1.1912 + public void run() { 1.1913 + JavaFileObject previousClassFile = currentClassFile; 1.1914 + try { 1.1915 + // Reset the interim value set earlier in 1.1916 + // attachAnnotationDefault(). 1.1917 + sym.defaultValue = null; 1.1918 + currentClassFile = classFile; 1.1919 + sym.defaultValue = deproxy(sym.type.getReturnType(), value); 1.1920 + } finally { 1.1921 + currentClassFile = previousClassFile; 1.1922 + } 1.1923 + } 1.1924 + } 1.1925 + 1.1926 + class AnnotationCompleter extends AnnotationDeproxy implements Annotate.Worker { 1.1927 + final Symbol sym; 1.1928 + final List<CompoundAnnotationProxy> l; 1.1929 + final JavaFileObject classFile; 1.1930 + @Override 1.1931 + public String toString() { 1.1932 + return " ClassReader annotate " + sym.owner + "." + sym + " with " + l; 1.1933 + } 1.1934 + AnnotationCompleter(Symbol sym, List<CompoundAnnotationProxy> l) { 1.1935 + this.sym = sym; 1.1936 + this.l = l; 1.1937 + this.classFile = currentClassFile; 1.1938 + } 1.1939 + // implement Annotate.Worker.run() 1.1940 + public void run() { 1.1941 + JavaFileObject previousClassFile = currentClassFile; 1.1942 + try { 1.1943 + currentClassFile = classFile; 1.1944 + List<Attribute.Compound> newList = deproxyCompoundList(l); 1.1945 + if (sym.annotationsPendingCompletion()) { 1.1946 + sym.setDeclarationAttributes(newList); 1.1947 + } else { 1.1948 + sym.appendAttributes(newList); 1.1949 + } 1.1950 + } finally { 1.1951 + currentClassFile = previousClassFile; 1.1952 + } 1.1953 + } 1.1954 + } 1.1955 + 1.1956 + class TypeAnnotationCompleter extends AnnotationCompleter { 1.1957 + 1.1958 + List<TypeAnnotationProxy> proxies; 1.1959 + 1.1960 + TypeAnnotationCompleter(Symbol sym, 1.1961 + List<TypeAnnotationProxy> proxies) { 1.1962 + super(sym, List.<CompoundAnnotationProxy>nil()); 1.1963 + this.proxies = proxies; 1.1964 + } 1.1965 + 1.1966 + List<Attribute.TypeCompound> deproxyTypeCompoundList(List<TypeAnnotationProxy> proxies) { 1.1967 + ListBuffer<Attribute.TypeCompound> buf = new ListBuffer<>(); 1.1968 + for (TypeAnnotationProxy proxy: proxies) { 1.1969 + Attribute.Compound compound = deproxyCompound(proxy.compound); 1.1970 + Attribute.TypeCompound typeCompound = new Attribute.TypeCompound(compound, proxy.position); 1.1971 + buf.add(typeCompound); 1.1972 + } 1.1973 + return buf.toList(); 1.1974 + } 1.1975 + 1.1976 + @Override 1.1977 + public void run() { 1.1978 + JavaFileObject previousClassFile = currentClassFile; 1.1979 + try { 1.1980 + currentClassFile = classFile; 1.1981 + List<Attribute.TypeCompound> newList = deproxyTypeCompoundList(proxies); 1.1982 + sym.setTypeAttributes(newList.prependList(sym.getRawTypeAttributes())); 1.1983 + } finally { 1.1984 + currentClassFile = previousClassFile; 1.1985 + } 1.1986 + } 1.1987 + } 1.1988 + 1.1989 + 1.1990 +/************************************************************************ 1.1991 + * Reading Symbols 1.1992 + ***********************************************************************/ 1.1993 + 1.1994 + /** Read a field. 1.1995 + */ 1.1996 + VarSymbol readField() { 1.1997 + long flags = adjustFieldFlags(nextChar()); 1.1998 + Name name = readName(nextChar()); 1.1999 + Type type = readType(nextChar()); 1.2000 + VarSymbol v = new VarSymbol(flags, name, type, currentOwner); 1.2001 + readMemberAttrs(v); 1.2002 + return v; 1.2003 + } 1.2004 + 1.2005 + /** Read a method. 1.2006 + */ 1.2007 + MethodSymbol readMethod() { 1.2008 + long flags = adjustMethodFlags(nextChar()); 1.2009 + Name name = readName(nextChar()); 1.2010 + Type type = readType(nextChar()); 1.2011 + if (currentOwner.isInterface() && 1.2012 + (flags & ABSTRACT) == 0 && !name.equals(names.clinit)) { 1.2013 + if (majorVersion > Target.JDK1_8.majorVersion || 1.2014 + (majorVersion == Target.JDK1_8.majorVersion && minorVersion >= Target.JDK1_8.minorVersion)) { 1.2015 + if ((flags & STATIC) == 0) { 1.2016 + currentOwner.flags_field |= DEFAULT; 1.2017 + flags |= DEFAULT | ABSTRACT; 1.2018 + } 1.2019 + } else { 1.2020 + //protect against ill-formed classfiles 1.2021 + throw badClassFile((flags & STATIC) == 0 ? "invalid.default.interface" : "invalid.static.interface", 1.2022 + Integer.toString(majorVersion), 1.2023 + Integer.toString(minorVersion)); 1.2024 + } 1.2025 + } 1.2026 + if (name == names.init && currentOwner.hasOuterInstance()) { 1.2027 + // Sometimes anonymous classes don't have an outer 1.2028 + // instance, however, there is no reliable way to tell so 1.2029 + // we never strip this$n 1.2030 + if (!currentOwner.name.isEmpty()) 1.2031 + type = new MethodType(adjustMethodParams(flags, type.getParameterTypes()), 1.2032 + type.getReturnType(), 1.2033 + type.getThrownTypes(), 1.2034 + syms.methodClass); 1.2035 + } 1.2036 + MethodSymbol m = new MethodSymbol(flags, name, type, currentOwner); 1.2037 + if (types.isSignaturePolymorphic(m)) { 1.2038 + m.flags_field |= SIGNATURE_POLYMORPHIC; 1.2039 + } 1.2040 + if (saveParameterNames) 1.2041 + initParameterNames(m); 1.2042 + Symbol prevOwner = currentOwner; 1.2043 + currentOwner = m; 1.2044 + try { 1.2045 + readMemberAttrs(m); 1.2046 + } finally { 1.2047 + currentOwner = prevOwner; 1.2048 + } 1.2049 + if (saveParameterNames) 1.2050 + setParameterNames(m, type); 1.2051 + return m; 1.2052 + } 1.2053 + 1.2054 + private List<Type> adjustMethodParams(long flags, List<Type> args) { 1.2055 + boolean isVarargs = (flags & VARARGS) != 0; 1.2056 + if (isVarargs) { 1.2057 + Type varargsElem = args.last(); 1.2058 + ListBuffer<Type> adjustedArgs = new ListBuffer<>(); 1.2059 + for (Type t : args) { 1.2060 + adjustedArgs.append(t != varargsElem ? 1.2061 + t : 1.2062 + ((ArrayType)t).makeVarargs()); 1.2063 + } 1.2064 + args = adjustedArgs.toList(); 1.2065 + } 1.2066 + return args.tail; 1.2067 + } 1.2068 + 1.2069 + /** 1.2070 + * Init the parameter names array. 1.2071 + * Parameter names are currently inferred from the names in the 1.2072 + * LocalVariableTable attributes of a Code attribute. 1.2073 + * (Note: this means parameter names are currently not available for 1.2074 + * methods without a Code attribute.) 1.2075 + * This method initializes an array in which to store the name indexes 1.2076 + * of parameter names found in LocalVariableTable attributes. It is 1.2077 + * slightly supersized to allow for additional slots with a start_pc of 0. 1.2078 + */ 1.2079 + void initParameterNames(MethodSymbol sym) { 1.2080 + // make allowance for synthetic parameters. 1.2081 + final int excessSlots = 4; 1.2082 + int expectedParameterSlots = 1.2083 + Code.width(sym.type.getParameterTypes()) + excessSlots; 1.2084 + if (parameterNameIndices == null 1.2085 + || parameterNameIndices.length < expectedParameterSlots) { 1.2086 + parameterNameIndices = new int[expectedParameterSlots]; 1.2087 + } else 1.2088 + Arrays.fill(parameterNameIndices, 0); 1.2089 + haveParameterNameIndices = false; 1.2090 + sawMethodParameters = false; 1.2091 + } 1.2092 + 1.2093 + /** 1.2094 + * Set the parameter names for a symbol from the name index in the 1.2095 + * parameterNameIndicies array. The type of the symbol may have changed 1.2096 + * while reading the method attributes (see the Signature attribute). 1.2097 + * This may be because of generic information or because anonymous 1.2098 + * synthetic parameters were added. The original type (as read from 1.2099 + * the method descriptor) is used to help guess the existence of 1.2100 + * anonymous synthetic parameters. 1.2101 + * On completion, sym.savedParameter names will either be null (if 1.2102 + * no parameter names were found in the class file) or will be set to a 1.2103 + * list of names, one per entry in sym.type.getParameterTypes, with 1.2104 + * any missing names represented by the empty name. 1.2105 + */ 1.2106 + void setParameterNames(MethodSymbol sym, Type jvmType) { 1.2107 + // if no names were found in the class file, there's nothing more to do 1.2108 + if (!haveParameterNameIndices) 1.2109 + return; 1.2110 + // If we get parameter names from MethodParameters, then we 1.2111 + // don't need to skip. 1.2112 + int firstParam = 0; 1.2113 + if (!sawMethodParameters) { 1.2114 + firstParam = ((sym.flags() & STATIC) == 0) ? 1 : 0; 1.2115 + // the code in readMethod may have skipped the first 1.2116 + // parameter when setting up the MethodType. If so, we 1.2117 + // make a corresponding allowance here for the position of 1.2118 + // the first parameter. Note that this assumes the 1.2119 + // skipped parameter has a width of 1 -- i.e. it is not 1.2120 + // a double width type (long or double.) 1.2121 + if (sym.name == names.init && currentOwner.hasOuterInstance()) { 1.2122 + // Sometimes anonymous classes don't have an outer 1.2123 + // instance, however, there is no reliable way to tell so 1.2124 + // we never strip this$n 1.2125 + if (!currentOwner.name.isEmpty()) 1.2126 + firstParam += 1; 1.2127 + } 1.2128 + 1.2129 + if (sym.type != jvmType) { 1.2130 + // reading the method attributes has caused the 1.2131 + // symbol's type to be changed. (i.e. the Signature 1.2132 + // attribute.) This may happen if there are hidden 1.2133 + // (synthetic) parameters in the descriptor, but not 1.2134 + // in the Signature. The position of these hidden 1.2135 + // parameters is unspecified; for now, assume they are 1.2136 + // at the beginning, and so skip over them. The 1.2137 + // primary case for this is two hidden parameters 1.2138 + // passed into Enum constructors. 1.2139 + int skip = Code.width(jvmType.getParameterTypes()) 1.2140 + - Code.width(sym.type.getParameterTypes()); 1.2141 + firstParam += skip; 1.2142 + } 1.2143 + } 1.2144 + List<Name> paramNames = List.nil(); 1.2145 + int index = firstParam; 1.2146 + for (Type t: sym.type.getParameterTypes()) { 1.2147 + int nameIdx = (index < parameterNameIndices.length 1.2148 + ? parameterNameIndices[index] : 0); 1.2149 + Name name = nameIdx == 0 ? names.empty : readName(nameIdx); 1.2150 + paramNames = paramNames.prepend(name); 1.2151 + index += Code.width(t); 1.2152 + } 1.2153 + sym.savedParameterNames = paramNames.reverse(); 1.2154 + } 1.2155 + 1.2156 + /** 1.2157 + * skip n bytes 1.2158 + */ 1.2159 + void skipBytes(int n) { 1.2160 + bp = bp + n; 1.2161 + } 1.2162 + 1.2163 + /** Skip a field or method 1.2164 + */ 1.2165 + void skipMember() { 1.2166 + bp = bp + 6; 1.2167 + char ac = nextChar(); 1.2168 + for (int i = 0; i < ac; i++) { 1.2169 + bp = bp + 2; 1.2170 + int attrLen = nextInt(); 1.2171 + bp = bp + attrLen; 1.2172 + } 1.2173 + } 1.2174 + 1.2175 + /** Enter type variables of this classtype and all enclosing ones in 1.2176 + * `typevars'. 1.2177 + */ 1.2178 + protected void enterTypevars(Type t) { 1.2179 + if (t.getEnclosingType() != null && t.getEnclosingType().hasTag(CLASS)) 1.2180 + enterTypevars(t.getEnclosingType()); 1.2181 + for (List<Type> xs = t.getTypeArguments(); xs.nonEmpty(); xs = xs.tail) 1.2182 + typevars.enter(xs.head.tsym); 1.2183 + } 1.2184 + 1.2185 + protected void enterTypevars(Symbol sym) { 1.2186 + if (sym.owner.kind == MTH) { 1.2187 + enterTypevars(sym.owner); 1.2188 + enterTypevars(sym.owner.owner); 1.2189 + } 1.2190 + enterTypevars(sym.type); 1.2191 + } 1.2192 + 1.2193 + /** Read contents of a given class symbol `c'. Both external and internal 1.2194 + * versions of an inner class are read. 1.2195 + */ 1.2196 + void readClass(ClassSymbol c) { 1.2197 + ClassType ct = (ClassType)c.type; 1.2198 + 1.2199 + // allocate scope for members 1.2200 + c.members_field = new Scope(c); 1.2201 + 1.2202 + // prepare type variable table 1.2203 + typevars = typevars.dup(currentOwner); 1.2204 + if (ct.getEnclosingType().hasTag(CLASS)) 1.2205 + enterTypevars(ct.getEnclosingType()); 1.2206 + 1.2207 + // read flags, or skip if this is an inner class 1.2208 + long flags = adjustClassFlags(nextChar()); 1.2209 + if (c.owner.kind == PCK) c.flags_field = flags; 1.2210 + 1.2211 + // read own class name and check that it matches 1.2212 + ClassSymbol self = readClassSymbol(nextChar()); 1.2213 + if (c != self) 1.2214 + throw badClassFile("class.file.wrong.class", 1.2215 + self.flatname); 1.2216 + 1.2217 + // class attributes must be read before class 1.2218 + // skip ahead to read class attributes 1.2219 + int startbp = bp; 1.2220 + nextChar(); 1.2221 + char interfaceCount = nextChar(); 1.2222 + bp += interfaceCount * 2; 1.2223 + char fieldCount = nextChar(); 1.2224 + for (int i = 0; i < fieldCount; i++) skipMember(); 1.2225 + char methodCount = nextChar(); 1.2226 + for (int i = 0; i < methodCount; i++) skipMember(); 1.2227 + readClassAttrs(c); 1.2228 + 1.2229 + if (readAllOfClassFile) { 1.2230 + for (int i = 1; i < poolObj.length; i++) readPool(i); 1.2231 + c.pool = new Pool(poolObj.length, poolObj, types); 1.2232 + } 1.2233 + 1.2234 + // reset and read rest of classinfo 1.2235 + bp = startbp; 1.2236 + int n = nextChar(); 1.2237 + if (ct.supertype_field == null) 1.2238 + ct.supertype_field = (n == 0) 1.2239 + ? Type.noType 1.2240 + : readClassSymbol(n).erasure(types); 1.2241 + n = nextChar(); 1.2242 + List<Type> is = List.nil(); 1.2243 + for (int i = 0; i < n; i++) { 1.2244 + Type _inter = readClassSymbol(nextChar()).erasure(types); 1.2245 + is = is.prepend(_inter); 1.2246 + } 1.2247 + if (ct.interfaces_field == null) 1.2248 + ct.interfaces_field = is.reverse(); 1.2249 + 1.2250 + Assert.check(fieldCount == nextChar()); 1.2251 + for (int i = 0; i < fieldCount; i++) enterMember(c, readField()); 1.2252 + Assert.check(methodCount == nextChar()); 1.2253 + for (int i = 0; i < methodCount; i++) enterMember(c, readMethod()); 1.2254 + 1.2255 + typevars = typevars.leave(); 1.2256 + } 1.2257 + 1.2258 + /** Read inner class info. For each inner/outer pair allocate a 1.2259 + * member class. 1.2260 + */ 1.2261 + void readInnerClasses(ClassSymbol c) { 1.2262 + int n = nextChar(); 1.2263 + for (int i = 0; i < n; i++) { 1.2264 + nextChar(); // skip inner class symbol 1.2265 + ClassSymbol outer = readClassSymbol(nextChar()); 1.2266 + Name name = readName(nextChar()); 1.2267 + if (name == null) name = names.empty; 1.2268 + long flags = adjustClassFlags(nextChar()); 1.2269 + if (outer != null) { // we have a member class 1.2270 + if (name == names.empty) 1.2271 + name = names.one; 1.2272 + ClassSymbol member = enterClass(name, outer); 1.2273 + if ((flags & STATIC) == 0) { 1.2274 + ((ClassType)member.type).setEnclosingType(outer.type); 1.2275 + if (member.erasure_field != null) 1.2276 + ((ClassType)member.erasure_field).setEnclosingType(types.erasure(outer.type)); 1.2277 + } 1.2278 + if (c == outer) { 1.2279 + member.flags_field = flags; 1.2280 + enterMember(c, member); 1.2281 + } 1.2282 + } 1.2283 + } 1.2284 + } 1.2285 + 1.2286 + /** Read a class file. 1.2287 + */ 1.2288 + private void readClassFile(ClassSymbol c) throws IOException { 1.2289 + int magic = nextInt(); 1.2290 + if (magic != JAVA_MAGIC) 1.2291 + throw badClassFile("illegal.start.of.class.file"); 1.2292 + 1.2293 + minorVersion = nextChar(); 1.2294 + majorVersion = nextChar(); 1.2295 + int maxMajor = Target.MAX().majorVersion; 1.2296 + int maxMinor = Target.MAX().minorVersion; 1.2297 + if (majorVersion > maxMajor || 1.2298 + majorVersion * 1000 + minorVersion < 1.2299 + Target.MIN().majorVersion * 1000 + Target.MIN().minorVersion) 1.2300 + { 1.2301 + if (majorVersion == (maxMajor + 1)) 1.2302 + log.warning("big.major.version", 1.2303 + currentClassFile, 1.2304 + majorVersion, 1.2305 + maxMajor); 1.2306 + else 1.2307 + throw badClassFile("wrong.version", 1.2308 + Integer.toString(majorVersion), 1.2309 + Integer.toString(minorVersion), 1.2310 + Integer.toString(maxMajor), 1.2311 + Integer.toString(maxMinor)); 1.2312 + } 1.2313 + else if (checkClassFile && 1.2314 + majorVersion == maxMajor && 1.2315 + minorVersion > maxMinor) 1.2316 + { 1.2317 + printCCF("found.later.version", 1.2318 + Integer.toString(minorVersion)); 1.2319 + } 1.2320 + indexPool(); 1.2321 + if (signatureBuffer.length < bp) { 1.2322 + int ns = Integer.highestOneBit(bp) << 1; 1.2323 + signatureBuffer = new byte[ns]; 1.2324 + } 1.2325 + readClass(c); 1.2326 + } 1.2327 + 1.2328 +/************************************************************************ 1.2329 + * Adjusting flags 1.2330 + ***********************************************************************/ 1.2331 + 1.2332 + long adjustFieldFlags(long flags) { 1.2333 + return flags; 1.2334 + } 1.2335 + long adjustMethodFlags(long flags) { 1.2336 + if ((flags & ACC_BRIDGE) != 0) { 1.2337 + flags &= ~ACC_BRIDGE; 1.2338 + flags |= BRIDGE; 1.2339 + if (!allowGenerics) 1.2340 + flags &= ~SYNTHETIC; 1.2341 + } 1.2342 + if ((flags & ACC_VARARGS) != 0) { 1.2343 + flags &= ~ACC_VARARGS; 1.2344 + flags |= VARARGS; 1.2345 + } 1.2346 + return flags; 1.2347 + } 1.2348 + long adjustClassFlags(long flags) { 1.2349 + return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded 1.2350 + } 1.2351 + 1.2352 +/************************************************************************ 1.2353 + * Loading Classes 1.2354 + ***********************************************************************/ 1.2355 + 1.2356 + /** Define a new class given its name and owner. 1.2357 + */ 1.2358 + public ClassSymbol defineClass(Name name, Symbol owner) { 1.2359 + ClassSymbol c = new ClassSymbol(0, name, owner); 1.2360 + if (owner.kind == PCK) 1.2361 + Assert.checkNull(classes.get(c.flatname), c); 1.2362 + c.completer = thisCompleter; 1.2363 + return c; 1.2364 + } 1.2365 + 1.2366 + /** Create a new toplevel or member class symbol with given name 1.2367 + * and owner and enter in `classes' unless already there. 1.2368 + */ 1.2369 + public ClassSymbol enterClass(Name name, TypeSymbol owner) { 1.2370 + Name flatname = TypeSymbol.formFlatName(name, owner); 1.2371 + ClassSymbol c = classes.get(flatname); 1.2372 + if (c == null) { 1.2373 + c = defineClass(name, owner); 1.2374 + classes.put(flatname, c); 1.2375 + } else if ((c.name != name || c.owner != owner) && owner.kind == TYP && c.owner.kind == PCK) { 1.2376 + // reassign fields of classes that might have been loaded with 1.2377 + // their flat names. 1.2378 + c.owner.members().remove(c); 1.2379 + c.name = name; 1.2380 + c.owner = owner; 1.2381 + c.fullname = ClassSymbol.formFullName(name, owner); 1.2382 + } 1.2383 + return c; 1.2384 + } 1.2385 + 1.2386 + /** 1.2387 + * Creates a new toplevel class symbol with given flat name and 1.2388 + * given class (or source) file. 1.2389 + * 1.2390 + * @param flatName a fully qualified binary class name 1.2391 + * @param classFile the class file or compilation unit defining 1.2392 + * the class (may be {@code null}) 1.2393 + * @return a newly created class symbol 1.2394 + * @throws AssertionError if the class symbol already exists 1.2395 + */ 1.2396 + public ClassSymbol enterClass(Name flatName, JavaFileObject classFile) { 1.2397 + ClassSymbol cs = classes.get(flatName); 1.2398 + if (cs != null) { 1.2399 + String msg = Log.format("%s: completer = %s; class file = %s; source file = %s", 1.2400 + cs.fullname, 1.2401 + cs.completer, 1.2402 + cs.classfile, 1.2403 + cs.sourcefile); 1.2404 + throw new AssertionError(msg); 1.2405 + } 1.2406 + Name packageName = Convert.packagePart(flatName); 1.2407 + PackageSymbol owner = packageName.isEmpty() 1.2408 + ? syms.unnamedPackage 1.2409 + : enterPackage(packageName); 1.2410 + cs = defineClass(Convert.shortName(flatName), owner); 1.2411 + cs.classfile = classFile; 1.2412 + classes.put(flatName, cs); 1.2413 + return cs; 1.2414 + } 1.2415 + 1.2416 + /** Create a new member or toplevel class symbol with given flat name 1.2417 + * and enter in `classes' unless already there. 1.2418 + */ 1.2419 + public ClassSymbol enterClass(Name flatname) { 1.2420 + ClassSymbol c = classes.get(flatname); 1.2421 + if (c == null) 1.2422 + return enterClass(flatname, (JavaFileObject)null); 1.2423 + else 1.2424 + return c; 1.2425 + } 1.2426 + 1.2427 + /** Completion for classes to be loaded. Before a class is loaded 1.2428 + * we make sure its enclosing class (if any) is loaded. 1.2429 + */ 1.2430 + private void complete(Symbol sym) throws CompletionFailure { 1.2431 + if (sym.kind == TYP) { 1.2432 + ClassSymbol c = (ClassSymbol)sym; 1.2433 + c.members_field = new Scope.ErrorScope(c); // make sure it's always defined 1.2434 + annotate.enterStart(); 1.2435 + try { 1.2436 + completeOwners(c.owner); 1.2437 + completeEnclosing(c); 1.2438 + } finally { 1.2439 + // The flush needs to happen only after annotations 1.2440 + // are filled in. 1.2441 + annotate.enterDoneWithoutFlush(); 1.2442 + } 1.2443 + fillIn(c); 1.2444 + } else if (sym.kind == PCK) { 1.2445 + PackageSymbol p = (PackageSymbol)sym; 1.2446 + try { 1.2447 + fillIn(p); 1.2448 + } catch (IOException ex) { 1.2449 + throw new CompletionFailure(sym, ex.getLocalizedMessage()).initCause(ex); 1.2450 + } 1.2451 + } 1.2452 + if (!filling) 1.2453 + annotate.flush(); // finish attaching annotations 1.2454 + } 1.2455 + 1.2456 + /** complete up through the enclosing package. */ 1.2457 + private void completeOwners(Symbol o) { 1.2458 + if (o.kind != PCK) completeOwners(o.owner); 1.2459 + o.complete(); 1.2460 + } 1.2461 + 1.2462 + /** 1.2463 + * Tries to complete lexically enclosing classes if c looks like a 1.2464 + * nested class. This is similar to completeOwners but handles 1.2465 + * the situation when a nested class is accessed directly as it is 1.2466 + * possible with the Tree API or javax.lang.model.*. 1.2467 + */ 1.2468 + private void completeEnclosing(ClassSymbol c) { 1.2469 + if (c.owner.kind == PCK) { 1.2470 + Symbol owner = c.owner; 1.2471 + for (Name name : Convert.enclosingCandidates(Convert.shortName(c.name))) { 1.2472 + Symbol encl = owner.members().lookup(name).sym; 1.2473 + if (encl == null) 1.2474 + encl = classes.get(TypeSymbol.formFlatName(name, owner)); 1.2475 + if (encl != null) 1.2476 + encl.complete(); 1.2477 + } 1.2478 + } 1.2479 + } 1.2480 + 1.2481 + /** We can only read a single class file at a time; this 1.2482 + * flag keeps track of when we are currently reading a class 1.2483 + * file. 1.2484 + */ 1.2485 + private boolean filling = false; 1.2486 + 1.2487 + /** Fill in definition of class `c' from corresponding class or 1.2488 + * source file. 1.2489 + */ 1.2490 + private void fillIn(ClassSymbol c) { 1.2491 + if (completionFailureName == c.fullname) { 1.2492 + throw new CompletionFailure(c, "user-selected completion failure by class name"); 1.2493 + } 1.2494 + currentOwner = c; 1.2495 + warnedAttrs.clear(); 1.2496 + JavaFileObject classfile = c.classfile; 1.2497 + if (classfile != null) { 1.2498 + JavaFileObject previousClassFile = currentClassFile; 1.2499 + try { 1.2500 + if (filling) { 1.2501 + Assert.error("Filling " + classfile.toUri() + " during " + previousClassFile); 1.2502 + } 1.2503 + currentClassFile = classfile; 1.2504 + if (verbose) { 1.2505 + log.printVerbose("loading", currentClassFile.toString()); 1.2506 + } 1.2507 + if (classfile.getKind() == JavaFileObject.Kind.CLASS) { 1.2508 + filling = true; 1.2509 + try { 1.2510 + bp = 0; 1.2511 + buf = readInputStream(buf, classfile.openInputStream()); 1.2512 + readClassFile(c); 1.2513 + if (!missingTypeVariables.isEmpty() && !foundTypeVariables.isEmpty()) { 1.2514 + List<Type> missing = missingTypeVariables; 1.2515 + List<Type> found = foundTypeVariables; 1.2516 + missingTypeVariables = List.nil(); 1.2517 + foundTypeVariables = List.nil(); 1.2518 + filling = false; 1.2519 + ClassType ct = (ClassType)currentOwner.type; 1.2520 + ct.supertype_field = 1.2521 + types.subst(ct.supertype_field, missing, found); 1.2522 + ct.interfaces_field = 1.2523 + types.subst(ct.interfaces_field, missing, found); 1.2524 + } else if (missingTypeVariables.isEmpty() != 1.2525 + foundTypeVariables.isEmpty()) { 1.2526 + Name name = missingTypeVariables.head.tsym.name; 1.2527 + throw badClassFile("undecl.type.var", name); 1.2528 + } 1.2529 + } finally { 1.2530 + missingTypeVariables = List.nil(); 1.2531 + foundTypeVariables = List.nil(); 1.2532 + filling = false; 1.2533 + } 1.2534 + } else { 1.2535 + if (sourceCompleter != null) { 1.2536 + sourceCompleter.complete(c); 1.2537 + } else { 1.2538 + throw new IllegalStateException("Source completer required to read " 1.2539 + + classfile.toUri()); 1.2540 + } 1.2541 + } 1.2542 + return; 1.2543 + } catch (IOException ex) { 1.2544 + throw badClassFile("unable.to.access.file", ex.getMessage()); 1.2545 + } finally { 1.2546 + currentClassFile = previousClassFile; 1.2547 + } 1.2548 + } else { 1.2549 + JCDiagnostic diag = 1.2550 + diagFactory.fragment("class.file.not.found", c.flatname); 1.2551 + throw 1.2552 + newCompletionFailure(c, diag); 1.2553 + } 1.2554 + } 1.2555 + // where 1.2556 + private static byte[] readInputStream(byte[] buf, InputStream s) throws IOException { 1.2557 + try { 1.2558 + buf = ensureCapacity(buf, s.available()); 1.2559 + int r = s.read(buf); 1.2560 + int bp = 0; 1.2561 + while (r != -1) { 1.2562 + bp += r; 1.2563 + buf = ensureCapacity(buf, bp); 1.2564 + r = s.read(buf, bp, buf.length - bp); 1.2565 + } 1.2566 + return buf; 1.2567 + } finally { 1.2568 + try { 1.2569 + s.close(); 1.2570 + } catch (IOException e) { 1.2571 + /* Ignore any errors, as this stream may have already 1.2572 + * thrown a related exception which is the one that 1.2573 + * should be reported. 1.2574 + */ 1.2575 + } 1.2576 + } 1.2577 + } 1.2578 + /* 1.2579 + * ensureCapacity will increase the buffer as needed, taking note that 1.2580 + * the new buffer will always be greater than the needed and never 1.2581 + * exactly equal to the needed size or bp. If equal then the read (above) 1.2582 + * will infinitely loop as buf.length - bp == 0. 1.2583 + */ 1.2584 + private static byte[] ensureCapacity(byte[] buf, int needed) { 1.2585 + if (buf.length <= needed) { 1.2586 + byte[] old = buf; 1.2587 + buf = new byte[Integer.highestOneBit(needed) << 1]; 1.2588 + System.arraycopy(old, 0, buf, 0, old.length); 1.2589 + } 1.2590 + return buf; 1.2591 + } 1.2592 + /** Static factory for CompletionFailure objects. 1.2593 + * In practice, only one can be used at a time, so we share one 1.2594 + * to reduce the expense of allocating new exception objects. 1.2595 + */ 1.2596 + private CompletionFailure newCompletionFailure(TypeSymbol c, 1.2597 + JCDiagnostic diag) { 1.2598 + if (!cacheCompletionFailure) { 1.2599 + // log.warning("proc.messager", 1.2600 + // Log.getLocalizedString("class.file.not.found", c.flatname)); 1.2601 + // c.debug.printStackTrace(); 1.2602 + return new CompletionFailure(c, diag); 1.2603 + } else { 1.2604 + CompletionFailure result = cachedCompletionFailure; 1.2605 + result.sym = c; 1.2606 + result.diag = diag; 1.2607 + return result; 1.2608 + } 1.2609 + } 1.2610 + private CompletionFailure cachedCompletionFailure = 1.2611 + new CompletionFailure(null, (JCDiagnostic) null); 1.2612 + { 1.2613 + cachedCompletionFailure.setStackTrace(new StackTraceElement[0]); 1.2614 + } 1.2615 + 1.2616 + /** Load a toplevel class with given fully qualified name 1.2617 + * The class is entered into `classes' only if load was successful. 1.2618 + */ 1.2619 + public ClassSymbol loadClass(Name flatname) throws CompletionFailure { 1.2620 + boolean absent = classes.get(flatname) == null; 1.2621 + ClassSymbol c = enterClass(flatname); 1.2622 + if (c.members_field == null && c.completer != null) { 1.2623 + try { 1.2624 + c.complete(); 1.2625 + } catch (CompletionFailure ex) { 1.2626 + if (absent) classes.remove(flatname); 1.2627 + throw ex; 1.2628 + } 1.2629 + } 1.2630 + return c; 1.2631 + } 1.2632 + 1.2633 +/************************************************************************ 1.2634 + * Loading Packages 1.2635 + ***********************************************************************/ 1.2636 + 1.2637 + /** Check to see if a package exists, given its fully qualified name. 1.2638 + */ 1.2639 + public boolean packageExists(Name fullname) { 1.2640 + return enterPackage(fullname).exists(); 1.2641 + } 1.2642 + 1.2643 + /** Make a package, given its fully qualified name. 1.2644 + */ 1.2645 + public PackageSymbol enterPackage(Name fullname) { 1.2646 + PackageSymbol p = packages.get(fullname); 1.2647 + if (p == null) { 1.2648 + Assert.check(!fullname.isEmpty(), "rootPackage missing!"); 1.2649 + p = new PackageSymbol( 1.2650 + Convert.shortName(fullname), 1.2651 + enterPackage(Convert.packagePart(fullname))); 1.2652 + p.completer = thisCompleter; 1.2653 + packages.put(fullname, p); 1.2654 + } 1.2655 + return p; 1.2656 + } 1.2657 + 1.2658 + /** Make a package, given its unqualified name and enclosing package. 1.2659 + */ 1.2660 + public PackageSymbol enterPackage(Name name, PackageSymbol owner) { 1.2661 + return enterPackage(TypeSymbol.formFullName(name, owner)); 1.2662 + } 1.2663 + 1.2664 + /** Include class corresponding to given class file in package, 1.2665 + * unless (1) we already have one the same kind (.class or .java), or 1.2666 + * (2) we have one of the other kind, and the given class file 1.2667 + * is older. 1.2668 + */ 1.2669 + protected void includeClassFile(PackageSymbol p, JavaFileObject file) { 1.2670 + if ((p.flags_field & EXISTS) == 0) 1.2671 + for (Symbol q = p; q != null && q.kind == PCK; q = q.owner) 1.2672 + q.flags_field |= EXISTS; 1.2673 + JavaFileObject.Kind kind = file.getKind(); 1.2674 + int seen; 1.2675 + if (kind == JavaFileObject.Kind.CLASS) 1.2676 + seen = CLASS_SEEN; 1.2677 + else 1.2678 + seen = SOURCE_SEEN; 1.2679 + String binaryName = fileManager.inferBinaryName(currentLoc, file); 1.2680 + int lastDot = binaryName.lastIndexOf("."); 1.2681 + Name classname = names.fromString(binaryName.substring(lastDot + 1)); 1.2682 + boolean isPkgInfo = classname == names.package_info; 1.2683 + ClassSymbol c = isPkgInfo 1.2684 + ? p.package_info 1.2685 + : (ClassSymbol) p.members_field.lookup(classname).sym; 1.2686 + if (c == null) { 1.2687 + c = enterClass(classname, p); 1.2688 + if (c.classfile == null) // only update the file if's it's newly created 1.2689 + c.classfile = file; 1.2690 + if (isPkgInfo) { 1.2691 + p.package_info = c; 1.2692 + } else { 1.2693 + if (c.owner == p) // it might be an inner class 1.2694 + p.members_field.enter(c); 1.2695 + } 1.2696 + } else if (c.classfile != null && (c.flags_field & seen) == 0) { 1.2697 + // if c.classfile == null, we are currently compiling this class 1.2698 + // and no further action is necessary. 1.2699 + // if (c.flags_field & seen) != 0, we have already encountered 1.2700 + // a file of the same kind; again no further action is necessary. 1.2701 + if ((c.flags_field & (CLASS_SEEN | SOURCE_SEEN)) != 0) 1.2702 + c.classfile = preferredFileObject(file, c.classfile); 1.2703 + } 1.2704 + c.flags_field |= seen; 1.2705 + } 1.2706 + 1.2707 + /** Implement policy to choose to derive information from a source 1.2708 + * file or a class file when both are present. May be overridden 1.2709 + * by subclasses. 1.2710 + */ 1.2711 + protected JavaFileObject preferredFileObject(JavaFileObject a, 1.2712 + JavaFileObject b) { 1.2713 + 1.2714 + if (preferSource) 1.2715 + return (a.getKind() == JavaFileObject.Kind.SOURCE) ? a : b; 1.2716 + else { 1.2717 + long adate = a.getLastModified(); 1.2718 + long bdate = b.getLastModified(); 1.2719 + // 6449326: policy for bad lastModifiedTime in ClassReader 1.2720 + //assert adate >= 0 && bdate >= 0; 1.2721 + return (adate > bdate) ? a : b; 1.2722 + } 1.2723 + } 1.2724 + 1.2725 + /** 1.2726 + * specifies types of files to be read when filling in a package symbol 1.2727 + */ 1.2728 + protected EnumSet<JavaFileObject.Kind> getPackageFileKinds() { 1.2729 + return EnumSet.of(JavaFileObject.Kind.CLASS, JavaFileObject.Kind.SOURCE); 1.2730 + } 1.2731 + 1.2732 + /** 1.2733 + * this is used to support javadoc 1.2734 + */ 1.2735 + protected void extraFileActions(PackageSymbol pack, JavaFileObject fe) { 1.2736 + } 1.2737 + 1.2738 + protected Location currentLoc; // FIXME 1.2739 + 1.2740 + private boolean verbosePath = true; 1.2741 + 1.2742 + /** Load directory of package into members scope. 1.2743 + */ 1.2744 + private void fillIn(PackageSymbol p) throws IOException { 1.2745 + if (p.members_field == null) p.members_field = new Scope(p); 1.2746 + String packageName = p.fullname.toString(); 1.2747 + 1.2748 + Set<JavaFileObject.Kind> kinds = getPackageFileKinds(); 1.2749 + 1.2750 + fillIn(p, PLATFORM_CLASS_PATH, 1.2751 + fileManager.list(PLATFORM_CLASS_PATH, 1.2752 + packageName, 1.2753 + EnumSet.of(JavaFileObject.Kind.CLASS), 1.2754 + false)); 1.2755 + 1.2756 + Set<JavaFileObject.Kind> classKinds = EnumSet.copyOf(kinds); 1.2757 + classKinds.remove(JavaFileObject.Kind.SOURCE); 1.2758 + boolean wantClassFiles = !classKinds.isEmpty(); 1.2759 + 1.2760 + Set<JavaFileObject.Kind> sourceKinds = EnumSet.copyOf(kinds); 1.2761 + sourceKinds.remove(JavaFileObject.Kind.CLASS); 1.2762 + boolean wantSourceFiles = !sourceKinds.isEmpty(); 1.2763 + 1.2764 + boolean haveSourcePath = fileManager.hasLocation(SOURCE_PATH); 1.2765 + 1.2766 + if (verbose && verbosePath) { 1.2767 + if (fileManager instanceof StandardJavaFileManager) { 1.2768 + StandardJavaFileManager fm = (StandardJavaFileManager)fileManager; 1.2769 + if (haveSourcePath && wantSourceFiles) { 1.2770 + List<File> path = List.nil(); 1.2771 + for (File file : fm.getLocation(SOURCE_PATH)) { 1.2772 + path = path.prepend(file); 1.2773 + } 1.2774 + log.printVerbose("sourcepath", path.reverse().toString()); 1.2775 + } else if (wantSourceFiles) { 1.2776 + List<File> path = List.nil(); 1.2777 + for (File file : fm.getLocation(CLASS_PATH)) { 1.2778 + path = path.prepend(file); 1.2779 + } 1.2780 + log.printVerbose("sourcepath", path.reverse().toString()); 1.2781 + } 1.2782 + if (wantClassFiles) { 1.2783 + List<File> path = List.nil(); 1.2784 + for (File file : fm.getLocation(PLATFORM_CLASS_PATH)) { 1.2785 + path = path.prepend(file); 1.2786 + } 1.2787 + for (File file : fm.getLocation(CLASS_PATH)) { 1.2788 + path = path.prepend(file); 1.2789 + } 1.2790 + log.printVerbose("classpath", path.reverse().toString()); 1.2791 + } 1.2792 + } 1.2793 + } 1.2794 + 1.2795 + if (wantSourceFiles && !haveSourcePath) { 1.2796 + fillIn(p, CLASS_PATH, 1.2797 + fileManager.list(CLASS_PATH, 1.2798 + packageName, 1.2799 + kinds, 1.2800 + false)); 1.2801 + } else { 1.2802 + if (wantClassFiles) 1.2803 + fillIn(p, CLASS_PATH, 1.2804 + fileManager.list(CLASS_PATH, 1.2805 + packageName, 1.2806 + classKinds, 1.2807 + false)); 1.2808 + if (wantSourceFiles) 1.2809 + fillIn(p, SOURCE_PATH, 1.2810 + fileManager.list(SOURCE_PATH, 1.2811 + packageName, 1.2812 + sourceKinds, 1.2813 + false)); 1.2814 + } 1.2815 + verbosePath = false; 1.2816 + } 1.2817 + // where 1.2818 + private void fillIn(PackageSymbol p, 1.2819 + Location location, 1.2820 + Iterable<JavaFileObject> files) 1.2821 + { 1.2822 + currentLoc = location; 1.2823 + for (JavaFileObject fo : files) { 1.2824 + switch (fo.getKind()) { 1.2825 + case CLASS: 1.2826 + case SOURCE: { 1.2827 + // TODO pass binaryName to includeClassFile 1.2828 + String binaryName = fileManager.inferBinaryName(currentLoc, fo); 1.2829 + String simpleName = binaryName.substring(binaryName.lastIndexOf(".") + 1); 1.2830 + if (SourceVersion.isIdentifier(simpleName) || 1.2831 + simpleName.equals("package-info")) 1.2832 + includeClassFile(p, fo); 1.2833 + break; 1.2834 + } 1.2835 + default: 1.2836 + extraFileActions(p, fo); 1.2837 + } 1.2838 + } 1.2839 + } 1.2840 + 1.2841 + /** Output for "-checkclassfile" option. 1.2842 + * @param key The key to look up the correct internationalized string. 1.2843 + * @param arg An argument for substitution into the output string. 1.2844 + */ 1.2845 + private void printCCF(String key, Object arg) { 1.2846 + log.printLines(key, arg); 1.2847 + } 1.2848 + 1.2849 + 1.2850 + public interface SourceCompleter { 1.2851 + void complete(ClassSymbol sym) 1.2852 + throws CompletionFailure; 1.2853 + } 1.2854 + 1.2855 + /** 1.2856 + * A subclass of JavaFileObject for the sourcefile attribute found in a classfile. 1.2857 + * The attribute is only the last component of the original filename, so is unlikely 1.2858 + * to be valid as is, so operations other than those to access the name throw 1.2859 + * UnsupportedOperationException 1.2860 + */ 1.2861 + private static class SourceFileObject extends BaseFileObject { 1.2862 + 1.2863 + /** The file's name. 1.2864 + */ 1.2865 + private Name name; 1.2866 + private Name flatname; 1.2867 + 1.2868 + public SourceFileObject(Name name, Name flatname) { 1.2869 + super(null); // no file manager; never referenced for this file object 1.2870 + this.name = name; 1.2871 + this.flatname = flatname; 1.2872 + } 1.2873 + 1.2874 + @Override 1.2875 + public URI toUri() { 1.2876 + try { 1.2877 + return new URI(null, name.toString(), null); 1.2878 + } catch (URISyntaxException e) { 1.2879 + throw new CannotCreateUriError(name.toString(), e); 1.2880 + } 1.2881 + } 1.2882 + 1.2883 + @Override 1.2884 + public String getName() { 1.2885 + return name.toString(); 1.2886 + } 1.2887 + 1.2888 + @Override 1.2889 + public String getShortName() { 1.2890 + return getName(); 1.2891 + } 1.2892 + 1.2893 + @Override 1.2894 + public JavaFileObject.Kind getKind() { 1.2895 + return getKind(getName()); 1.2896 + } 1.2897 + 1.2898 + @Override 1.2899 + public InputStream openInputStream() { 1.2900 + throw new UnsupportedOperationException(); 1.2901 + } 1.2902 + 1.2903 + @Override 1.2904 + public OutputStream openOutputStream() { 1.2905 + throw new UnsupportedOperationException(); 1.2906 + } 1.2907 + 1.2908 + @Override 1.2909 + public CharBuffer getCharContent(boolean ignoreEncodingErrors) { 1.2910 + throw new UnsupportedOperationException(); 1.2911 + } 1.2912 + 1.2913 + @Override 1.2914 + public Reader openReader(boolean ignoreEncodingErrors) { 1.2915 + throw new UnsupportedOperationException(); 1.2916 + } 1.2917 + 1.2918 + @Override 1.2919 + public Writer openWriter() { 1.2920 + throw new UnsupportedOperationException(); 1.2921 + } 1.2922 + 1.2923 + @Override 1.2924 + public long getLastModified() { 1.2925 + throw new UnsupportedOperationException(); 1.2926 + } 1.2927 + 1.2928 + @Override 1.2929 + public boolean delete() { 1.2930 + throw new UnsupportedOperationException(); 1.2931 + } 1.2932 + 1.2933 + @Override 1.2934 + protected String inferBinaryName(Iterable<? extends File> path) { 1.2935 + return flatname.toString(); 1.2936 + } 1.2937 + 1.2938 + @Override 1.2939 + public boolean isNameCompatible(String simpleName, JavaFileObject.Kind kind) { 1.2940 + return true; // fail-safe mode 1.2941 + } 1.2942 + 1.2943 + /** 1.2944 + * Check if two file objects are equal. 1.2945 + * SourceFileObjects are just placeholder objects for the value of a 1.2946 + * SourceFile attribute, and do not directly represent specific files. 1.2947 + * Two SourceFileObjects are equal if their names are equal. 1.2948 + */ 1.2949 + @Override 1.2950 + public boolean equals(Object other) { 1.2951 + if (this == other) 1.2952 + return true; 1.2953 + 1.2954 + if (!(other instanceof SourceFileObject)) 1.2955 + return false; 1.2956 + 1.2957 + SourceFileObject o = (SourceFileObject) other; 1.2958 + return name.equals(o.name); 1.2959 + } 1.2960 + 1.2961 + @Override 1.2962 + public int hashCode() { 1.2963 + return name.hashCode(); 1.2964 + } 1.2965 + } 1.2966 +}