Merge
This commit is contained in:
commit
47757481e4
langtools
src/jdk.compiler/share/classes/com/sun/tools
javac
code
comp
file
BaseFileObject.javaCacheFSInfo.javaFSInfo.javaJRTIndex.javaJavacFileManager.javaLocations.javaRegularFileObject.javaRelativePath.javaZipArchive.javaZipFileIndex.javaZipFileIndexArchive.javaZipFileIndexCache.java
jvm
main
nio
parser
resources
tree
util
javah
javap
sjavac
test
lib/annotations/annotations/classfile
tools/javac
4980495/std
NonStatic2StaticImportClash.javaNonStatic2StaticImportClash.outStatic2NonStaticImportClash.javaStatic2NonStaticImportClash.outTest.out
8062359
T6181889
T6725036.javaT8020997
T8059921
TryWithResources
BadTwrSyntax.outResDeclOutsideTry.javaResDeclOutsideTry.outTwrForVariable1.javaTwrForVariable1.outTwrForVariable2.javaTwrForVariable2.outTwrForVariable3.javaTwrForVariable3.outTwrForVariable4.javaTwrForVariable4.out
VersionOpt.javaannotations
SyntheticParameters.java
typeAnnotations
api
diags
file
flow
generics
importChecks
importscope
@ -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;
|
||||
|
6
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java
6
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java
@ -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);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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.
|
||||
|
198
langtools/test/tools/javac/annotations/SyntheticParameters.java
Normal file
198
langtools/test/tools/javac/annotations/SyntheticParameters.java
Normal file
@ -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 { }
|
||||
|
40
langtools/test/tools/javac/diags/examples/TryWithResourcesExprEffectivelyFinalVar.java
Normal file
40
langtools/test/tools/javac/diags/examples/TryWithResourcesExprEffectivelyFinalVar.java
Normal file
@ -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 {
|
||||
}
|
||||
}
|
41
langtools/test/tools/javac/diags/examples/VarInTryWithResourcesNotSupportedInSource.java
Normal file
41
langtools/test/tools/javac/diags/examples/VarInTryWithResourcesNotSupportedInSource.java
Normal file
@ -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);
|
||||
|
24
langtools/test/tools/javac/flow/T8062747.java
Normal file
24
langtools/test/tools/javac/flow/T8062747.java
Normal file
@ -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));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
53
langtools/test/tools/javac/generics/8064803/T8064803.java
Normal file
53
langtools/test/tools/javac/generics/8064803/T8064803.java
Normal file
@ -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 { }
|
||||
}
|
||||
}
|
49
langtools/test/tools/javac/importscope/T7101822A.java
Normal file
49
langtools/test/tools/javac/importscope/T7101822A.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
25
langtools/test/tools/javac/importscope/T7101822Z.java
Normal file
25
langtools/test/tools/javac/importscope/T7101822Z.java
Normal file
@ -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 {}
|
240
langtools/test/tools/javac/importscope/TestDuplicateImport.java
Normal file
240
langtools/test/tools/javac/importscope/TestDuplicateImport.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
224
langtools/test/tools/javac/importscope/TestLazyImportScope.java
Normal file
224
langtools/test/tools/javac/importscope/TestLazyImportScope.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
38
langtools/test/tools/javac/importscope/TypeParamCycle.java
Normal file
38
langtools/test/tools/javac/importscope/TypeParamCycle.java
Normal file
@ -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 {} }
|
||||
}
|
||||
|
41
langtools/test/tools/javac/importscope/TypeParamCycle2.java
Normal file
41
langtools/test/tools/javac/importscope/TypeParamCycle2.java
Normal file
@ -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 {} }
|
||||
}
|
||||
|
42
langtools/test/tools/javac/importscope/TypeParamCycle3.java
Normal file
42
langtools/test/tools/javac/importscope/TypeParamCycle3.java
Normal file
@ -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
Loading…
x
Reference in New Issue
Block a user