mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-06 19:59:17 +00:00
Merge
This commit is contained in:
commit
293d514c13
@ -28,6 +28,8 @@ package com.sun.tools.doclets.formats.html;
|
||||
import java.io.*;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.sun.javadoc.*;
|
||||
import com.sun.tools.doclets.formats.html.markup.*;
|
||||
@ -139,42 +141,37 @@ public class HtmlDocletWriter extends HtmlDocWriter {
|
||||
if (index < 0) {
|
||||
return htmlstr;
|
||||
}
|
||||
String lowerHtml = StringUtils.toLowerCase(htmlstr);
|
||||
final String docroot = "{@docroot}";
|
||||
// Return index of first occurrence of {@docroot}
|
||||
// Note: {@docRoot} is not case sensitive when passed in w/command line option
|
||||
index = lowerHtml.indexOf(docroot, index);
|
||||
if (index < 0) {
|
||||
Matcher docrootMatcher = docrootPattern.matcher(htmlstr);
|
||||
if (!docrootMatcher.find()) {
|
||||
return htmlstr;
|
||||
}
|
||||
StringBuilder buf = new StringBuilder();
|
||||
int previndex = 0;
|
||||
while (true) {
|
||||
// Search for lowercase version of {@docRoot}
|
||||
index = lowerHtml.indexOf(docroot, previndex);
|
||||
// If next {@docRoot} tag not found, append rest of htmlstr and exit loop
|
||||
if (index < 0) {
|
||||
buf.append(htmlstr.substring(previndex));
|
||||
break;
|
||||
}
|
||||
// If next {@docroot} tag found, append htmlstr up to start of tag
|
||||
buf.append(htmlstr.substring(previndex, index));
|
||||
previndex = index + docroot.length();
|
||||
if (configuration.docrootparent.length() > 0 && htmlstr.startsWith("/..", previndex)) {
|
||||
int prevEnd = 0;
|
||||
do {
|
||||
int match = docrootMatcher.start();
|
||||
// append htmlstr up to start of next {@docroot}
|
||||
buf.append(htmlstr.substring(prevEnd, match));
|
||||
prevEnd = docrootMatcher.end();
|
||||
if (configuration.docrootparent.length() > 0 && htmlstr.startsWith("/..", prevEnd)) {
|
||||
// Insert the absolute link if {@docRoot} is followed by "/..".
|
||||
buf.append(configuration.docrootparent);
|
||||
previndex += 3;
|
||||
prevEnd += 3;
|
||||
} else {
|
||||
// Insert relative path where {@docRoot} was located
|
||||
buf.append(pathToRoot.isEmpty() ? "." : pathToRoot.getPath());
|
||||
}
|
||||
// Append slash if next character is not a slash
|
||||
if (previndex < htmlstr.length() && htmlstr.charAt(previndex) != '/') {
|
||||
if (prevEnd < htmlstr.length() && htmlstr.charAt(prevEnd) != '/') {
|
||||
buf.append('/');
|
||||
}
|
||||
}
|
||||
} while (docrootMatcher.find());
|
||||
buf.append(htmlstr.substring(prevEnd));
|
||||
return buf.toString();
|
||||
}
|
||||
//where:
|
||||
// Note: {@docRoot} is not case sensitive when passed in w/command line option:
|
||||
private static final Pattern docrootPattern =
|
||||
Pattern.compile(Pattern.quote("{@docroot}"), Pattern.CASE_INSENSITIVE);
|
||||
|
||||
/**
|
||||
* Get the script to show or hide the All classes link.
|
||||
@ -1690,13 +1687,13 @@ public class HtmlDocletWriter extends HtmlDocWriter {
|
||||
}
|
||||
|
||||
//Redirect all relative links.
|
||||
int end, begin = StringUtils.toLowerCase(text).indexOf("<a");
|
||||
int end, begin = StringUtils.indexOfIgnoreCase(text, "<a");
|
||||
if(begin >= 0){
|
||||
StringBuilder textBuff = new StringBuilder(text);
|
||||
|
||||
while(begin >=0){
|
||||
if (textBuff.length() > begin + 2 && ! Character.isWhitespace(textBuff.charAt(begin+2))) {
|
||||
begin = StringUtils.toLowerCase(textBuff.toString()).indexOf("<a", begin + 1);
|
||||
begin = StringUtils.indexOfIgnoreCase(textBuff.toString(), "<a", begin + 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1736,7 +1733,7 @@ public class HtmlDocletWriter extends HtmlDocWriter {
|
||||
+ redirectPathFromRoot.resolve(relativeLink).getPath();
|
||||
textBuff.replace(begin, end, relativeLink);
|
||||
}
|
||||
begin = StringUtils.toLowerCase(textBuff.toString()).indexOf("<a", begin + 1);
|
||||
begin = StringUtils.indexOfIgnoreCase(textBuff.toString(), "<a", begin + 1);
|
||||
}
|
||||
return textBuff.toString();
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -331,24 +331,6 @@ public class MethodWriterImpl extends AbstractExecutableMemberWriter
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the <Code> tag and return the text.
|
||||
*/
|
||||
protected String parseCodeTag(String tag){
|
||||
if(tag == null){
|
||||
return "";
|
||||
}
|
||||
|
||||
String lc = StringUtils.toLowerCase(tag);
|
||||
int begin = lc.indexOf("<code>");
|
||||
int end = lc.indexOf("</code>");
|
||||
if(begin == -1 || end == -1 || end <= begin){
|
||||
return tag;
|
||||
} else {
|
||||
return tag.substring(begin + 6, end);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
|
||||
@ -0,0 +1,537 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.javac.code;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
import javax.lang.model.SourceVersion;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.JavaFileManager;
|
||||
import javax.tools.JavaFileManager.Location;
|
||||
import javax.tools.StandardJavaFileManager;
|
||||
|
||||
import static javax.tools.StandardLocation.*;
|
||||
|
||||
import com.sun.tools.javac.comp.Annotate;
|
||||
import com.sun.tools.javac.code.Symbol.*;
|
||||
import com.sun.tools.javac.jvm.ClassReader;
|
||||
import com.sun.tools.javac.util.*;
|
||||
|
||||
import static com.sun.tools.javac.code.Flags.*;
|
||||
import static com.sun.tools.javac.code.Kinds.*;
|
||||
|
||||
import static com.sun.tools.javac.main.Option.*;
|
||||
|
||||
/**
|
||||
* This class provides operations to locate class definitions
|
||||
* from the source and class files on the paths provided to javac.
|
||||
*
|
||||
* <p><b>This is NOT part of any supported API.
|
||||
* If you write code that depends on this, you do so at your own risk.
|
||||
* This code and its internal interfaces are subject to change or
|
||||
* deletion without notice.</b>
|
||||
*/
|
||||
public class ClassFinder {
|
||||
/** The context key for the class finder. */
|
||||
protected static final Context.Key<ClassFinder> classFinderKey = new Context.Key<>();
|
||||
|
||||
ClassReader reader;
|
||||
|
||||
Annotate annotate;
|
||||
|
||||
/** Switch: verbose output.
|
||||
*/
|
||||
boolean verbose;
|
||||
|
||||
/**
|
||||
* Switch: cache completion failures unless -XDdev is used
|
||||
*/
|
||||
private boolean cacheCompletionFailure;
|
||||
|
||||
/**
|
||||
* Switch: prefer source files instead of newer when both source
|
||||
* and class are available
|
||||
**/
|
||||
protected boolean preferSource;
|
||||
|
||||
/**
|
||||
* Switch: Search classpath and sourcepath for classes before the
|
||||
* bootclasspath
|
||||
*/
|
||||
protected boolean userPathsFirst;
|
||||
|
||||
/** The log to use for verbose output
|
||||
*/
|
||||
final Log log;
|
||||
|
||||
/** The symbol table. */
|
||||
Symtab syms;
|
||||
|
||||
/** The name table. */
|
||||
final Names names;
|
||||
|
||||
/** Force a completion failure on this name
|
||||
*/
|
||||
final Name completionFailureName;
|
||||
|
||||
/** Access to files
|
||||
*/
|
||||
private final JavaFileManager fileManager;
|
||||
|
||||
/** Factory for diagnostics
|
||||
*/
|
||||
JCDiagnostic.Factory diagFactory;
|
||||
|
||||
/** Can be reassigned from outside:
|
||||
* the completer to be used for ".java" files. If this remains unassigned
|
||||
* ".java" files will not be loaded.
|
||||
*/
|
||||
public Completer sourceCompleter = null;
|
||||
|
||||
/** The path name of the class file currently being read.
|
||||
*/
|
||||
protected JavaFileObject currentClassFile = null;
|
||||
|
||||
/** The class or method currently being read.
|
||||
*/
|
||||
protected Symbol currentOwner = null;
|
||||
|
||||
/**
|
||||
* Completer that delegates to the complete-method of this class.
|
||||
*/
|
||||
private final Completer thisCompleter = new Completer() {
|
||||
@Override
|
||||
public void complete(Symbol sym) throws CompletionFailure {
|
||||
ClassFinder.this.complete(sym);
|
||||
}
|
||||
};
|
||||
|
||||
public Completer getCompleter() {
|
||||
return thisCompleter;
|
||||
}
|
||||
|
||||
/** Get the ClassFinder instance for this invocation. */
|
||||
public static ClassFinder instance(Context context) {
|
||||
ClassFinder instance = context.get(classFinderKey);
|
||||
if (instance == null)
|
||||
instance = new ClassFinder(context);
|
||||
return instance;
|
||||
}
|
||||
|
||||
/** Construct a new class reader. */
|
||||
protected ClassFinder(Context context) {
|
||||
context.put(classFinderKey, this);
|
||||
reader = ClassReader.instance(context);
|
||||
names = Names.instance(context);
|
||||
syms = Symtab.instance(context);
|
||||
fileManager = context.get(JavaFileManager.class);
|
||||
if (fileManager == null)
|
||||
throw new AssertionError("FileManager initialization error");
|
||||
diagFactory = JCDiagnostic.Factory.instance(context);
|
||||
|
||||
log = Log.instance(context);
|
||||
annotate = Annotate.instance(context);
|
||||
|
||||
Options options = Options.instance(context);
|
||||
verbose = options.isSet(VERBOSE);
|
||||
cacheCompletionFailure = options.isUnset("dev");
|
||||
preferSource = "source".equals(options.get("-Xprefer"));
|
||||
userPathsFirst = options.isSet(XXUSERPATHSFIRST);
|
||||
|
||||
|
||||
completionFailureName =
|
||||
options.isSet("failcomplete")
|
||||
? names.fromString(options.get("failcomplete"))
|
||||
: null;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Loading Classes
|
||||
***********************************************************************/
|
||||
|
||||
/** Completion for classes to be loaded. Before a class is loaded
|
||||
* we make sure its enclosing class (if any) is loaded.
|
||||
*/
|
||||
private void complete(Symbol sym) throws CompletionFailure {
|
||||
if (sym.kind == TYP) {
|
||||
ClassSymbol c = (ClassSymbol)sym;
|
||||
c.members_field = new Scope.ErrorScope(c); // make sure it's always defined
|
||||
annotate.enterStart();
|
||||
try {
|
||||
completeOwners(c.owner);
|
||||
completeEnclosing(c);
|
||||
} finally {
|
||||
// The flush needs to happen only after annotations
|
||||
// are filled in.
|
||||
annotate.enterDoneWithoutFlush();
|
||||
}
|
||||
fillIn(c);
|
||||
} else if (sym.kind == PCK) {
|
||||
PackageSymbol p = (PackageSymbol)sym;
|
||||
try {
|
||||
fillIn(p);
|
||||
} catch (IOException ex) {
|
||||
throw new CompletionFailure(sym, ex.getLocalizedMessage()).initCause(ex);
|
||||
}
|
||||
}
|
||||
if (!reader.filling)
|
||||
annotate.flush(); // finish attaching annotations
|
||||
}
|
||||
|
||||
/** complete up through the enclosing package. */
|
||||
private void completeOwners(Symbol o) {
|
||||
if (o.kind != PCK) completeOwners(o.owner);
|
||||
o.complete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to complete lexically enclosing classes if c looks like a
|
||||
* nested class. This is similar to completeOwners but handles
|
||||
* the situation when a nested class is accessed directly as it is
|
||||
* possible with the Tree API or javax.lang.model.*.
|
||||
*/
|
||||
private void completeEnclosing(ClassSymbol c) {
|
||||
if (c.owner.kind == PCK) {
|
||||
Symbol owner = c.owner;
|
||||
for (Name name : Convert.enclosingCandidates(Convert.shortName(c.name))) {
|
||||
Symbol encl = owner.members().lookup(name).sym;
|
||||
if (encl == null)
|
||||
encl = syms.classes.get(TypeSymbol.formFlatName(name, owner));
|
||||
if (encl != null)
|
||||
encl.complete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Fill in definition of class `c' from corresponding class or
|
||||
* source file.
|
||||
*/
|
||||
private void fillIn(ClassSymbol c) {
|
||||
if (completionFailureName == c.fullname) {
|
||||
throw new CompletionFailure(c, "user-selected completion failure by class name");
|
||||
}
|
||||
currentOwner = c;
|
||||
JavaFileObject classfile = c.classfile;
|
||||
if (classfile != null) {
|
||||
JavaFileObject previousClassFile = currentClassFile;
|
||||
try {
|
||||
if (reader.filling) {
|
||||
Assert.error("Filling " + classfile.toUri() + " during " + previousClassFile);
|
||||
}
|
||||
currentClassFile = classfile;
|
||||
if (verbose) {
|
||||
log.printVerbose("loading", currentClassFile.toString());
|
||||
}
|
||||
if (classfile.getKind() == JavaFileObject.Kind.CLASS) {
|
||||
reader.readClassFile(c);
|
||||
} else {
|
||||
if (sourceCompleter != null) {
|
||||
sourceCompleter.complete(c);
|
||||
} else {
|
||||
throw new IllegalStateException("Source completer required to read "
|
||||
+ classfile.toUri());
|
||||
}
|
||||
}
|
||||
return;
|
||||
} finally {
|
||||
currentClassFile = previousClassFile;
|
||||
}
|
||||
} else {
|
||||
JCDiagnostic diag =
|
||||
diagFactory.fragment("class.file.not.found", c.flatname);
|
||||
throw
|
||||
newCompletionFailure(c, diag);
|
||||
}
|
||||
}
|
||||
// where
|
||||
/** Static factory for CompletionFailure objects.
|
||||
* In practice, only one can be used at a time, so we share one
|
||||
* to reduce the expense of allocating new exception objects.
|
||||
*/
|
||||
private CompletionFailure newCompletionFailure(TypeSymbol c,
|
||||
JCDiagnostic diag) {
|
||||
if (!cacheCompletionFailure) {
|
||||
// log.warning("proc.messager",
|
||||
// Log.getLocalizedString("class.file.not.found", c.flatname));
|
||||
// c.debug.printStackTrace();
|
||||
return new CompletionFailure(c, diag);
|
||||
} else {
|
||||
CompletionFailure result = cachedCompletionFailure;
|
||||
result.sym = c;
|
||||
result.diag = diag;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
private CompletionFailure cachedCompletionFailure =
|
||||
new CompletionFailure(null, (JCDiagnostic) null);
|
||||
{
|
||||
cachedCompletionFailure.setStackTrace(new StackTraceElement[0]);
|
||||
}
|
||||
|
||||
|
||||
/** Load a toplevel class with given fully qualified name
|
||||
* The class is entered into `classes' only if load was successful.
|
||||
*/
|
||||
public ClassSymbol loadClass(Name flatname) throws CompletionFailure {
|
||||
boolean absent = syms.classes.get(flatname) == null;
|
||||
ClassSymbol c = syms.enterClass(flatname);
|
||||
if (c.members_field == null && c.completer != null) {
|
||||
try {
|
||||
c.complete();
|
||||
} catch (CompletionFailure ex) {
|
||||
if (absent) syms.classes.remove(flatname);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Loading Packages
|
||||
***********************************************************************/
|
||||
|
||||
/** Include class corresponding to given class file in package,
|
||||
* unless (1) we already have one the same kind (.class or .java), or
|
||||
* (2) we have one of the other kind, and the given class file
|
||||
* is older.
|
||||
*/
|
||||
protected void includeClassFile(PackageSymbol p, JavaFileObject file) {
|
||||
if ((p.flags_field & EXISTS) == 0)
|
||||
for (Symbol q = p; q != null && q.kind == PCK; q = q.owner)
|
||||
q.flags_field |= EXISTS;
|
||||
JavaFileObject.Kind kind = file.getKind();
|
||||
int seen;
|
||||
if (kind == JavaFileObject.Kind.CLASS)
|
||||
seen = CLASS_SEEN;
|
||||
else
|
||||
seen = SOURCE_SEEN;
|
||||
String binaryName = fileManager.inferBinaryName(currentLoc, file);
|
||||
int lastDot = binaryName.lastIndexOf(".");
|
||||
Name classname = names.fromString(binaryName.substring(lastDot + 1));
|
||||
boolean isPkgInfo = classname == names.package_info;
|
||||
ClassSymbol c = isPkgInfo
|
||||
? p.package_info
|
||||
: (ClassSymbol) p.members_field.lookup(classname).sym;
|
||||
if (c == null) {
|
||||
c = syms.enterClass(classname, p);
|
||||
if (c.classfile == null) // only update the file if's it's newly created
|
||||
c.classfile = file;
|
||||
if (isPkgInfo) {
|
||||
p.package_info = c;
|
||||
} else {
|
||||
if (c.owner == p) // it might be an inner class
|
||||
p.members_field.enter(c);
|
||||
}
|
||||
} else if (!preferCurrent && c.classfile != null && (c.flags_field & seen) == 0) {
|
||||
// if c.classfile == null, we are currently compiling this class
|
||||
// and no further action is necessary.
|
||||
// if (c.flags_field & seen) != 0, we have already encountered
|
||||
// a file of the same kind; again no further action is necessary.
|
||||
if ((c.flags_field & (CLASS_SEEN | SOURCE_SEEN)) != 0)
|
||||
c.classfile = preferredFileObject(file, c.classfile);
|
||||
}
|
||||
c.flags_field |= seen;
|
||||
}
|
||||
|
||||
/** Implement policy to choose to derive information from a source
|
||||
* file or a class file when both are present. May be overridden
|
||||
* by subclasses.
|
||||
*/
|
||||
protected JavaFileObject preferredFileObject(JavaFileObject a,
|
||||
JavaFileObject b) {
|
||||
|
||||
if (preferSource)
|
||||
return (a.getKind() == JavaFileObject.Kind.SOURCE) ? a : b;
|
||||
else {
|
||||
long adate = a.getLastModified();
|
||||
long bdate = b.getLastModified();
|
||||
// 6449326: policy for bad lastModifiedTime in ClassReader
|
||||
//assert adate >= 0 && bdate >= 0;
|
||||
return (adate > bdate) ? a : b;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* specifies types of files to be read when filling in a package symbol
|
||||
*/
|
||||
protected EnumSet<JavaFileObject.Kind> getPackageFileKinds() {
|
||||
return EnumSet.of(JavaFileObject.Kind.CLASS, JavaFileObject.Kind.SOURCE);
|
||||
}
|
||||
|
||||
/**
|
||||
* this is used to support javadoc
|
||||
*/
|
||||
protected void extraFileActions(PackageSymbol pack, JavaFileObject fe) {
|
||||
}
|
||||
|
||||
protected Location currentLoc; // FIXME
|
||||
|
||||
private boolean verbosePath = true;
|
||||
|
||||
// Set to true when the currently selected file should be kept
|
||||
private boolean preferCurrent;
|
||||
|
||||
/** Load directory of package into members scope.
|
||||
*/
|
||||
private void fillIn(PackageSymbol p) throws IOException {
|
||||
if (p.members_field == null)
|
||||
p.members_field = new Scope(p);
|
||||
|
||||
preferCurrent = false;
|
||||
if (userPathsFirst) {
|
||||
scanUserPaths(p);
|
||||
preferCurrent = true;
|
||||
scanPlatformPath(p);
|
||||
} else {
|
||||
scanPlatformPath(p);
|
||||
scanUserPaths(p);
|
||||
}
|
||||
verbosePath = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans class path and source path for files in given package.
|
||||
*/
|
||||
private void scanUserPaths(PackageSymbol p) throws IOException {
|
||||
Set<JavaFileObject.Kind> kinds = getPackageFileKinds();
|
||||
|
||||
Set<JavaFileObject.Kind> classKinds = EnumSet.copyOf(kinds);
|
||||
classKinds.remove(JavaFileObject.Kind.SOURCE);
|
||||
boolean wantClassFiles = !classKinds.isEmpty();
|
||||
|
||||
Set<JavaFileObject.Kind> sourceKinds = EnumSet.copyOf(kinds);
|
||||
sourceKinds.remove(JavaFileObject.Kind.CLASS);
|
||||
boolean wantSourceFiles = !sourceKinds.isEmpty();
|
||||
|
||||
boolean haveSourcePath = fileManager.hasLocation(SOURCE_PATH);
|
||||
|
||||
if (verbose && verbosePath) {
|
||||
if (fileManager instanceof StandardJavaFileManager) {
|
||||
StandardJavaFileManager fm = (StandardJavaFileManager)fileManager;
|
||||
if (haveSourcePath && wantSourceFiles) {
|
||||
List<File> path = List.nil();
|
||||
for (File file : fm.getLocation(SOURCE_PATH)) {
|
||||
path = path.prepend(file);
|
||||
}
|
||||
log.printVerbose("sourcepath", path.reverse().toString());
|
||||
} else if (wantSourceFiles) {
|
||||
List<File> path = List.nil();
|
||||
for (File file : fm.getLocation(CLASS_PATH)) {
|
||||
path = path.prepend(file);
|
||||
}
|
||||
log.printVerbose("sourcepath", path.reverse().toString());
|
||||
}
|
||||
if (wantClassFiles) {
|
||||
List<File> path = List.nil();
|
||||
for (File file : fm.getLocation(PLATFORM_CLASS_PATH)) {
|
||||
path = path.prepend(file);
|
||||
}
|
||||
for (File file : fm.getLocation(CLASS_PATH)) {
|
||||
path = path.prepend(file);
|
||||
}
|
||||
log.printVerbose("classpath", path.reverse().toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String packageName = p.fullname.toString();
|
||||
if (wantSourceFiles && !haveSourcePath) {
|
||||
fillIn(p, CLASS_PATH,
|
||||
fileManager.list(CLASS_PATH,
|
||||
packageName,
|
||||
kinds,
|
||||
false));
|
||||
} else {
|
||||
if (wantClassFiles)
|
||||
fillIn(p, CLASS_PATH,
|
||||
fileManager.list(CLASS_PATH,
|
||||
packageName,
|
||||
classKinds,
|
||||
false));
|
||||
if (wantSourceFiles)
|
||||
fillIn(p, SOURCE_PATH,
|
||||
fileManager.list(SOURCE_PATH,
|
||||
packageName,
|
||||
sourceKinds,
|
||||
false));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans platform class path for files in given package.
|
||||
*/
|
||||
private void scanPlatformPath(PackageSymbol p) throws IOException {
|
||||
fillIn(p, PLATFORM_CLASS_PATH,
|
||||
fileManager.list(PLATFORM_CLASS_PATH,
|
||||
p.fullname.toString(),
|
||||
EnumSet.of(JavaFileObject.Kind.CLASS),
|
||||
false));
|
||||
}
|
||||
// where
|
||||
private void fillIn(PackageSymbol p,
|
||||
Location location,
|
||||
Iterable<JavaFileObject> files)
|
||||
{
|
||||
currentLoc = location;
|
||||
for (JavaFileObject fo : files) {
|
||||
switch (fo.getKind()) {
|
||||
case CLASS:
|
||||
case SOURCE: {
|
||||
// TODO pass binaryName to includeClassFile
|
||||
String binaryName = fileManager.inferBinaryName(currentLoc, fo);
|
||||
String simpleName = binaryName.substring(binaryName.lastIndexOf(".") + 1);
|
||||
if (SourceVersion.isIdentifier(simpleName) ||
|
||||
simpleName.equals("package-info"))
|
||||
includeClassFile(p, fo);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
extraFileActions(p, fo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for bad class definition files, such as bad .class files or
|
||||
* for .java files with unexpected package or class names.
|
||||
*/
|
||||
public static class BadClassFile extends CompletionFailure {
|
||||
private static final long serialVersionUID = 0;
|
||||
|
||||
public BadClassFile(TypeSymbol sym, JavaFileObject file, JCDiagnostic diag,
|
||||
JCDiagnostic.Factory diagFactory) {
|
||||
super(sym, createBadClassFileDiagnostic(file, diag, diagFactory));
|
||||
}
|
||||
// where
|
||||
private static JCDiagnostic createBadClassFileDiagnostic(
|
||||
JavaFileObject file, JCDiagnostic diag, JCDiagnostic.Factory diagFactory) {
|
||||
String key = (file.getKind() == JavaFileObject.Kind.SOURCE
|
||||
? "bad.source.file.header" : "bad.class.file.header");
|
||||
return diagFactory.fragment(key, file, diag);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -50,7 +50,6 @@ import com.sun.tools.javac.code.Type.JCVoidType;
|
||||
import com.sun.tools.javac.code.Type.MethodType;
|
||||
import com.sun.tools.javac.code.Type.UnknownType;
|
||||
import com.sun.tools.javac.jvm.ByteCodes;
|
||||
import com.sun.tools.javac.jvm.ClassReader;
|
||||
import com.sun.tools.javac.jvm.Target;
|
||||
import com.sun.tools.javac.util.Assert;
|
||||
import com.sun.tools.javac.util.Context;
|
||||
@ -470,8 +469,8 @@ public class Symtab {
|
||||
Scope scope = new Scope(predefClass);
|
||||
predefClass.members_field = scope;
|
||||
|
||||
// Get the initial completer for Symbols from the ClassReader
|
||||
initialCompleter = ClassReader.instance(context).getCompleter();
|
||||
// Get the initial completer for Symbols from the ClassFinder
|
||||
initialCompleter = ClassFinder.instance(context).getCompleter();
|
||||
rootPackage.completer = initialCompleter;
|
||||
unnamedPackage.completer = initialCompleter;
|
||||
|
||||
|
||||
@ -42,9 +42,8 @@ import com.sun.tools.javac.comp.AttrContext;
|
||||
import com.sun.tools.javac.comp.Check;
|
||||
import com.sun.tools.javac.comp.Enter;
|
||||
import com.sun.tools.javac.comp.Env;
|
||||
import com.sun.tools.javac.jvm.ClassReader;
|
||||
import com.sun.tools.javac.tree.JCTree;
|
||||
import com.sun.tools.javac.util.*;
|
||||
|
||||
import static com.sun.tools.javac.code.BoundKind.*;
|
||||
import static com.sun.tools.javac.code.Flags.*;
|
||||
import static com.sun.tools.javac.code.Scope.*;
|
||||
@ -84,7 +83,6 @@ public class Types {
|
||||
final boolean allowBoxing;
|
||||
final boolean allowCovariantReturns;
|
||||
final boolean allowObjectToPrimitiveCast;
|
||||
final ClassReader reader;
|
||||
final Check chk;
|
||||
final Enter enter;
|
||||
JCDiagnostic.Factory diags;
|
||||
@ -110,7 +108,6 @@ public class Types {
|
||||
allowBoxing = source.allowBoxing();
|
||||
allowCovariantReturns = source.allowCovariantReturns();
|
||||
allowObjectToPrimitiveCast = source.allowObjectToPrimitiveCast();
|
||||
reader = ClassReader.instance(context);
|
||||
chk = Check.instance(context);
|
||||
enter = Enter.instance(context);
|
||||
capturedName = names.fromString("<captured wildcard>");
|
||||
|
||||
@ -282,7 +282,7 @@ public class Check {
|
||||
*/
|
||||
public Type completionError(DiagnosticPosition pos, CompletionFailure ex) {
|
||||
log.error(JCDiagnostic.DiagnosticFlag.NON_DEFERRABLE, pos, "cant.access", ex.sym, ex.getDetailValue());
|
||||
if (ex instanceof ClassReader.BadClassFile
|
||||
if (ex instanceof ClassFinder.BadClassFile
|
||||
&& !suppressAbortOnBadClassFile) throw new Abort();
|
||||
else return syms.errType;
|
||||
}
|
||||
|
||||
@ -96,7 +96,6 @@ public class Enter extends JCTree.Visitor {
|
||||
Symtab syms;
|
||||
Check chk;
|
||||
TreeMaker make;
|
||||
ClassReader reader;
|
||||
Annotate annotate;
|
||||
MemberEnter memberEnter;
|
||||
Types types;
|
||||
@ -118,7 +117,6 @@ public class Enter extends JCTree.Visitor {
|
||||
context.put(enterKey, this);
|
||||
|
||||
log = Log.instance(context);
|
||||
reader = ClassReader.instance(context);
|
||||
make = TreeMaker.instance(context);
|
||||
syms = Symtab.instance(context);
|
||||
chk = Check.instance(context);
|
||||
|
||||
@ -67,25 +67,24 @@ public class Lower extends TreeTranslator {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private Names names;
|
||||
private Log log;
|
||||
private Symtab syms;
|
||||
private Resolve rs;
|
||||
private Check chk;
|
||||
private Attr attr;
|
||||
private final Names names;
|
||||
private final Log log;
|
||||
private final Symtab syms;
|
||||
private final Resolve rs;
|
||||
private final Check chk;
|
||||
private final Attr attr;
|
||||
private TreeMaker make;
|
||||
private DiagnosticPosition make_pos;
|
||||
private ClassWriter writer;
|
||||
private ClassReader reader;
|
||||
private ConstFold cfolder;
|
||||
private Target target;
|
||||
private Source source;
|
||||
private boolean allowEnums;
|
||||
private final ClassWriter writer;
|
||||
private final ConstFold cfolder;
|
||||
private final Target target;
|
||||
private final Source source;
|
||||
private final boolean allowEnums;
|
||||
private final Name dollarAssertionsDisabled;
|
||||
private final Name classDollar;
|
||||
private Types types;
|
||||
private boolean debugLower;
|
||||
private PkgInfo pkginfoOpt;
|
||||
private final Types types;
|
||||
private final boolean debugLower;
|
||||
private final PkgInfo pkginfoOpt;
|
||||
|
||||
protected Lower(Context context) {
|
||||
context.put(lowerKey, this);
|
||||
@ -97,7 +96,6 @@ public class Lower extends TreeTranslator {
|
||||
attr = Attr.instance(context);
|
||||
make = TreeMaker.instance(context);
|
||||
writer = ClassWriter.instance(context);
|
||||
reader = ClassReader.instance(context);
|
||||
cfolder = ConstFold.instance(context);
|
||||
target = Target.instance(context);
|
||||
source = Source.instance(context);
|
||||
|
||||
@ -25,10 +25,7 @@
|
||||
|
||||
package com.sun.tools.javac.comp;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.tools.JavaFileObject;
|
||||
@ -49,6 +46,7 @@ import static com.sun.tools.javac.code.TypeTag.CLASS;
|
||||
import static com.sun.tools.javac.code.TypeTag.ERROR;
|
||||
import static com.sun.tools.javac.code.TypeTag.TYPEVAR;
|
||||
import static com.sun.tools.javac.tree.JCTree.Tag.*;
|
||||
|
||||
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
|
||||
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
|
||||
|
||||
@ -75,7 +73,6 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
private final Attr attr;
|
||||
private final Symtab syms;
|
||||
private final TreeMaker make;
|
||||
private final ClassReader reader;
|
||||
private final Todo todo;
|
||||
private final Annotate annotate;
|
||||
private final TypeAnnotations typeAnnotations;
|
||||
@ -102,7 +99,6 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
attr = Attr.instance(context);
|
||||
syms = Symtab.instance(context);
|
||||
make = TreeMaker.instance(context);
|
||||
reader = ClassReader.instance(context);
|
||||
todo = Todo.instance(context);
|
||||
annotate = Annotate.instance(context);
|
||||
typeAnnotations = TypeAnnotations.instance(context);
|
||||
|
||||
@ -87,7 +87,7 @@ public class Resolve {
|
||||
DeferredAttr deferredAttr;
|
||||
Check chk;
|
||||
Infer infer;
|
||||
ClassReader reader;
|
||||
ClassFinder finder;
|
||||
TreeInfo treeinfo;
|
||||
Types types;
|
||||
JCDiagnostic.Factory diags;
|
||||
@ -121,7 +121,7 @@ public class Resolve {
|
||||
deferredAttr = DeferredAttr.instance(context);
|
||||
chk = Check.instance(context);
|
||||
infer = Infer.instance(context);
|
||||
reader = ClassReader.instance(context);
|
||||
finder = ClassFinder.instance(context);
|
||||
treeinfo = TreeInfo.instance(context);
|
||||
types = Types.instance(context);
|
||||
diags = JCDiagnostic.Factory.instance(context);
|
||||
@ -1886,9 +1886,9 @@ public class Resolve {
|
||||
*/
|
||||
Symbol loadClass(Env<AttrContext> env, Name name) {
|
||||
try {
|
||||
ClassSymbol c = reader.loadClass(name);
|
||||
ClassSymbol c = finder.loadClass(name);
|
||||
return isAccessible(env, c) ? c : new AccessError(c);
|
||||
} catch (ClassReader.BadClassFile err) {
|
||||
} catch (ClassFinder.BadClassFile err) {
|
||||
throw err;
|
||||
} catch (CompletionFailure ex) {
|
||||
return typeNotFound;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -108,11 +108,21 @@ public class ClassFile {
|
||||
V50(50, 0), // JDK 1.6: stackmaps
|
||||
V51(51, 0), // JDK 1.7
|
||||
V52(52, 0); // JDK 1.8: lambda, type annos, param names
|
||||
// JDK9 still marked as V52 // V53(53, 0); // JDK 1.9
|
||||
|
||||
Version(int major, int minor) {
|
||||
this.major = major;
|
||||
this.minor = minor;
|
||||
}
|
||||
public final int major, minor;
|
||||
|
||||
private static final Version MIN = values()[0];
|
||||
/** Return the least version supported, MIN */
|
||||
public static Version MIN() { return MIN; }
|
||||
|
||||
private static final Version MAX = values()[values().length-1];
|
||||
/** Return the largest version supported, MAX */
|
||||
public static Version MAX() { return MAX; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -35,13 +35,8 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.lang.model.SourceVersion;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.JavaFileManager;
|
||||
import javax.tools.JavaFileManager.Location;
|
||||
import javax.tools.StandardJavaFileManager;
|
||||
|
||||
import static javax.tools.StandardLocation.*;
|
||||
|
||||
import com.sun.tools.javac.comp.Annotate;
|
||||
import com.sun.tools.javac.code.*;
|
||||
@ -119,23 +114,6 @@ public class ClassReader {
|
||||
*/
|
||||
public boolean saveParameterNames;
|
||||
|
||||
/**
|
||||
* Switch: cache completion failures unless -XDdev is used
|
||||
*/
|
||||
private boolean cacheCompletionFailure;
|
||||
|
||||
/**
|
||||
* Switch: prefer source files instead of newer when both source
|
||||
* and class are available
|
||||
**/
|
||||
public boolean preferSource;
|
||||
|
||||
/**
|
||||
* Switch: Search classpath and sourcepath for classes before the
|
||||
* bootclasspath
|
||||
*/
|
||||
public boolean userPathsFirst;
|
||||
|
||||
/**
|
||||
* The currently selected profile.
|
||||
*/
|
||||
@ -153,10 +131,6 @@ public class ClassReader {
|
||||
/** The name table. */
|
||||
final Names names;
|
||||
|
||||
/** Force a completion failure on this name
|
||||
*/
|
||||
final Name completionFailureName;
|
||||
|
||||
/** Access to files
|
||||
*/
|
||||
private final JavaFileManager fileManager;
|
||||
@ -165,12 +139,6 @@ public class ClassReader {
|
||||
*/
|
||||
JCDiagnostic.Factory diagFactory;
|
||||
|
||||
/** Can be reassigned from outside:
|
||||
* the completer to be used for ".java" files. If this remains unassigned
|
||||
* ".java" files will not be loaded.
|
||||
*/
|
||||
public SourceCompleter sourceCompleter = null;
|
||||
|
||||
/** The current scope where type variables are entered.
|
||||
*/
|
||||
protected Scope typevars;
|
||||
@ -227,20 +195,6 @@ public class ClassReader {
|
||||
*/
|
||||
Set<Name> warnedAttrs = new HashSet<>();
|
||||
|
||||
/**
|
||||
* Completer that delegates to the complete-method of this class.
|
||||
*/
|
||||
private final Completer thisCompleter = new Completer() {
|
||||
@Override
|
||||
public void complete(Symbol sym) throws CompletionFailure {
|
||||
ClassReader.this.complete(sym);
|
||||
}
|
||||
};
|
||||
|
||||
public Completer getCompleter() {
|
||||
return thisCompleter;
|
||||
}
|
||||
|
||||
/** Get the ClassReader instance for this invocation. */
|
||||
public static ClassReader instance(Context context) {
|
||||
ClassReader instance = context.get(classReaderKey);
|
||||
@ -274,17 +228,9 @@ public class ClassReader {
|
||||
allowSimplifiedVarargs = source.allowSimplifiedVarargs();
|
||||
|
||||
saveParameterNames = options.isSet("save-parameter-names");
|
||||
cacheCompletionFailure = options.isUnset("dev");
|
||||
preferSource = "source".equals(options.get("-Xprefer"));
|
||||
userPathsFirst = options.isSet(XXUSERPATHSFIRST);
|
||||
|
||||
profile = Profile.instance(context);
|
||||
|
||||
completionFailureName =
|
||||
options.isSet("failcomplete")
|
||||
? names.fromString(options.get("failcomplete"))
|
||||
: null;
|
||||
|
||||
typevars = new Scope(syms.noSymbol);
|
||||
|
||||
lintClassfile = Lint.instance(context).isEnabled(LintCategory.CLASSFILE);
|
||||
@ -305,26 +251,12 @@ public class ClassReader {
|
||||
* Error Diagnoses
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
public class BadClassFile extends CompletionFailure {
|
||||
private static final long serialVersionUID = 0;
|
||||
|
||||
public BadClassFile(TypeSymbol sym, JavaFileObject file, JCDiagnostic diag) {
|
||||
super(sym, createBadClassFileDiagnostic(file, diag));
|
||||
}
|
||||
}
|
||||
// where
|
||||
private JCDiagnostic createBadClassFileDiagnostic(JavaFileObject file, JCDiagnostic diag) {
|
||||
String key = (file.getKind() == JavaFileObject.Kind.SOURCE
|
||||
? "bad.source.file.header" : "bad.class.file.header");
|
||||
return diagFactory.fragment(key, file, diag);
|
||||
}
|
||||
|
||||
public BadClassFile badClassFile(String key, Object... args) {
|
||||
return new BadClassFile (
|
||||
public ClassFinder.BadClassFile badClassFile(String key, Object... args) {
|
||||
return new ClassFinder.BadClassFile (
|
||||
currentOwner.enclClass(),
|
||||
currentClassFile,
|
||||
diagFactory.fragment(key, args));
|
||||
diagFactory.fragment(key, args),
|
||||
diagFactory);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
@ -1501,7 +1433,7 @@ public class ClassReader {
|
||||
int tag = nextByte(); // TargetType tag is a byte
|
||||
|
||||
if (!TargetType.isValidTargetTypeValue(tag))
|
||||
throw this.badClassFile("bad.type.annotation.value", String.format("0x%02X", tag));
|
||||
throw badClassFile("bad.type.annotation.value", String.format("0x%02X", tag));
|
||||
|
||||
TargetType type = TargetType.fromTargetTypeValue(tag);
|
||||
|
||||
@ -2080,8 +2012,8 @@ public class ClassReader {
|
||||
Type type = readType(nextChar());
|
||||
if (currentOwner.isInterface() &&
|
||||
(flags & ABSTRACT) == 0 && !name.equals(names.clinit)) {
|
||||
if (majorVersion > Target.JDK1_8.majorVersion ||
|
||||
(majorVersion == Target.JDK1_8.majorVersion && minorVersion >= Target.JDK1_8.minorVersion)) {
|
||||
if (majorVersion > Version.V52.major ||
|
||||
(majorVersion == Version.V52.major && minorVersion >= Version.V52.minor)) {
|
||||
if ((flags & STATIC) == 0) {
|
||||
currentOwner.flags_field |= DEFAULT;
|
||||
flags |= DEFAULT | ABSTRACT;
|
||||
@ -2353,20 +2285,20 @@ public class ClassReader {
|
||||
}
|
||||
}
|
||||
|
||||
/** Read a class file.
|
||||
/** Read a class definition from the bytes in buf.
|
||||
*/
|
||||
private void readClassFile(ClassSymbol c) throws IOException {
|
||||
private void readClassBuffer(ClassSymbol c) throws IOException {
|
||||
int magic = nextInt();
|
||||
if (magic != JAVA_MAGIC)
|
||||
throw badClassFile("illegal.start.of.class.file");
|
||||
|
||||
minorVersion = nextChar();
|
||||
majorVersion = nextChar();
|
||||
int maxMajor = Target.MAX().majorVersion;
|
||||
int maxMinor = Target.MAX().minorVersion;
|
||||
int maxMajor = Version.MAX().major;
|
||||
int maxMinor = Version.MAX().minor;
|
||||
if (majorVersion > maxMajor ||
|
||||
majorVersion * 1000 + minorVersion <
|
||||
Target.MIN().majorVersion * 1000 + Target.MIN().minorVersion)
|
||||
Version.MIN().major * 1000 + Version.MIN().minor)
|
||||
{
|
||||
if (majorVersion == (maxMajor + 1))
|
||||
log.warning("big.major.version",
|
||||
@ -2395,162 +2327,39 @@ public class ClassReader {
|
||||
readClass(c);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Adjusting flags
|
||||
***********************************************************************/
|
||||
|
||||
long adjustFieldFlags(long flags) {
|
||||
return flags;
|
||||
}
|
||||
long adjustMethodFlags(long flags) {
|
||||
if ((flags & ACC_BRIDGE) != 0) {
|
||||
flags &= ~ACC_BRIDGE;
|
||||
flags |= BRIDGE;
|
||||
if (!allowGenerics)
|
||||
flags &= ~SYNTHETIC;
|
||||
}
|
||||
if ((flags & ACC_VARARGS) != 0) {
|
||||
flags &= ~ACC_VARARGS;
|
||||
flags |= VARARGS;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
long adjustClassFlags(long flags) {
|
||||
return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Loading Classes
|
||||
***********************************************************************/
|
||||
|
||||
/** Completion for classes to be loaded. Before a class is loaded
|
||||
* we make sure its enclosing class (if any) is loaded.
|
||||
*/
|
||||
private void complete(Symbol sym) throws CompletionFailure {
|
||||
if (sym.kind == TYP) {
|
||||
ClassSymbol c = (ClassSymbol)sym;
|
||||
c.members_field = new Scope.ErrorScope(c); // make sure it's always defined
|
||||
annotate.enterStart();
|
||||
try {
|
||||
completeOwners(c.owner);
|
||||
completeEnclosing(c);
|
||||
} finally {
|
||||
// The flush needs to happen only after annotations
|
||||
// are filled in.
|
||||
annotate.enterDoneWithoutFlush();
|
||||
}
|
||||
fillIn(c);
|
||||
} else if (sym.kind == PCK) {
|
||||
PackageSymbol p = (PackageSymbol)sym;
|
||||
try {
|
||||
fillIn(p);
|
||||
} catch (IOException ex) {
|
||||
throw new CompletionFailure(sym, ex.getLocalizedMessage()).initCause(ex);
|
||||
}
|
||||
}
|
||||
if (!filling)
|
||||
annotate.flush(); // finish attaching annotations
|
||||
}
|
||||
|
||||
/** complete up through the enclosing package. */
|
||||
private void completeOwners(Symbol o) {
|
||||
if (o.kind != PCK) completeOwners(o.owner);
|
||||
o.complete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to complete lexically enclosing classes if c looks like a
|
||||
* nested class. This is similar to completeOwners but handles
|
||||
* the situation when a nested class is accessed directly as it is
|
||||
* possible with the Tree API or javax.lang.model.*.
|
||||
*/
|
||||
private void completeEnclosing(ClassSymbol c) {
|
||||
if (c.owner.kind == PCK) {
|
||||
Symbol owner = c.owner;
|
||||
for (Name name : Convert.enclosingCandidates(Convert.shortName(c.name))) {
|
||||
Symbol encl = owner.members().lookup(name).sym;
|
||||
if (encl == null)
|
||||
encl = syms.classes.get(TypeSymbol.formFlatName(name, owner));
|
||||
if (encl != null)
|
||||
encl.complete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** We can only read a single class file at a time; this
|
||||
* flag keeps track of when we are currently reading a class
|
||||
* file.
|
||||
*/
|
||||
private boolean filling = false;
|
||||
|
||||
/** Fill in definition of class `c' from corresponding class or
|
||||
* source file.
|
||||
*/
|
||||
private void fillIn(ClassSymbol c) {
|
||||
if (completionFailureName == c.fullname) {
|
||||
throw new CompletionFailure(c, "user-selected completion failure by class name");
|
||||
}
|
||||
public void readClassFile(ClassSymbol c) {
|
||||
currentOwner = c;
|
||||
currentClassFile = c.classfile;
|
||||
warnedAttrs.clear();
|
||||
JavaFileObject classfile = c.classfile;
|
||||
if (classfile != null) {
|
||||
JavaFileObject previousClassFile = currentClassFile;
|
||||
try {
|
||||
if (filling) {
|
||||
Assert.error("Filling " + classfile.toUri() + " during " + previousClassFile);
|
||||
}
|
||||
currentClassFile = classfile;
|
||||
if (verbose) {
|
||||
log.printVerbose("loading", currentClassFile.toString());
|
||||
}
|
||||
if (classfile.getKind() == JavaFileObject.Kind.CLASS) {
|
||||
filling = true;
|
||||
try {
|
||||
bp = 0;
|
||||
buf = readInputStream(buf, classfile.openInputStream());
|
||||
readClassFile(c);
|
||||
if (!missingTypeVariables.isEmpty() && !foundTypeVariables.isEmpty()) {
|
||||
List<Type> missing = missingTypeVariables;
|
||||
List<Type> found = foundTypeVariables;
|
||||
missingTypeVariables = List.nil();
|
||||
foundTypeVariables = List.nil();
|
||||
filling = false;
|
||||
ClassType ct = (ClassType)currentOwner.type;
|
||||
ct.supertype_field =
|
||||
types.subst(ct.supertype_field, missing, found);
|
||||
ct.interfaces_field =
|
||||
types.subst(ct.interfaces_field, missing, found);
|
||||
} else if (missingTypeVariables.isEmpty() !=
|
||||
foundTypeVariables.isEmpty()) {
|
||||
Name name = missingTypeVariables.head.tsym.name;
|
||||
throw badClassFile("undecl.type.var", name);
|
||||
}
|
||||
} finally {
|
||||
missingTypeVariables = List.nil();
|
||||
foundTypeVariables = List.nil();
|
||||
filling = false;
|
||||
}
|
||||
} else {
|
||||
if (sourceCompleter != null) {
|
||||
sourceCompleter.complete(c);
|
||||
} else {
|
||||
throw new IllegalStateException("Source completer required to read "
|
||||
+ classfile.toUri());
|
||||
}
|
||||
}
|
||||
return;
|
||||
} catch (IOException ex) {
|
||||
throw badClassFile("unable.to.access.file", ex.getMessage());
|
||||
} catch (ArrayIndexOutOfBoundsException ex) {
|
||||
throw badClassFile("bad.class.file", c.flatname);
|
||||
} finally {
|
||||
currentClassFile = previousClassFile;
|
||||
filling = true;
|
||||
try {
|
||||
bp = 0;
|
||||
buf = readInputStream(buf, c.classfile.openInputStream());
|
||||
readClassBuffer(c);
|
||||
if (!missingTypeVariables.isEmpty() && !foundTypeVariables.isEmpty()) {
|
||||
List<Type> missing = missingTypeVariables;
|
||||
List<Type> found = foundTypeVariables;
|
||||
missingTypeVariables = List.nil();
|
||||
foundTypeVariables = List.nil();
|
||||
filling = false;
|
||||
ClassType ct = (ClassType)currentOwner.type;
|
||||
ct.supertype_field =
|
||||
types.subst(ct.supertype_field, missing, found);
|
||||
ct.interfaces_field =
|
||||
types.subst(ct.interfaces_field, missing, found);
|
||||
} else if (missingTypeVariables.isEmpty() !=
|
||||
foundTypeVariables.isEmpty()) {
|
||||
Name name = missingTypeVariables.head.tsym.name;
|
||||
throw badClassFile("undecl.type.var", name);
|
||||
}
|
||||
} else {
|
||||
JCDiagnostic diag =
|
||||
diagFactory.fragment("class.file.not.found", c.flatname);
|
||||
throw
|
||||
newCompletionFailure(c, diag);
|
||||
} catch (IOException ex) {
|
||||
throw badClassFile("unable.to.access.file", ex.getMessage());
|
||||
} catch (ArrayIndexOutOfBoundsException ex) {
|
||||
throw badClassFile("bad.class.file", c.flatname);
|
||||
} finally {
|
||||
missingTypeVariables = List.nil();
|
||||
foundTypeVariables = List.nil();
|
||||
filling = false;
|
||||
}
|
||||
}
|
||||
// where
|
||||
@ -2590,253 +2399,39 @@ public class ClassReader {
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
/** Static factory for CompletionFailure objects.
|
||||
* In practice, only one can be used at a time, so we share one
|
||||
* to reduce the expense of allocating new exception objects.
|
||||
*/
|
||||
private CompletionFailure newCompletionFailure(TypeSymbol c,
|
||||
JCDiagnostic diag) {
|
||||
if (!cacheCompletionFailure) {
|
||||
// log.warning("proc.messager",
|
||||
// Log.getLocalizedString("class.file.not.found", c.flatname));
|
||||
// c.debug.printStackTrace();
|
||||
return new CompletionFailure(c, diag);
|
||||
} else {
|
||||
CompletionFailure result = cachedCompletionFailure;
|
||||
result.sym = c;
|
||||
result.diag = diag;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
private CompletionFailure cachedCompletionFailure =
|
||||
new CompletionFailure(null, (JCDiagnostic) null);
|
||||
{
|
||||
cachedCompletionFailure.setStackTrace(new StackTraceElement[0]);
|
||||
}
|
||||
|
||||
|
||||
/** Load a toplevel class with given fully qualified name
|
||||
* The class is entered into `classes' only if load was successful.
|
||||
/** We can only read a single class file at a time; this
|
||||
* flag keeps track of when we are currently reading a class
|
||||
* file.
|
||||
*/
|
||||
public ClassSymbol loadClass(Name flatname) throws CompletionFailure {
|
||||
boolean absent = syms.classes.get(flatname) == null;
|
||||
ClassSymbol c = syms.enterClass(flatname);
|
||||
if (c.members_field == null && c.completer != null) {
|
||||
try {
|
||||
c.complete();
|
||||
} catch (CompletionFailure ex) {
|
||||
if (absent) syms.classes.remove(flatname);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
public boolean filling = false;
|
||||
|
||||
/************************************************************************
|
||||
* Loading Packages
|
||||
* Adjusting flags
|
||||
***********************************************************************/
|
||||
|
||||
/** Include class corresponding to given class file in package,
|
||||
* unless (1) we already have one the same kind (.class or .java), or
|
||||
* (2) we have one of the other kind, and the given class file
|
||||
* is older.
|
||||
*/
|
||||
protected void includeClassFile(PackageSymbol p, JavaFileObject file) {
|
||||
if ((p.flags_field & EXISTS) == 0)
|
||||
for (Symbol q = p; q != null && q.kind == PCK; q = q.owner)
|
||||
q.flags_field |= EXISTS;
|
||||
JavaFileObject.Kind kind = file.getKind();
|
||||
int seen;
|
||||
if (kind == JavaFileObject.Kind.CLASS)
|
||||
seen = CLASS_SEEN;
|
||||
else
|
||||
seen = SOURCE_SEEN;
|
||||
String binaryName = fileManager.inferBinaryName(currentLoc, file);
|
||||
int lastDot = binaryName.lastIndexOf(".");
|
||||
Name classname = names.fromString(binaryName.substring(lastDot + 1));
|
||||
boolean isPkgInfo = classname == names.package_info;
|
||||
ClassSymbol c = isPkgInfo
|
||||
? p.package_info
|
||||
: (ClassSymbol) p.members_field.lookup(classname).sym;
|
||||
if (c == null) {
|
||||
c = syms.enterClass(classname, p);
|
||||
if (c.classfile == null) // only update the file if's it's newly created
|
||||
c.classfile = file;
|
||||
if (isPkgInfo) {
|
||||
p.package_info = c;
|
||||
} else {
|
||||
if (c.owner == p) // it might be an inner class
|
||||
p.members_field.enter(c);
|
||||
}
|
||||
} else if (!preferCurrent && c.classfile != null && (c.flags_field & seen) == 0) {
|
||||
// if c.classfile == null, we are currently compiling this class
|
||||
// and no further action is necessary.
|
||||
// if (c.flags_field & seen) != 0, we have already encountered
|
||||
// a file of the same kind; again no further action is necessary.
|
||||
if ((c.flags_field & (CLASS_SEEN | SOURCE_SEEN)) != 0)
|
||||
c.classfile = preferredFileObject(file, c.classfile);
|
||||
long adjustFieldFlags(long flags) {
|
||||
return flags;
|
||||
}
|
||||
|
||||
long adjustMethodFlags(long flags) {
|
||||
if ((flags & ACC_BRIDGE) != 0) {
|
||||
flags &= ~ACC_BRIDGE;
|
||||
flags |= BRIDGE;
|
||||
if (!allowGenerics)
|
||||
flags &= ~SYNTHETIC;
|
||||
}
|
||||
c.flags_field |= seen;
|
||||
}
|
||||
|
||||
/** Implement policy to choose to derive information from a source
|
||||
* file or a class file when both are present. May be overridden
|
||||
* by subclasses.
|
||||
*/
|
||||
protected JavaFileObject preferredFileObject(JavaFileObject a,
|
||||
JavaFileObject b) {
|
||||
|
||||
if (preferSource)
|
||||
return (a.getKind() == JavaFileObject.Kind.SOURCE) ? a : b;
|
||||
else {
|
||||
long adate = a.getLastModified();
|
||||
long bdate = b.getLastModified();
|
||||
// 6449326: policy for bad lastModifiedTime in ClassReader
|
||||
//assert adate >= 0 && bdate >= 0;
|
||||
return (adate > bdate) ? a : b;
|
||||
if ((flags & ACC_VARARGS) != 0) {
|
||||
flags &= ~ACC_VARARGS;
|
||||
flags |= VARARGS;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* specifies types of files to be read when filling in a package symbol
|
||||
*/
|
||||
protected EnumSet<JavaFileObject.Kind> getPackageFileKinds() {
|
||||
return EnumSet.of(JavaFileObject.Kind.CLASS, JavaFileObject.Kind.SOURCE);
|
||||
long adjustClassFlags(long flags) {
|
||||
return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded
|
||||
}
|
||||
|
||||
/**
|
||||
* this is used to support javadoc
|
||||
*/
|
||||
protected void extraFileActions(PackageSymbol pack, JavaFileObject fe) {
|
||||
}
|
||||
|
||||
protected Location currentLoc; // FIXME
|
||||
|
||||
private boolean verbosePath = true;
|
||||
|
||||
// Set to true when the currently selected file should be kept
|
||||
private boolean preferCurrent;
|
||||
|
||||
/** Load directory of package into members scope.
|
||||
*/
|
||||
private void fillIn(PackageSymbol p) throws IOException {
|
||||
if (p.members_field == null)
|
||||
p.members_field = new Scope(p);
|
||||
|
||||
preferCurrent = false;
|
||||
if (userPathsFirst) {
|
||||
scanUserPaths(p);
|
||||
preferCurrent = true;
|
||||
scanPlatformPath(p);
|
||||
} else {
|
||||
scanPlatformPath(p);
|
||||
scanUserPaths(p);
|
||||
}
|
||||
verbosePath = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans class path and source path for files in given package.
|
||||
*/
|
||||
private void scanUserPaths(PackageSymbol p) throws IOException {
|
||||
Set<JavaFileObject.Kind> kinds = getPackageFileKinds();
|
||||
|
||||
Set<JavaFileObject.Kind> classKinds = EnumSet.copyOf(kinds);
|
||||
classKinds.remove(JavaFileObject.Kind.SOURCE);
|
||||
boolean wantClassFiles = !classKinds.isEmpty();
|
||||
|
||||
Set<JavaFileObject.Kind> sourceKinds = EnumSet.copyOf(kinds);
|
||||
sourceKinds.remove(JavaFileObject.Kind.CLASS);
|
||||
boolean wantSourceFiles = !sourceKinds.isEmpty();
|
||||
|
||||
boolean haveSourcePath = fileManager.hasLocation(SOURCE_PATH);
|
||||
|
||||
if (verbose && verbosePath) {
|
||||
if (fileManager instanceof StandardJavaFileManager) {
|
||||
StandardJavaFileManager fm = (StandardJavaFileManager)fileManager;
|
||||
if (haveSourcePath && wantSourceFiles) {
|
||||
List<File> path = List.nil();
|
||||
for (File file : fm.getLocation(SOURCE_PATH)) {
|
||||
path = path.prepend(file);
|
||||
}
|
||||
log.printVerbose("sourcepath", path.reverse().toString());
|
||||
} else if (wantSourceFiles) {
|
||||
List<File> path = List.nil();
|
||||
for (File file : fm.getLocation(CLASS_PATH)) {
|
||||
path = path.prepend(file);
|
||||
}
|
||||
log.printVerbose("sourcepath", path.reverse().toString());
|
||||
}
|
||||
if (wantClassFiles) {
|
||||
List<File> path = List.nil();
|
||||
for (File file : fm.getLocation(PLATFORM_CLASS_PATH)) {
|
||||
path = path.prepend(file);
|
||||
}
|
||||
for (File file : fm.getLocation(CLASS_PATH)) {
|
||||
path = path.prepend(file);
|
||||
}
|
||||
log.printVerbose("classpath", path.reverse().toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String packageName = p.fullname.toString();
|
||||
if (wantSourceFiles && !haveSourcePath) {
|
||||
fillIn(p, CLASS_PATH,
|
||||
fileManager.list(CLASS_PATH,
|
||||
packageName,
|
||||
kinds,
|
||||
false));
|
||||
} else {
|
||||
if (wantClassFiles)
|
||||
fillIn(p, CLASS_PATH,
|
||||
fileManager.list(CLASS_PATH,
|
||||
packageName,
|
||||
classKinds,
|
||||
false));
|
||||
if (wantSourceFiles)
|
||||
fillIn(p, SOURCE_PATH,
|
||||
fileManager.list(SOURCE_PATH,
|
||||
packageName,
|
||||
sourceKinds,
|
||||
false));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans platform class path for files in given package.
|
||||
*/
|
||||
private void scanPlatformPath(PackageSymbol p) throws IOException {
|
||||
fillIn(p, PLATFORM_CLASS_PATH,
|
||||
fileManager.list(PLATFORM_CLASS_PATH,
|
||||
p.fullname.toString(),
|
||||
EnumSet.of(JavaFileObject.Kind.CLASS),
|
||||
false));
|
||||
}
|
||||
// where
|
||||
private void fillIn(PackageSymbol p,
|
||||
Location location,
|
||||
Iterable<JavaFileObject> files)
|
||||
{
|
||||
currentLoc = location;
|
||||
for (JavaFileObject fo : files) {
|
||||
switch (fo.getKind()) {
|
||||
case CLASS:
|
||||
case SOURCE: {
|
||||
// TODO pass binaryName to includeClassFile
|
||||
String binaryName = fileManager.inferBinaryName(currentLoc, fo);
|
||||
String simpleName = binaryName.substring(binaryName.lastIndexOf(".") + 1);
|
||||
if (SourceVersion.isIdentifier(simpleName) ||
|
||||
simpleName.equals("package-info"))
|
||||
includeClassFile(p, fo);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
extraFileActions(p, fo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Output for "-checkclassfile" option.
|
||||
* @param key The key to look up the correct internationalized string.
|
||||
* @param arg An argument for substitution into the output string.
|
||||
@ -2845,12 +2440,6 @@ public class ClassReader {
|
||||
log.printLines(key, arg);
|
||||
}
|
||||
|
||||
|
||||
public interface SourceCompleter {
|
||||
void complete(ClassSymbol sym)
|
||||
throws CompletionFailure;
|
||||
}
|
||||
|
||||
/**
|
||||
* A subclass of JavaFileObject for the sourcefile attribute found in a classfile.
|
||||
* The attribute is only the last component of the original filename, so is unlikely
|
||||
|
||||
@ -459,11 +459,11 @@ public class ClassWriter extends ClassFile {
|
||||
poolbuf.appendChar(pool.put(names.fromString((String)value)));
|
||||
} else if (value instanceof UniqueType) {
|
||||
Type type = ((UniqueType)value).type;
|
||||
if (type instanceof MethodType) {
|
||||
if (type.hasTag(METHOD)) {
|
||||
poolbuf.appendByte(CONSTANT_MethodType);
|
||||
poolbuf.appendChar(pool.put(typeSig((MethodType)type)));
|
||||
} else {
|
||||
if (type.hasTag(CLASS)) enterInner((ClassSymbol)type.tsym);
|
||||
Assert.check(type.hasTag(ARRAY));
|
||||
poolbuf.appendByte(CONSTANT_Class);
|
||||
poolbuf.appendChar(pool.put(xClassName(type)));
|
||||
}
|
||||
|
||||
@ -28,6 +28,7 @@ package com.sun.tools.javac.jvm;
|
||||
import com.sun.tools.javac.code.Kinds;
|
||||
import com.sun.tools.javac.code.Symbol;
|
||||
import com.sun.tools.javac.code.Symbol.*;
|
||||
import com.sun.tools.javac.code.TypeTag;
|
||||
import com.sun.tools.javac.code.Type;
|
||||
import com.sun.tools.javac.code.Types;
|
||||
import com.sun.tools.javac.code.Types.UniqueType;
|
||||
@ -127,7 +128,14 @@ public class Pool {
|
||||
} else if (o instanceof VarSymbol) {
|
||||
return new Variable((VarSymbol)o, types);
|
||||
} else if (o instanceof Type) {
|
||||
return new UniqueType((Type)o, types);
|
||||
Type t = (Type)o;
|
||||
// ClassRefs can come from ClassSymbols or from Types.
|
||||
// Return the symbol for these types to avoid duplicates
|
||||
// in the constant pool
|
||||
if (t.hasTag(TypeTag.CLASS))
|
||||
return t.tsym;
|
||||
else
|
||||
return new UniqueType(t, types);
|
||||
} else {
|
||||
return o;
|
||||
}
|
||||
|
||||
@ -219,6 +219,10 @@ public class JavaCompiler {
|
||||
*/
|
||||
protected TreeMaker make;
|
||||
|
||||
/** The class finder.
|
||||
*/
|
||||
protected ClassFinder finder;
|
||||
|
||||
/** The class reader.
|
||||
*/
|
||||
protected ClassReader reader;
|
||||
@ -296,13 +300,13 @@ public class JavaCompiler {
|
||||
protected MultiTaskListener taskListener;
|
||||
|
||||
/**
|
||||
* SourceCompleter that delegates to the complete-method of this class.
|
||||
* SourceCompleter that delegates to the readSourceFile method of this class.
|
||||
*/
|
||||
protected final ClassReader.SourceCompleter thisCompleter =
|
||||
new ClassReader.SourceCompleter() {
|
||||
protected final Symbol.Completer sourceCompleter =
|
||||
new Symbol.Completer() {
|
||||
@Override
|
||||
public void complete(ClassSymbol sym) throws CompletionFailure {
|
||||
JavaCompiler.this.complete(sym);
|
||||
public void complete(Symbol sym) throws CompletionFailure {
|
||||
readSourceFile((ClassSymbol) sym);
|
||||
}
|
||||
};
|
||||
|
||||
@ -338,6 +342,7 @@ public class JavaCompiler {
|
||||
names = Names.instance(context);
|
||||
log = Log.instance(context);
|
||||
diagFactory = JCDiagnostic.Factory.instance(context);
|
||||
finder = ClassFinder.instance(context);
|
||||
reader = ClassReader.instance(context);
|
||||
make = TreeMaker.instance(context);
|
||||
writer = ClassWriter.instance(context);
|
||||
@ -355,7 +360,7 @@ public class JavaCompiler {
|
||||
} catch (CompletionFailure ex) {
|
||||
// inlined Check.completionError as it is not initialized yet
|
||||
log.error("cant.access", ex.sym, ex.getDetailValue());
|
||||
if (ex instanceof ClassReader.BadClassFile)
|
||||
if (ex instanceof ClassFinder.BadClassFile)
|
||||
throw new Abort();
|
||||
}
|
||||
source = Source.instance(context);
|
||||
@ -370,7 +375,7 @@ public class JavaCompiler {
|
||||
types = Types.instance(context);
|
||||
taskListener = MultiTaskListener.instance(context);
|
||||
|
||||
reader.sourceCompleter = thisCompleter;
|
||||
finder.sourceCompleter = sourceCompleter;
|
||||
|
||||
options = Options.instance(context);
|
||||
|
||||
@ -663,7 +668,7 @@ public class JavaCompiler {
|
||||
public Symbol resolveBinaryNameOrIdent(String name) {
|
||||
try {
|
||||
Name flatname = names.fromString(name.replace("/", "."));
|
||||
return reader.loadClass(flatname);
|
||||
return finder.loadClass(flatname);
|
||||
} catch (CompletionFailure ignore) {
|
||||
return resolveIdent(name);
|
||||
}
|
||||
@ -737,22 +742,20 @@ public class JavaCompiler {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Complete compiling a source file that has been accessed
|
||||
* by the class file reader.
|
||||
/** Compile a source file that has been accessed by the class finder.
|
||||
* @param c The class the source file of which needs to be compiled.
|
||||
*/
|
||||
public void complete(ClassSymbol c) throws CompletionFailure {
|
||||
complete(null, c);
|
||||
private void readSourceFile(ClassSymbol c) throws CompletionFailure {
|
||||
readSourceFile(null, c);
|
||||
}
|
||||
|
||||
/** Complete a ClassSymbol from source, optionally using the given compilation unit as
|
||||
/** Compile a ClassSymbol from source, optionally using the given compilation unit as
|
||||
* the source tree.
|
||||
* @param tree the compilation unit int which the given ClassSymbol resides,
|
||||
* @param tree the compilation unit in which the given ClassSymbol resides,
|
||||
* or null if should be parsed from source
|
||||
* @param c the ClassSymbol to complete
|
||||
*/
|
||||
public void complete(JCCompilationUnit tree, ClassSymbol c) throws CompletionFailure {
|
||||
// System.err.println("completing " + c);//DEBUG
|
||||
public void readSourceFile(JCCompilationUnit tree, ClassSymbol c) throws CompletionFailure {
|
||||
if (completionFailureName == c.fullname) {
|
||||
throw new CompletionFailure(c, "user-selected completion failure by class name");
|
||||
}
|
||||
@ -791,13 +794,13 @@ public class JavaCompiler {
|
||||
JCDiagnostic diag =
|
||||
diagFactory.fragment("file.does.not.contain.package",
|
||||
c.location());
|
||||
throw reader.new BadClassFile(c, filename, diag);
|
||||
throw new ClassFinder.BadClassFile(c, filename, diag, diagFactory);
|
||||
}
|
||||
} else {
|
||||
JCDiagnostic diag =
|
||||
diagFactory.fragment("file.doesnt.contain.class",
|
||||
c.getQualifiedName());
|
||||
throw reader.new BadClassFile(c, filename, diag);
|
||||
throw new ClassFinder.BadClassFile(c, filename, diag, diagFactory);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1663,6 +1666,7 @@ public class JavaCompiler {
|
||||
*/
|
||||
public void close() {
|
||||
rootClasses = null;
|
||||
finder = null;
|
||||
reader = null;
|
||||
make = null;
|
||||
writer = null;
|
||||
|
||||
@ -54,8 +54,6 @@ import com.sun.tools.javac.comp.Check;
|
||||
import com.sun.tools.javac.comp.Enter;
|
||||
import com.sun.tools.javac.comp.Env;
|
||||
import com.sun.tools.javac.file.JavacFileManager;
|
||||
import com.sun.tools.javac.jvm.*;
|
||||
import com.sun.tools.javac.jvm.ClassReader.BadClassFile;
|
||||
import com.sun.tools.javac.main.JavaCompiler;
|
||||
import com.sun.tools.javac.model.JavacElements;
|
||||
import com.sun.tools.javac.model.JavacTypes;
|
||||
@ -203,7 +201,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
|
||||
symtab = Symtab.instance(context);
|
||||
names = Names.instance(context);
|
||||
enter = Enter.instance(context);
|
||||
initialCompleter = ClassReader.instance(context).getCompleter();
|
||||
initialCompleter = ClassFinder.instance(context).getCompleter();
|
||||
chk = Check.instance(context);
|
||||
initProcessorClassLoader();
|
||||
}
|
||||
@ -799,7 +797,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
|
||||
RoundEnvironment renv) {
|
||||
try {
|
||||
return proc.process(tes, renv);
|
||||
} catch (BadClassFile ex) {
|
||||
} catch (ClassFinder.BadClassFile ex) {
|
||||
log.error("proc.cant.access.1", ex.sym, ex.getDetailValue());
|
||||
return false;
|
||||
} catch (CompletionFailure ex) {
|
||||
@ -1308,7 +1306,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
|
||||
}
|
||||
|
||||
@Override public void complete(Symbol sym) throws CompletionFailure {
|
||||
compiler.complete(topLevel, (ClassSymbol) sym);
|
||||
compiler.readSourceFile(topLevel, (ClassSymbol) sym);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -26,6 +26,8 @@
|
||||
package com.sun.tools.javac.util;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/** A collection of utilities for String manipulation.
|
||||
*
|
||||
@ -50,4 +52,19 @@ public class StringUtils {
|
||||
return source.toUpperCase(Locale.US);
|
||||
}
|
||||
|
||||
/**Case insensitive version of {@link String#indexOf(java.lang.String)}. Equivalent to
|
||||
* {@code text.indexOf(str)}, except the matching is case insensitive.
|
||||
*/
|
||||
public static int indexOfIgnoreCase(String text, String str) {
|
||||
return indexOfIgnoreCase(text, str, 0);
|
||||
}
|
||||
|
||||
/**Case insensitive version of {@link String#indexOf(java.lang.String, int)}. Equivalent to
|
||||
* {@code text.indexOf(str, startIndex)}, except the matching is case insensitive.
|
||||
*/
|
||||
public static int indexOfIgnoreCase(String text, String str, int startIndex) {
|
||||
Matcher m = Pattern.compile(Pattern.quote(str), Pattern.CASE_INSENSITIVE).matcher(text);
|
||||
return m.find(startIndex) ? m.start() : -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -37,11 +37,19 @@ import com.sun.tools.doclint.DocLint;
|
||||
import com.sun.tools.javac.api.BasicJavacTask;
|
||||
import com.sun.tools.javac.code.*;
|
||||
import com.sun.tools.javac.code.Symbol.*;
|
||||
import com.sun.tools.javac.code.Symbol.ClassSymbol;
|
||||
import com.sun.tools.javac.code.Symbol.CompletionFailure;
|
||||
import com.sun.tools.javac.code.Symbol.MethodSymbol;
|
||||
import com.sun.tools.javac.code.Symbol.PackageSymbol;
|
||||
import com.sun.tools.javac.code.Symbol.VarSymbol;
|
||||
import com.sun.tools.javac.code.Type.ClassType;
|
||||
import com.sun.tools.javac.comp.Check;
|
||||
import com.sun.tools.javac.comp.Enter;
|
||||
import com.sun.tools.javac.file.JavacFileManager;
|
||||
import com.sun.tools.javac.tree.JCTree;
|
||||
import com.sun.tools.javac.tree.JCTree.*;
|
||||
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
|
||||
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
|
||||
import com.sun.tools.javac.tree.JCTree.JCPackageDecl;
|
||||
import com.sun.tools.javac.util.Context;
|
||||
import com.sun.tools.javac.util.Names;
|
||||
|
||||
@ -71,21 +79,21 @@ public class DocEnv {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private Messager messager;
|
||||
|
||||
DocLocale doclocale;
|
||||
|
||||
private final Messager messager;
|
||||
|
||||
/** Predefined symbols known to the compiler. */
|
||||
Symtab syms;
|
||||
final Symtab syms;
|
||||
|
||||
/** Referenced directly in RootDocImpl. */
|
||||
JavadocClassReader reader;
|
||||
private final ClassFinder finder;
|
||||
|
||||
/** Javadoc's own version of the compiler's enter phase. */
|
||||
JavadocEnter enter;
|
||||
final Enter enter;
|
||||
|
||||
/** The name table. */
|
||||
Names names;
|
||||
private Names names;
|
||||
|
||||
/** The encoding name. */
|
||||
private String encoding;
|
||||
@ -139,8 +147,8 @@ public class DocEnv {
|
||||
|
||||
messager = Messager.instance0(context);
|
||||
syms = Symtab.instance(context);
|
||||
reader = JavadocClassReader.instance0(context);
|
||||
enter = JavadocEnter.instance0(context);
|
||||
finder = JavadocClassFinder.instance(context);
|
||||
enter = JavadocEnter.instance(context);
|
||||
names = Names.instance(context);
|
||||
externalizableSym = syms.enterClass(names.fromString("java.io.Externalizable"));
|
||||
chk = Check.instance(context);
|
||||
@ -176,7 +184,7 @@ public class DocEnv {
|
||||
*/
|
||||
public ClassDocImpl loadClass(String name) {
|
||||
try {
|
||||
ClassSymbol c = reader.loadClass(names.fromString(name));
|
||||
ClassSymbol c = finder.loadClass(names.fromString(name));
|
||||
return getClassDoc(c);
|
||||
} catch (CompletionFailure ex) {
|
||||
chk.completionError(null, ex);
|
||||
|
||||
@ -29,10 +29,10 @@ import java.util.EnumSet;
|
||||
import javax.tools.JavaFileObject;
|
||||
|
||||
import com.sun.tools.javac.code.Symbol.PackageSymbol;
|
||||
import com.sun.tools.javac.jvm.ClassReader;
|
||||
import com.sun.tools.javac.code.ClassFinder;
|
||||
import com.sun.tools.javac.util.Context;
|
||||
|
||||
/** Javadoc uses an extended class reader that records package.html entries
|
||||
/** Javadoc uses an extended class finder that records package.html entries
|
||||
*
|
||||
* <p><b>This is NOT part of any supported API.
|
||||
* If you write code that depends on this, you do so at your own risk.
|
||||
@ -41,19 +41,19 @@ import com.sun.tools.javac.util.Context;
|
||||
*
|
||||
* @author Neal Gafter
|
||||
*/
|
||||
public class JavadocClassReader extends ClassReader {
|
||||
public class JavadocClassFinder extends ClassFinder {
|
||||
|
||||
public static JavadocClassReader instance0(Context context) {
|
||||
ClassReader instance = context.get(classReaderKey);
|
||||
public static JavadocClassFinder instance(Context context) {
|
||||
ClassFinder instance = context.get(classFinderKey);
|
||||
if (instance == null)
|
||||
instance = new JavadocClassReader(context);
|
||||
return (JavadocClassReader)instance;
|
||||
instance = new JavadocClassFinder(context);
|
||||
return (JavadocClassFinder)instance;
|
||||
}
|
||||
|
||||
public static void preRegister(Context context) {
|
||||
context.put(classReaderKey, new Context.Factory<ClassReader>() {
|
||||
public ClassReader make(Context c) {
|
||||
return new JavadocClassReader(c);
|
||||
context.put(classFinderKey, new Context.Factory<ClassFinder>() {
|
||||
public ClassFinder make(Context c) {
|
||||
return new JavadocClassFinder(c);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -65,7 +65,7 @@ public class JavadocClassReader extends ClassReader {
|
||||
private EnumSet<JavaFileObject.Kind> noSource = EnumSet.of(JavaFileObject.Kind.CLASS,
|
||||
JavaFileObject.Kind.HTML);
|
||||
|
||||
public JavadocClassReader(Context context) {
|
||||
public JavadocClassFinder(Context context) {
|
||||
super(context);
|
||||
docenv = DocEnv.instance(context);
|
||||
preferSource = true;
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -48,7 +48,7 @@ import com.sun.tools.javac.util.List;
|
||||
* @author Neal Gafter
|
||||
*/
|
||||
public class JavadocEnter extends Enter {
|
||||
public static JavadocEnter instance0(Context context) {
|
||||
public static JavadocEnter instance(Context context) {
|
||||
Enter instance = context.get(enterKey);
|
||||
if (instance == null)
|
||||
instance = new JavadocEnter(context);
|
||||
|
||||
@ -33,12 +33,15 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.tools.JavaFileManager.Location;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.StandardJavaFileManager;
|
||||
import javax.tools.StandardLocation;
|
||||
|
||||
import com.sun.tools.javac.code.ClassFinder;
|
||||
import com.sun.tools.javac.code.Symbol.CompletionFailure;
|
||||
import com.sun.tools.javac.comp.Enter;
|
||||
import com.sun.tools.javac.tree.JCTree;
|
||||
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
|
||||
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
|
||||
@ -66,8 +69,8 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler {
|
||||
DocEnv docenv;
|
||||
|
||||
final Messager messager;
|
||||
final JavadocClassReader javadocReader;
|
||||
final JavadocEnter javadocEnter;
|
||||
final ClassFinder javadocFinder;
|
||||
final Enter javadocEnter;
|
||||
final Set<JavaFileObject> uniquefiles;
|
||||
|
||||
/**
|
||||
@ -77,8 +80,8 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler {
|
||||
protected JavadocTool(Context context) {
|
||||
super(context);
|
||||
messager = Messager.instance0(context);
|
||||
javadocReader = JavadocClassReader.instance0(context);
|
||||
javadocEnter = JavadocEnter.instance0(context);
|
||||
javadocFinder = JavadocClassFinder.instance(context);
|
||||
javadocEnter = JavadocEnter.instance(context);
|
||||
uniquefiles = new HashSet<>();
|
||||
}
|
||||
|
||||
@ -95,8 +98,8 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler {
|
||||
public static JavadocTool make0(Context context) {
|
||||
Messager messager = null;
|
||||
try {
|
||||
// force the use of Javadoc's class reader
|
||||
JavadocClassReader.preRegister(context);
|
||||
// force the use of Javadoc's class finder
|
||||
JavadocClassFinder.preRegister(context);
|
||||
|
||||
// force the use of Javadoc's own enter phase
|
||||
JavadocEnter.preRegister(context);
|
||||
@ -137,7 +140,8 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler {
|
||||
docenv.setEncoding(encoding);
|
||||
docenv.docClasses = docClasses;
|
||||
docenv.legacyDoclet = legacyDoclet;
|
||||
javadocReader.sourceCompleter = docClasses ? null : thisCompleter;
|
||||
|
||||
javadocFinder.sourceCompleter = docClasses ? null : sourceCompleter;
|
||||
|
||||
ListBuffer<String> names = new ListBuffer<>();
|
||||
ListBuffer<JCCompilationUnit> classTrees = new ListBuffer<>();
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4460354 8014636
|
||||
* @bug 4460354 8014636 8043186
|
||||
* @summary Test to make sure that relative paths are redirected in the
|
||||
* output so that they are not broken.
|
||||
* @author jamieh
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -30,7 +30,7 @@ package pkg;
|
||||
public class C {
|
||||
|
||||
/**
|
||||
* Here is a relative link in a field:
|
||||
* Here is a relative link in a field:\u0130
|
||||
* <a href="relative-field-link.html">relative field link</a>.
|
||||
*/
|
||||
public C field = null;
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6227616
|
||||
* @bug 6227616 8043186
|
||||
* @summary Test the new -top option.
|
||||
* @author jamieh
|
||||
* @library ../lib
|
||||
@ -43,7 +43,30 @@ public class TestTopOption extends JavadocTester {
|
||||
javadoc("-overview", testSrc("overview.html"),
|
||||
"-use",
|
||||
"-top", "TOP TEXT",
|
||||
"-d", "out",
|
||||
"-d", "out-1",
|
||||
"-sourcepath", testSrc,
|
||||
"pkg");
|
||||
checkExit(Exit.OK);
|
||||
|
||||
checkTopText(
|
||||
"pkg/AnnotationType.html",
|
||||
"pkg/class-use/AnnotationType.html",
|
||||
"pkg/Cl.html",
|
||||
"pkg/class-use/Cl.html",
|
||||
"pkg/package-summary.html",
|
||||
"pkg/package-use.html",
|
||||
"overview-summary.html",
|
||||
"overview-tree.html",
|
||||
"constant-values.html",
|
||||
"help-doc.html");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDocRootRewrite() {
|
||||
javadoc("-overview", testSrc("overview.html"),
|
||||
"-use",
|
||||
"-top", "\u0130{@docroot}TOP TEXT",
|
||||
"-d", "out-2",
|
||||
"-sourcepath", testSrc,
|
||||
"pkg");
|
||||
checkExit(Exit.OK);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -36,7 +36,7 @@ import java.nio.*;
|
||||
import java.io.*;
|
||||
import java.nio.channels.*;
|
||||
import com.sun.tools.javac.api.JavacTaskImpl;
|
||||
import com.sun.tools.javac.jvm.ClassReader.BadClassFile;
|
||||
import com.sun.tools.javac.code.ClassFinder.BadClassFile;
|
||||
import com.sun.tools.javac.main.JavaCompiler;
|
||||
import javax.tools.ToolProvider;
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -129,14 +129,14 @@ public class MethodParametersTest {
|
||||
if (out.length() > 0)
|
||||
System.err.println(out);
|
||||
|
||||
// Now get the class reader, construct a name for Baz, and load it.
|
||||
com.sun.tools.javac.jvm.ClassReader cr =
|
||||
com.sun.tools.javac.jvm.ClassReader.instance(context);
|
||||
// Now get the class finder, construct a name for Baz, and load it.
|
||||
com.sun.tools.javac.code.ClassFinder cf =
|
||||
com.sun.tools.javac.code.ClassFinder.instance(context);
|
||||
Name name = Names.instance(context).fromString(Baz_name);
|
||||
|
||||
// Now walk down the language model and check the name of the
|
||||
// parameter.
|
||||
final Element baz = cr.loadClass(name);
|
||||
final Element baz = cf.loadClass(name);
|
||||
for (Element e : baz.getEnclosedElements()) {
|
||||
if (e instanceof ExecutableElement) {
|
||||
final ExecutableElement ee = (ExecutableElement) e;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -30,7 +30,7 @@
|
||||
*/
|
||||
|
||||
import com.sun.tools.javac.api.JavacTaskImpl;
|
||||
import com.sun.tools.javac.jvm.ClassReader.BadClassFile;
|
||||
import com.sun.tools.javac.code.ClassFinder.BadClassFile;
|
||||
import com.sun.tools.javac.main.JavaCompiler;
|
||||
import javax.tools.ToolProvider;
|
||||
|
||||
|
||||
@ -24,10 +24,11 @@
|
||||
/*
|
||||
* @test
|
||||
* @summary sourcefile attribute test for file compiled without debug information.
|
||||
* @bug 8040129
|
||||
* @library /tools/javac/lib ../lib
|
||||
* @build SourceFileTestBase TestBase InMemoryFileManager ToolBox
|
||||
* @compile -g:none NoSourceFileAttribute.java
|
||||
* @run main NoSourceFileAttribute
|
||||
* @run main NoSourceFileAttribute
|
||||
*/
|
||||
|
||||
import com.sun.tools.classfile.Attribute;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -32,8 +32,8 @@
|
||||
|
||||
import com.sun.tools.classfile.*;
|
||||
import com.sun.tools.javac.api.JavacTaskImpl;
|
||||
import com.sun.tools.javac.code.ClassFinder.BadClassFile;
|
||||
import com.sun.tools.javac.code.Symbol;
|
||||
import com.sun.tools.javac.jvm.ClassReader.BadClassFile;
|
||||
import com.sun.tools.javac.jvm.Target;
|
||||
import com.sun.tools.javac.util.Assert;
|
||||
import com.sun.tools.javac.util.JCDiagnostic;
|
||||
|
||||
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8015927
|
||||
* @summary Class reference duplicates in constant pool
|
||||
* @clean ClassRefDupInConstantPoolTest$Duplicates.class
|
||||
* @run main ClassRefDupInConstantPoolTest
|
||||
*/
|
||||
|
||||
import java.util.TreeSet;
|
||||
|
||||
import com.sun.tools.classfile.*;
|
||||
import com.sun.tools.classfile.ConstantPool.*;
|
||||
|
||||
public class ClassRefDupInConstantPoolTest {
|
||||
public static void main(String[] args) throws Exception {
|
||||
ClassFile cls = ClassFile.read(ClassRefDupInConstantPoolTest.class.
|
||||
getResourceAsStream("ClassRefDupInConstantPoolTest$Duplicates.class"));
|
||||
ConstantPool pool = cls.constant_pool;
|
||||
|
||||
int duplicates = 0;
|
||||
TreeSet<Integer> set = new TreeSet<>();
|
||||
for (CPInfo i : pool.entries()) {
|
||||
if (i.getTag() == ConstantPool.CONSTANT_Class) {
|
||||
CONSTANT_Class_info ci = (CONSTANT_Class_info)i;
|
||||
if (!set.add(ci.name_index)) {
|
||||
duplicates++;
|
||||
System.out.println("DUPLICATE CLASS REF " + ci.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (duplicates > 0)
|
||||
throw new Exception("Test Failed");
|
||||
}
|
||||
|
||||
class Duplicates {
|
||||
String concat(String s1, String s2) {
|
||||
return s1 + (s2 == s1 ? " " : s2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8029800
|
||||
* @bug 8029800 8043186
|
||||
* @summary Unit test StringUtils
|
||||
* @run main StringUtilsTest
|
||||
*/
|
||||
@ -44,12 +44,14 @@ public class StringUtilsTest {
|
||||
assertEquals("\u0131", "I".toLowerCase());
|
||||
assertEquals("\u0130", "i".toUpperCase());
|
||||
|
||||
//verify the StringUtils does what it should
|
||||
//verify the StringUtils.toLowerCase/toUpperCase do what they should:
|
||||
assertEquals("i", StringUtils.toLowerCase("I"));
|
||||
assertEquals("I", StringUtils.toUpperCase("i"));
|
||||
|
||||
//verify we can use index from indexOf of toLowerCase String in the original:
|
||||
assertEquals(2, StringUtils.toLowerCase("\u0130\u0130lookFor").indexOf("lookfor"));
|
||||
//verify StringUtils.caseInsensitiveIndexOf works:
|
||||
assertEquals(2, StringUtils.indexOfIgnoreCase(" lookFor", "lookfor"));
|
||||
assertEquals(11, StringUtils.indexOfIgnoreCase(" lookFor LOOKfor", "lookfor", 11));
|
||||
assertEquals(2, StringUtils.indexOfIgnoreCase("\u0130\u0130lookFor", "lookfor"));
|
||||
}
|
||||
|
||||
void assertEquals(String expected, String actual) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user