This commit is contained in:
Lana Steuck 2014-12-04 15:22:53 -08:00
commit 47757481e4
137 changed files with 5612 additions and 1652 deletions
langtools
src/jdk.compiler/share/classes/com/sun/tools
test
lib/annotations/annotations/classfile
tools/javac

@ -58,6 +58,7 @@ import static com.sun.tools.javac.code.Flags.*;
import static com.sun.tools.javac.code.Kinds.Kind.*;
import static com.sun.tools.javac.main.Option.*;
import com.sun.tools.javac.util.Dependencies.CompletionCause;
/**
* This class provides operations to locate class definitions
@ -270,7 +271,7 @@ public class ClassFinder {
if (sym.kind == TYP) {
try {
ClassSymbol c = (ClassSymbol) sym;
dependencies.push(c);
dependencies.push(c, CompletionCause.CLASS_READER);
c.members_field = new Scope.ErrorScope(c); // make sure it's always defined
annotate.enterStart();
try {

@ -168,6 +168,7 @@ public class Kinds {
public static final KindSelector MTH = new KindSelector(0x10);
public static final KindSelector ERR = new KindSelector(0x3f);
public static final KindSelector POLY = new KindSelector(0x20);
public static final KindSelector ASG = new KindSelector(0x44);
//common derived selectors
public static final KindSelector TYP_PCK = of(TYP, PCK);

@ -80,6 +80,16 @@ public class Lint
return l;
}
/**
* Returns a new Lint that has the given LintCategory suppressed.
*/
public Lint suppress(LintCategory lc) {
Lint l = new Lint(this);
l.values.remove(lc);
l.suppressedValues.add(lc);
return l;
}
private final AugmentVisitor augmentor;
private final EnumSet<LintCategory> values;

@ -25,13 +25,18 @@
package com.sun.tools.javac.code;
import com.sun.tools.javac.code.Kinds.Kind;
import java.util.*;
import com.sun.tools.javac.code.Symbol.TypeSymbol;
import com.sun.tools.javac.tree.JCTree.JCImport;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.List;
import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
import static com.sun.tools.javac.code.Scope.LookupKind.RECURSIVE;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
/** A scope represents an area of visibility in a Java program. The
* Scope class is a container for symbols which provides
@ -672,28 +677,67 @@ public abstract class Scope {
}
public static class NamedImportScope extends CompoundScope {
public static class ImportScope extends CompoundScope {
public ImportScope(Symbol owner) {
super(owner);
}
/**Finalize the content of the ImportScope to speed-up future lookups.
* No further changes to class hierarchy or class content will be reflected.
*/
public void finalizeScope() {
for (List<Scope> scopes = this.subScopes; scopes.nonEmpty(); scopes = scopes.tail) {
Scope impScope = scopes.head;
if (impScope instanceof FilterImportScope && impScope.owner.kind == Kind.TYP) {
WriteableScope finalized = WriteableScope.create(impScope.owner);
for (Symbol sym : impScope.getSymbols()) {
finalized.enter(sym);
}
finalized.addScopeListener(new ScopeListener() {
@Override
public void symbolAdded(Symbol sym, Scope s) {
Assert.error("The scope is sealed.");
}
@Override
public void symbolRemoved(Symbol sym, Scope s) {
Assert.error("The scope is sealed.");
}
});
scopes.head = finalized;
}
}
}
}
public static class NamedImportScope extends ImportScope {
public NamedImportScope(Symbol owner, Scope currentFileScope) {
super(owner);
prependSubScope(currentFileScope);
}
public void importByName(Scope delegate, Scope origin, Name name, ImportFilter filter) {
appendScope(new FilterImportScope(delegate, origin, name, filter, true));
public Scope importByName(Types types, Scope origin, Name name, ImportFilter filter) {
return appendScope(new FilterImportScope(types, origin, name, filter, true));
}
public void importType(Scope delegate, Scope origin, Symbol sym) {
appendScope(new SingleEntryScope(delegate.owner, sym, origin));
public Scope importType(Scope delegate, Scope origin, Symbol sym) {
return appendScope(new SingleEntryScope(delegate.owner, sym, origin));
}
private void appendScope(Scope newScope) {
private Scope appendScope(Scope newScope) {
List<Scope> existingScopes = this.subScopes.reverse();
subScopes = List.of(existingScopes.head);
subScopes = subScopes.prepend(newScope);
for (Scope s : existingScopes.tail) {
subScopes = subScopes.prepend(s);
}
return newScope;
}
private static class SingleEntryScope extends Scope {
@ -735,24 +779,23 @@ public abstract class Scope {
}
}
public static class StarImportScope extends CompoundScope {
public static class StarImportScope extends ImportScope {
public StarImportScope(Symbol owner) {
super(owner);
}
public void importAll(Scope delegate,
Scope origin,
public void importAll(Types types, Scope origin,
ImportFilter filter,
boolean staticImport) {
for (Scope existing : subScopes) {
Assert.check(existing instanceof FilterImportScope);
FilterImportScope fis = (FilterImportScope) existing;
if (fis.delegate == delegate && fis.origin == origin &&
fis.filter == filter && fis.staticImport == staticImport)
if (fis.origin == origin && fis.filter == filter &&
fis.staticImport == staticImport)
return ; //avoid entering the same scope twice
}
prependSubScope(new FilterImportScope(delegate, origin, null, filter, staticImport));
prependSubScope(new FilterImportScope(types, origin, null, filter, staticImport));
}
}
@ -763,19 +806,19 @@ public abstract class Scope {
private static class FilterImportScope extends Scope {
private final Scope delegate;
private final Types types;
private final Scope origin;
private final Name filterName;
private final ImportFilter filter;
private final boolean staticImport;
public FilterImportScope(Scope delegate,
public FilterImportScope(Types types,
Scope origin,
Name filterName,
ImportFilter filter,
boolean staticImport) {
super(delegate.owner);
this.delegate = delegate;
super(origin.owner);
this.types = types;
this.origin = origin;
this.filterName = filterName;
this.filter = filter;
@ -783,19 +826,31 @@ public abstract class Scope {
}
@Override
public Iterable<Symbol> getSymbols(Filter<Symbol> sf, LookupKind lookupKind) {
public Iterable<Symbol> getSymbols(final Filter<Symbol> sf, final LookupKind lookupKind) {
if (filterName != null)
return getSymbolsByName(filterName, sf, lookupKind);
return new FilteredIterable(delegate.getSymbols(sf, lookupKind));
SymbolImporter si = new SymbolImporter(staticImport) {
@Override
Iterable<Symbol> doLookup(TypeSymbol tsym) {
return tsym.members().getSymbols(sf, lookupKind);
}
};
return si.importFrom((TypeSymbol) origin.owner) :: iterator;
}
@Override
public Iterable<Symbol> getSymbolsByName(Name name,
Filter<Symbol> sf,
LookupKind lookupKind) {
public Iterable<Symbol> getSymbolsByName(final Name name,
final Filter<Symbol> sf,
final LookupKind lookupKind) {
if (filterName != null && filterName != name)
return Collections.emptyList();
return new FilteredIterable(delegate.getSymbolsByName(name, sf, lookupKind));
SymbolImporter si = new SymbolImporter(staticImport) {
@Override
Iterable<Symbol> doLookup(TypeSymbol tsym) {
return tsym.members().getSymbolsByName(name, sf, lookupKind);
}
};
return si.importFrom((TypeSymbol) origin.owner) :: iterator;
}
@Override
@ -808,57 +863,31 @@ public abstract class Scope {
return staticImport;
}
private class FilteredIterator implements Iterator<Symbol> {
private final Iterator<Symbol> delegate;
private Symbol next;
public FilteredIterator(Iterator<Symbol> delegate) {
this.delegate = delegate;
update();
abstract class SymbolImporter {
Set<Symbol> processed = new HashSet<>();
List<Iterable<Symbol>> delegates = List.nil();
final boolean inspectSuperTypes;
public SymbolImporter(boolean inspectSuperTypes) {
this.inspectSuperTypes = inspectSuperTypes;
}
Stream<Symbol> importFrom(TypeSymbol tsym) {
if (tsym == null || !processed.add(tsym))
return Stream.empty();
void update() {
while (delegate.hasNext()) {
if (filter.accepts(origin, next = delegate.next()))
return;
Stream<Symbol> result = Stream.empty();
if (inspectSuperTypes) {
// also import inherited names
result = importFrom(types.supertype(tsym.type).tsym);
for (Type t : types.interfaces(tsym.type))
result = Stream.concat(importFrom(t.tsym), result);
}
next = null;
}
@Override
public boolean hasNext() {
return next != null;
}
@Override
public Symbol next() {
Symbol result = next;
update();
return result;
}
@Override
public void remove() {
throw new UnsupportedOperationException("Not supported.");
}
}
private class FilteredIterable implements Iterable<Symbol> {
private final Iterable<Symbol> unfiltered;
public FilteredIterable(Iterable<Symbol> unfiltered) {
this.unfiltered = unfiltered;
}
@Override
public Iterator<Symbol> iterator() {
return new FilteredIterator(unfiltered.iterator());
return Stream.concat(StreamSupport.stream(doLookup(tsym).spliterator(), false)
.filter(s -> filter.accepts(origin, s)),
result);
}
abstract Iterable<Symbol> doLookup(TypeSymbol tsym);
}
}

@ -140,6 +140,9 @@ public enum Source {
public boolean allowTryWithResources() {
return compareTo(JDK1_7) >= 0;
}
public boolean allowEffectivelyFinalVariablesInTryWithResources() {
return compareTo(JDK1_9) >= 0;
}
public boolean allowBinaryLiterals() {
return compareTo(JDK1_7) >= 0;
}
@ -149,6 +152,9 @@ public enum Source {
public boolean allowStringsInSwitch() {
return compareTo(JDK1_7) >= 0;
}
public boolean allowDeprecationOnImport() {
return compareTo(JDK1_9) < 0;
}
public boolean allowSimplifiedVarargs() {
return compareTo(JDK1_7) >= 0;
}

@ -87,6 +87,7 @@ public class Attr extends JCTree.Visitor {
final Check chk;
final Flow flow;
final MemberEnter memberEnter;
final TypeEnter typeEnter;
final TreeMaker make;
final ConstFold cfolder;
final Enter enter;
@ -116,6 +117,7 @@ public class Attr extends JCTree.Visitor {
chk = Check.instance(context);
flow = Flow.instance(context);
memberEnter = MemberEnter.instance(context);
typeEnter = TypeEnter.instance(context);
make = TreeMaker.instance(context);
enter = Enter.instance(context);
infer = Infer.instance(context);
@ -148,7 +150,7 @@ public class Attr extends JCTree.Visitor {
identifyLambdaCandidate = options.getBoolean("identifyLambdaCandidate", false);
statInfo = new ResultInfo(KindSelector.NIL, Type.noType);
varInfo = new ResultInfo(KindSelector.VAR, Type.noType);
varAssignmentInfo = new ResultInfo(KindSelector.ASG, Type.noType);
unknownExprInfo = new ResultInfo(KindSelector.VAL, Type.noType);
unknownAnyPolyInfo = new ResultInfo(KindSelector.VAL, Infer.anyPoly);
unknownTypeInfo = new ResultInfo(KindSelector.TYP, Type.noType);
@ -498,7 +500,7 @@ public class Attr extends JCTree.Visitor {
}
final ResultInfo statInfo;
final ResultInfo varInfo;
final ResultInfo varAssignmentInfo;
final ResultInfo unknownAnyPolyInfo;
final ResultInfo unknownExprInfo;
final ResultInfo unknownTypeInfo;
@ -629,19 +631,19 @@ public class Attr extends JCTree.Visitor {
/** Attribute the arguments in a method call, returning the method kind.
*/
KindSelector attribArgs(List<JCExpression> trees, Env<AttrContext> env, ListBuffer<Type> argtypes) {
boolean polykind = false;
KindSelector attribArgs(KindSelector initialKind, List<JCExpression> trees, Env<AttrContext> env, ListBuffer<Type> argtypes) {
KindSelector kind = initialKind;
for (JCExpression arg : trees) {
Type argtype;
if (allowPoly && deferredAttr.isDeferred(env, arg)) {
argtype = deferredAttr.new DeferredType(arg, env);
polykind = true;
kind = KindSelector.of(KindSelector.POLY, kind);
} else {
argtype = chk.checkNonVoid(arg, attribTree(arg, env, unknownAnyPolyInfo));
}
argtypes.append(argtype);
}
return polykind ? KindSelector.VAL_POLY : KindSelector.VAL;
return kind;
}
/** Attribute a type argument list, returning a list of types.
@ -949,7 +951,7 @@ public class Attr extends JCTree.Visitor {
if (body.stats.isEmpty() ||
!TreeInfo.isSelfCall(body.stats.head)) {
body.stats = body.stats.
prepend(memberEnter.SuperCall(make.at(body.pos),
prepend(typeEnter.SuperCall(make.at(body.pos),
List.<Type>nil(),
List.<JCVariableDecl>nil(),
false));
@ -1293,7 +1295,7 @@ public class Attr extends JCTree.Visitor {
}
};
ResultInfo twrResult =
new ResultInfo(KindSelector.VAL,
new ResultInfo(KindSelector.VAR,
syms.autoCloseableType,
twrContext);
if (resource.hasTag(VARDEF)) {
@ -1704,7 +1706,7 @@ public class Attr extends JCTree.Visitor {
localEnv.info.isSelfCall = true;
// Attribute arguments, yielding list of argument types.
attribArgs(tree.args, localEnv, argtypesBuf);
KindSelector kind = attribArgs(KindSelector.MTH, tree.args, localEnv, argtypesBuf);
argtypes = argtypesBuf.toList();
typeargtypes = attribTypes(tree.typeargs, localEnv);
@ -1770,7 +1772,7 @@ public class Attr extends JCTree.Visitor {
// (this will also set the tree's type)
Type mpt = newMethodTemplate(resultInfo.pt, argtypes, typeargtypes);
checkId(tree.meth, site, sym, localEnv,
new ResultInfo(KindSelector.MTH, mpt));
new ResultInfo(kind, mpt));
}
// Otherwise, `site' is an error type and we do nothing
}
@ -1778,7 +1780,7 @@ public class Attr extends JCTree.Visitor {
} else {
// Otherwise, we are seeing a regular method call.
// Attribute the arguments, yielding list of argument types, ...
KindSelector kind = attribArgs(tree.args, localEnv, argtypesBuf);
KindSelector kind = attribArgs(KindSelector.VAL, tree.args, localEnv, argtypesBuf);
argtypes = argtypesBuf.toList();
typeargtypes = attribAnyTypes(tree.typeargs, localEnv);
@ -1958,7 +1960,7 @@ public class Attr extends JCTree.Visitor {
// Attribute constructor arguments.
ListBuffer<Type> argtypesBuf = new ListBuffer<>();
final KindSelector pkind =
attribArgs(tree.args, localEnv, argtypesBuf);
attribArgs(KindSelector.VAL, tree.args, localEnv, argtypesBuf);
List<Type> argtypes = argtypesBuf.toList();
List<Type> typeargtypes = attribTypes(tree.typeargs, localEnv);
@ -2942,7 +2944,7 @@ public class Attr extends JCTree.Visitor {
}
public void visitAssign(JCAssign tree) {
Type owntype = attribTree(tree.lhs, env.dup(tree), varInfo);
Type owntype = attribTree(tree.lhs, env.dup(tree), varAssignmentInfo);
Type capturedType = capture(owntype);
attribExpr(tree.rhs, env, owntype);
result = check(tree, capturedType, KindSelector.VAL, resultInfo);
@ -2950,7 +2952,7 @@ public class Attr extends JCTree.Visitor {
public void visitAssignop(JCAssignOp tree) {
// Attribute arguments.
Type owntype = attribTree(tree.lhs, env, varInfo);
Type owntype = attribTree(tree.lhs, env, varAssignmentInfo);
Type operand = attribExpr(tree.rhs, env);
// Find operator.
Symbol operator = tree.operator = rs.resolveBinaryOperator(
@ -2976,7 +2978,7 @@ public class Attr extends JCTree.Visitor {
public void visitUnary(JCUnary tree) {
// Attribute arguments.
Type argtype = (tree.getTag().isIncOrDecUnaryOp())
? attribTree(tree.arg, env, varInfo)
? attribTree(tree.arg, env, varAssignmentInfo)
: chk.checkNonVoid(tree.arg.pos(), attribExpr(tree.arg, env));
// Find operator.
@ -3156,7 +3158,7 @@ public class Attr extends JCTree.Visitor {
// If we are expecting a variable (as opposed to a value), check
// that the variable is assignable in the current environment.
if (pkind() == KindSelector.VAR)
if (KindSelector.ASG.subset(pkind()))
checkAssignable(tree.pos(), v, null, env);
}
@ -3233,6 +3235,10 @@ public class Attr extends JCTree.Visitor {
// Determine the symbol represented by the selection.
env.info.pendingResolutionPhase = null;
Symbol sym = selectSym(tree, sitesym, site, env, resultInfo);
if (sym.kind == VAR && sym.name != names._super && env.info.defaultSuperCallSite != null) {
log.error(tree.selected.pos(), "not.encl.class", site.tsym);
sym = syms.errSymbol;
}
if (sym.exists() && !isType(sym) && pkind().contains(KindSelector.TYP_PCK)) {
site = capture(site);
sym = selectSym(tree, sitesym, site, env, resultInfo);
@ -3255,7 +3261,7 @@ public class Attr extends JCTree.Visitor {
// If we are expecting a variable (as opposed to a value), check
// that the variable is assignable in the current environment.
if (pkind() == KindSelector.VAR)
if (KindSelector.ASG.subset(pkind()))
checkAssignable(tree.pos(), v, tree.selected, env);
}
@ -3538,7 +3544,7 @@ public class Attr extends JCTree.Visitor {
// Test (4): if symbol is an instance field of a raw type,
// which is being assigned to, issue an unchecked warning if
// its type changes under erasure.
if (resultInfo.pkind == KindSelector.VAR &&
if (KindSelector.ASG.subset(pkind()) &&
v.owner.kind == TYP &&
(v.flags() & STATIC) == 0 &&
(site.hasTag(CLASS) || site.hasTag(TYPEVAR))) {
@ -4486,14 +4492,15 @@ public class Attr extends JCTree.Visitor {
super.visitTypeTest(tree);
}
public void visitNewClass(JCNewClass tree) {
if (tree.clazz.hasTag(ANNOTATED_TYPE)) {
checkForDeclarationAnnotations(((JCAnnotatedType) tree.clazz).annotations,
tree.clazz.type.tsym);
}
if (tree.def != null) {
checkForDeclarationAnnotations(tree.def.mods.annotations, tree.clazz.type.tsym);
}
if (tree.clazz.type != null) {
if (tree.clazz != null && tree.clazz.type != null) {
if (tree.clazz.hasTag(ANNOTATED_TYPE)) {
checkForDeclarationAnnotations(((JCAnnotatedType) tree.clazz).annotations,
tree.clazz.type.tsym);
}
if (tree.def != null) {
checkForDeclarationAnnotations(tree.def.mods.annotations, tree.clazz.type.tsym);
}
validateAnnotatedType(tree.clazz, tree.clazz.type);
}
super.visitNewClass(tree);

@ -28,7 +28,6 @@ package com.sun.tools.javac.comp;
import java.util.*;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Attribute.Compound;
@ -40,6 +39,7 @@ import com.sun.tools.javac.util.List;
import com.sun.tools.javac.code.Lint;
import com.sun.tools.javac.code.Lint.LintCategory;
import com.sun.tools.javac.code.Scope.CompoundScope;
import com.sun.tools.javac.code.Scope.NamedImportScope;
import com.sun.tools.javac.code.Scope.WriteableScope;
import com.sun.tools.javac.code.Type.*;
@ -3415,56 +3415,69 @@ public class Check {
}
}
/** Check that single-type import is not already imported or top-level defined,
* but make an exception for two single-type imports which denote the same type.
* @param pos Position for error reporting.
* @param toplevel The file in which in the check is performed.
* @param sym The symbol.
/**Check that types imported through the ordinary imports don't clash with types imported
* by other (static or ordinary) imports. Note that two static imports may import two clashing
* types without an error on the imports.
* @param toplevel The toplevel tree for which the test should be performed.
*/
boolean checkUniqueImport(DiagnosticPosition pos, JCCompilationUnit toplevel, Symbol sym) {
return checkUniqueImport(pos, toplevel, sym, false);
}
/** Check that static single-type import is not already imported or top-level defined,
* but make an exception for two single-type imports which denote the same type.
* @param pos Position for error reporting.
* @param toplevel The file in which in the check is performed.
* @param sym The symbol.
*/
boolean checkUniqueStaticImport(DiagnosticPosition pos, JCCompilationUnit toplevel, Symbol sym) {
return checkUniqueImport(pos, toplevel, sym, true);
}
/** Check that single-type import is not already imported or top-level defined,
* but make an exception for two single-type imports which denote the same type.
* @param pos Position for error reporting.
* @param toplevel The file in which in the check is performed.
* @param sym The symbol.
* @param staticImport Whether or not this was a static import
*/
private boolean checkUniqueImport(DiagnosticPosition pos, JCCompilationUnit toplevel, Symbol sym, boolean staticImport) {
NamedImportScope namedImportScope = toplevel.namedImportScope;
void checkImportsUnique(JCCompilationUnit toplevel) {
WriteableScope ordinallyImportedSoFar = WriteableScope.create(toplevel.packge);
WriteableScope staticallyImportedSoFar = WriteableScope.create(toplevel.packge);
WriteableScope topLevelScope = toplevel.toplevelScope;
for (Symbol byName : namedImportScope.getSymbolsByName(sym.name)) {
// is encountered class entered via a class declaration?
boolean isClassDecl = namedImportScope.getOrigin(byName) == topLevelScope;
if ((isClassDecl || sym != byName) &&
sym.kind == byName.kind &&
sym.name != names.error &&
(!staticImport || !namedImportScope.isStaticallyImported(byName))) {
if (!byName.type.isErroneous()) {
if (!isClassDecl) {
if (staticImport)
log.error(pos, "already.defined.static.single.import", byName);
else
log.error(pos, "already.defined.single.import", byName);
}
else if (sym != byName)
log.error(pos, "already.defined.this.unit", byName);
for (JCTree def : toplevel.defs) {
if (!def.hasTag(IMPORT))
continue;
JCImport imp = (JCImport) def;
if (imp.importScope == null)
continue;
for (Symbol sym : imp.importScope.getSymbols(sym -> sym.kind == TYP)) {
if (imp.isStatic()) {
checkUniqueImport(imp.pos(), ordinallyImportedSoFar, staticallyImportedSoFar, topLevelScope, sym, true);
staticallyImportedSoFar.enter(sym);
} else {
checkUniqueImport(imp.pos(), ordinallyImportedSoFar, staticallyImportedSoFar, topLevelScope, sym, false);
ordinallyImportedSoFar.enter(sym);
}
return false;
}
imp.importScope = null;
}
}
/** Check that single-type import is not already imported or top-level defined,
* but make an exception for two single-type imports which denote the same type.
* @param pos Position for error reporting.
* @param ordinallyImportedSoFar A Scope containing types imported so far through
* ordinary imports.
* @param staticallyImportedSoFar A Scope containing types imported so far through
* static imports.
* @param topLevelScope The current file's top-level Scope
* @param sym The symbol.
* @param staticImport Whether or not this was a static import
*/
private boolean checkUniqueImport(DiagnosticPosition pos, Scope ordinallyImportedSoFar,
Scope staticallyImportedSoFar, Scope topLevelScope,
Symbol sym, boolean staticImport) {
Filter<Symbol> duplicates = candidate -> candidate != sym && !candidate.type.isErroneous();
Symbol clashing = ordinallyImportedSoFar.findFirst(sym.name, duplicates);
if (clashing == null && !staticImport) {
clashing = staticallyImportedSoFar.findFirst(sym.name, duplicates);
}
if (clashing != null) {
if (staticImport)
log.error(pos, "already.defined.static.single.import", clashing);
else
log.error(pos, "already.defined.single.import", clashing);
return false;
}
clashing = topLevelScope.findFirst(sym.name, duplicates);
if (clashing != null) {
log.error(pos, "already.defined.this.unit", clashing);
return false;
}
return true;
}
@ -3570,18 +3583,13 @@ public class Check {
if (select.name == names.asterisk || (origin = TreeInfo.symbol(select.selected)) == null || origin.kind != TYP)
continue;
JavaFileObject prev = log.useSource(toplevel.sourcefile);
try {
TypeSymbol site = (TypeSymbol) TreeInfo.symbol(select.selected);
if (!checkTypeContainsImportableElement(site, site, toplevel.packge, select.name, new HashSet<Symbol>())) {
log.error(imp.pos(), "cant.resolve.location",
KindName.STATIC,
select.name, List.<Type>nil(), List.<Type>nil(),
Kinds.typeKindName(TreeInfo.symbol(select.selected).type),
TreeInfo.symbol(select.selected).type);
}
} finally {
log.useSource(prev);
TypeSymbol site = (TypeSymbol) TreeInfo.symbol(select.selected);
if (!checkTypeContainsImportableElement(site, site, toplevel.packge, select.name, new HashSet<Symbol>())) {
log.error(imp.pos(), "cant.resolve.location",
KindName.STATIC,
select.name, List.<Type>nil(), List.<Type>nil(),
Kinds.typeKindName(TreeInfo.symbol(select.selected).type),
TreeInfo.symbol(select.selected).type);
}
}
}

@ -47,40 +47,34 @@ import static com.sun.tools.javac.code.Flags.*;
import static com.sun.tools.javac.code.Kinds.Kind.*;
/** This class enters symbols for all encountered definitions into
* the symbol table. The pass consists of two phases, organized as
* follows:
* the symbol table. The pass consists of high-level two phases,
* organized as follows:
*
* <p>In the first phase, all class symbols are entered into their
* enclosing scope, descending recursively down the tree for classes
* which are members of other classes. The class symbols are given a
* MemberEnter object as completer.
* TypeEnter object as completer.
*
* <p>In the second phase classes are completed using
* MemberEnter.complete(). Completion might occur on demand, but
* TypeEnter.complete(). Completion might occur on demand, but
* any classes that are not completed that way will be eventually
* completed by processing the `uncompleted' queue. Completion
* entails (1) determination of a class's parameters, supertype and
* interfaces, as well as (2) entering all symbols defined in the
* completed by processing the `uncompleted' queue. Completion
* entails determination of a class's parameters, supertype and
* interfaces, as well as entering all symbols defined in the
* class into its scope, with the exception of class symbols which
* have been entered in phase 1. (2) depends on (1) having been
* completed for a class and all its superclasses and enclosing
* classes. That's why, after doing (1), we put classes in a
* `halfcompleted' queue. Only when we have performed (1) for a class
* and all it's superclasses and enclosing classes, we proceed to
* (2).
* have been entered in phase 1.
*
* <p>Whereas the first phase is organized as a sweep through all
* compiled syntax trees, the second phase is demand. Members of a
* compiled syntax trees, the second phase is on-demand. Members of a
* class are entered when the contents of a class are first
* accessed. This is accomplished by installing completer objects in
* class symbols for compiled classes which invoke the member-enter
* class symbols for compiled classes which invoke the type-enter
* phase for the corresponding class tree.
*
* <p>Classes migrate from one phase to the next via queues:
*
* <pre>{@literal
* class enter -> (Enter.uncompleted) --> member enter (1)
* -> (MemberEnter.halfcompleted) --> member enter (2)
* class enter -> (Enter.uncompleted) --> type enter
* -> (Todo) --> attribute
* (only for toplevel classes)
* }</pre>
@ -98,7 +92,7 @@ public class Enter extends JCTree.Visitor {
Check chk;
TreeMaker make;
Annotate annotate;
MemberEnter memberEnter;
TypeEnter typeEnter;
Types types;
Lint lint;
Names names;
@ -122,7 +116,7 @@ public class Enter extends JCTree.Visitor {
make = TreeMaker.instance(context);
syms = Symtab.instance(context);
chk = Check.instance(context);
memberEnter = MemberEnter.instance(context);
typeEnter = TypeEnter.instance(context);
types = Types.instance(context);
annotate = Annotate.instance(context);
lint = Lint.instance(context);
@ -391,7 +385,7 @@ public class Enter extends JCTree.Visitor {
typeEnvs.put(c, localEnv);
// Fill out class fields.
c.completer = memberEnter;
c.completer = typeEnter;
c.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, c, tree);
c.sourcefile = env.toplevel.sourcefile;
c.members_field = WriteableScope.create(c);
@ -469,22 +463,23 @@ public class Enter extends JCTree.Visitor {
complete(trees, null);
}
/** Main method: enter one class from a list of toplevel trees and
* place the rest on uncompleted for later processing.
/** Main method: enter classes from the list of toplevel trees, possibly
* skipping TypeEnter for all but 'c' by placing them on the uncompleted
* list.
* @param trees The list of trees to be processed.
* @param c The class symbol to be processed.
* @param c The class symbol to be processed or null to process all.
*/
public void complete(List<JCCompilationUnit> trees, ClassSymbol c) {
annotate.enterStart();
ListBuffer<ClassSymbol> prevUncompleted = uncompleted;
if (memberEnter.completionEnabled) uncompleted = new ListBuffer<>();
if (typeEnter.completionEnabled) uncompleted = new ListBuffer<>();
try {
// enter all classes, and construct uncompleted list
classEnter(trees, null);
// complete all uncompleted classes in memberEnter
if (memberEnter.completionEnabled) {
if (typeEnter.completionEnabled) {
while (uncompleted.nonEmpty()) {
ClassSymbol clazz = uncompleted.next();
if (c == null || c == clazz || prevUncompleted == null)
@ -494,16 +489,7 @@ public class Enter extends JCTree.Visitor {
prevUncompleted.append(clazz);
}
// if there remain any unimported toplevels (these must have
// no classes at all), process their import statements as well.
for (JCCompilationUnit tree : trees) {
if (tree.starImportScope.isEmpty()) {
JavaFileObject prev = log.useSource(tree.sourcefile);
Env<AttrContext> topEnv = topLevelEnv(tree);
memberEnter.memberEnter(tree, topEnv);
log.useSource(prev);
}
}
typeEnter.ensureImportsChecked(trees);
}
} finally {
uncompleted = prevUncompleted;

@ -242,9 +242,15 @@ public class Flow {
Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log);
try {
new AssignAnalyzer() {
WriteableScope enclosedSymbols = WriteableScope.create(env.enclClass.sym);
@Override
public void visitVarDef(JCVariableDecl tree) {
enclosedSymbols.enter(tree.sym);
super.visitVarDef(tree);
}
@Override
protected boolean trackable(VarSymbol sym) {
return !env.info.scope.includes(sym) &&
return enclosedSymbols.includes(sym) &&
sym.owner.kind == MTH;
}
}.analyzeTree(env, that);
@ -2556,6 +2562,8 @@ public class Flow {
* This pass implements the last step of the dataflow analysis, namely
* the effectively-final analysis check. This checks that every local variable
* reference from a lambda body/local inner class is either final or effectively final.
* Additional this also checks that every variable that is used as an operand to
* try-with-resources is final or effectively final.
* As effectively final variables are marked as such during DA/DU, this pass must run after
* AssignAnalyzer.
*/
@ -2684,6 +2692,18 @@ public class Flow {
}
}
public void visitTry(JCTry tree) {
for (JCTree resource : tree.resources) {
if (!resource.hasTag(VARDEF)) {
Symbol var = TreeInfo.symbol(resource);
if (var != null && (var.flags() & (FINAL | EFFECTIVELY_FINAL)) == 0) {
log.error(resource.pos(), "try.with.resources.expr.effectively.final.var", var);
}
}
}
super.visitTry(tree);
}
/**************************************************************************
* main method
*************************************************************************/

@ -40,6 +40,7 @@ import com.sun.tools.javac.code.Symbol.VarSymbol;
import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Type.MethodType;
import com.sun.tools.javac.code.Type.TypeVar;
import com.sun.tools.javac.code.Types;
import com.sun.tools.javac.comp.LambdaToMethod.LambdaAnalyzerPreprocessor.*;
import com.sun.tools.javac.comp.Lower.BasicFreeVarCollector;
@ -60,6 +61,7 @@ import static com.sun.tools.javac.code.Flags.*;
import static com.sun.tools.javac.code.Kinds.Kind.*;
import static com.sun.tools.javac.code.TypeTag.*;
import static com.sun.tools.javac.tree.JCTree.Tag.*;
import javax.lang.model.type.TypeKind;
/**
* This pass desugars lambda expressions into static methods
@ -759,49 +761,10 @@ public class LambdaToMethod extends TreeTranslator {
int prevPos = make.pos;
try {
make.at(tree);
Type samDesc = localContext.bridgedRefSig();
List<Type> samPTypes = samDesc.getParameterTypes();
// an extra argument is prepended in the case where the member
// reference is an unbound instance method reference (in which
// case the receiver expression in passed.
VarSymbol rcvr;
switch (tree.kind) {
case BOUND:
rcvr = addParameter("rec$", tree.getQualifierExpression().type, false);
receiverExpression = attr.makeNullCheck(tree.getQualifierExpression());
break;
case UNBOUND:
rcvr = addParameter("rec$", samPTypes.head, false);
samPTypes = samPTypes.tail;
break;
default:
rcvr = null;
break;
}
// generate the parameter list for the coverted member reference.
// the signature will match the signature of the target sam descriptor
List<Type> refPTypes = tree.sym.type.getParameterTypes();
int refSize = refPTypes.size();
int samSize = samPTypes.size();
// Last parameter to copy from referenced method
int last = localContext.needsVarArgsConversion() ? refSize - 1 : refSize;
List<Type> l = refPTypes;
// Use parameter types of the referenced method, excluding final var args
for (int i = 0; l.nonEmpty() && i < last; ++i) {
addParameter("x$" + i, l.head, true);
l = l.tail;
}
// Flatten out the var args
for (int i = last; i < samSize; ++i) {
addParameter("xva$" + i, tree.varargsElement, true);
}
//body generation - this can be either a method call or a
//new instance creation expression, depending on the member reference kind
VarSymbol rcvr = addParametersReturnReceiver();
JCExpression expr = (tree.getMode() == ReferenceMode.INVOKE)
? expressionInvoke(rcvr)
: expressionNew();
@ -816,6 +779,78 @@ public class LambdaToMethod extends TreeTranslator {
}
}
/**
* Generate the parameter list for the converted member reference.
*
* @return The receiver variable symbol, if any
*/
VarSymbol addParametersReturnReceiver() {
Type samDesc = localContext.bridgedRefSig();
List<Type> samPTypes = samDesc.getParameterTypes();
List<Type> descPTypes = tree.getDescriptorType(types).getParameterTypes();
// Determine the receiver, if any
VarSymbol rcvr;
switch (tree.kind) {
case BOUND:
// The receiver is explicit in the method reference
rcvr = addParameter("rec$", tree.getQualifierExpression().type, false);
receiverExpression = attr.makeNullCheck(tree.getQualifierExpression());
break;
case UNBOUND:
// The receiver is the first parameter, extract it and
// adjust the SAM and unerased type lists accordingly
rcvr = addParameter("rec$", samDesc.getParameterTypes().head, false);
samPTypes = samPTypes.tail;
descPTypes = descPTypes.tail;
break;
default:
rcvr = null;
break;
}
List<Type> implPTypes = tree.sym.type.getParameterTypes();
int implSize = implPTypes.size();
int samSize = samPTypes.size();
// Last parameter to copy from referenced method, exclude final var args
int last = localContext.needsVarArgsConversion() ? implSize - 1 : implSize;
// Failsafe -- assure match-up
boolean checkForIntersection = tree.varargsElement != null || implSize == descPTypes.size();
// Use parameter types of the implementation method unless the unerased
// SAM parameter type is an intersection type, in that case use the
// erased SAM parameter type so that the supertype relationship
// the implementation method parameters is not obscured.
// Note: in this loop, the lists implPTypes, samPTypes, and descPTypes
// are used as pointers to the current parameter type information
// and are thus not usable afterwards.
for (int i = 0; implPTypes.nonEmpty() && i < last; ++i) {
// By default use the implementation method parmeter type
Type parmType = implPTypes.head;
// If the unerased parameter type is a type variable whose
// bound is an intersection (eg. <T extends A & B>) then
// use the SAM parameter type
if (checkForIntersection && descPTypes.head.getKind() == TypeKind.TYPEVAR) {
TypeVar tv = (TypeVar) descPTypes.head;
if (tv.bound.getKind() == TypeKind.INTERSECTION) {
parmType = samPTypes.head;
}
}
addParameter("x$" + i, parmType, true);
// Advance to the next parameter
implPTypes = implPTypes.tail;
samPTypes = samPTypes.tail;
descPTypes = descPTypes.tail;
}
// Flatten out the var args
for (int i = last; i < samSize; ++i) {
addParameter("xva$" + i, tree.varargsElement, true);
}
return rcvr;
}
JCExpression getReceiverExpression() {
return receiverExpression;
}
@ -2063,12 +2098,36 @@ public class LambdaToMethod extends TreeTranslator {
types.isSignaturePolymorphic((MethodSymbol)tree.sym);
}
/**
* Erasure destroys the implementation parameter subtype
* relationship for intersection types
*/
boolean interfaceParameterIsIntersectionType() {
List<Type> tl = tree.getDescriptorType(types).getParameterTypes();
if (tree.kind == ReferenceKind.UNBOUND) {
tl = tl.tail;
}
for (; tl.nonEmpty(); tl = tl.tail) {
Type pt = tl.head;
if (pt.getKind() == TypeKind.TYPEVAR) {
TypeVar tv = (TypeVar) pt;
if (tv.bound.getKind() == TypeKind.INTERSECTION) {
return true;
}
}
}
return false;
}
/**
* Does this reference need to be converted to a lambda
* (i.e. var args need to be expanded or "super" is used)
*/
final boolean needsConversionToLambda() {
return isSuper || needsVarArgsConversion() || isArrayOp() ||
return interfaceParameterIsIntersectionType() ||
isSuper ||
needsVarArgsConversion() ||
isArrayOp() ||
isPrivateInOtherClass() ||
!receiverAccessible() ||
(tree.getMode() == ReferenceMode.NEW &&

@ -25,75 +25,45 @@
package com.sun.tools.javac.comp;
import java.util.Collections;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Set;
import javax.tools.JavaFileObject;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Scope.ImportFilter;
import com.sun.tools.javac.code.Scope.NamedImportScope;
import com.sun.tools.javac.code.Scope.StarImportScope;
import com.sun.tools.javac.code.Scope.WriteableScope;
import com.sun.tools.javac.jvm.*;
import com.sun.tools.javac.tree.*;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.DefinedBy.Api;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.tree.JCTree.*;
import static com.sun.tools.javac.code.Flags.*;
import static com.sun.tools.javac.code.Flags.ANNOTATION;
import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
import static com.sun.tools.javac.code.Kinds.*;
import static com.sun.tools.javac.code.Kinds.Kind.*;
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.Dependencies.AttributionKind;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
/** This is the second phase of Enter, in which classes are completed
* by entering their members into the class scope using
* MemberEnter.complete(). See Enter for an overview.
/** Resolves field, method and constructor header, and constructs corresponding Symbols.
*
* <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 MemberEnter extends JCTree.Visitor implements Completer {
public class MemberEnter extends JCTree.Visitor {
protected static final Context.Key<MemberEnter> memberEnterKey = new Context.Key<>();
/** A switch to determine whether we check for package/class conflicts
*/
final static boolean checkClash = true;
private final Names names;
private final Enter enter;
private final Log log;
private final Check chk;
private final Attr attr;
private final Symtab syms;
private final TreeMaker make;
private final Todo todo;
private final Annotate annotate;
private final TypeAnnotations typeAnnotations;
private final Types types;
private final JCDiagnostic.Factory diags;
private final Source source;
private final Target target;
private final DeferredLintHandler deferredLintHandler;
private final Lint lint;
private final TypeEnvs typeEnvs;
private final Dependencies dependencies;
public static MemberEnter instance(Context context) {
MemberEnter instance = context.get(memberEnterKey);
@ -104,172 +74,14 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
protected MemberEnter(Context context) {
context.put(memberEnterKey, this);
names = Names.instance(context);
enter = Enter.instance(context);
log = Log.instance(context);
chk = Check.instance(context);
attr = Attr.instance(context);
syms = Symtab.instance(context);
make = TreeMaker.instance(context);
todo = Todo.instance(context);
annotate = Annotate.instance(context);
typeAnnotations = TypeAnnotations.instance(context);
types = Types.instance(context);
diags = JCDiagnostic.Factory.instance(context);
source = Source.instance(context);
target = Target.instance(context);
deferredLintHandler = DeferredLintHandler.instance(context);
lint = Lint.instance(context);
typeEnvs = TypeEnvs.instance(context);
dependencies = Dependencies.instance(context);
allowTypeAnnos = source.allowTypeAnnotations();
}
/** Switch: support type annotations.
*/
boolean allowTypeAnnos;
/** A queue for classes whose members still need to be entered into the
* symbol table.
*/
ListBuffer<Env<AttrContext>> halfcompleted = new ListBuffer<>();
/** Set to true only when the first of a set of classes is
* processed from the half completed queue.
*/
boolean isFirst = true;
/** A flag to disable completion from time to time during member
* enter, as we only need to look up types. This avoids
* unnecessarily deep recursion.
*/
boolean completionEnabled = true;
/* ---------- Processing import clauses ----------------
*/
/** Import all classes of a class or package on demand.
* @param pos Position to be used for error reporting.
* @param tsym The class or package the members of which are imported.
* @param env The env in which the imported classes will be entered.
*/
private void importAll(int pos,
final TypeSymbol tsym,
Env<AttrContext> env) {
// Check that packages imported from exist (JLS ???).
if (tsym.kind == PCK && tsym.members().isEmpty() && !tsym.exists()) {
// If we can't find java.lang, exit immediately.
if (((PackageSymbol)tsym).fullname.equals(names.java_lang)) {
JCDiagnostic msg = diags.fragment("fatal.err.no.java.lang");
throw new FatalError(msg);
} else {
log.error(DiagnosticFlag.RESOLVE_ERROR, pos, "doesnt.exist", tsym);
}
}
env.toplevel.starImportScope.importAll(tsym.members(), tsym.members(), typeImportFilter, false);
}
/** Import all static members of a class or package on demand.
* @param pos Position to be used for error reporting.
* @param tsym The class or package the members of which are imported.
* @param env The env in which the imported classes will be entered.
*/
private void importStaticAll(int pos,
final TypeSymbol tsym,
Env<AttrContext> env) {
final StarImportScope toScope = env.toplevel.starImportScope;
final PackageSymbol packge = env.toplevel.packge;
final TypeSymbol origin = tsym;
// enter imported types immediately
new SymbolImporter() {
void doImport(TypeSymbol tsym) {
toScope.importAll(tsym.members(), origin.members(), staticImportFilter, true);
}
}.importFrom(tsym);
}
/** Import statics types of a given name. Non-types are handled in Attr.
* @param pos Position to be used for error reporting.
* @param tsym The class from which the name is imported.
* @param name The (simple) name being imported.
* @param env The environment containing the named import
* scope to add to.
*/
private void importNamedStatic(final DiagnosticPosition pos,
final TypeSymbol tsym,
final Name name,
final Env<AttrContext> env) {
if (tsym.kind != TYP) {
log.error(DiagnosticFlag.RECOVERABLE, pos, "static.imp.only.classes.and.interfaces");
return;
}
final NamedImportScope toScope = env.toplevel.namedImportScope;
final Scope originMembers = tsym.members();
// enter imported types immediately
new SymbolImporter() {
void doImport(TypeSymbol tsym) {
Set<Symbol> maskedOut = null;
for (Symbol sym : tsym.members().getSymbolsByName(name)) {
if (sym.kind == TYP &&
staticImportFilter.accepts(originMembers, sym) &&
!chk.checkUniqueStaticImport(pos, env.toplevel, sym)) {
if (maskedOut == null)
maskedOut = Collections.newSetFromMap(new IdentityHashMap<Symbol, Boolean>());
maskedOut.add(sym);
}
}
ImportFilter importFilter = maskedOut != null ?
new MaskedImportFilter(staticImportFilter, maskedOut) :
staticImportFilter;
toScope.importByName(tsym.members(), originMembers, name, importFilter);
}
}.importFrom(tsym);
}
//where:
class MaskedImportFilter implements ImportFilter {
private final ImportFilter delegate;
private final Set<Symbol> maskedOut;
public MaskedImportFilter(ImportFilter delegate, Set<Symbol> maskedOut) {
this.delegate = delegate;
this.maskedOut = maskedOut;
}
@Override
public boolean accepts(Scope origin, Symbol sym) {
return !maskedOut.contains(sym) && delegate.accepts(origin, sym);
}
}
abstract class SymbolImporter {
Set<Symbol> processed = new HashSet<>();
void importFrom(TypeSymbol tsym) {
if (tsym == null || !processed.add(tsym))
return;
// also import inherited names
importFrom(types.supertype(tsym.type).tsym);
for (Type t : types.interfaces(tsym.type))
importFrom(t.tsym);
doImport(tsym);
}
abstract void doImport(TypeSymbol tsym);
}
/** Import given class.
* @param pos Position to be used for error reporting.
* @param tsym The class to be imported.
* @param env The environment containing the named import
* scope to add to.
*/
private void importNamed(DiagnosticPosition pos, final Symbol tsym, Env<AttrContext> env) {
if (tsym.kind == TYP &&
chk.checkUniqueImport(pos, env.toplevel, tsym))
env.toplevel.namedImportScope.importType(tsym.owner.members(), tsym.owner.members(), tsym);
}
/** Construct method type from method signature.
@ -338,32 +150,6 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
* Visitor methods for member enter
*********************************************************************/
ImportFilter staticImportFilter;
ImportFilter typeImportFilter = new ImportFilter() {
@Override
public boolean accepts(Scope origin, Symbol t) {
return t.kind == TYP;
}
};
protected void memberEnter(JCCompilationUnit tree, Env<AttrContext> env) {
ImportFilter prevStaticImportFilter = staticImportFilter;
try {
final PackageSymbol packge = env.toplevel.packge;
this.staticImportFilter = new ImportFilter() {
@Override
public boolean accepts(Scope origin, Symbol sym) {
return sym.isStatic() &&
chk.staticImportAccessible(sym, packge) &&
sym.isMemberOf((TypeSymbol) origin.owner, types);
}
};
memberEnter((JCTree) tree, env);
} finally {
this.staticImportFilter = prevStaticImportFilter;
}
}
/** Visitor argument: the current environment
*/
protected Env<AttrContext> env;
@ -390,122 +176,6 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
memberEnter(l.head, env);
}
/** Enter members for a class.
*/
void finishClass(JCClassDecl tree, Env<AttrContext> env) {
if ((tree.mods.flags & Flags.ENUM) != 0 &&
(types.supertype(tree.sym.type).tsym.flags() & Flags.ENUM) == 0) {
addEnumMembers(tree, env);
}
memberEnter(tree.defs, env);
}
/** Add the implicit members for an enum type
* to the symbol table.
*/
private void addEnumMembers(JCClassDecl tree, Env<AttrContext> env) {
JCExpression valuesType = make.Type(new ArrayType(tree.sym.type, syms.arrayClass));
// public static T[] values() { return ???; }
JCMethodDecl values = make.
MethodDef(make.Modifiers(Flags.PUBLIC|Flags.STATIC),
names.values,
valuesType,
List.<JCTypeParameter>nil(),
List.<JCVariableDecl>nil(),
List.<JCExpression>nil(), // thrown
null, //make.Block(0, Tree.emptyList.prepend(make.Return(make.Ident(names._null)))),
null);
memberEnter(values, env);
// public static T valueOf(String name) { return ???; }
JCMethodDecl valueOf = make.
MethodDef(make.Modifiers(Flags.PUBLIC|Flags.STATIC),
names.valueOf,
make.Type(tree.sym.type),
List.<JCTypeParameter>nil(),
List.of(make.VarDef(make.Modifiers(Flags.PARAMETER |
Flags.MANDATED),
names.fromString("name"),
make.Type(syms.stringType), null)),
List.<JCExpression>nil(), // thrown
null, //make.Block(0, Tree.emptyList.prepend(make.Return(make.Ident(names._null)))),
null);
memberEnter(valueOf, env);
}
public void visitTopLevel(JCCompilationUnit tree) {
if (!tree.starImportScope.isEmpty()) {
// we must have already processed this toplevel
return;
}
DiagnosticPosition prevLintPos = deferredLintHandler.immediate();
Lint prevLint = chk.setLint(lint);
try {
// Import-on-demand java.lang.
importAll(tree.pos, syms.enterPackage(names.java_lang), env);
// Process the package def and all import clauses.
memberEnter(tree.defs, env);
} finally {
chk.setLint(prevLint);
deferredLintHandler.setPos(prevLintPos);
}
}
public void visitPackageDef(JCPackageDecl tree) {
// check that no class exists with same fully qualified name as
// toplevel package
if (checkClash && tree.pid != null) {
Symbol p = env.toplevel.packge;
while (p.owner != syms.rootPackage) {
p.owner.complete(); // enter all class members of p
if (syms.classes.get(p.getQualifiedName()) != null) {
log.error(tree.pos,
"pkg.clashes.with.class.of.same.name",
p);
}
p = p.owner;
}
}
// process package annotations
annotate.annotateLater(tree.annotations, env, env.toplevel.packge, null);
}
// process the non-static imports and the static imports of types.
public void visitImport(JCImport tree) {
dependencies.push(AttributionKind.IMPORT, tree);
JCFieldAccess imp = (JCFieldAccess)tree.qualid;
Name name = TreeInfo.name(imp);
// Create a local environment pointing to this tree to disable
// effects of other imports in Resolve.findGlobalType
Env<AttrContext> localEnv = env.dup(tree);
TypeSymbol p = attr.attribImportQualifier(tree, localEnv).tsym;
if (name == names.asterisk) {
// Import on demand.
chk.checkCanonical(imp.selected);
if (tree.staticImport)
importStaticAll(tree.pos, p, env);
else
importAll(tree.pos, p, env);
} else {
// Named type import.
if (tree.staticImport) {
importNamedStatic(tree.pos(), p, name, localEnv);
chk.checkCanonical(imp.selected);
} else {
TypeSymbol c = attribImportType(imp, localEnv).tsym;
chk.checkCanonical(imp);
importNamed(tree.pos(), c, env);
}
}
dependencies.pop();
}
public void visitMethodDef(JCMethodDecl tree) {
WriteableScope enclScope = enter.enterScope(env);
MethodSymbol m = new MethodSymbol(0, tree.name, null, enclScope.owner);
@ -765,35 +435,6 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
return iEnv;
}
/* ********************************************************************
* Type completion
*********************************************************************/
Type attribImportType(JCTree tree, Env<AttrContext> env) {
Assert.check(completionEnabled);
try {
// To prevent deep recursion, suppress completion of some
// types.
completionEnabled = false;
return attr.attribType(tree, env);
} finally {
completionEnabled = true;
}
}
/**
* Check if a list of annotations contains a reference to
* java.lang.Deprecated.
**/
private boolean hasDeprecatedAnnotation(List<JCAnnotation> annotations) {
for (List<JCAnnotation> al = annotations; !al.isEmpty(); al = al.tail) {
JCAnnotation a = al.head;
if (a.annotationType.type == syms.deprecatedType && a.args.isEmpty())
return true;
}
return false;
}
/** Queue processing of an attribute default value. */
void annotateDefaultValueLater(final JCExpression defaultValue,
final Env<AttrContext> localEnv,
@ -839,534 +480,4 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
localEnv);
}
/* ********************************************************************
* Source completer
*********************************************************************/
/** Complete entering a class.
* @param sym The symbol of the class to be completed.
*/
public void complete(Symbol sym) throws CompletionFailure {
// Suppress some (recursive) MemberEnter invocations
if (!completionEnabled) {
// Re-install same completer for next time around and return.
Assert.check((sym.flags() & Flags.COMPOUND) == 0);
sym.completer = this;
return;
}
try {
annotate.enterStart();
ClassSymbol c = (ClassSymbol)sym;
ClassType ct = (ClassType)c.type;
Env<AttrContext> env = typeEnvs.get(c);
JCClassDecl tree = (JCClassDecl)env.tree;
boolean wasFirst = isFirst;
isFirst = false;
JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
DiagnosticPosition prevLintPos = deferredLintHandler.setPos(tree.pos());
try {
dependencies.push(c);
// Save class environment for later member enter (2) processing.
halfcompleted.append(env);
// Mark class as not yet attributed.
c.flags_field |= UNATTRIBUTED;
// If this is a toplevel-class, make sure any preceding import
// clauses have been seen.
if (c.owner.kind == PCK) {
memberEnter(env.toplevel, env.enclosing(TOPLEVEL));
todo.append(env);
}
if (c.owner.kind == TYP)
c.owner.complete();
// create an environment for evaluating the base clauses
Env<AttrContext> baseEnv = baseEnv(tree, env);
if (tree.extending != null)
annotate.annotateTypeLater(tree.extending, baseEnv, sym, tree.pos());
for (JCExpression impl : tree.implementing)
annotate.annotateTypeLater(impl, baseEnv, sym, tree.pos());
annotate.flush();
// Determine supertype.
Type supertype;
if (tree.extending != null) {
dependencies.push(AttributionKind.EXTENDS, tree.extending);
try {
supertype = attr.attribBase(tree.extending, baseEnv,
true, false, true);
} finally {
dependencies.pop();
}
} else {
supertype = ((tree.mods.flags & Flags.ENUM) != 0)
? attr.attribBase(enumBase(tree.pos, c), baseEnv,
true, false, false)
: (c.fullname == names.java_lang_Object)
? Type.noType
: syms.objectType;
}
ct.supertype_field = modelMissingTypes(supertype, tree.extending, false);
// Determine interfaces.
ListBuffer<Type> interfaces = new ListBuffer<>();
ListBuffer<Type> all_interfaces = null; // lazy init
Set<Type> interfaceSet = new HashSet<>();
List<JCExpression> interfaceTrees = tree.implementing;
for (JCExpression iface : interfaceTrees) {
dependencies.push(AttributionKind.IMPLEMENTS, iface);
try {
Type it = attr.attribBase(iface, baseEnv, false, true, true);
if (it.hasTag(CLASS)) {
interfaces.append(it);
if (all_interfaces != null) all_interfaces.append(it);
chk.checkNotRepeated(iface.pos(), types.erasure(it), interfaceSet);
} else {
if (all_interfaces == null)
all_interfaces = new ListBuffer<Type>().appendList(interfaces);
all_interfaces.append(modelMissingTypes(it, iface, true));
}
} finally {
dependencies.pop();
}
}
if ((c.flags_field & ANNOTATION) != 0) {
ct.interfaces_field = List.of(syms.annotationType);
ct.all_interfaces_field = ct.interfaces_field;
} else {
ct.interfaces_field = interfaces.toList();
ct.all_interfaces_field = (all_interfaces == null)
? ct.interfaces_field : all_interfaces.toList();
}
if (c.fullname == names.java_lang_Object) {
if (tree.extending != null) {
chk.checkNonCyclic(tree.extending.pos(),
supertype);
ct.supertype_field = Type.noType;
}
else if (tree.implementing.nonEmpty()) {
chk.checkNonCyclic(tree.implementing.head.pos(),
ct.interfaces_field.head);
ct.interfaces_field = List.nil();
}
}
// Annotations.
// In general, we cannot fully process annotations yet, but we
// can attribute the annotation types and then check to see if the
// @Deprecated annotation is present.
attr.attribAnnotationTypes(tree.mods.annotations, baseEnv);
if (hasDeprecatedAnnotation(tree.mods.annotations))
c.flags_field |= DEPRECATED;
annotate.annotateLater(tree.mods.annotations, baseEnv,
c, tree.pos());
chk.checkNonCyclicDecl(tree);
// class type parameters use baseEnv but everything uses env
attr.attribTypeVariables(tree.typarams, baseEnv);
for (JCTypeParameter tp : tree.typarams)
annotate.annotateTypeLater(tp, baseEnv, sym, tree.pos());
// Add default constructor if needed.
if ((c.flags() & INTERFACE) == 0 &&
!TreeInfo.hasConstructors(tree.defs)) {
List<Type> argtypes = List.nil();
List<Type> typarams = List.nil();
List<Type> thrown = List.nil();
long ctorFlags = 0;
boolean based = false;
boolean addConstructor = true;
JCNewClass nc = null;
if (c.name.isEmpty()) {
nc = (JCNewClass)env.next.tree;
if (nc.constructor != null) {
addConstructor = nc.constructor.kind != ERR;
Type superConstrType = types.memberType(c.type,
nc.constructor);
argtypes = superConstrType.getParameterTypes();
typarams = superConstrType.getTypeArguments();
ctorFlags = nc.constructor.flags() & VARARGS;
if (nc.encl != null) {
argtypes = argtypes.prepend(nc.encl.type);
based = true;
}
thrown = superConstrType.getThrownTypes();
}
}
if (addConstructor) {
MethodSymbol basedConstructor = nc != null ?
(MethodSymbol)nc.constructor : null;
JCTree constrDef = DefaultConstructor(make.at(tree.pos), c,
basedConstructor,
typarams, argtypes, thrown,
ctorFlags, based);
tree.defs = tree.defs.prepend(constrDef);
}
}
// enter symbols for 'this' into current scope.
VarSymbol thisSym =
new VarSymbol(FINAL | HASINIT, names._this, c.type, c);
thisSym.pos = Position.FIRSTPOS;
env.info.scope.enter(thisSym);
// if this is a class, enter symbol for 'super' into current scope.
if ((c.flags_field & INTERFACE) == 0 &&
ct.supertype_field.hasTag(CLASS)) {
VarSymbol superSym =
new VarSymbol(FINAL | HASINIT, names._super,
ct.supertype_field, c);
superSym.pos = Position.FIRSTPOS;
env.info.scope.enter(superSym);
}
// check that no package exists with same fully qualified name,
// but admit classes in the unnamed package which have the same
// name as a top-level package.
if (checkClash &&
c.owner.kind == PCK && c.owner != syms.unnamedPackage &&
syms.packageExists(c.fullname)) {
log.error(tree.pos, "clash.with.pkg.of.same.name", Kinds.kindName(sym), c);
}
if (c.owner.kind == PCK && (c.flags_field & PUBLIC) == 0 &&
!env.toplevel.sourcefile.isNameCompatible(c.name.toString(),JavaFileObject.Kind.SOURCE)) {
c.flags_field |= AUXILIARY;
}
} catch (CompletionFailure ex) {
chk.completionError(tree.pos(), ex);
} finally {
deferredLintHandler.setPos(prevLintPos);
log.useSource(prev);
dependencies.pop();
}
// Enter all member fields and methods of a set of half completed
// classes in a second phase.
if (wasFirst) {
Set<JCCompilationUnit> topLevels = new HashSet<>();
try {
while (halfcompleted.nonEmpty()) {
Env<AttrContext> toFinish = halfcompleted.next();
topLevels.add(toFinish.toplevel);
finish(toFinish);
if (allowTypeAnnos) {
typeAnnotations.organizeTypeAnnotationsSignatures(toFinish, (JCClassDecl)toFinish.tree);
typeAnnotations.validateTypeAnnotationsSignatures(toFinish, (JCClassDecl)toFinish.tree);
}
}
} finally {
isFirst = true;
}
for (JCCompilationUnit toplevel : topLevels) {
chk.checkImportsResolvable(toplevel);
}
}
} finally {
annotate.enterDone();
}
}
private Env<AttrContext> baseEnv(JCClassDecl tree, Env<AttrContext> env) {
WriteableScope baseScope = WriteableScope.create(tree.sym);
//import already entered local classes into base scope
for (Symbol sym : env.outer.info.scope.getSymbols(NON_RECURSIVE)) {
if (sym.isLocal()) {
baseScope.enter(sym);
}
}
//import current type-parameters into base scope
if (tree.typarams != null)
for (List<JCTypeParameter> typarams = tree.typarams;
typarams.nonEmpty();
typarams = typarams.tail)
baseScope.enter(typarams.head.type.tsym);
Env<AttrContext> outer = env.outer; // the base clause can't see members of this class
Env<AttrContext> localEnv = outer.dup(tree, outer.info.dup(baseScope));
localEnv.baseClause = true;
localEnv.outer = outer;
localEnv.info.isSelfCall = false;
return localEnv;
}
/** Enter member fields and methods of a class
* @param env the environment current for the class block.
*/
private void finish(Env<AttrContext> env) {
JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
try {
JCClassDecl tree = (JCClassDecl)env.tree;
finishClass(tree, env);
} finally {
log.useSource(prev);
}
}
/** Generate a base clause for an enum type.
* @param pos The position for trees and diagnostics, if any
* @param c The class symbol of the enum
*/
private JCExpression enumBase(int pos, ClassSymbol c) {
JCExpression result = make.at(pos).
TypeApply(make.QualIdent(syms.enumSym),
List.<JCExpression>of(make.Type(c.type)));
return result;
}
Type modelMissingTypes(Type t, final JCExpression tree, final boolean interfaceExpected) {
if (!t.hasTag(ERROR))
return t;
return new ErrorType(t.getOriginalType(), t.tsym) {
private Type modelType;
@Override
public Type getModelType() {
if (modelType == null)
modelType = new Synthesizer(getOriginalType(), interfaceExpected).visit(tree);
return modelType;
}
};
}
// where
private class Synthesizer extends JCTree.Visitor {
Type originalType;
boolean interfaceExpected;
List<ClassSymbol> synthesizedSymbols = List.nil();
Type result;
Synthesizer(Type originalType, boolean interfaceExpected) {
this.originalType = originalType;
this.interfaceExpected = interfaceExpected;
}
Type visit(JCTree tree) {
tree.accept(this);
return result;
}
List<Type> visit(List<? extends JCTree> trees) {
ListBuffer<Type> lb = new ListBuffer<>();
for (JCTree t: trees)
lb.append(visit(t));
return lb.toList();
}
@Override
public void visitTree(JCTree tree) {
result = syms.errType;
}
@Override
public void visitIdent(JCIdent tree) {
if (!tree.type.hasTag(ERROR)) {
result = tree.type;
} else {
result = synthesizeClass(tree.name, syms.unnamedPackage).type;
}
}
@Override
public void visitSelect(JCFieldAccess tree) {
if (!tree.type.hasTag(ERROR)) {
result = tree.type;
} else {
Type selectedType;
boolean prev = interfaceExpected;
try {
interfaceExpected = false;
selectedType = visit(tree.selected);
} finally {
interfaceExpected = prev;
}
ClassSymbol c = synthesizeClass(tree.name, selectedType.tsym);
result = c.type;
}
}
@Override
public void visitTypeApply(JCTypeApply tree) {
if (!tree.type.hasTag(ERROR)) {
result = tree.type;
} else {
ClassType clazzType = (ClassType) visit(tree.clazz);
if (synthesizedSymbols.contains(clazzType.tsym))
synthesizeTyparams((ClassSymbol) clazzType.tsym, tree.arguments.size());
final List<Type> actuals = visit(tree.arguments);
result = new ErrorType(tree.type, clazzType.tsym) {
@Override @DefinedBy(Api.LANGUAGE_MODEL)
public List<Type> getTypeArguments() {
return actuals;
}
};
}
}
ClassSymbol synthesizeClass(Name name, Symbol owner) {
int flags = interfaceExpected ? INTERFACE : 0;
ClassSymbol c = new ClassSymbol(flags, name, owner);
c.members_field = new Scope.ErrorScope(c);
c.type = new ErrorType(originalType, c) {
@Override @DefinedBy(Api.LANGUAGE_MODEL)
public List<Type> getTypeArguments() {
return typarams_field;
}
};
synthesizedSymbols = synthesizedSymbols.prepend(c);
return c;
}
void synthesizeTyparams(ClassSymbol sym, int n) {
ClassType ct = (ClassType) sym.type;
Assert.check(ct.typarams_field.isEmpty());
if (n == 1) {
TypeVar v = new TypeVar(names.fromString("T"), sym, syms.botType);
ct.typarams_field = ct.typarams_field.prepend(v);
} else {
for (int i = n; i > 0; i--) {
TypeVar v = new TypeVar(names.fromString("T" + i), sym,
syms.botType);
ct.typarams_field = ct.typarams_field.prepend(v);
}
}
}
}
/* ***************************************************************************
* tree building
****************************************************************************/
/** Generate default constructor for given class. For classes different
* from java.lang.Object, this is:
*
* c(argtype_0 x_0, ..., argtype_n x_n) throws thrown {
* super(x_0, ..., x_n)
* }
*
* or, if based == true:
*
* c(argtype_0 x_0, ..., argtype_n x_n) throws thrown {
* x_0.super(x_1, ..., x_n)
* }
*
* @param make The tree factory.
* @param c The class owning the default constructor.
* @param argtypes The parameter types of the constructor.
* @param thrown The thrown exceptions of the constructor.
* @param based Is first parameter a this$n?
*/
JCTree DefaultConstructor(TreeMaker make,
ClassSymbol c,
MethodSymbol baseInit,
List<Type> typarams,
List<Type> argtypes,
List<Type> thrown,
long flags,
boolean based) {
JCTree result;
if ((c.flags() & ENUM) != 0 &&
(types.supertype(c.type).tsym == syms.enumSym)) {
// constructors of true enums are private
flags = (flags & ~AccessFlags) | PRIVATE | GENERATEDCONSTR;
} else
flags |= (c.flags() & AccessFlags) | GENERATEDCONSTR;
if (c.name.isEmpty()) {
flags |= ANONCONSTR;
}
Type mType = new MethodType(argtypes, null, thrown, c);
Type initType = typarams.nonEmpty() ?
new ForAll(typarams, mType) :
mType;
MethodSymbol init = new MethodSymbol(flags, names.init,
initType, c);
init.params = createDefaultConstructorParams(make, baseInit, init,
argtypes, based);
List<JCVariableDecl> params = make.Params(argtypes, init);
List<JCStatement> stats = List.nil();
if (c.type != syms.objectType) {
stats = stats.prepend(SuperCall(make, typarams, params, based));
}
result = make.MethodDef(init, make.Block(0, stats));
return result;
}
private List<VarSymbol> createDefaultConstructorParams(
TreeMaker make,
MethodSymbol baseInit,
MethodSymbol init,
List<Type> argtypes,
boolean based) {
List<VarSymbol> initParams = null;
List<Type> argTypesList = argtypes;
if (based) {
/* In this case argtypes will have an extra type, compared to baseInit,
* corresponding to the type of the enclosing instance i.e.:
*
* Inner i = outer.new Inner(1){}
*
* in the above example argtypes will be (Outer, int) and baseInit
* will have parameter's types (int). So in this case we have to add
* first the extra type in argtypes and then get the names of the
* parameters from baseInit.
*/
initParams = List.nil();
VarSymbol param = new VarSymbol(PARAMETER, make.paramName(0), argtypes.head, init);
initParams = initParams.append(param);
argTypesList = argTypesList.tail;
}
if (baseInit != null && baseInit.params != null &&
baseInit.params.nonEmpty() && argTypesList.nonEmpty()) {
initParams = (initParams == null) ? List.<VarSymbol>nil() : initParams;
List<VarSymbol> baseInitParams = baseInit.params;
while (baseInitParams.nonEmpty() && argTypesList.nonEmpty()) {
VarSymbol param = new VarSymbol(baseInitParams.head.flags() | PARAMETER,
baseInitParams.head.name, argTypesList.head, init);
initParams = initParams.append(param);
baseInitParams = baseInitParams.tail;
argTypesList = argTypesList.tail;
}
}
return initParams;
}
/** Generate call to superclass constructor. This is:
*
* super(id_0, ..., id_n)
*
* or, if based == true
*
* id_0.super(id_1,...,id_n)
*
* where id_0, ..., id_n are the names of the given parameters.
*
* @param make The tree factory
* @param params The parameters that need to be passed to super
* @param typarams The type parameters that need to be passed to super
* @param based Is first parameter a this$n?
*/
JCExpressionStatement SuperCall(TreeMaker make,
List<Type> typarams,
List<JCVariableDecl> params,
boolean based) {
JCExpression meth;
if (based) {
meth = make.Select(make.Ident(params.head), names._super);
params = params.tail;
} else {
meth = make.Ident(names._super);
}
List<JCExpression> typeargs = typarams.nonEmpty() ? make.Types(typarams) : null;
return make.Exec(make.Apply(typeargs, meth, make.Idents(params)));
}
}

@ -3172,7 +3172,7 @@ public class Resolve {
super(referenceTree, name, site, argtypes.tail, typeargtypes, maxPhase);
if (site.isRaw() && !argtypes.head.hasTag(NONE)) {
Type asSuperSite = types.asSuper(argtypes.head, site.tsym);
this.site = asSuperSite;
this.site = types.capture(asSuperSite);
}
}
@ -4039,7 +4039,7 @@ public class Resolve {
s : new MethodSymbol(
s.flags(),
s.name,
types.createMethodTypeWithThrown(mt, allThrown),
types.createMethodTypeWithThrown(s.type, allThrown),
s.owner);
}
}

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 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
@ -25,20 +25,19 @@
package com.sun.tools.javac.file;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.CharsetDecoder;
import java.nio.file.Path;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.NestingKind;
import javax.tools.FileObject;
import javax.tools.JavaFileObject;
import static javax.tools.JavaFileObject.Kind.*;
import com.sun.tools.javac.util.BaseFileManager;
import com.sun.tools.javac.util.DefinedBy;
import com.sun.tools.javac.util.DefinedBy.Api;
@ -78,7 +77,7 @@ public abstract class BaseFileObject implements JavaFileObject {
throw new UnsupportedOperationException();
}
protected abstract String inferBinaryName(Iterable<? extends File> path);
protected abstract String inferBinaryName(Iterable<? extends Path> path);
protected static JavaFileObject.Kind getKind(String filename) {
return BaseFileManager.getKind(filename);
@ -89,8 +88,8 @@ public abstract class BaseFileObject implements JavaFileObject {
return (lastDot == -1 ? fileName : fileName.substring(0, lastDot));
}
protected static URI createJarUri(File jarFile, String entryName) {
URI jarURI = jarFile.toURI().normalize();
protected static URI createJarUri(Path jarFile, String entryName) {
URI jarURI = jarFile.toUri().normalize();
String separator = entryName.startsWith("/") ? "!" : "!/";
try {
// The jar URI convention appears to be not to re-encode the jarURI

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 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
@ -25,8 +25,8 @@
package com.sun.tools.javac.file;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@ -61,31 +61,31 @@ public class CacheFSInfo extends FSInfo {
}
@Override
public File getCanonicalFile(File file) {
public Path getCanonicalFile(Path file) {
Entry e = getEntry(file);
return e.canonicalFile;
}
@Override
public boolean exists(File file) {
public boolean exists(Path file) {
Entry e = getEntry(file);
return e.exists;
}
@Override
public boolean isDirectory(File file) {
public boolean isDirectory(Path file) {
Entry e = getEntry(file);
return e.isDirectory;
}
@Override
public boolean isFile(File file) {
public boolean isFile(Path file) {
Entry e = getEntry(file);
return e.isFile;
}
@Override
public List<File> getJarClassPath(File file) throws IOException {
public List<Path> getJarClassPath(Path file) throws IOException {
// don't bother to lock the cache, because it is thread-safe, and
// because the worst that can happen would be to create two identical
// jar class paths together and have one overwrite the other.
@ -95,7 +95,7 @@ public class CacheFSInfo extends FSInfo {
return e.jarClassPath;
}
private Entry getEntry(File file) {
private Entry getEntry(Path file) {
// don't bother to lock the cache, because it is thread-safe, and
// because the worst that can happen would be to create two identical
// entries together and have one overwrite the other.
@ -112,13 +112,13 @@ public class CacheFSInfo extends FSInfo {
}
// could also be a Map<File,SoftReference<Entry>> ?
private Map<File,Entry> cache = new ConcurrentHashMap<>();
private final Map<Path,Entry> cache = new ConcurrentHashMap<>();
private static class Entry {
File canonicalFile;
Path canonicalFile;
boolean exists;
boolean isFile;
boolean isDirectory;
List<File> jarClassPath;
List<Path> jarClassPath;
}
}

@ -1,8 +1,10 @@
package com.sun.tools.javac.file;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@ -42,29 +44,29 @@ public class FSInfo {
context.put(FSInfo.class, this);
}
public File getCanonicalFile(File file) {
public Path getCanonicalFile(Path file) {
try {
return file.getCanonicalFile();
return file.toRealPath();
} catch (IOException e) {
return file.getAbsoluteFile();
return file.toAbsolutePath();
}
}
public boolean exists(File file) {
return file.exists();
public boolean exists(Path file) {
return Files.exists(file);
}
public boolean isDirectory(File file) {
return file.isDirectory();
public boolean isDirectory(Path file) {
return Files.isDirectory(file);
}
public boolean isFile(File file) {
return file.isFile();
public boolean isFile(Path file) {
return Files.isRegularFile(file);
}
public List<File> getJarClassPath(File file) throws IOException {
String parent = file.getParent();
try (JarFile jarFile = new JarFile(file)) {
public List<Path> getJarClassPath(Path file) throws IOException {
Path parent = file.getParent();
try (JarFile jarFile = new JarFile(file.toFile())) {
Manifest man = jarFile.getManifest();
if (man == null)
return Collections.emptyList();
@ -77,14 +79,14 @@ public class FSInfo {
if (path == null)
return Collections.emptyList();
List<File> list = new ArrayList<>();
List<Path> list = new ArrayList<>();
for (StringTokenizer st = new StringTokenizer(path);
st.hasMoreTokens(); ) {
String elt = st.nextToken();
File f = new File(elt);
Path f = Paths.get(elt);
if (!f.isAbsolute() && parent != null)
f = new File(parent,elt).getAbsoluteFile();
f = parent.resolve(f).toAbsolutePath();
list.add(f);
}

@ -31,8 +31,10 @@ import java.net.URI;
import java.nio.file.DirectoryStream;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.FileSystemNotFoundException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.ProviderNotFoundException;
import java.nio.file.spi.FileSystemProvider;
import java.util.Collections;
import java.util.HashMap;
@ -79,11 +81,12 @@ public class JRTIndex {
}
public static boolean isAvailable() {
for (FileSystemProvider p: FileSystemProvider.installedProviders()) {
if (p.getScheme().equals("jrt"))
return true;
try {
FileSystems.getFileSystem(URI.create("jrt:/"));
return true;
} catch (ProviderNotFoundException | FileSystemNotFoundException e) {
return false;
}
return false;
}

@ -34,7 +34,12 @@ import java.net.URISyntaxException;
import java.net.URL;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.LinkOption;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@ -45,6 +50,8 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.zip.ZipFile;
import javax.lang.model.SourceVersion;
@ -97,17 +104,17 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
protected boolean mmappedIO;
protected boolean symbolFileEnabled;
protected enum SortFiles implements Comparator<File> {
protected enum SortFiles implements Comparator<Path> {
FORWARD {
@Override
public int compare(File f1, File f2) {
return f1.getName().compareTo(f2.getName());
public int compare(Path f1, Path f2) {
return f1.getFileName().compareTo(f2.getFileName());
}
},
REVERSE {
@Override
public int compare(File f1, File f2) {
return -f1.getName().compareTo(f2.getName());
public int compare(Path f1, Path f2) {
return -f1.getFileName().compareTo(f2.getFileName());
}
}
}
@ -171,10 +178,10 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
}
public JavaFileObject getFileForInput(String name) {
return getRegularFile(new File(name));
return getRegularFile(Paths.get(name));
}
public JavaFileObject getRegularFile(File file) {
public JavaFileObject getRegularFile(Path file) {
return new RegularFileObject(this, file);
}
@ -298,25 +305,36 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
* Insert all files in subdirectory subdirectory of directory directory
* which match fileKinds into resultList
*/
private void listDirectory(File directory,
private void listDirectory(Path directory,
RelativeDirectory subdirectory,
Set<JavaFileObject.Kind> fileKinds,
boolean recurse,
ListBuffer<JavaFileObject> resultList) {
File d = subdirectory.getFile(directory);
if (!caseMapCheck(d, subdirectory))
Path d;
try {
d = subdirectory.getFile(directory);
} catch (InvalidPathException ignore) {
return;
}
File[] files = d.listFiles();
if (files == null)
if (!Files.exists(d)) {
return;
}
if (!caseMapCheck(d, subdirectory)) {
return;
}
if (sortFiles != null)
Arrays.sort(files, sortFiles);
java.util.List<Path> files;
try (Stream<Path> s = Files.list(d)) {
files = (sortFiles == null ? s : s.sorted(sortFiles)).collect(Collectors.toList());
} catch (IOException ignore) {
return;
}
for (File f: files) {
String fname = f.getName();
if (f.isDirectory()) {
for (Path f: files) {
String fname = f.getFileName().toString();
if (Files.isDirectory(f)) {
if (recurse && SourceVersion.isIdentifier(fname)) {
listDirectory(directory,
new RelativeDirectory(subdirectory, fname),
@ -327,7 +345,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
} else {
if (isValidFile(fname, fileKinds)) {
JavaFileObject fe =
new RegularFileObject(this, fname, new File(d, fname));
new RegularFileObject(this, fname, d.resolve(fname));
resultList.append(fe);
}
}
@ -370,7 +388,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
* Insert all files in subdirectory subdirectory of container which
* match fileKinds into resultList
*/
private void listContainer(File container,
private void listContainer(Path container,
RelativeDirectory subdirectory,
Set<JavaFileObject.Kind> fileKinds,
boolean recurse,
@ -378,10 +396,10 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
Archive archive = archives.get(container);
if (archive == null) {
// Very temporary and obnoxious interim hack
if (container.getName().equals("bootmodules.jimage")) {
if (container.endsWith("bootmodules.jimage")) {
System.err.println("Warning: reference to bootmodules.jimage replaced by jrt:");
container = Locations.JRT_MARKER_FILE;
} else if (container.getName().endsWith(".jimage")) {
} else if (container.getFileName().toString().endsWith(".jimage")) {
System.err.println("Warning: reference to " + container + " ignored");
return;
}
@ -436,13 +454,15 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
* ends in a string of characters with the same case as given name.
* Ignore file separators in both path and name.
*/
private boolean caseMapCheck(File f, RelativePath name) {
private boolean caseMapCheck(Path f, RelativePath name) {
if (fileSystemIsCaseSensitive) return true;
// Note that getCanonicalPath() returns the case-sensitive
// Note that toRealPath() returns the case-sensitive
// spelled file name.
String path;
char sep;
try {
path = f.getCanonicalPath();
path = f.toRealPath(LinkOption.NOFOLLOW_LINKS).toString();
sep = f.getFileSystem().getSeparator().charAt(0);
} catch (IOException ex) {
return false;
}
@ -451,7 +471,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
int i = pcs.length - 1;
int j = ncs.length - 1;
while (i >= 0 && j >= 0) {
while (i >= 0 && pcs[i] == File.separatorChar) i--;
while (i >= 0 && pcs[i] == sep) i--;
while (j >= 0 && ncs[j] == '/') j--;
if (i >= 0 && j >= 0) {
if (pcs[i] != ncs[j]) return false;
@ -479,8 +499,8 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
}
public class MissingArchive implements Archive {
final File zipFileName;
public MissingArchive(File name) {
final Path zipFileName;
public MissingArchive(Path name) {
zipFileName = name;
}
@Override
@ -515,7 +535,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
/** A directory of zip files already opened.
*/
Map<File, Archive> archives = new HashMap<>();
Map<Path, Archive> archives = new HashMap<>();
/*
* This method looks for a ZipFormatException and takes appropriate
@ -523,7 +543,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
* fail over to the platform zip, and allow it to deal with a potentially
* non compliant zip file.
*/
protected Archive openArchive(File zipFilename) throws IOException {
protected Archive openArchive(Path zipFilename) throws IOException {
try {
return openArchive(zipFilename, contextUseOptimizedZip);
} catch (IOException ioe) {
@ -537,7 +557,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
/** Open a new zip file directory, and cache it.
*/
private Archive openArchive(File zipFileName, boolean useOptimizedZip) throws IOException {
private Archive openArchive(Path zipFileName, boolean useOptimizedZip) throws IOException {
Archive archive;
try {
@ -547,7 +567,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
String preindexCacheLocation = null;
if (!useOptimizedZip) {
zdir = new ZipFile(zipFileName);
zdir = new ZipFile(zipFileName.toFile());
} else {
usePreindexedCache = options.isSet("usezipindex");
preindexCacheLocation = options.get("java.io.tmpdir");
@ -584,12 +604,12 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
preindexCacheLocation,
options.isSet("writezipindexfiles")));
}
} catch (FileNotFoundException ex) {
} catch (FileNotFoundException | NoSuchFileException ex) {
archive = new MissingArchive(zipFileName);
} catch (ZipFileIndex.ZipFormatException zfe) {
throw zfe;
} catch (IOException ex) {
if (zipFileName.exists())
if (Files.exists(zipFileName))
log.error("error.reading.file", zipFileName, getMessage(ex));
archive = new MissingArchive(zipFileName);
}
@ -649,13 +669,13 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
nullCheck(packageName);
nullCheck(kinds);
Iterable<? extends File> path = getLocation(location);
Iterable<? extends Path> path = getLocationAsPaths(location);
if (path == null)
return List.nil();
RelativeDirectory subdirectory = RelativeDirectory.forPackage(packageName);
ListBuffer<JavaFileObject> results = new ListBuffer<>();
for (File directory : path)
for (Path directory : path)
listContainer(directory, subdirectory, kinds, recurse, results);
return results.toList();
}
@ -665,7 +685,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
file.getClass(); // null check
location.getClass(); // null check
// Need to match the path semantics of list(location, ...)
Iterable<? extends File> path = getLocation(location);
Iterable<? extends Path> path = getLocationAsPaths(location);
if (path == null) {
return null;
}
@ -730,11 +750,11 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
}
private JavaFileObject getFileForInput(Location location, RelativeFile name) throws IOException {
Iterable<? extends File> path = getLocation(location);
Iterable<? extends Path> path = getLocationAsPaths(location);
if (path == null)
return null;
for (File file: path) {
for (Path file: path) {
Archive a = archives.get(file);
if (a == null) {
// archives are not created for directories or jrt: images
@ -747,9 +767,12 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
return PathFileObject.createJRTPathFileObject(this, p);
continue;
} else if (fsInfo.isDirectory(file)) {
File f = name.getFile(file);
if (f.exists())
return new RegularFileObject(this, f);
try {
Path f = name.getFile(file);
if (Files.exists(f))
return new RegularFileObject(this, f);
} catch (InvalidPathException ignore) {
}
continue;
}
// Not a directory, create the archive
@ -802,31 +825,37 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
FileObject sibling)
throws IOException
{
File dir;
Path dir;
if (location == CLASS_OUTPUT) {
if (getClassOutDir() != null) {
dir = getClassOutDir();
} else {
File siblingDir = null;
Path siblingDir = null;
if (sibling != null && sibling instanceof RegularFileObject) {
siblingDir = ((RegularFileObject)sibling).file.getParentFile();
siblingDir = ((RegularFileObject)sibling).file.getParent();
}
return new RegularFileObject(this, new File(siblingDir, fileName.basename()));
if (siblingDir == null)
return new RegularFileObject(this, Paths.get(fileName.basename()));
else
return new RegularFileObject(this, siblingDir.resolve(fileName.basename()));
}
} else if (location == SOURCE_OUTPUT) {
dir = (getSourceOutDir() != null ? getSourceOutDir() : getClassOutDir());
} else {
Iterable<? extends File> path = locations.getLocation(location);
Iterable<? extends Path> path = locations.getLocation(location);
dir = null;
for (File f: path) {
for (Path f: path) {
dir = f;
break;
}
}
File file = fileName.getFile(dir); // null-safe
return new RegularFileObject(this, file);
try {
Path file = fileName.getFile(dir); // null-safe
return new RegularFileObject(this, file);
} catch (InvalidPathException e) {
throw new IOException("bad filename " + fileName, e);
}
}
@Override @DefinedBy(Api.COMPILER)
@ -839,7 +868,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
else
result = new ArrayList<>();
for (File f: files)
result.add(new RegularFileObject(this, nullCheck(f)));
result.add(new RegularFileObject(this, nullCheck(f).toPath()));
return result;
}
@ -850,24 +879,29 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
@Override @DefinedBy(Api.COMPILER)
public void setLocation(Location location,
Iterable<? extends File> path)
Iterable<? extends File> searchpath)
throws IOException
{
nullCheck(location);
locations.setLocation(location, path);
locations.setLocation(location, asPaths(searchpath));
}
@Override @DefinedBy(Api.COMPILER)
public Iterable<? extends File> getLocation(Location location) {
nullCheck(location);
return asFiles(locations.getLocation(location));
}
private Iterable<? extends Path> getLocationAsPaths(Location location) {
nullCheck(location);
return locations.getLocation(location);
}
private File getClassOutDir() {
private Path getClassOutDir() {
return locations.getOutputLocation(CLASS_OUTPUT);
}
private File getSourceOutDir() {
private Path getSourceOutDir() {
return locations.getOutputLocation(SOURCE_OUTPUT);
}
@ -938,4 +972,50 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
return s;
return e.toString();
}
/* Converters between files and paths.
* These are temporary until we can update the StandardJavaFileManager API.
*/
private static Iterable<Path> asPaths(final Iterable<? extends File> files) {
if (files == null)
return null;
return () -> new Iterator<Path>() {
Iterator<? extends File> iter = files.iterator();
@Override
public boolean hasNext() {
return iter.hasNext();
}
@Override
public Path next() {
return iter.next().toPath();
}
};
}
private static Iterable<File> asFiles(final Iterable<? extends Path> paths) {
if (paths == null)
return null;
return () -> new Iterator<File>() {
Iterator<? extends Path> iter = paths.iterator();
@Override
public boolean hasNext() {
return iter.hasNext();
}
@Override
public File next() {
return iter.next().toFile();
}
};
}
private static File asFile(Path path) {
return path == null ? null : path.toFile();
}
}

@ -33,6 +33,7 @@ import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
@ -44,7 +45,7 @@ import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.zip.ZipFile;
@ -104,7 +105,7 @@ public class Locations {
// should use the jrt: file system.
// When Locations has been converted to use java.nio.file.Path,
// Locations can use Paths.get(URI.create("jrt:"))
static final File JRT_MARKER_FILE = new File("JRT_MARKER_FILE");
static final Path JRT_MARKER_FILE = Paths.get("JRT_MARKER_FILE");
public Locations() {
initHandlers();
@ -117,7 +118,7 @@ public class Locations {
this.fsInfo = fsInfo;
}
public Collection<File> bootClassPath() {
public Collection<Path> bootClassPath() {
return getLocation(PLATFORM_CLASS_PATH);
}
@ -127,50 +128,46 @@ public class Locations {
return h.isDefault();
}
public Collection<File> userClassPath() {
public Collection<Path> userClassPath() {
return getLocation(CLASS_PATH);
}
public Collection<File> sourcePath() {
Collection<File> p = getLocation(SOURCE_PATH);
public Collection<Path> sourcePath() {
Collection<Path> p = getLocation(SOURCE_PATH);
// TODO: this should be handled by the LocationHandler
return p == null || p.isEmpty() ? null : p;
}
/**
* Split a path into its elements. Empty path elements will be ignored.
* Split a search path into its elements. Empty path elements will be ignored.
*
* @param path The path to be split
* @param searchPath The search path to be split
* @return The elements of the path
*/
private static Iterable<File> getPathEntries(String path) {
return getPathEntries(path, null);
private static Iterable<Path> getPathEntries(String searchPath) {
return getPathEntries(searchPath, null);
}
/**
* Split a path into its elements. If emptyPathDefault is not null, all empty elements in the
* Split a search path into its elements. If emptyPathDefault is not null, all empty elements in the
* path, including empty elements at either end of the path, will be replaced with the value of
* emptyPathDefault.
*
* @param path The path to be split
* @param searchPath The search path to be split
* @param emptyPathDefault The value to substitute for empty path elements, or null, to ignore
* empty path elements
* @return The elements of the path
*/
private static Iterable<File> getPathEntries(String path, File emptyPathDefault) {
ListBuffer<File> entries = new ListBuffer<>();
int start = 0;
while (start <= path.length()) {
int sep = path.indexOf(File.pathSeparatorChar, start);
if (sep == -1) {
sep = path.length();
private static Iterable<Path> getPathEntries(String searchPath, Path emptyPathDefault) {
ListBuffer<Path> entries = new ListBuffer<>();
for (String s: searchPath.split(Pattern.quote(File.pathSeparator), -1)) {
if (s.isEmpty()) {
if (emptyPathDefault != null) {
entries.add(emptyPathDefault);
}
} else {
entries.add(Paths.get(s));
}
if (start < sep) {
entries.add(new File(path.substring(start, sep)));
} else if (emptyPathDefault != null) {
entries.add(emptyPathDefault);
}
start = sep + 1;
}
return entries;
}
@ -179,12 +176,12 @@ public class Locations {
* Utility class to help evaluate a path option. Duplicate entries are ignored, jar class paths
* can be expanded.
*/
private class SearchPath extends LinkedHashSet<File> {
private class SearchPath extends LinkedHashSet<Path> {
private static final long serialVersionUID = 0;
private boolean expandJarClassPaths = false;
private final Set<File> canonicalValues = new HashSet<>();
private final Set<Path> canonicalValues = new HashSet<>();
public SearchPath expandJarClassPaths(boolean x) {
expandJarClassPaths = x;
@ -194,9 +191,9 @@ public class Locations {
/**
* What to use when path element is the empty string
*/
private File emptyPathDefault = null;
private Path emptyPathDefault = null;
public SearchPath emptyPathDefault(File x) {
public SearchPath emptyPathDefault(Path x) {
emptyPathDefault = x;
return this;
}
@ -206,7 +203,7 @@ public class Locations {
expandJarClassPaths = true;
try {
if (dirs != null) {
for (File dir : getPathEntries(dirs)) {
for (Path dir : getPathEntries(dirs)) {
addDirectory(dir, warn);
}
}
@ -220,8 +217,8 @@ public class Locations {
return addDirectories(dirs, warn);
}
private void addDirectory(File dir, boolean warn) {
if (!dir.isDirectory()) {
private void addDirectory(Path dir, boolean warn) {
if (!Files.isDirectory(dir)) {
if (warn) {
log.warning(Lint.LintCategory.PATH,
"dir.path.element.not.found", dir);
@ -229,15 +226,10 @@ public class Locations {
return;
}
File[] files = dir.listFiles();
if (files == null) {
return;
}
for (File direntry : files) {
if (isArchive(direntry)) {
addFile(direntry, warn);
}
try (Stream<Path> s = Files.list(dir)) {
s.filter(dirEntry -> isArchive(dirEntry))
.forEach(dirEntry -> addFile(dirEntry, warn));
} catch (IOException ignore) {
}
}
@ -252,20 +244,20 @@ public class Locations {
return addFiles(files, warn);
}
public SearchPath addFiles(Iterable<? extends File> files, boolean warn) {
public SearchPath addFiles(Iterable<? extends Path> files, boolean warn) {
if (files != null) {
for (File file : files) {
for (Path file : files) {
addFile(file, warn);
}
}
return this;
}
public SearchPath addFiles(Iterable<? extends File> files) {
public SearchPath addFiles(Iterable<? extends Path> files) {
return addFiles(files, warn);
}
public void addFile(File file, boolean warn) {
public void addFile(Path file, boolean warn) {
if (contains(file)) {
// discard duplicates
return;
@ -281,7 +273,7 @@ public class Locations {
return;
}
File canonFile = fsInfo.getCanonicalFile(file);
Path canonFile = fsInfo.getCanonicalFile(file);
if (canonicalValues.contains(canonFile)) {
/* Discard duplicates and avoid infinite recursion */
return;
@ -289,11 +281,11 @@ public class Locations {
if (fsInfo.isFile(file)) {
/* File is an ordinary file. */
if (!isArchive(file) && !file.getName().endsWith(".jimage")) {
if (!isArchive(file) && !file.getFileName().toString().endsWith(".jimage")) {
/* Not a recognized extension; open it to see if
it looks like a valid zip file. */
try {
ZipFile z = new ZipFile(file);
ZipFile z = new ZipFile(file.toFile());
z.close();
if (warn) {
log.warning(Lint.LintCategory.PATH,
@ -315,7 +307,7 @@ public class Locations {
super.add(file);
canonicalValues.add(canonFile);
if (expandJarClassPaths && fsInfo.isFile(file) && !file.getName().endsWith(".jimage")) {
if (expandJarClassPaths && fsInfo.isFile(file) && !file.getFileName().toString().endsWith(".jimage")) {
addJarClassPath(file, warn);
}
}
@ -324,9 +316,9 @@ public class Locations {
// Manifest entry. In some future release, we may want to
// update this code to recognize URLs rather than simple
// filenames, but if we do, we should redo all path-related code.
private void addJarClassPath(File jarFile, boolean warn) {
private void addJarClassPath(Path jarFile, boolean warn) {
try {
for (File f : fsInfo.getJarClassPath(jarFile)) {
for (Path f : fsInfo.getJarClassPath(jarFile)) {
addFile(f, warn);
}
} catch (IOException e) {
@ -371,12 +363,12 @@ public class Locations {
/**
* @see StandardJavaFileManager#getLocation
*/
abstract Collection<File> getLocation();
abstract Collection<Path> getLocation();
/**
* @see StandardJavaFileManager#setLocation
*/
abstract void setLocation(Iterable<? extends File> files) throws IOException;
abstract void setLocation(Iterable<? extends Path> files) throws IOException;
}
/**
@ -386,7 +378,7 @@ public class Locations {
*/
private class OutputLocationHandler extends LocationHandler {
private File outputDir;
private Path outputDir;
OutputLocationHandler(Location location, Option... options) {
super(location, options);
@ -402,31 +394,31 @@ public class Locations {
// need to decide how best to report issue for benefit of
// direct API call on JavaFileManager.handleOption(specifies IAE)
// vs. command line decoding.
outputDir = (value == null) ? null : new File(value);
outputDir = (value == null) ? null : Paths.get(value);
return true;
}
@Override
Collection<File> getLocation() {
Collection<Path> getLocation() {
return (outputDir == null) ? null : Collections.singleton(outputDir);
}
@Override
void setLocation(Iterable<? extends File> files) throws IOException {
void setLocation(Iterable<? extends Path> files) throws IOException {
if (files == null) {
outputDir = null;
} else {
Iterator<? extends File> pathIter = files.iterator();
Iterator<? extends Path> pathIter = files.iterator();
if (!pathIter.hasNext()) {
throw new IllegalArgumentException("empty path for directory");
}
File dir = pathIter.next();
Path dir = pathIter.next();
if (pathIter.hasNext()) {
throw new IllegalArgumentException("path too long for directory");
}
if (!dir.exists()) {
if (!Files.exists(dir)) {
throw new FileNotFoundException(dir + ": does not exist");
} else if (!dir.isDirectory()) {
} else if (!Files.isDirectory(dir)) {
throw new IOException(dir + ": not a directory");
}
outputDir = dir;
@ -441,7 +433,7 @@ public class Locations {
*/
private class SimpleLocationHandler extends LocationHandler {
protected Collection<File> searchPath;
protected Collection<Path> searchPath;
SimpleLocationHandler(Location location, Option... options) {
super(location, options);
@ -458,12 +450,12 @@ public class Locations {
}
@Override
Collection<File> getLocation() {
Collection<Path> getLocation() {
return searchPath;
}
@Override
void setLocation(Iterable<? extends File> files) {
void setLocation(Iterable<? extends Path> files) {
SearchPath p;
if (files == null) {
p = computePath(null);
@ -494,7 +486,7 @@ public class Locations {
}
@Override
Collection<File> getLocation() {
Collection<Path> getLocation() {
lazy();
return searchPath;
}
@ -526,7 +518,7 @@ public class Locations {
protected SearchPath createPath() {
return new SearchPath()
.expandJarClassPaths(true) // Only search user jars for Class-Paths
.emptyPathDefault(new File(".")); // Empty path elt ==> current directory
.emptyPathDefault(Paths.get(".")); // Empty path elt ==> current directory
}
private void lazy() {
@ -545,7 +537,7 @@ public class Locations {
*/
private class BootClassPathLocationHandler extends LocationHandler {
private Collection<File> searchPath;
private Collection<Path> searchPath;
final Map<Option, String> optionValues = new EnumMap<>(Option.class);
/**
@ -599,13 +591,13 @@ public class Locations {
}
@Override
Collection<File> getLocation() {
Collection<Path> getLocation() {
lazy();
return searchPath;
}
@Override
void setLocation(Iterable<? extends File> files) {
void setLocation(Iterable<? extends Path> files) {
if (files == null) {
searchPath = null; // reset to "uninitialized"
} else {
@ -638,7 +630,7 @@ public class Locations {
path.addFiles(bootclasspathOpt);
} else {
// Standard system classes for this compiler's release.
Collection<File> systemClasses = systemClasses(java_home);
Collection<Path> systemClasses = systemClasses(java_home);
if (systemClasses != null) {
path.addFiles(systemClasses, false);
} else {
@ -657,8 +649,8 @@ public class Locations {
path.addDirectories(extdirsOpt);
} else {
// Add lib/jfxrt.jar to the search path
File jfxrt = new File(new File(java_home, "lib"), "jfxrt.jar");
if (jfxrt.exists()) {
Path jfxrt = Paths.get(java_home, "lib", "jfxrt.jar");
if (Files.exists(jfxrt)) {
path.addFile(jfxrt, false);
}
path.addDirectories(System.getProperty("java.ext.dirs"), false);
@ -678,7 +670,7 @@ public class Locations {
*
* @throws UncheckedIOException if an I/O errors occurs
*/
private Collection<File> systemClasses(String java_home) throws IOException {
private Collection<Path> systemClasses(String java_home) throws IOException {
// Return .jimage files if available
Path libModules = Paths.get(java_home, "lib", "modules");
if (Files.exists(libModules)) {
@ -695,7 +687,6 @@ public class Locations {
if (Files.exists(libModules.resolve("java.base"))) {
return Files.list(libModules)
.map(d -> d.resolve("classes"))
.map(Path::toFile)
.collect(Collectors.toList());
}
@ -703,7 +694,6 @@ public class Locations {
Path modules = Paths.get(java_home, "modules");
if (Files.isDirectory(modules.resolve("java.base"))) {
return Files.list(modules)
.map(Path::toFile)
.collect(Collectors.toList());
}
@ -753,12 +743,12 @@ public class Locations {
return (h == null ? false : h.handleOption(option, value));
}
Collection<File> getLocation(Location location) {
Collection<Path> getLocation(Location location) {
LocationHandler h = getHandler(location);
return (h == null ? null : h.getLocation());
}
File getOutputLocation(Location location) {
Path getOutputLocation(Location location) {
if (!location.isOutputLocation()) {
throw new IllegalArgumentException();
}
@ -766,7 +756,7 @@ public class Locations {
return ((OutputLocationHandler) h).outputDir;
}
void setLocation(Location location, Iterable<? extends File> files) throws IOException {
void setLocation(Location location, Iterable<? extends Path> files) throws IOException {
LocationHandler h = getHandler(location);
if (h == null) {
if (location.isOutputLocation()) {
@ -787,8 +777,8 @@ public class Locations {
/**
* Is this the name of an archive file?
*/
private boolean isArchive(File file) {
String n = StringUtils.toLowerCase(file.getName());
private boolean isArchive(Path file) {
String n = StringUtils.toLowerCase(file.getFileName().toString());
return fsInfo.isFile(file)
&& (n.endsWith(".jar") || n.endsWith(".zip"));
}
@ -797,50 +787,41 @@ public class Locations {
* Utility method for converting a search path string to an array of directory and JAR file
* URLs.
*
* Note that this method is called by apt and the DocletInvoker.
* Note that this method is called by the DocletInvoker.
*
* @param path the search path string
* @return the resulting array of directory and JAR file URLs
*/
public static URL[] pathToURLs(String path) {
StringTokenizer st = new StringTokenizer(path, File.pathSeparator);
URL[] urls = new URL[st.countTokens()];
int count = 0;
while (st.hasMoreTokens()) {
URL url = fileToURL(new File(st.nextToken()));
if (url != null) {
urls[count++] = url;
java.util.List<URL> urls = new ArrayList<>();
for (String s: path.split(Pattern.quote(File.pathSeparator))) {
if (!s.isEmpty()) {
URL url = fileToURL(Paths.get(s));
if (url != null) {
urls.add(url);
}
}
}
urls = Arrays.copyOf(urls, count);
return urls;
return urls.toArray(new URL[urls.size()]);
}
/**
* Returns the directory or JAR file URL corresponding to the specified local file name.
*
* @param file the File object
* @param file the Path object
* @return the resulting directory or JAR file URL, or null if unknown
*/
private static URL fileToURL(File file) {
String name;
private static URL fileToURL(Path file) {
Path p;
try {
name = file.getCanonicalPath();
p = file.toRealPath();
} catch (IOException e) {
name = file.getAbsolutePath();
}
name = name.replace(File.separatorChar, '/');
if (!name.startsWith("/")) {
name = "/" + name;
}
// If the file does not exist, then assume that it's a directory
if (!file.isFile()) {
name = name + "/";
p = file.toAbsolutePath();
}
try {
return new URL("file", "", name);
return p.normalize().toUri().toURL();
} catch (MalformedURLException e) {
throw new IllegalArgumentException(file.toString());
return null;
}
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 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
@ -25,9 +25,6 @@
package com.sun.tools.javac.file;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@ -39,9 +36,13 @@ import java.net.URI;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharsetDecoder;
import javax.tools.JavaFileObject;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.Normalizer;
import javax.tools.JavaFileObject;
import com.sun.tools.javac.util.DefinedBy;
import com.sun.tools.javac.util.DefinedBy.Api;
@ -59,33 +60,33 @@ class RegularFileObject extends BaseFileObject {
*/
private boolean hasParents = false;
private String name;
final File file;
private Reference<File> absFileRef;
final Path file;
private Reference<Path> absFileRef;
final static boolean isMacOS = System.getProperty("os.name", "").contains("OS X");
public RegularFileObject(JavacFileManager fileManager, File f) {
this(fileManager, f.getName(), f);
public RegularFileObject(JavacFileManager fileManager, Path f) {
this(fileManager, f.getFileName().toString(), f);
}
public RegularFileObject(JavacFileManager fileManager, String name, File f) {
public RegularFileObject(JavacFileManager fileManager, String name, Path f) {
super(fileManager);
if (f.isDirectory()) {
if (Files.isDirectory(f)) {
throw new IllegalArgumentException("directories not supported");
}
this.name = name;
this.file = f;
if (f.lastModified() > System.currentTimeMillis())
if (getLastModified() > System.currentTimeMillis())
fileManager.log.warning("file.from.future", f);
}
@Override @DefinedBy(Api.COMPILER)
public URI toUri() {
return file.toURI().normalize();
return file.toUri().normalize();
}
@Override @DefinedBy(Api.COMPILER)
public String getName() {
return file.getPath();
return file.toString();
}
@Override
@ -100,21 +101,21 @@ class RegularFileObject extends BaseFileObject {
@Override @DefinedBy(Api.COMPILER)
public InputStream openInputStream() throws IOException {
return new FileInputStream(file);
return Files.newInputStream(file);
}
@Override @DefinedBy(Api.COMPILER)
public OutputStream openOutputStream() throws IOException {
fileManager.flushCache(this);
ensureParentDirectoriesExist();
return new FileOutputStream(file);
return Files.newOutputStream(file);
}
@Override @DefinedBy(Api.COMPILER)
public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
CharBuffer cb = fileManager.getCachedContent(this);
if (cb == null) {
try (InputStream in = new FileInputStream(file)) {
try (InputStream in = Files.newInputStream(file)) {
ByteBuffer bb = fileManager.makeByteBuffer(in);
JavaFileObject prev = fileManager.log.useSource(this);
try {
@ -135,17 +136,26 @@ class RegularFileObject extends BaseFileObject {
public Writer openWriter() throws IOException {
fileManager.flushCache(this);
ensureParentDirectoriesExist();
return new OutputStreamWriter(new FileOutputStream(file), fileManager.getEncodingName());
return new OutputStreamWriter(Files.newOutputStream(file), fileManager.getEncodingName());
}
@Override @DefinedBy(Api.COMPILER)
public long getLastModified() {
return file.lastModified();
try {
return Files.getLastModifiedTime(file).toMillis();
} catch (IOException e) {
return 0;
}
}
@Override @DefinedBy(Api.COMPILER)
public boolean delete() {
return file.delete();
try {
Files.delete(file);
return true;
} catch (IOException e) {
return false;
}
}
@Override
@ -154,20 +164,21 @@ class RegularFileObject extends BaseFileObject {
}
@Override
protected String inferBinaryName(Iterable<? extends File> path) {
String fPath = file.getPath();
protected String inferBinaryName(Iterable<? extends Path> path) {
String fPath = file.toString();
//System.err.println("RegularFileObject " + file + " " +r.getPath());
for (File dir: path) {
for (Path dir: path) {
//System.err.println("dir: " + dir);
String dPath = dir.getPath();
String sep = dir.getFileSystem().getSeparator();
String dPath = dir.toString();
if (dPath.length() == 0)
dPath = System.getProperty("user.dir");
if (!dPath.endsWith(File.separator))
dPath += File.separator;
if (!dPath.endsWith(sep))
dPath += sep;
if (fPath.regionMatches(true, 0, dPath, 0, dPath.length())
&& new File(fPath.substring(0, dPath.length())).equals(new File(dPath))) {
&& Paths.get(fPath.substring(0, dPath.length())).equals(Paths.get(dPath))) {
String relativeName = fPath.substring(dPath.length());
return removeExtension(relativeName).replace(File.separatorChar, '.');
return removeExtension(relativeName).replace(sep, ".");
}
}
return null;
@ -199,7 +210,7 @@ class RegularFileObject extends BaseFileObject {
if (name.equalsIgnoreCase(n)) {
try {
// allow for Windows
return file.getCanonicalFile().getName().equals(n);
return file.toRealPath().getFileName().toString().equals(n);
} catch (IOException e) {
}
}
@ -208,12 +219,12 @@ class RegularFileObject extends BaseFileObject {
private void ensureParentDirectoriesExist() throws IOException {
if (!hasParents) {
File parent = file.getParentFile();
if (parent != null && !parent.exists()) {
if (!parent.mkdirs()) {
if (!parent.exists() || !parent.isDirectory()) {
throw new IOException("could not create parent directories");
}
Path parent = file.getParent();
if (parent != null && !Files.isDirectory(parent)) {
try {
Files.createDirectories(parent);
} catch (IOException e) {
throw new IOException("could not create parent directories", e);
}
}
hasParents = true;
@ -242,10 +253,10 @@ class RegularFileObject extends BaseFileObject {
return getAbsoluteFile().hashCode();
}
private File getAbsoluteFile() {
File absFile = (absFileRef == null ? null : absFileRef.get());
private Path getAbsoluteFile() {
Path absFile = (absFileRef == null ? null : absFileRef.get());
if (absFile == null) {
absFile = file.getAbsoluteFile();
absFile = file.toAbsolutePath();
absFileRef = new SoftReference<>(absFile);
}
return absFile;

@ -57,12 +57,6 @@ public abstract class RelativePath implements Comparable<RelativePath> {
public abstract String basename();
public File getFile(File directory) {
if (path.length() == 0)
return directory;
return new File(directory, path.replace('/', File.separatorChar));
}
public Path getFile(Path directory) throws /*unchecked*/ InvalidPathException {
if (directory == null) {
String sep = FileSystems.getDefault().getSeparator();
@ -73,6 +67,7 @@ public abstract class RelativePath implements Comparable<RelativePath> {
}
}
@Override
public int compareTo(RelativePath other) {
return path.compareTo(other.path);
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 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
@ -25,15 +25,18 @@
package com.sun.tools.javac.file;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Writer;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.net.URI;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharsetDecoder;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
@ -49,8 +52,6 @@ import com.sun.tools.javac.file.RelativePath.RelativeFile;
import com.sun.tools.javac.util.DefinedBy;
import com.sun.tools.javac.util.DefinedBy.Api;
import com.sun.tools.javac.util.List;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
/**
* <p><b>This is NOT part of any supported API.
@ -131,10 +132,10 @@ public class ZipArchive implements Archive {
return "ZipArchive[" + zfile.getName() + "]";
}
private File getAbsoluteFile() {
File absFile = (absFileRef == null ? null : absFileRef.get());
private Path getAbsoluteFile() {
Path absFile = (absFileRef == null ? null : absFileRef.get());
if (absFile == null) {
absFile = new File(zfile.getName()).getAbsoluteFile();
absFile = Paths.get(zfile.getName()).toAbsolutePath();
absFileRef = new SoftReference<>(absFile);
}
return absFile;
@ -155,7 +156,7 @@ public class ZipArchive implements Archive {
/**
* A reference to the absolute filename for the zip file for the archive.
*/
protected Reference<File> absFileRef;
protected Reference<Path> absFileRef;
/**
* A subclass of JavaFileObject representing zip entries.
@ -175,7 +176,7 @@ public class ZipArchive implements Archive {
@DefinedBy(Api.COMPILER)
public URI toUri() {
File zipFile = new File(zarch.zfile.getName());
Path zipFile = Paths.get(zarch.zfile.getName());
return createJarUri(zipFile, entry.getName());
}
@ -186,7 +187,7 @@ public class ZipArchive implements Archive {
@Override
public String getShortName() {
return new File(zarch.zfile.getName()).getName() + "(" + entry + ")";
return Paths.get(zarch.zfile.getName()).getFileName() + "(" + entry + ")";
}
@Override @DefinedBy(Api.COMPILER)
@ -246,7 +247,7 @@ public class ZipArchive implements Archive {
}
@Override
protected String inferBinaryName(Iterable<? extends File> path) {
protected String inferBinaryName(Iterable<? extends Path> path) {
String entryName = entry.getName();
return removeExtension(entryName).replace('/', '.');
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 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,18 +26,20 @@
package com.sun.tools.javac.file;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -91,14 +93,14 @@ public class ZipFileIndex {
Collections.<RelativeDirectory>emptySet();
// ZipFileIndex data entries
final File zipFile;
private Reference<File> absFileRef;
final Path zipFile;
private Reference<Path> absFileRef;
long zipFileLastModified = NOT_MODIFIED;
private RandomAccessFile zipRandomFile;
private Entry[] entries;
private boolean readFromIndex = false;
private File zipIndexFile = null;
private Path zipIndexFile = null;
private boolean triedToReadIndex = false;
final RelativeDirectory symbolFilePrefix;
private final int symbolFilePrefixLength;
@ -117,7 +119,7 @@ public class ZipFileIndex {
return (zipRandomFile != null);
}
ZipFileIndex(File zipFile, RelativeDirectory symbolFilePrefix, boolean writeIndex,
ZipFileIndex(Path zipFile, RelativeDirectory symbolFilePrefix, boolean writeIndex,
boolean useCache, String cacheLocation) throws IOException {
this.zipFile = zipFile;
this.symbolFilePrefix = symbolFilePrefix;
@ -128,7 +130,7 @@ public class ZipFileIndex {
this.preindexedCacheLocation = cacheLocation;
if (zipFile != null) {
this.zipFileLastModified = zipFile.lastModified();
this.zipFileLastModified = Files.getLastModifiedTime(zipFile).toMillis();
}
// Validate integrity of the zip file
@ -148,10 +150,11 @@ public class ZipFileIndex {
}
private boolean isUpToDate() {
if (zipFile != null
&& ((!NON_BATCH_MODE) || zipFileLastModified == zipFile.lastModified())
&& hasPopulatedData) {
return true;
try {
return (zipFile != null
&& ((!NON_BATCH_MODE) || zipFileLastModified == Files.getLastModifiedTime(zipFile).toMillis())
&& hasPopulatedData);
} catch (IOException ignore) {
}
return false;
@ -199,7 +202,7 @@ public class ZipFileIndex {
private void openFile() throws FileNotFoundException {
if (zipRandomFile == null && zipFile != null) {
zipRandomFile = new RandomAccessFile(zipFile, "r");
zipRandomFile = new RandomAccessFile(zipFile.toFile(), "r");
}
}
@ -785,11 +788,11 @@ public class ZipFileIndex {
entries.add(zipFileIndex.entries[i]);
}
} else {
File indexFile = zipFileIndex.getIndexFile();
Path indexFile = zipFileIndex.getIndexFile();
if (indexFile != null) {
RandomAccessFile raf = null;
try {
raf = new RandomAccessFile(indexFile, "r");
raf = new RandomAccessFile(indexFile.toFile(), "r");
raf.seek(writtenOffsetOffset);
for (int nFiles = 0; nFiles < numEntries; nFiles++) {
@ -856,11 +859,11 @@ public class ZipFileIndex {
triedToReadIndex = true;
RandomAccessFile raf = null;
try {
File indexFileName = getIndexFile();
raf = new RandomAccessFile(indexFileName, "r");
Path indexFileName = getIndexFile();
raf = new RandomAccessFile(indexFileName.toFile(), "r");
long fileStamp = raf.readLong();
if (zipFile.lastModified() != fileStamp) {
if (Files.getLastModifiedTime(zipFile).toMillis() != fileStamp) {
ret = false;
} else {
directories = new LinkedHashMap<>();
@ -908,7 +911,7 @@ public class ZipFileIndex {
return true;
}
File indexFile = getIndexFile();
Path indexFile = getIndexFile();
if (indexFile == null) {
return false;
}
@ -916,7 +919,7 @@ public class ZipFileIndex {
RandomAccessFile raf = null;
long writtenSoFar = 0;
try {
raf = new RandomAccessFile(indexFile, "rw");
raf = new RandomAccessFile(indexFile.toFile(), "rw");
raf.writeLong(zipFileLastModified);
writtenSoFar += 8;
@ -1016,27 +1019,27 @@ public class ZipFileIndex {
}
}
private File getIndexFile() {
private Path getIndexFile() {
if (zipIndexFile == null) {
if (zipFile == null) {
return null;
}
zipIndexFile = new File((preindexedCacheLocation == null ? "" : preindexedCacheLocation) +
zipFile.getName() + ".index");
zipIndexFile = Paths.get((preindexedCacheLocation == null ? "" : preindexedCacheLocation) +
zipFile.getFileName() + ".index");
}
return zipIndexFile;
}
public File getZipFile() {
public Path getZipFile() {
return zipFile;
}
File getAbsoluteFile() {
File absFile = (absFileRef == null ? null : absFileRef.get());
Path getAbsoluteFile() {
Path absFile = (absFileRef == null ? null : absFileRef.get());
if (absFile == null) {
absFile = zipFile.getAbsoluteFile();
absFile = zipFile.toAbsolutePath();
absFileRef = new SoftReference<>(absFile);
}
return absFile;

@ -25,12 +25,8 @@
package com.sun.tools.javac.file;
import java.io.IOException;
import java.util.Set;
import javax.tools.JavaFileObject;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Writer;
@ -38,6 +34,10 @@ import java.net.URI;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharsetDecoder;
import java.nio.file.Path;
import java.util.Set;
import javax.tools.JavaFileObject;
import com.sun.tools.javac.file.JavacFileManager.Archive;
import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
@ -56,7 +56,7 @@ import com.sun.tools.javac.util.List;
public class ZipFileIndexArchive implements Archive {
private final ZipFileIndex zfIndex;
private JavacFileManager fileManager;
private final JavacFileManager fileManager;
public ZipFileIndexArchive(JavacFileManager fileManager, ZipFileIndex zdir) throws IOException {
super();
@ -111,10 +111,10 @@ public class ZipFileIndexArchive implements Archive {
/** The name of the zip file where this entry resides.
*/
File zipName;
Path zipName;
ZipFileIndexFileObject(JavacFileManager fileManager, ZipFileIndex zfIndex, ZipFileIndex.Entry entry, File zipFileName) {
ZipFileIndexFileObject(JavacFileManager fileManager, ZipFileIndex zfIndex, ZipFileIndex.Entry entry, Path zipFileName) {
super(fileManager);
this.name = entry.getFileName();
this.zfIndex = zfIndex;
@ -134,7 +134,7 @@ public class ZipFileIndexArchive implements Archive {
@Override
public String getShortName() {
return zipName.getName() + "(" + entry.getName() + ")";
return zipName.getFileName() + "(" + entry.getName() + ")";
}
@Override @DefinedBy(Api.COMPILER)
@ -194,7 +194,7 @@ public class ZipFileIndexArchive implements Archive {
}
@Override
protected String inferBinaryName(Iterable<? extends File> path) {
protected String inferBinaryName(Iterable<? extends Path> path) {
String entryName = entry.getName();
if (zfIndex.symbolFilePrefix != null) {
String prefix = zfIndex.symbolFilePrefix.path;

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 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
@ -25,21 +25,22 @@
package com.sun.tools.javac.file;
import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
import com.sun.tools.javac.util.Context;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
import com.sun.tools.javac.util.Context;
/** A cache for ZipFileIndex objects. */
public class ZipFileIndexCache {
private final Map<File, ZipFileIndex> map = new HashMap<>();
private final Map<Path, ZipFileIndex> map = new HashMap<>();
/** Get a shared instance of the cache. */
private static ZipFileIndexCache sharedInstance;
@ -89,13 +90,13 @@ public class ZipFileIndexCache {
return zipFileIndexes;
}
public synchronized ZipFileIndex getZipFileIndex(File zipFile,
public synchronized ZipFileIndex getZipFileIndex(Path zipFile,
RelativeDirectory symbolFilePrefix,
boolean useCache, String cacheLocation,
boolean writeIndex) throws IOException {
ZipFileIndex zi = getExistingZipIndex(zipFile);
if (zi == null || (zi != null && zipFile.lastModified() != zi.zipFileLastModified)) {
if (zi == null || (zi != null && Files.getLastModifiedTime(zipFile).toMillis() != zi.zipFileLastModified)) {
zi = new ZipFileIndex(zipFile, symbolFilePrefix, writeIndex,
useCache, cacheLocation);
map.put(zipFile, zi);
@ -103,7 +104,7 @@ public class ZipFileIndexCache {
return zi;
}
public synchronized ZipFileIndex getExistingZipIndex(File zipFile) {
public synchronized ZipFileIndex getExistingZipIndex(Path zipFile) {
return map.get(zipFile);
}
@ -112,7 +113,7 @@ public class ZipFileIndexCache {
}
public synchronized void clearCache(long timeNotUsed) {
for (File cachedFile : map.keySet()) {
for (Path cachedFile : map.keySet()) {
ZipFileIndex cachedZipIndex = map.get(cachedFile);
if (cachedZipIndex != null) {
long timeToTest = cachedZipIndex.lastReferenceTimeStamp + timeNotUsed;
@ -124,7 +125,7 @@ public class ZipFileIndexCache {
}
}
public synchronized void removeFromCache(File file) {
public synchronized void removeFromCache(Path file) {
map.remove(file);
}

@ -29,23 +29,27 @@ import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.CharBuffer;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.tools.JavaFileObject;
import javax.tools.JavaFileManager;
import com.sun.tools.javac.comp.Annotate;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Lint.LintCategory;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.code.Scope.WriteableScope;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.comp.Annotate;
import com.sun.tools.javac.file.BaseFileObject;
import com.sun.tools.javac.jvm.ClassFile.NameAndType;
import com.sun.tools.javac.jvm.ClassFile.Version;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.DefinedBy.Api;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
@ -2467,7 +2471,7 @@ public class ClassReader {
}
@Override
protected String inferBinaryName(Iterable<? extends File> path) {
protected String inferBinaryName(Iterable<? extends Path> path) {
return flatname.toString();
}

@ -640,6 +640,27 @@ public class ClassWriter extends ClassFile {
}
private void writeParamAnnotations(List<VarSymbol> params,
RetentionPolicy retention) {
for (VarSymbol s : params) {
ListBuffer<Attribute.Compound> buf = new ListBuffer<>();
for (Attribute.Compound a : s.getRawAttributes())
if (types.getRetention(a) == retention)
buf.append(a);
databuf.appendChar(buf.length());
for (Attribute.Compound a : buf)
writeCompoundAttribute(a);
}
}
private void writeParamAnnotations(MethodSymbol m,
RetentionPolicy retention) {
databuf.appendByte(m.params.length() + m.extraParams.length());
writeParamAnnotations(m.extraParams, retention);
writeParamAnnotations(m.params, retention);
}
/** Write method parameter annotations;
* return number of attributes written.
*/
@ -662,31 +683,13 @@ public class ClassWriter extends ClassFile {
int attrCount = 0;
if (hasVisible) {
int attrIndex = writeAttr(names.RuntimeVisibleParameterAnnotations);
databuf.appendByte(m.params.length());
for (VarSymbol s : m.params) {
ListBuffer<Attribute.Compound> buf = new ListBuffer<>();
for (Attribute.Compound a : s.getRawAttributes())
if (types.getRetention(a) == RetentionPolicy.RUNTIME)
buf.append(a);
databuf.appendChar(buf.length());
for (Attribute.Compound a : buf)
writeCompoundAttribute(a);
}
writeParamAnnotations(m, RetentionPolicy.RUNTIME);
endAttr(attrIndex);
attrCount++;
}
if (hasInvisible) {
int attrIndex = writeAttr(names.RuntimeInvisibleParameterAnnotations);
databuf.appendByte(m.params.length());
for (VarSymbol s : m.params) {
ListBuffer<Attribute.Compound> buf = new ListBuffer<>();
for (Attribute.Compound a : s.getRawAttributes())
if (types.getRetention(a) == RetentionPolicy.CLASS)
buf.append(a);
databuf.appendChar(buf.length());
for (Attribute.Compound a : buf)
writeCompoundAttribute(a);
}
writeParamAnnotations(m, RetentionPolicy.CLASS);
endAttr(attrIndex);
attrCount++;
}

@ -29,10 +29,10 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URL;
import java.nio.file.NoSuchFileException;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Set;
import javax.tools.JavaFileManager;
@ -160,13 +160,15 @@ public class Main {
Option.HELP.process(new OptionHelper.GrumpyHelper(log) {
@Override
public String getOwnName() { return ownName; }
@Override
public void put(String name, String value) { }
}, "-help");
return Result.CMDERR;
}
try {
argv = CommandLine.parse(argv);
} catch (FileNotFoundException e) {
} catch (FileNotFoundException | NoSuchFileException e) {
warning("err.file.not.found", e.getMessage());
return Result.SYSERR;
} catch (IOException ex) {

@ -30,12 +30,13 @@ import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitOption;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
@ -48,6 +49,7 @@ import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import javax.lang.model.SourceVersion;
import javax.tools.FileObject;
import javax.tools.JavaFileManager;
@ -55,9 +57,6 @@ import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind;
import javax.tools.StandardLocation;
import static java.nio.file.FileVisitOption.*;
import static javax.tools.StandardLocation.*;
import com.sun.tools.javac.util.BaseFileManager;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.DefinedBy;
@ -65,6 +64,10 @@ import com.sun.tools.javac.util.DefinedBy.Api;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
import static java.nio.file.FileVisitOption.*;
import static javax.tools.StandardLocation.*;
import static com.sun.tools.javac.main.Option.*;
@ -221,7 +224,7 @@ public class JavacPathFileManager extends BaseFileManager implements PathFileMan
}
private void setDefaultForLocation(Location locn) {
Collection<File> files = null;
Collection<Path> files = null;
if (locn instanceof StandardLocation) {
switch ((StandardLocation) locn) {
case CLASS_PATH:
@ -235,12 +238,12 @@ public class JavacPathFileManager extends BaseFileManager implements PathFileMan
break;
case CLASS_OUTPUT: {
String arg = options.get(D);
files = (arg == null ? null : Collections.singleton(new File(arg)));
files = (arg == null ? null : Collections.singleton(Paths.get(arg)));
break;
}
case SOURCE_OUTPUT: {
String arg = options.get(S);
files = (arg == null ? null : Collections.singleton(new File(arg)));
files = (arg == null ? null : Collections.singleton(Paths.get(arg)));
break;
}
}
@ -248,8 +251,8 @@ public class JavacPathFileManager extends BaseFileManager implements PathFileMan
PathsForLocation pl = new PathsForLocation();
if (files != null) {
for (File f: files)
pl.add(f.toPath());
for (Path f: files)
pl.add(f);
}
if (!pl.isEmpty())
pathsForLocation.put(locn, pl);

@ -145,6 +145,8 @@ public class JavacParser implements Parser {
this.names = fac.names;
this.source = fac.source;
this.allowTWR = source.allowTryWithResources();
this.allowEffectivelyFinalVariablesInTWR =
source.allowEffectivelyFinalVariablesInTryWithResources();
this.allowDiamond = source.allowDiamond();
this.allowMulticatch = source.allowMulticatch();
this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
@ -184,6 +186,10 @@ public class JavacParser implements Parser {
*/
boolean allowTWR;
/** Switch: should we allow (effectively) final variables as resources in try-with-resources?
*/
boolean allowEffectivelyFinalVariablesInTWR;
/** Switch: should we fold strings?
*/
boolean allowStringFolding;
@ -3003,14 +3009,28 @@ public class JavacParser implements Parser {
return defs.toList();
}
/** Resource = VariableModifiersOpt Type VariableDeclaratorId = Expression
/** Resource = VariableModifiersOpt Type VariableDeclaratorId "=" Expression
* | Expression
*/
protected JCTree resource() {
JCModifiers optFinal = optFinal(Flags.FINAL);
JCExpression type = parseType();
int pos = token.pos;
Name ident = ident();
return variableDeclaratorRest(pos, optFinal, type, ident, true, null);
int startPos = token.pos;
if (token.kind == FINAL || token.kind == MONKEYS_AT) {
JCModifiers mods = optFinal(Flags.FINAL);
JCExpression t = parseType();
return variableDeclaratorRest(token.pos, mods, t, ident(), true, null);
}
JCExpression t = term(EXPR | TYPE);
if ((lastmode & TYPE) != 0 && LAX_IDENTIFIER.accepts(token.kind)) {
JCModifiers mods = toP(F.at(startPos).Modifiers(Flags.FINAL));
return variableDeclaratorRest(token.pos, mods, t, ident(), true, null);
} else {
checkVariableInTryWithResources(startPos);
if (!t.hasTag(IDENT) && !t.hasTag(SELECT)) {
log.error(t.pos(), "try.with.resources.expr.needs.var");
}
return t;
}
}
/** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
@ -3933,6 +3953,12 @@ public class JavacParser implements Parser {
allowTWR = true;
}
}
void checkVariableInTryWithResources(int startPos) {
if (!allowEffectivelyFinalVariablesInTWR) {
error(startPos, "var.in.try.with.resources.not.supported.in.source", source.name);
allowEffectivelyFinalVariablesInTWR = true;
}
}
void checkLambda() {
if (!allowLambda) {
log.error(token.pos, "lambda.not.supported.in.source", source.name);

@ -252,6 +252,14 @@ compiler.err.cant.assign.val.to.final.var=\
compiler.err.cant.ref.non.effectively.final.var=\
local variables referenced from {1} must be final or effectively final
compiler.err.try.with.resources.expr.needs.var=\
the try-with-resources resource must either be a variable declaration or an expression denoting \
a reference to a final or effectively final variable
# 0: symbol
compiler.err.try.with.resources.expr.effectively.final.var=\
variable {0} used as a try-with-resources resource neither final nor effectively final
compiler.misc.lambda=\
a lambda expression
@ -2262,6 +2270,11 @@ compiler.err.try.with.resources.not.supported.in.source=\
try-with-resources is not supported in -source {0}\n\
(use -source 7 or higher to enable try-with-resources)
# 0: string
compiler.err.var.in.try.with.resources.not.supported.in.source=\
variables in try-with-resources not supported in -source {0}\n\
(use -source 9 or higher to enable variables in try-with-resources)
compiler.warn.underscore.as.identifier=\
''_'' used as an identifier\n\
(use of ''_'' as an identifier might not be supported in releases after Java SE 8)

@ -1,5 +1,5 @@
#
# Copyright (c) 1999, 2013, 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
@ -1526,7 +1526,7 @@ compiler.warn.override.unchecked.ret={0}\n\u623B\u308A\u5024\u306E\u578B\u306F{1
compiler.warn.override.unchecked.thrown={0}\n\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u3055\u308C\u305F\u30E1\u30BD\u30C3\u30C9\u306F{1}\u3092\u30B9\u30ED\u30FC\u3057\u307E\u305B\u3093
# 0: symbol
compiler.warn.override.equals.but.not.hashcode=\u30AF\u30E9\u30B9{0}\u306F\u7B49\u53F7\u3092\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u3057\u307E\u3059\u304C\u3001\u3053\u306E\u30AF\u30E9\u30B9\u3082\u30B9\u30FC\u30D1\u30FC\u30AF\u30E9\u30B9\u3082hashCode\u30E1\u30BD\u30C3\u30C9\u3092\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u3057\u307E\u305B\u3093
compiler.warn.override.equals.but.not.hashcode=\u30AF\u30E9\u30B9{0}\u306Fequals\u3092\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u3057\u307E\u3059\u304C\u3001\u3053\u306E\u30AF\u30E9\u30B9\u3082\u3001\u307E\u305F\u3001\u3044\u304B\u306A\u308B\u30B9\u30FC\u30D1\u30FC\u30AF\u30E9\u30B9\u3082\u3001hashCode\u30E1\u30BD\u30C3\u30C9\u3092\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u3057\u307E\u305B\u3093
## The following are all possible strings for the first argument ({0}) of the
## above strings.

@ -1,5 +1,5 @@
#
# Copyright (c) 1999, 2013, 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
@ -1526,7 +1526,7 @@ compiler.warn.override.unchecked.ret={0}\n\u8FD4\u56DE\u7C7B\u578B\u9700\u8981\u
compiler.warn.override.unchecked.thrown={0}\n\u88AB\u8986\u76D6\u7684\u65B9\u6CD5\u672A\u629B\u51FA{1}
# 0: symbol
compiler.warn.override.equals.but.not.hashcode=\u7C7B{0}\u8986\u76D6\u4E86\u7B49\u53F7, \u4F46\u8BE5\u7C7B\u6216\u4EFB\u4F55\u8D85\u7C7B\u90FD\u672A\u8986\u76D6 hashCode \u65B9\u6CD5
compiler.warn.override.equals.but.not.hashcode=\u7C7B{0}\u8986\u76D6\u4E86 equals, \u4F46\u8BE5\u7C7B\u6216\u4EFB\u4F55\u8D85\u7C7B\u90FD\u672A\u8986\u76D6 hashCode \u65B9\u6CD5
## The following are all possible strings for the first argument ({0}) of the
## above strings.

@ -612,6 +612,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
public boolean staticImport;
/** The imported class(es). */
public JCTree qualid;
public com.sun.tools.javac.code.Scope importScope;
protected JCImport(JCTree qualid, boolean importStatic) {
this.qualid = qualid;
this.staticImport = importStatic;

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 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
@ -24,6 +24,7 @@
*/
package com.sun.tools.javac.util;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumSet;
@ -48,6 +49,7 @@ import com.sun.tools.javac.file.BaseFileObject;
import com.sun.tools.javac.jvm.Profile;
import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.tree.Pretty;
import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticType.*;
/**
@ -186,7 +188,7 @@ public abstract class AbstractDiagnosticFormatter implements DiagnosticFormatter
else if (arg instanceof JCExpression) {
return expr2String((JCExpression)arg);
}
else if (arg instanceof Iterable<?>) {
else if (arg instanceof Iterable<?> && !(arg instanceof Path)) {
return formatIterable(d, (Iterable<?>)arg, l);
}
else if (arg instanceof Type) {

@ -73,7 +73,7 @@ public abstract class Dependencies {
return instance;
}
Dependencies(Context context) {
protected Dependencies(Context context) {
context.put(dependenciesKey, this);
}
@ -122,7 +122,7 @@ public abstract class Dependencies {
/**
* Push a new completion node on the stack.
*/
abstract public void push(ClassSymbol s);
abstract public void push(ClassSymbol s, CompletionCause phase);
/**
* Push a new attribution node on the stack.
@ -134,6 +134,15 @@ public abstract class Dependencies {
*/
abstract public void pop();
public enum CompletionCause {
CLASS_READER,
HEADER_PHASE,
HIERARCHY_PHASE,
IMPORTS_PHASE,
MEMBER_ENTER,
MEMBERS_PHASE;
}
/**
* This class creates a graph of all dependencies as symbols are completed;
* when compilation finishes, the resulting dependecy graph is then dumped
@ -391,7 +400,7 @@ public abstract class Dependencies {
Map<String, Node> dependencyNodeMap = new LinkedHashMap<>();
@Override
public void push(ClassSymbol s) {
public void push(ClassSymbol s, CompletionCause phase) {
Node n = new CompletionNode(s);
if (n == push(n)) {
s.completer = this;
@ -454,7 +463,7 @@ public abstract class Dependencies {
@Override
public void complete(Symbol sym) throws CompletionFailure {
push((ClassSymbol) sym);
push((ClassSymbol) sym, null);
pop();
sym.completer = this;
}
@ -542,7 +551,7 @@ public abstract class Dependencies {
}
@Override
public void push(ClassSymbol s) {
public void push(ClassSymbol s, CompletionCause phase) {
//do nothing
}

@ -24,6 +24,7 @@
*/
package com.sun.tools.javac.util;
import java.nio.file.Path;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
@ -39,8 +40,8 @@ import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.code.Types;
import static com.sun.tools.javac.code.TypeTag.*;
import static com.sun.tools.javac.code.Flags.*;
import static com.sun.tools.javac.code.TypeTag.*;
import static com.sun.tools.javac.code.Kinds.*;
import static com.sun.tools.javac.code.Kinds.Kind.*;
import static com.sun.tools.javac.util.LayoutCharacters.*;
@ -186,7 +187,7 @@ public class RichDiagnosticFormatter extends
else if (arg instanceof JCDiagnostic) {
preprocessDiagnostic((JCDiagnostic)arg);
}
else if (arg instanceof Iterable<?>) {
else if (arg instanceof Iterable<?> && !(arg instanceof Path)) {
for (Object o : (Iterable<?>)arg) {
preprocessArgument(o);
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 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
@ -25,7 +25,6 @@
package com.sun.tools.javah;
import java.io.UnsupportedEncodingException;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
@ -33,6 +32,8 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.nio.file.NoSuchFileException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -40,7 +41,6 @@ import java.util.Set;
import java.util.Stack;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
@ -48,7 +48,6 @@ import javax.lang.model.element.VariableElement;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import javax.tools.FileObject;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
@ -204,7 +203,7 @@ public abstract class Gen {
event = "[Overwriting file ";
}
} catch (FileNotFoundException e) {
} catch (FileNotFoundException | NoSuchFileException e) {
mustWrite = true;
event = "[Creating file ";
}

@ -31,6 +31,7 @@ import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.nio.file.NoSuchFileException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
@ -50,7 +51,6 @@ import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
@ -62,7 +62,6 @@ import javax.lang.model.type.TypeVisitor;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.SimpleTypeVisitor9;
import javax.lang.model.util.Types;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticListener;
import javax.tools.JavaCompiler;
@ -72,13 +71,15 @@ import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;
import static javax.tools.Diagnostic.Kind.*;
import com.sun.tools.javac.code.Symbol.CompletionFailure;
import com.sun.tools.javac.main.CommandLine;
import com.sun.tools.javac.util.DefinedBy;
import com.sun.tools.javac.util.DefinedBy.Api;
import static javax.tools.Diagnostic.Kind.*;
/**
* Javah generates support files for native methods.
* Parse commandline options and invokes javadoc to execute those commands.
@ -420,7 +421,7 @@ public class JavahTask implements NativeHeaderTool.NativeHeaderTask {
List<String> l = new ArrayList<>();
for (String arg: args) l.add(arg);
return Arrays.asList(CommandLine.parse(l.toArray(new String[l.size()])));
} catch (FileNotFoundException e) {
} catch (FileNotFoundException | NoSuchFileException e) {
throw new BadArgs("at.args.file.not.found", e.getLocalizedMessage());
} catch (IOException e) {
throw new BadArgs("at.args.io.exception", e.getLocalizedMessage());

@ -36,6 +36,10 @@ import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.file.NoSuchFileException;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@ -61,10 +65,6 @@ import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import com.sun.tools.classfile.*;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import com.sun.tools.javac.util.DefinedBy;
import com.sun.tools.javac.util.DefinedBy.Api;
@ -568,7 +568,7 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
} catch (EOFException e) {
reportError("err.end.of.file", className);
result = EXIT_ERROR;
} catch (FileNotFoundException e) {
} catch (FileNotFoundException | NoSuchFileException e) {
reportError("err.file.not.found", e.getLocalizedMessage());
result = EXIT_ERROR;
} catch (IOException e) {
@ -668,9 +668,12 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
if (fileManager instanceof StandardJavaFileManager) {
StandardJavaFileManager sfm = (StandardJavaFileManager) fileManager;
fo = sfm.getJavaFileObjects(className).iterator().next();
if (fo != null && fo.getLastModified() != 0) {
return fo;
try {
fo = sfm.getJavaFileObjects(className).iterator().next();
if (fo != null && fo.getLastModified() != 0) {
return fo;
}
} catch (IllegalArgumentException ignore) {
}
}
@ -860,11 +863,15 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
}
private JavaFileObject getClassFileObject(String className) throws IOException {
JavaFileObject fo;
fo = fileManager.getJavaFileForInput(StandardLocation.PLATFORM_CLASS_PATH, className, JavaFileObject.Kind.CLASS);
if (fo == null)
fo = fileManager.getJavaFileForInput(StandardLocation.CLASS_PATH, className, JavaFileObject.Kind.CLASS);
return fo;
try {
JavaFileObject fo;
fo = fileManager.getJavaFileForInput(StandardLocation.PLATFORM_CLASS_PATH, className, JavaFileObject.Kind.CLASS);
if (fo == null)
fo = fileManager.getJavaFileForInput(StandardLocation.CLASS_PATH, className, JavaFileObject.Kind.CLASS);
return fo;
} catch (IllegalArgumentException e) {
return null;
}
}
private void showHelp() {

@ -26,16 +26,17 @@
package com.sun.tools.sjavac;
import java.io.*;
import java.net.URI;
import java.nio.file.NoSuchFileException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Collections;
import java.util.Date;
import java.util.Set;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.text.SimpleDateFormat;
import java.net.URI;
import java.util.*;
import java.util.Set;
import com.sun.tools.sjavac.options.Options;
import com.sun.tools.sjavac.server.Sjavac;
@ -364,7 +365,7 @@ public class JavacState {
}
}
}
} catch (FileNotFoundException e) {
} catch (FileNotFoundException | NoSuchFileException e) {
// Silently create a new javac_state file.
noFileFound = true;
} catch (IOException e) {
@ -841,7 +842,7 @@ public class JavacState {
}
listedSources.add(l);
}
} catch (FileNotFoundException e) {
} catch (FileNotFoundException | NoSuchFileException e) {
throw new ProblemException("Could not open "+makefileSourceList.getPath()+" since it does not exist!");
} catch (IOException e) {
throw new ProblemException("Could not read "+makefileSourceList.getPath());

@ -27,6 +27,8 @@ package com.sun.tools.sjavac.comp;
import java.io.*;
import java.net.URI;
import java.nio.file.NoSuchFileException;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.NestingKind;
import javax.tools.JavaFileObject;
@ -108,7 +110,7 @@ public class SmartFileObject implements JavaFileObject {
while (r.ready()) {
s.append(r.readLine()+lineseparator);
}
} catch (FileNotFoundException e) {
} catch (FileNotFoundException | NoSuchFileException e) {
// Perfectly ok.
}
return new SmartWriter(file, s.toString(), file.getName(), stdout);

@ -0,0 +1,14 @@
/*
* @test /nodynamiccopyright/
* @bug 7101822
* @summary Check the when clashing types are imported through an ordinary and static import,
* the compile-time error is properly reported.
* @compile/fail/ref=NonStatic2StaticImportClash.out -XDrawDiagnostics NonStatic2StaticImportClash.java p1/A1.java p2/A2.java
*
*/
import p1.A1.f;
import static p2.A2.f;
public class NonStatic2StaticImportClash {
}

@ -0,0 +1,2 @@
NonStatic2StaticImportClash.java:11:1: compiler.err.already.defined.static.single.import: p1.A1.f
1 error

@ -0,0 +1,14 @@
/*
* @test /nodynamiccopyright/
* @bug 7101822
* @summary Check the when clashing types are imported through an ordinary and static import,
* the compile-time error is properly reported.
* @compile/fail/ref=Static2NonStaticImportClash.out -XDrawDiagnostics Static2NonStaticImportClash.java p1/A1.java p2/A2.java
*
*/
import static p2.A2.f;
import p1.A1.f;
public class Static2NonStaticImportClash {
}

@ -0,0 +1,2 @@
Static2NonStaticImportClash.java:11:1: compiler.err.already.defined.single.import: p2.A2.f
1 error

@ -1,2 +1,3 @@
Test.java:11:1: compiler.err.already.defined.single.import: p1.A1.f
1 error
Test.java:16:13: compiler.err.ref.ambiguous: f, kindname.class, p1.A1.f, p1.A1, kindname.class, p2.A2.f, p2.A2
2 errors

@ -0,0 +1,17 @@
/*
* @test /nodynamiccopyright/
* @bug 8062359
* @summary NullPointerException in Attr when type-annotating an anonymous
* inner class in an unresolvable class
* @compile/fail/ref=UnresolvableClassNPEInAttrTest.out -XDrawDiagnostics UnresolvableClassNPEInAttrTest.java
*/
public class UnresolvableClassNPEInAttrTest {
public static void main(String[] args) {
new Undefined() {
void test() {
new Object() {};
}
};
}
}

@ -0,0 +1,2 @@
UnresolvableClassNPEInAttrTest.java:11:13: compiler.err.cant.resolve.location: kindname.class, Undefined, , , (compiler.misc.location: kindname.class, UnresolvableClassNPEInAttrTest, null)
1 error

@ -1,8 +1,3 @@
import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.file.Paths;
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@ -32,6 +27,10 @@ import java.nio.file.Paths;
* @summary Empty try/finally results in bytecodes being generated
*/
import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.file.Paths;
public class EmptyFinallyTest {
private static final String assertionErrorMsg =
"No \"Exception table\" should be generated in this case";

@ -60,7 +60,7 @@ public class T6725036 {
long jarEntryTime = je.getTime();
ZipFileIndexCache zfic = ZipFileIndexCache.getSharedInstance();
ZipFileIndex zfi = zfic.getZipFileIndex(testJar, null, false, null, false);
ZipFileIndex zfi = zfic.getZipFileIndex(testJar.toPath(), null, false, null, false);
long zfiTime = zfi.getLastModified(TEST_ENTRY_NAME);
check(je, jarEntryTime, zfi + ":" + TEST_ENTRY_NAME.getPath(), zfiTime);
@ -85,7 +85,7 @@ public class T6725036 {
try (JavaFileManager fm = comp.getStandardFileManager(null, null, null)) {
File f = new File(name);
ToolBox tb = new ToolBox();
tb.new JarTask(f.getPath())
tb.new JarTask(name)
.files(fm, StandardLocation.PLATFORM_CLASS_PATH, paths)
.run();
return f;

@ -1,4 +1,3 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.

@ -0,0 +1,31 @@
/*
* @test /nodynamiccopyright/
* @bug 8059921
* @summary Missing compile error in Java 8 mode for Interface.super.field access
* @compile/fail/ref=ForbidAccessToFieldUsingSuperTest.out -XDrawDiagnostics ForbidAccessToFieldUsingSuperTest.java
*/
public class ForbidAccessToFieldUsingSuperTest {
class C {
int m() { return 0; }
}
interface T {
int f = 0;
C c = null;
default int mm() {
return 0;
}
}
interface T1 extends T {}
class X implements T1 {
int i = T1.super.f; //fail
int j = T1.super.c.m(); //fail
void foo(Runnable r) {
foo(T1.super::mm); //should'n fail
}
}
}

@ -0,0 +1,3 @@
ForbidAccessToFieldUsingSuperTest.java:24:19: compiler.err.not.encl.class: ForbidAccessToFieldUsingSuperTest.T1
ForbidAccessToFieldUsingSuperTest.java:25:19: compiler.err.not.encl.class: ForbidAccessToFieldUsingSuperTest.T1
2 errors

@ -1,2 +1,2 @@
BadTwrSyntax.java:14:43: compiler.err.illegal.start.of.type
BadTwrSyntax.java:14:43: compiler.err.illegal.start.of.expr
1 error

@ -13,6 +13,11 @@ public class ResDeclOutsideTry implements AutoCloseable {
String test1() {
try (tr1 = new ResDeclOutsideTry(); tr2;) {
}
return null;
}
@Override
public void close() throws Exception {
}
}

@ -1,3 +1,2 @@
ResDeclOutsideTry.java:14:17: compiler.err.expected: token.identifier
ResDeclOutsideTry.java:14:48: compiler.err.expected: token.identifier
2 errors
ResDeclOutsideTry.java:14:18: compiler.err.try.with.resources.expr.needs.var
1 error

@ -0,0 +1,69 @@
/* @test /nodynamiccopyright/
* @bug 7196163
* @summary Verify that variables can be used as operands to try-with-resources
* @compile/fail/ref=TwrForVariable1.out -source 8 -XDrawDiagnostics -Xlint:-options TwrForVariable1.java
* @compile TwrForVariable1.java
* @run main TwrForVariable1
*/
public class TwrForVariable1 implements AutoCloseable {
private static int closeCount = 0;
public static void main(String... args) {
TwrForVariable1 v = new TwrForVariable1();
try (v) {
assertCloseCount(0);
}
try (/**@deprecated*/v) {
assertCloseCount(1);
}
try (v.finalWrapper.finalField) {
assertCloseCount(2);
} catch (Exception ex) {
}
try (new TwrForVariable1() { }.finalWrapper.finalField) {
assertCloseCount(3);
} catch (Exception ex) {
}
try ((args.length > 0 ? v : new TwrForVariable1()).finalWrapper.finalField) {
assertCloseCount(4);
} catch (Exception ex) {
}
try {
throw new CloseableException();
} catch (CloseableException ex) {
try (ex) {
assertCloseCount(5);
}
}
assertCloseCount(6);
}
static void assertCloseCount(int expectedCloseCount) {
if (closeCount != expectedCloseCount)
throw new RuntimeException("bad closeCount: " + closeCount +
"; expected: " + expectedCloseCount);
}
public void close() {
closeCount++;
}
final FinalWrapper finalWrapper = new FinalWrapper();
static class FinalWrapper {
public final AutoCloseable finalField = new AutoCloseable() {
@Override
public void close() throws Exception {
closeCount++;
}
};
}
static class CloseableException extends Exception implements AutoCloseable {
@Override
public void close() {
closeCount++;
}
}
}

@ -0,0 +1,2 @@
TwrForVariable1.java:13:14: compiler.err.var.in.try.with.resources.not.supported.in.source: 1.8
1 error

@ -0,0 +1,39 @@
/* @test /nodynamiccopyright/
* @bug 7196163
* @summary Verify that an improper combination of modifiers and variable is rejected
* in an operand to try-with-resources
* @compile/fail/ref=TwrForVariable2.out -XDrawDiagnostics -Xlint:-options TwrForVariable2.java
*/
public class TwrForVariable2 implements AutoCloseable {
public static void main(String... args) {
TwrForVariable2 v = new TwrForVariable2();
TwrForVariable3[] v2 = new TwrForVariable3[1];
try (final v) {
fail("no modifiers before variables");
}
try (@Deprecated v) {
fail("no annotations before variables");
}
try (v;;) {
fail("illegal double semicolon");
}
try ((v)) {
fail("parentheses not allowed");
}
try (v2[0]) {
fail("array access not allowed");
}
try (args.length == 0 ? v : v) {
fail("general expressions not allowed");
}
}
static void fail(String reason) {
throw new RuntimeException(reason);
}
public void close() {
}
}

@ -0,0 +1,7 @@
TwrForVariable2.java:12:21: compiler.err.expected: token.identifier
TwrForVariable2.java:15:27: compiler.err.expected: token.identifier
TwrForVariable2.java:18:16: compiler.err.illegal.start.of.expr
TwrForVariable2.java:21:14: compiler.err.try.with.resources.expr.needs.var
TwrForVariable2.java:24:16: compiler.err.try.with.resources.expr.needs.var
TwrForVariable2.java:27:31: compiler.err.try.with.resources.expr.needs.var
6 errors

@ -0,0 +1,29 @@
/* @test /nodynamiccopyright/
* @bug 7196163
* @summary Verify that improper expressions used as an operand to try-with-resources are rejected.
* @compile/fail/ref=TwrForVariable3.out -XDrawDiagnostics -Xlint:-options TwrForVariable3.java
*/
public class TwrForVariable3 implements AutoCloseable {
public static void main(String... args) {
TwrForVariable3 v1 = new TwrForVariable3();
Object v2 = new Object();
try (v2) {
fail("no an AutoCloseable");
}
try (java.lang.Object) {
fail("not a variable access");
}
try (java.lang) {
fail("not a variable access");
}
}
static void fail(String reason) {
throw new RuntimeException(reason);
}
public void close() {
}
}

@ -0,0 +1,4 @@
TwrForVariable3.java:11:14: compiler.err.prob.found.req: (compiler.misc.try.not.applicable.to.type: (compiler.misc.inconvertible.types: java.lang.Object, java.lang.AutoCloseable))
TwrForVariable3.java:14:18: compiler.err.cant.resolve.location: kindname.class, lang, , , (compiler.misc.location: kindname.package, java, null)
TwrForVariable3.java:17:14: compiler.err.cant.resolve.location: kindname.variable, java, , , (compiler.misc.location: kindname.class, TwrForVariable3, null)
3 errors

@ -0,0 +1,45 @@
/* @test /nodynamiccopyright/
* @bug 7196163
* @summary Verify that variable used as an operand to try-with-resources is rejected if it is not
* definitelly assigned before use and or not final or effectivelly final.
* @compile/fail/ref=TwrForVariable4.out -XDrawDiagnostics -Xlint:-options TwrForVariable4.java
*/
public class TwrForVariable4 implements AutoCloseable {
public static void main(String... args) {
TwrForVariable4 uninitialized;
try (uninitialized) {
fail("must be initialized before use");
}
uninitialized = new TwrForVariable4();
TwrForVariable4 notEffectivellyFinal1 = new TwrForVariable4();
notEffectivellyFinal1 = new TwrForVariable4();
try (notEffectivellyFinal1) {
fail("not effectivelly final");
}
TwrForVariable4 notEffectivellyFinal2 = new TwrForVariable4();
try (notEffectivellyFinal2) {
notEffectivellyFinal2 = new TwrForVariable4();
fail("not effectivelly final");
}
try (notFinal) {
fail("not final");
}
}
static TwrForVariable4 notFinal = new TwrForVariable4();
static void fail(String reason) {
throw new RuntimeException(reason);
}
public void close() {
}
}

@ -0,0 +1,5 @@
TwrForVariable4.java:11:14: compiler.err.var.might.not.have.been.initialized: uninitialized
TwrForVariable4.java:20:14: compiler.err.try.with.resources.expr.effectively.final.var: notEffectivellyFinal1
TwrForVariable4.java:26:14: compiler.err.try.with.resources.expr.effectively.final.var: notEffectivellyFinal2
TwrForVariable4.java:31:14: compiler.err.try.with.resources.expr.effectively.final.var: notFinal
4 errors

@ -1,4 +1,3 @@
/*
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.

@ -0,0 +1,198 @@
/*
* 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 SyntheticParameters
* @bug 8065132
* @summary Test generation of annotations on inner class parameters.
* @library /lib/annotations/
* @run main SyntheticParameters
*/
import annotations.classfile.ClassfileInspector;
import java.io.*;
import java.lang.annotation.*;
import com.sun.tools.classfile.*;
public class SyntheticParameters extends ClassfileInspector {
private static final String Inner_class = "SyntheticParameters$Inner.class";
private static final String Foo_class = "SyntheticParameters$Foo.class";
private static final Expected Inner_expected =
new Expected("SyntheticParameters$Inner",
null,
null,
new ExpectedParameterAnnotation[] {
(ExpectedParameterAnnotation)
// Assert there is no annotation on the
// this$0 parameter.
new ExpectedParameterAnnotation(
"<init>",
0,
"A",
true,
0),
(ExpectedParameterAnnotation)
// Assert there is an annotation on the
// first parameter.
new ExpectedParameterAnnotation(
"<init>",
1,
"A",
true,
1),
(ExpectedParameterAnnotation)
new ExpectedParameterAnnotation(
"foo",
0,
"A",
true,
1),
(ExpectedParameterAnnotation)
new ExpectedParameterAnnotation(
"foo",
1,
"A",
true,
0),
(ExpectedParameterAnnotation)
// Assert there is no annotation on the
// this$0 parameter.
new ExpectedParameterAnnotation(
"<init>",
0,
"B",
false,
0),
(ExpectedParameterAnnotation)
// Assert there is an annotation on the
// first parameter.
new ExpectedParameterAnnotation(
"<init>",
1,
"B",
false,
1),
(ExpectedParameterAnnotation)
new ExpectedParameterAnnotation(
"foo",
0,
"B",
false,
1),
(ExpectedParameterAnnotation)
new ExpectedParameterAnnotation(
"foo",
1,
"B",
false,
0)
},
null);
private static final Expected Foo_expected =
new Expected("SyntheticParameters$Foo",
null,
null,
new ExpectedParameterAnnotation[] {
(ExpectedParameterAnnotation)
// Assert there is no annotation on the
// $enum$name parameter.
new ExpectedParameterAnnotation(
"<init>",
0,
"A",
true,
0),
(ExpectedParameterAnnotation)
// Assert there is no annotation on the
// $enum$ordinal parameter.
new ExpectedParameterAnnotation(
"<init>",
1,
"A",
true,
0),
(ExpectedParameterAnnotation)
// Assert there is an annotation on the
// first parameter.
new ExpectedParameterAnnotation(
"<init>",
2,
"A",
true,
1),
(ExpectedParameterAnnotation)
// Assert there is no annotation on the
// $enum$name parameter.
new ExpectedParameterAnnotation(
"<init>",
0,
"B",
false,
0),
(ExpectedParameterAnnotation)
// Assert there is no annotation on the
// $enum$ordinal parameter.
new ExpectedParameterAnnotation(
"<init>",
1,
"B",
false,
0),
(ExpectedParameterAnnotation)
// Assert there is an annotation on the
// first parameter.
new ExpectedParameterAnnotation(
"<init>",
2,
"B",
false,
1)
},
null);
public static void main(String... args) throws Exception {
new SyntheticParameters().run(
new ClassFile[] { getClassFile(Inner_class, Inner.class),
getClassFile(Foo_class, Foo.class) },
new Expected[] { Inner_expected, Foo_expected });
}
public class Inner {
public Inner(@A @B int a) {}
public void foo(@A @B int a, int b) {}
}
public static enum Foo {
ONE(null);
Foo(@A @B Object a) {}
}
}
@Retention(RetentionPolicy.RUNTIME)
@interface A {}
@Retention(RetentionPolicy.CLASS)
@interface B {}

@ -1,5 +1,3 @@
import java.lang.annotation.ElementType;
/*
* Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.

@ -24,10 +24,12 @@
/*
* @test SyntheticParameters
* @summary Test generation of annotations on inner class parameters.
* @build ClassfileInspector
* @library /lib/annotations/
* @run main SyntheticParameters
*/
import annotations.classfile.ClassfileInspector;
import java.io.*;
import java.lang.annotation.*;
@ -111,7 +113,8 @@ public class SyntheticParameters extends ClassfileInspector {
public static void main(String... args) throws Exception {
new SyntheticParameters().run(
new ClassFile[] { getClassFile(Inner_class), getClassFile(Foo_class) },
new ClassFile[] { getClassFile(Inner_class, Inner.class),
getClassFile(Foo_class, Foo.class) },
new Expected[] { Inner_expected, Foo_expected });
}

@ -1,4 +1,3 @@
/*
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.

@ -34,6 +34,7 @@
import java.io.File;
import java.lang.reflect.Field;
import java.nio.file.Path;
import java.util.Arrays;
import static javax.tools.StandardLocation.CLASS_OUTPUT;
import javax.tools.*;
@ -59,10 +60,10 @@ public class T6440528 extends ToolTester {
System.err.println("Got: " + got);
}
private File getUnderlyingFile(Object o) throws Exception {
Field file = o.getClass().getDeclaredField("file");
private File getUnderlyingFile(FileObject o) throws Exception {
Field file = o.getClass().getDeclaredField("file"); // assumes RegularFileObject
file.setAccessible(true);
return (File)file.get(o);
return ((Path)file.get(o)).toFile();
}
public static void main(String... args) throws Exception {

@ -61,7 +61,10 @@ public class TestJavacTask {
try {
getTask(testFile);
} catch (IllegalArgumentException iae) {
if (!iae.getMessage().contains("\"" + testFile.getName() + "\"")) {
// The following check is somewhat fragile, since the content of the ILA is not
// formally specified. If we want to fix this, we should catch/rewrap ILA coming
// from use of java.nio.file.Path inside javac's impl of JavaFileManager.
if (!iae.getMessage().contains(testFile.getName())) {
System.err.println("Got message: " + iae.getMessage());
throw new RuntimeException("Error: expected string not found");
}

@ -321,12 +321,17 @@ class Example implements Comparable<Example> {
first = opts.get(0);
rest = opts.subList(1, opts.size()).toArray(new String[opts.size() - 1]);
}
// For more details on the different compilers,
// see their respective class doc comments.
// See also README.examples.txt in this directory.
if (first == null || first.equals("jsr199"))
return new Jsr199Compiler(verbose, rest);
else if (first.equals("simple"))
return new SimpleCompiler(verbose);
else if (first.equals("backdoor"))
return new BackdoorCompiler(verbose);
else if (first.equals("exec"))
return new ExecCompiler(verbose);
else
throw new IllegalArgumentException(first);
}
@ -506,6 +511,84 @@ class Example implements Comparable<Example> {
}
}
/**
* Run the test in a separate process.
*/
static class ExecCompiler extends Compiler {
ExecCompiler(boolean verbose) {
super(verbose);
}
@Override
boolean run(PrintWriter out, Set<String> keys, boolean raw, List<String> opts, List<File> files) {
if (out != null && keys != null)
throw new IllegalArgumentException();
if (verbose)
System.err.println("run_exec: " + opts + " " + files);
List<String> args = new ArrayList<String>();
File javaHome = new File(System.getProperty("java.home"));
if (javaHome.getName().equals("jre"))
javaHome = javaHome.getParentFile();
File javaExe = new File(new File(javaHome, "bin"), "java");
args.add(javaExe.getPath());
File toolsJar = new File(new File(javaHome, "lib"), "tools.jar");
if (toolsJar.exists()) {
args.add("-classpath");
args.add(toolsJar.getPath());
}
addOpts(args, "test.vm.opts");
addOpts(args, "test.java.opts");
args.add(com.sun.tools.javac.Main.class.getName());
if (keys != null || raw)
args.add("-XDrawDiagnostics");
args.addAll(opts);
for (File f: files)
args.add(f.getPath());
try {
ProcessBuilder pb = new ProcessBuilder(args);
pb.redirectErrorStream(true);
Process p = pb.start();
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
if (keys != null)
scanForKeys(line, keys);
}
int rc = p.waitFor();
return (rc == 0);
} catch (IOException | InterruptedException e) {
System.err.println("Exception execing javac" + e);
System.err.println("Command line: " + opts);
return false;
}
}
private static void scanForKeys(String text, Set<String> keys) {
StringTokenizer st = new StringTokenizer(text, " ,\r\n():");
while (st.hasMoreElements()) {
String t = st.nextToken();
if (t.startsWith("compiler."))
keys.add(t);
}
}
private static void addOpts(List<String> args, String propName) {
String propValue = System.getProperty(propName);
if (propValue == null || propValue.isEmpty())
return;
args.addAll(Arrays.asList(propValue.split(" +", 0)));
}
}
static class BackdoorCompiler extends Compiler {
BackdoorCompiler(boolean verbose) {
super(verbose);

@ -123,6 +123,9 @@ different types of information may be given:
is required to detect and track messages that bypass the normal
diagnostic mechanisms, such as output generated by the -verbose
option.
exec -- The example will be run in a subprocess. This mode is useful when
the example will leave files open, such that the only way to close
them is to exit the process.
The "jsr199" run mode accepts the following options:
-cantRead:pattern

@ -23,6 +23,6 @@
// key: compiler.err.import.requires.canonical
import p.ExtendsBase.NestedInBase;
import java.util.HashMap.Entry;
class ImportRequiredCanonical { }

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010, 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,5 +23,6 @@
// key: compiler.warn.proc.unclosed.type.files
// options: -Xlint:processing -processor AnnoProc
// run: exec
class ProcUnclosedTypeFiles { }

@ -0,0 +1,40 @@
/*
* 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.
*/
// key: compiler.err.try.with.resources.expr.effectively.final.var
class TryWithResourcesExprEffectivelyFinalVar {
void m() {
CloseableImpl ac = new CloseableImpl();
try (ac) {
ac = null;
}
}
}
class CloseableImpl implements AutoCloseable {
@Override
public void close() {
}
}

@ -0,0 +1,37 @@
/*
* 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.
*/
// key: compiler.err.try.with.resources.expr.needs.var
class TryWithResourcesExprNeedsVar {
void m() {
try (new CloseableImpl()) {
}
}
}
class CloseableImpl implements AutoCloseable {
@Override
public void close() throws Exception {
}
}

@ -0,0 +1,41 @@
/*
* 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.
*/
// key: compiler.err.var.in.try.with.resources.not.supported.in.source
// key: compiler.warn.source.no.bootclasspath
// options: -source 8
class VarInTryWithResourcesNotSupportedInSource {
void m() {
AutoCloseable ac = new CloseableImpl();
try (ac) {
}
}
}
class CloseableImpl implements AutoCloseable {
@Override
public void close() throws Exception {
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 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
@ -99,7 +99,7 @@ public class T7018098 extends JavacTestingAbstractProcessor {
round++;
if (round == 1) {
boolean expect = Boolean.valueOf(options.get("expect"));
checkEqual("cache result", fsInfo.isDirectory(testDir), expect);
checkEqual("cache result", fsInfo.isDirectory(testDir.toPath()), expect);
initialFSInfo = fsInfo;
} else {
checkEqual("fsInfo", fsInfo, initialFSInfo);

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 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,6 +30,7 @@
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Writer;
import java.nio.file.NoSuchFileException;
import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
@ -104,7 +105,7 @@ public class T7068437 {
messager.printMessage(Kind.NOTE, "found previous content of length " +
filer.getResource(StandardLocation.SOURCE_OUTPUT, "p", "C.java").getCharContent(false).length());
found = true;
} catch (FileNotFoundException x) {
} catch (FileNotFoundException | NoSuchFileException x) {
messager.printMessage(Kind.NOTE, "not previously there");
found = false;
} catch (IOException x) {

@ -33,6 +33,7 @@ import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.nio.file.NoSuchFileException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@ -143,7 +144,7 @@ public class T7068451 {
try {
int len = filer.getResource(StandardLocation.SOURCE_OUTPUT, "p", "C.java").getCharContent(false).length();
messager.printMessage(Kind.NOTE, "C.java: found previous content of length " + len);
} catch (FileNotFoundException x) {
} catch (FileNotFoundException | NoSuchFileException x) {
messager.printMessage(Kind.NOTE, "C.java: not previously there");
} catch (IOException x) {
messager.printMessage(Kind.ERROR, "while reading: " + x);

@ -0,0 +1,24 @@
/**
* @test
* @bug 8062747
* @summary Avoiding an error for lambdas with thrown types inference inside an anonymous class.
* @compile T8062747.java
*/
public class T8062747 {
public interface Throwing<Y extends Exception> {
void canThrow() throws Y;
}
public static <Y extends Exception> void wrap(Throwing<Y> action) {
}
public static void invoke(String a) {
Runnable r = new Runnable() {
@Override
public void run() {
wrap(() -> System.out.println(a));
}
};
}
}

@ -0,0 +1,53 @@
/*
* 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. 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.
*/
/*
* @test
* @bug 8064803
* @summary Javac erroneously uses instantiated signatures when merging abstract most-specific methods
*/
public class T8064803 {
interface ParentA<T> {
T process() throws Exception;
}
interface ParentB<T> {
T process() throws Exception;
}
interface Child<T> extends ParentA<T>, ParentB<T> { }
static class ChildImpl<T> implements Child<T> {
@Override
public T process() {
return null;
}
}
public static void main(String[] args) throws Exception {
Child<String> child = new ChildImpl<String>();
child.process();
}
}

@ -0,0 +1,33 @@
/*
* @test /nodynamiccopyright/
* @bug 8065986
*
* @summary Compiler fails to NullPointerException when calling super with Object<>()
* @compile/fail/ref=T8065986a.out T8065986a.java -XDrawDiagnostics
*
*/
import java.util.ArrayList;
class T8065986a {
T8065986a() {
super(new Object<>());
}
T8065986a(boolean b) {
super(new ArrayList<>());
}
T8065986a(boolean b1, boolean b2) {
super(()->{});
}
T8065986a(boolean b1, boolean b2, boolean b3) {
super(T8065986a::m);
}
T8065986a(boolean cond, Object o1, Object o2) {
super(cond ? o1 : o2);
}
static void m() { }
}

@ -0,0 +1,6 @@
T8065986a.java:13:25: compiler.err.cant.apply.diamond.1: java.lang.Object, (compiler.misc.diamond.non.generic: java.lang.Object)
T8065986a.java:17:9: compiler.err.cant.apply.symbol: kindname.constructor, Object, compiler.misc.no.args, java.util.ArrayList<java.lang.Object>, kindname.class, java.lang.Object, (compiler.misc.arg.length.mismatch)
T8065986a.java:21:9: compiler.err.cant.apply.symbol: kindname.constructor, Object, compiler.misc.no.args, @438, kindname.class, java.lang.Object, (compiler.misc.arg.length.mismatch)
T8065986a.java:25:9: compiler.err.cant.apply.symbol: kindname.constructor, Object, compiler.misc.no.args, @520, kindname.class, java.lang.Object, (compiler.misc.arg.length.mismatch)
T8065986a.java:29:9: compiler.err.cant.apply.symbol: kindname.constructor, Object, compiler.misc.no.args, @608, kindname.class, java.lang.Object, (compiler.misc.arg.length.mismatch)
5 errors

@ -0,0 +1,33 @@
/*
* @test /nodynamiccopyright/
* @bug 8065986
*
* @summary Compiler fails to NullPointerException when calling super with Object<>()
* @compile/fail/ref=T8065986b.out T8065986b.java -XDrawDiagnostics
*
*/
import java.util.ArrayList;
class T8065986b {
T8065986b() {
this(new Object<>());
}
T8065986b(boolean b) {
this(new ArrayList<>());
}
T8065986b(boolean b1, boolean b2) {
this(()->{});
}
T8065986b(boolean b1, boolean b2, boolean b3) {
this(T8065986b::m);
}
T8065986b(boolean cond, Object o1, Object o2) {
this(cond ? o1 : o2);
}
static void m() { }
}

@ -0,0 +1,6 @@
T8065986b.java:13:24: compiler.err.cant.apply.diamond.1: java.lang.Object, (compiler.misc.diamond.non.generic: java.lang.Object)
T8065986b.java:17:9: compiler.err.cant.apply.symbols: kindname.constructor, T8065986b, java.util.ArrayList<java.lang.Object>,{(compiler.misc.inapplicable.method: kindname.constructor, T8065986b, T8065986b(), (compiler.misc.arg.length.mismatch)),(compiler.misc.inapplicable.method: kindname.constructor, T8065986b, T8065986b(boolean), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: java.util.ArrayList), (compiler.misc.infer.no.conforming.instance.exists: E, java.util.ArrayList<E>, boolean)))),(compiler.misc.inapplicable.method: kindname.constructor, T8065986b, T8065986b(boolean,boolean), (compiler.misc.arg.length.mismatch)),(compiler.misc.inapplicable.method: kindname.constructor, T8065986b, T8065986b(boolean,boolean,boolean), (compiler.misc.arg.length.mismatch)),(compiler.misc.inapplicable.method: kindname.constructor, T8065986b, T8065986b(boolean,java.lang.Object,java.lang.Object), (compiler.misc.arg.length.mismatch))}
T8065986b.java:21:9: compiler.err.cant.apply.symbols: kindname.constructor, T8065986b, @435,{(compiler.misc.inapplicable.method: kindname.constructor, T8065986b, T8065986b(), (compiler.misc.arg.length.mismatch)),(compiler.misc.inapplicable.method: kindname.constructor, T8065986b, T8065986b(boolean), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.not.a.functional.intf: boolean))),(compiler.misc.inapplicable.method: kindname.constructor, T8065986b, T8065986b(boolean,boolean), (compiler.misc.arg.length.mismatch)),(compiler.misc.inapplicable.method: kindname.constructor, T8065986b, T8065986b(boolean,boolean,boolean), (compiler.misc.arg.length.mismatch)),(compiler.misc.inapplicable.method: kindname.constructor, T8065986b, T8065986b(boolean,java.lang.Object,java.lang.Object), (compiler.misc.arg.length.mismatch))}
T8065986b.java:25:9: compiler.err.cant.apply.symbols: kindname.constructor, T8065986b, @516,{(compiler.misc.inapplicable.method: kindname.constructor, T8065986b, T8065986b(), (compiler.misc.arg.length.mismatch)),(compiler.misc.inapplicable.method: kindname.constructor, T8065986b, T8065986b(boolean), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.not.a.functional.intf: boolean))),(compiler.misc.inapplicable.method: kindname.constructor, T8065986b, T8065986b(boolean,boolean), (compiler.misc.arg.length.mismatch)),(compiler.misc.inapplicable.method: kindname.constructor, T8065986b, T8065986b(boolean,boolean,boolean), (compiler.misc.arg.length.mismatch)),(compiler.misc.inapplicable.method: kindname.constructor, T8065986b, T8065986b(boolean,java.lang.Object,java.lang.Object), (compiler.misc.arg.length.mismatch))}
T8065986b.java:29:9: compiler.err.cant.apply.symbols: kindname.constructor, T8065986b, @603,{(compiler.misc.inapplicable.method: kindname.constructor, T8065986b, T8065986b(), (compiler.misc.arg.length.mismatch)),(compiler.misc.inapplicable.method: kindname.constructor, T8065986b, T8065986b(boolean), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.type.in.conditional: (compiler.misc.inconvertible.types: java.lang.Object, boolean)))),(compiler.misc.inapplicable.method: kindname.constructor, T8065986b, T8065986b(boolean,boolean), (compiler.misc.arg.length.mismatch)),(compiler.misc.inapplicable.method: kindname.constructor, T8065986b, T8065986b(boolean,boolean,boolean), (compiler.misc.arg.length.mismatch)),(compiler.misc.inapplicable.method: kindname.constructor, T8065986b, T8065986b(boolean,java.lang.Object,java.lang.Object), (compiler.misc.arg.length.mismatch))}
5 errors

@ -0,0 +1,10 @@
/*
* @test /nodynamiccopyright/
* @bug 7101822
* @summary Verify that statically importing non-existing constant causes a compile-time error
* for files without a class.
*
* @compile/fail/ref=NoImportedNoClasses.out -XDrawDiagnostics NoImportedNoClasses.java
*/
import static java.lang.Runnable.UNKNOWN;

@ -0,0 +1,2 @@
NoImportedNoClasses.java:10:1: compiler.err.cant.resolve.location: kindname.static, UNKNOWN, , , kindname.interface, java.lang.Runnable
1 error

@ -0,0 +1,42 @@
/*
* 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 7101822
* @summary Verify that imports are declarations are processed in the correct order.
* @compile ImportResolvedTooSoon.java
*/
package pkg;
import static pkg.B.SubInner.Foo;
class B extends A {
static class SubInner extends Inner { }
}
class A {
static class Inner {
static class Foo { }
}
}

@ -0,0 +1,49 @@
/*
* 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 7101822
* @summary Verify that imports are declarations are processed in the correct order.
* @compile T7101822A.java T7101822Z.java
*/
package a;
import a.T7101822A.B.C;
import z.T7101822Z;
public class T7101822A {
class B extends T7101822Z {
class C {
}
}
class D {
Class foo() {
return C.class;
}
}
}

@ -0,0 +1,25 @@
/*
* 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.
*/
package z;
public class T7101822Z {}

@ -0,0 +1,240 @@
/*
* Copyright (c) 2011-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 7101822
* @summary static import fails to resolve interfaces on nested enums via import statements
*/
import com.sun.source.util.JavacTask;
import java.net.URI;
import java.util.Arrays;
import javax.tools.Diagnostic;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
public class TestDuplicateImport {
static int checkCount = 0;
enum ImportKind {
NORMAL("import a.#Q.#N;"),
STATIC("import static a.#Q.#N;");
String importStr;
ImportKind(String importStr) {
this.importStr = importStr;
}
String getImportStatement(QualifierKind qk, NameKind nk) {
return importStr.replaceAll("#Q", qk.qualifierStr)
.replaceAll("#N", nk.nameStr);
}
boolean isStatic() {
return this == STATIC;
}
}
enum QualifierKind {
A("A"),
B("B"),
C("C");
String qualifierStr;
QualifierKind(String qualifierStr) {
this.qualifierStr = qualifierStr;
}
public boolean compatible(QualifierKind ik) {
return this == ik || (this != A && ik != A);
}
}
enum NameKind {
D("D"),
E("E"),
M("m"),
F("f"),
STAR("*"),
NON_EXISTENT("NonExistent");
String nameStr;
NameKind(String nameStr) {
this.nameStr = nameStr;
}
boolean exists() {
return this != NON_EXISTENT;
}
boolean isMember() {
return this == M || this == F;
}
boolean isType() {
return this == D || this == E;
}
}
public static void main(String... args) throws Exception {
//create default shared JavaCompiler - reused across multiple compilations
JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
for (ImportKind ik1 : ImportKind.values()) {
for (ImportKind ik2 : ImportKind.values()) {
for (QualifierKind qk1 : QualifierKind.values()) {
for (QualifierKind qk2 : QualifierKind.values()) {
for (NameKind nk1 : NameKind.values()) {
for (NameKind nk2 : NameKind.values()) {
new TestDuplicateImport(ik1, ik2, qk1, qk2, nk1, nk2).run(comp, fm);
}
}
}
}
}
}
System.out.println("Total check executed: " + checkCount);
}
ImportKind ik1;
ImportKind ik2;
QualifierKind qk1;
QualifierKind qk2;
NameKind nk1;
NameKind nk2;
JavaSource source;
DiagnosticChecker diagChecker;
TestDuplicateImport(ImportKind ik1, ImportKind ik2, QualifierKind qk1, QualifierKind qk2, NameKind nk1, NameKind nk2) {
this.ik1 = ik1;
this.ik2 = ik2;
this.qk1 = qk1;
this.qk2 = qk2;
this.nk1 = nk1;
this.nk2 = nk2;
this.source = new JavaSource();
this.diagChecker = new DiagnosticChecker();
}
class JavaSource extends SimpleJavaFileObject {
String bodyTemplate = "package a;\n" +
"#I1\n" +
"#I2\n" +
"class A {\n" +
" static class D { }\n" +
" static class E { }\n" +
" static Object f;\n" +
" static void m() { }\n" +
"}\n" +
"class B {\n" +
" static class D { }\n" +
" static class E { }\n" +
" static Object f;\n" +
" static void m() { }\n" +
"}\n" +
"class C extends B {\n" +
"}\n";
String source;
public JavaSource() {
super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
source = bodyTemplate.replaceAll("#I1", ik1.getImportStatement(qk1, nk1))
.replaceAll("#I2", ik2.getImportStatement(qk2, nk2));
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return source;
}
}
void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
null, null, Arrays.asList(source));
try {
ct.analyze();
} catch (Throwable ex) {
throw new AssertionError("Error thrown when compiling the following code:\n" + source.getCharContent(true));
}
check();
}
void check() {
checkCount++;
boolean errorExpected = false;
//error if the import refers to a non-existent symbol
if (!nk1.exists() || !nk2.exists()) {
errorExpected = true;
}
//error if a non-static import refers to a non-type symbol
if ((nk1.isMember() && !ik1.isStatic()) ||
(nk2.isMember() && !ik2.isStatic())) {
errorExpected = true;
}
//error if two single non-static (or one static and one non-static)
//imports import same names from different places
if (nk1 == nk2 && nk1 != NameKind.STAR && !qk1.compatible(qk2) &&
(!ik1.isStatic() || !ik2.isStatic())) {
errorExpected = true;
}
if ((qk1 == QualifierKind.C && !ik1.isStatic() && nk1 != NameKind.STAR) ||
(qk2 == QualifierKind.C && !ik2.isStatic() && nk2 != NameKind.STAR)) {
errorExpected = true;
}
if (errorExpected != diagChecker.errorFound) {
throw new Error("invalid diagnostics for source:\n" +
source.getCharContent(true) +
"\nFound error: " + diagChecker.errorFound +
"\nExpected error: " + errorExpected);
}
}
static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
boolean errorFound;
public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
errorFound = true;
}
}
}
}

@ -0,0 +1,224 @@
/*
* Copyright (c) 2011-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 7101822
* @summary static import fails to resolve interfaces on nested enums via import statements
*/
import com.sun.source.util.JavacTask;
import java.net.URI;
import java.util.Arrays;
import javax.tools.Diagnostic;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
public class TestLazyImportScope {
static int checkCount = 0;
enum ImportOrder {
NORMAL("import a.C.D;\n" +
"#I"),
REVERSE("#I\n" +
"import a.C.D;");
String importLayout;
ImportOrder(String importLayout) {
this.importLayout = importLayout;
}
String getImportString(ImportKind ik) {
return importLayout.replaceAll("#I", ik.importStr);
}
}
enum ImportKind {
NAMED("import a.A.B.E;"),
ON_DEMAND("import a.A.B.*;"),
STATIC_NAMED_TYPE("import static a.A.B.E;"),
STATIC_NAMED_MEMBER("import static a.A.B.bm;"),
STATIC_ON_DEMAND("import static a.A.B.*;");
String importStr;
private ImportKind(String importStr) {
this.importStr = importStr;
}
}
enum TypeRefKind {
NONE(""),
E("E e = null;"),
F("F f = null;"),
BOTH("E e = null; F f = null;");
String typeRefStr;
private TypeRefKind(String typeRefStr) {
this.typeRefStr = typeRefStr;
}
boolean isImported(ImportKind ik) {
switch (ik) {
case NAMED:
case STATIC_NAMED_TYPE: return this == NONE || this == E;
case ON_DEMAND:
case STATIC_ON_DEMAND: return true;
default: return this == NONE;
}
}
}
enum MemberRefKind {
NONE(""),
FIELD("Object o = bf;"),
METHOD("bm();"),
BOTH("Object o = bf; bm();");
String memberRefStr;
private MemberRefKind(String memberRefStr) {
this.memberRefStr = memberRefStr;
}
boolean isImported(ImportKind ik) {
switch (ik) {
case STATIC_NAMED_MEMBER: return this == NONE || this == METHOD;
case STATIC_ON_DEMAND: return true;
default: return this == NONE;
}
}
}
public static void main(String... args) throws Exception {
//create default shared JavaCompiler - reused across multiple compilations
JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
for (ImportOrder ord : ImportOrder.values()) {
for (ImportKind ik : ImportKind.values()) {
for (TypeRefKind tk : TypeRefKind.values()) {
for (MemberRefKind mk : MemberRefKind.values()) {
new TestLazyImportScope(ord, ik, tk, mk).run(comp, fm);
}
}
}
}
System.out.println("Total check executed: " + checkCount);
}
ImportOrder ord;
ImportKind ik;
TypeRefKind tk;
MemberRefKind mk;
JavaSource source;
DiagnosticChecker diagChecker;
TestLazyImportScope(ImportOrder ord, ImportKind ik, TypeRefKind tk, MemberRefKind mk) {
this.ord = ord;
this.ik = ik;
this.tk = tk;
this.mk = mk;
this.source = new JavaSource();
this.diagChecker = new DiagnosticChecker();
}
class JavaSource extends SimpleJavaFileObject {
String bodyTemplate = "package a;\n" +
"#I\n" +
"class A {\n" +
" static class B extends D {\n" +
" static class E { }\n" +
" static class F { }\n" +
" static Object bf;\n" +
" static void bm() { }\n" +
" }\n" +
"}\n" +
"class C {\n" +
" static class D { }\n" +
"}\n" +
"class Test {\n" +
" void test() {\n" +
" #T\n" +
" #M\n" +
" }\n" +
"}";
String source;
public JavaSource() {
super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
source = bodyTemplate.replaceAll("#I", ord.getImportString(ik))
.replaceAll("#T", tk.typeRefStr)
.replaceAll("#M", mk.memberRefStr);
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return source;
}
}
void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
null, null, Arrays.asList(source));
try {
ct.analyze();
} catch (Throwable ex) {
throw new AssertionError("Error thrown when compiling the following code:\n" + source.getCharContent(true));
}
check();
}
void check() {
checkCount++;
boolean errorExpected = !tk.isImported(ik) || !mk.isImported(ik);
if (errorExpected != diagChecker.errorFound) {
throw new Error("invalid diagnostics for source:\n" +
source.getCharContent(true) +
"\nFound error: " + diagChecker.errorFound +
"\nExpected error: " + errorExpected);
}
}
static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
boolean errorFound;
public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
errorFound = true;
}
}
}
}

@ -0,0 +1,38 @@
/*
* 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 7101822
* @summary Verify that cycles between type parameter bounds and imports/class nesting
* are not a problem.
* @compile TypeParamCycle.java
*/
package pkg;
import pkg.A.Outer.Inner;
class A {
static class Outer<X extends Inner> { static class Inner {} }
}

@ -0,0 +1,41 @@
/*
* 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 7101822
* @summary Verify that cycles between type parameter bounds and imports/class nesting
* are not a problem.
* @compile TypeParamCycle2.java
*/
package pkg;
import pkg.A.Outer.Inner;
class B extends Inner {
}
class A {
static class Outer<X extends Inner> { static class Inner {} }
}

@ -0,0 +1,42 @@
/*
* 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 7101822
* @summary Verify that cycles between type parameter bounds and imports/class nesting
* are not a problem.
* @compile TypeParamCycle3.java
*/
package pkg;
import static pkg.A.Outer.Inner;
class A {
static class Outer<X extends Inner> extends B { }
}
class B {
static class Inner {}
}

@ -0,0 +1,366 @@
/*
* 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 7101822
* @summary Verify that the processing of classes in TypeEnter runs in the correct order.
* @library /tools/lib
* @build annotations.TriggersComplete annotations.TriggersCompleteRepeat annotations.Phase
* @build DependenciesTest
* @run main DependenciesTest
*/
import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.Stack;
import java.util.stream.Stream;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import annotations.*;
import com.sun.source.tree.AnnotationTree;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.ImportTree;
import com.sun.source.tree.Tree;
import com.sun.source.util.JavacTask;
import com.sun.source.util.SourcePositions;
import com.sun.source.util.TreePathScanner;
import com.sun.source.util.Trees;
import com.sun.tools.javac.api.JavacTool;
import com.sun.tools.javac.api.JavacTrees;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Context.Factory;
import com.sun.tools.javac.util.Dependencies;
public class DependenciesTest {
public static void main(String... args) throws IOException {
new DependenciesTest().run();
}
void run() throws IOException {
Path src = Paths.get(System.getProperty("test.src"), "tests");
try (Stream<Path> tests = Files.list(src)) {
tests.map(p -> Files.isRegularFile(p) ? Stream.of(p) : silentWalk(p))
.forEach(this :: runTest);
}
}
Stream<Path> silentWalk(Path src) {
try {
return Files.walk(src).filter(Files :: isRegularFile);
} catch (IOException ex) {
throw new IllegalStateException(ex);
}
}
void runTest(Stream<Path> inputs) {
JavacTool tool = JavacTool.create();
try (JavacFileManager fm = tool.getStandardFileManager(null, null, null)) {
Path classes = Paths.get(System.getProperty("test.classes"));
Iterable<? extends JavaFileObject> reconFiles =
fm.getJavaFileObjectsFromFiles(inputs.sorted().map(p -> p.toFile()) :: iterator);
List<String> options = Arrays.asList("-classpath", classes.toAbsolutePath().toString());
JavacTask reconTask = tool.getTask(null, fm, null, options, null, reconFiles);
Iterable<? extends CompilationUnitTree> reconUnits = reconTask.parse();
JavacTrees reconTrees = JavacTrees.instance(reconTask);
SearchAnnotations scanner = new SearchAnnotations(reconTrees,
reconTask.getElements());
List<JavaFileObject> validateFiles = new ArrayList<>();
reconTask.analyze();
scanner.scan(reconUnits, null);
for (CompilationUnitTree cut : reconUnits) {
validateFiles.add(ClearAnnotations.clearAnnotations(reconTrees, cut));
}
Context validateContext = new Context();
TestDependencies.preRegister(validateContext);
JavacTask validateTask =
tool.getTask(null, fm, null, options, null, validateFiles, validateContext);
validateTask.analyze();
TestDependencies deps = (TestDependencies) Dependencies.instance(validateContext);
if (!scanner.topLevel2Expected.equals(deps.topLevel2Completing)) {
throw new IllegalStateException( "expected=" + scanner.topLevel2Expected +
"; actual=" + deps.topLevel2Completing);
}
} catch (IOException ex) {
throw new IllegalStateException(ex);
} finally {
inputs.close();
}
}
static final class TestDependencies extends Dependencies {
public static void preRegister(Context context) {
context.put(dependenciesKey, (Factory<Dependencies>) TestDependencies :: new);
}
public TestDependencies(Context context) {
super(context);
}
final Stack<PhaseDescription> inProcess = new Stack<>();
String topLevelMemberEnter;
Map<String, Set<PhaseDescription>> topLevel2Completing = new HashMap<>();
@Override
public void push(ClassSymbol s, CompletionCause phase) {
String flatname = s.flatName().toString();
for (Phase p : Phase.values()) {
if (phase == p.cause) {
inProcess.push(new PhaseDescription(flatname, p));
return ;
}
}
if (phase == CompletionCause.MEMBER_ENTER) {
if (inProcess.isEmpty()) {
topLevelMemberEnter = flatname;
} else {
for (PhaseDescription running : inProcess) {
if (running == null)
continue;
Set<PhaseDescription> completing =
topLevel2Completing.computeIfAbsent(running.flatname, $ -> new HashSet<>());
completing.add(new PhaseDescription(flatname, running.phase));
}
}
}
inProcess.push(null);
}
@Override
public void push(AttributionKind ak, JCTree t) {
inProcess.push(null);
}
@Override
public void pop() {
inProcess.pop();
}
}
static final class SearchAnnotations extends TreePathScanner<Void, Void> {
final Trees trees;
final Elements elements;
final TypeElement triggersCompleteAnnotation;
final TypeElement triggersCompleteRepeatAnnotation;
final Map<String, Set<PhaseDescription>> topLevel2Expected =
new HashMap<>();
public SearchAnnotations(Trees trees, Elements elements) {
this.trees = trees;
this.elements = elements;
this.triggersCompleteAnnotation =
elements.getTypeElement(TriggersComplete.class.getName());
this.triggersCompleteRepeatAnnotation =
elements.getTypeElement(TriggersCompleteRepeat.class.getName());
}
@Override
public Void visitClass(ClassTree node, Void p) {
TypeElement te = (TypeElement) trees.getElement(getCurrentPath());
Set<PhaseDescription> expected = new HashSet<>();
for (AnnotationMirror am : getTriggersCompleteAnnotation(te)) {
TypeMirror of = (TypeMirror) findAttribute(am, "of").getValue();
Name ofName = elements.getBinaryName((TypeElement) ((DeclaredType) of).asElement());
Element at = (Element) findAttribute(am, "at").getValue();
Phase phase = Phase.valueOf(at.getSimpleName().toString());
expected.add(new PhaseDescription(ofName.toString(), phase));
}
if (!expected.isEmpty())
topLevel2Expected.put(elements.getBinaryName(te).toString(), expected);
return super.visitClass(node, p);
}
Collection<AnnotationMirror> getTriggersCompleteAnnotation(TypeElement te) {
for (AnnotationMirror am : te.getAnnotationMirrors()) {
if (triggersCompleteAnnotation.equals(am.getAnnotationType().asElement())) {
return Collections.singletonList(am);
}
if (triggersCompleteRepeatAnnotation.equals(am.getAnnotationType().asElement())) {
return (Collection<AnnotationMirror>) findAttribute(am, "value").getValue();
}
}
return Collections.emptyList();
}
AnnotationValue findAttribute(AnnotationMirror mirror, String name) {
for (Entry<? extends ExecutableElement, ? extends AnnotationValue> e :
mirror.getElementValues().entrySet()) {
if (e.getKey().getSimpleName().contentEquals(name)) {
return e.getValue();
}
}
throw new IllegalStateException("Could not find " + name + " in " + mirror);
}
}
static final class ClearAnnotations extends TreePathScanner<Void, Void> {
final SourcePositions positions;
final List<int[]> spans2Clear = new ArrayList<>();
ClearAnnotations(Trees trees) {
this.positions = trees.getSourcePositions();
}
@Override
public Void visitAnnotation(AnnotationTree node, Void p) {
removeCurrentNode();
return null;
}
@Override
public Void visitImport(ImportTree node, Void p) {
if (node.getQualifiedIdentifier().toString().startsWith("annotations.")) {
removeCurrentNode();
return null;
}
return super.visitImport(node, p);
}
void removeCurrentNode() {
CompilationUnitTree topLevel = getCurrentPath().getCompilationUnit();
Tree node = getCurrentPath().getLeaf();
spans2Clear.add(new int[] {(int) positions.getStartPosition(topLevel, node),
(int) positions.getEndPosition(topLevel, node)});
}
static JavaFileObject clearAnnotations(Trees trees, CompilationUnitTree cut)
throws IOException {
ClearAnnotations a = new ClearAnnotations(trees);
a.scan(cut, null);
Collections.sort(a.spans2Clear, (s1, s2) -> s2[0] - s1[0]);
StringBuilder result = new StringBuilder(cut.getSourceFile().getCharContent(true));
for (int[] toClear : a.spans2Clear) {
result.delete(toClear[0], toClear[1]);
}
return new TestJavaFileObject(cut.getSourceFile().toUri(), result.toString());
}
}
static final class PhaseDescription {
final String flatname;
final Phase phase;
public PhaseDescription(String flatname, Phase phase) {
this.flatname = flatname;
this.phase = phase;
}
@Override
public String toString() {
return "@annotations.TriggersComplete(of=" + flatname + ".class," +
"at=annotations.Phase." + phase + ')';
}
@Override
public int hashCode() {
int hash = 7;
hash = 89 * hash + Objects.hashCode(this.flatname);
hash = 89 * hash + Objects.hashCode(this.phase);
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final PhaseDescription other = (PhaseDescription) obj;
if (!Objects.equals(this.flatname, other.flatname)) {
return false;
}
if (this.phase != other.phase) {
return false;
}
return true;
}
}
static final class TestJavaFileObject extends SimpleJavaFileObject {
private final String content;
public TestJavaFileObject(URI uri, String content) {
super(uri, Kind.SOURCE);
this.content = content;
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
return content;
}
}
}

Some files were not shown because too many files have changed in this diff Show More