提交 ddda364c 编写于 作者: K kizune

Merge

......@@ -236,3 +236,7 @@ af6244ba81b6b8d1bf4ab06587a2067e021e4570 jdk8-b111
954dd199d6ff3e4cfc42b894c1f611150526eecd jdk8-b112
54150586ba785e1eb0c0de8d13906f643f640644 jdk8-b113
850d2602ae9811687b0f404d05ec3e55df91d9cb jdk8-b114
6b4d6205366c1170ebefea95b1b9ae1d69add036 jdk8-b115
3c040b04af05646878798216ebf939d27e6fe687 jdk8-b116
19de039a03a619b99f1a8b454e1618c9fa9dae66 jdk8-b117
4fd6a7ff8c068eceaaaf8bf12a394195203b99b3 jdk8-b118
......@@ -87,16 +87,17 @@ public class Kinds {
/** Kinds for erroneous symbols that complement the above
*/
public static final int ERRONEOUS = 1 << 7;
public static final int AMBIGUOUS = ERRONEOUS+1; // ambiguous reference
public static final int HIDDEN = ERRONEOUS+2; // hidden method or field
public static final int STATICERR = ERRONEOUS+3; // nonstatic member from static context
public static final int MISSING_ENCL = ERRONEOUS+4; // missing enclosing class
public static final int ABSENT_VAR = ERRONEOUS+5; // missing variable
public static final int WRONG_MTHS = ERRONEOUS+6; // methods with wrong arguments
public static final int WRONG_MTH = ERRONEOUS+7; // one method with wrong arguments
public static final int ABSENT_MTH = ERRONEOUS+8; // missing method
public static final int ABSENT_TYP = ERRONEOUS+9; // missing type
public static final int ERRONEOUS = 1 << 7;
public static final int AMBIGUOUS = ERRONEOUS + 1; // ambiguous reference
public static final int HIDDEN = ERRONEOUS + 2; // hidden method or field
public static final int STATICERR = ERRONEOUS + 3; // nonstatic member from static context
public static final int MISSING_ENCL = ERRONEOUS + 4; // missing enclosing class
public static final int ABSENT_VAR = ERRONEOUS + 5; // missing variable
public static final int WRONG_MTHS = ERRONEOUS + 6; // methods with wrong arguments
public static final int WRONG_MTH = ERRONEOUS + 7; // one method with wrong arguments
public static final int ABSENT_MTH = ERRONEOUS + 8; // missing method
public static final int ABSENT_TYP = ERRONEOUS + 9; // missing type
public static final int WRONG_STATICNESS = ERRONEOUS + 10; // wrong staticness for method references
public enum KindName implements Formattable {
ANNOTATION("kindname.annotation"),
......@@ -231,14 +232,14 @@ public class Kinds {
return KindName.CLASS;
}
/** A KindName representing the kind of a a missing symbol, given an
/** A KindName representing the kind of a missing symbol, given an
* error kind.
* */
public static KindName absentKind(int kind) {
switch (kind) {
case ABSENT_VAR:
return KindName.VAR;
case WRONG_MTHS: case WRONG_MTH: case ABSENT_MTH:
case WRONG_MTHS: case WRONG_MTH: case ABSENT_MTH: case WRONG_STATICNESS:
return KindName.METHOD;
case ABSENT_TYP:
return KindName.CLASS;
......
......@@ -244,7 +244,7 @@ public class Types {
public Type visitClassType(ClassType t, Symbol sym) {
if (t.tsym == sym)
return t;
Type base = asSuper(sym.type, t);
Type base = asSuper(sym.type, t.tsym);
if (base == null)
return null;
ListBuffer<Type> from = new ListBuffer<Type>();
......@@ -687,7 +687,7 @@ public class Types {
(t.flags() & SYNTHETIC) == 0;
}
};
private boolean pendingBridges(ClassSymbol origin, TypeSymbol sym) {
private boolean pendingBridges(ClassSymbol origin, TypeSymbol s) {
//a symbol will be completed from a classfile if (a) symbol has
//an associated file object with CLASS kind and (b) the symbol has
//not been entered
......@@ -696,11 +696,11 @@ public class Types {
enter.getEnv(origin) == null) {
return false;
}
if (origin == sym) {
if (origin == s) {
return true;
}
for (Type t : interfaces(origin.type)) {
if (pendingBridges((ClassSymbol)t.tsym, sym)) {
if (pendingBridges((ClassSymbol)t.tsym, s)) {
return true;
}
}
......@@ -761,7 +761,7 @@ public class Types {
} else if (t.hasTag(TYPEVAR)) {
return isSubtypeUnchecked(t.getUpperBound(), s, warn);
} else if (!s.isRaw()) {
Type t2 = asSuper(t, s);
Type t2 = asSuper(t, s.tsym);
if (t2 != null && t2.isRaw()) {
if (isReifiable(s)) {
warn.silentWarn(LintCategory.UNCHECKED);
......@@ -914,7 +914,7 @@ public class Types {
@Override
public Boolean visitClassType(ClassType t, Type s) {
Type sup = asSuper(t, s);
Type sup = asSuper(t, s.tsym);
return sup != null
&& sup.tsym == s.tsym
// You're not allowed to write
......@@ -1935,42 +1935,30 @@ public class Types {
* @param t a type
* @param sym a symbol
*/
public Type asSuper(Type t, Symbol s) {
return asSuper(t, s.type);
}
public Type asSuper(Type t, Type s) {
return asSuper.visit(t, s);
public Type asSuper(Type t, Symbol sym) {
return asSuper.visit(t, sym);
}
// where
private SimpleVisitor<Type,Type> asSuper = new SimpleVisitor<Type,Type>() {
private SimpleVisitor<Type,Symbol> asSuper = new SimpleVisitor<Type,Symbol>() {
public Type visitType(Type t, Type s) {
public Type visitType(Type t, Symbol sym) {
return null;
}
@Override
public Type visitClassType(ClassType t, Type s) {
if (t.tsym == s.tsym)
public Type visitClassType(ClassType t, Symbol sym) {
if (t.tsym == sym)
return t;
Type st = supertype(t);
switch(st.getTag()) {
default: break;
case CLASS:
case ARRAY:
case TYPEVAR:
case ERROR: {
Type x = asSuper(st, s);
if (st.hasTag(CLASS) || st.hasTag(TYPEVAR) || st.hasTag(ERROR)) {
Type x = asSuper(st, sym);
if (x != null)
return x;
} break;
}
if ((s.tsym.flags() & INTERFACE) != 0) {
if ((sym.flags() & INTERFACE) != 0) {
for (List<Type> l = interfaces(t); l.nonEmpty(); l = l.tail) {
Type x = asSuper(l.head, s);
Type x = asSuper(l.head, sym);
if (x != null)
return x;
}
......@@ -1979,20 +1967,22 @@ public class Types {
}
@Override
public Type visitArrayType(ArrayType t, Type s) {
return isSubtype(t, s) ? s : null;
public Type visitArrayType(ArrayType t, Symbol sym) {
return isSubtype(t, sym.type) ? sym.type : null;
}
@Override
public Type visitTypeVar(TypeVar t, Type s) {
if (t.tsym == s.tsym)
public Type visitTypeVar(TypeVar t, Symbol sym) {
if (t.tsym == sym)
return t;
else
return asSuper(t.bound, s);
return asSuper(t.bound, sym);
}
@Override
public Type visitErrorType(ErrorType t, Type s) { return t; }
public Type visitErrorType(ErrorType t, Symbol sym) {
return t;
}
};
/**
......@@ -3573,9 +3563,9 @@ public class Types {
//step 3 - for each element G in MEC, compute lci(Inv(G))
List<Type> candidates = List.nil();
for (Type erasedSupertype : mec) {
List<Type> lci = List.of(asSuper(ts.head, erasedSupertype));
List<Type> lci = List.of(asSuper(ts.head, erasedSupertype.tsym));
for (Type t : ts) {
lci = intersect(lci, List.of(asSuper(t, erasedSupertype)));
lci = intersect(lci, List.of(asSuper(t, erasedSupertype.tsym)));
}
candidates = candidates.appendList(lci);
}
......@@ -3995,7 +3985,7 @@ public class Types {
// The arguments to the supers could be unified here to
// get a more accurate analysis
while (commonSupers.nonEmpty()) {
Type t1 = asSuper(from, commonSupers.head);
Type t1 = asSuper(from, commonSupers.head.tsym);
Type t2 = commonSupers.head; // same as asSuper(to, commonSupers.head.tsym);
if (disjointTypes(t1.getTypeArguments(), t2.getTypeArguments()))
return false;
......@@ -4026,7 +4016,7 @@ public class Types {
from = target;
}
Assert.check((from.tsym.flags() & FINAL) != 0);
Type t1 = asSuper(from, to);
Type t1 = asSuper(from, to.tsym);
if (t1 == null) return false;
Type t2 = to;
if (disjointTypes(t1.getTypeArguments(), t2.getTypeArguments()))
......
......@@ -255,6 +255,9 @@ public class Annotate {
: attr.attribType(a.annotationType, env));
a.type = chk.checkType(a.annotationType.pos(), at, expected);
if (a.type.isErroneous()) {
// Need to make sure nested (anno)trees does not have null as .type
attr.postAttr(a);
if (typeAnnotation) {
return new Attribute.TypeCompound(a.type, List.<Pair<MethodSymbol,Attribute>>nil(),
new TypeAnnotationPosition());
......@@ -265,6 +268,10 @@ public class Annotate {
if ((a.type.tsym.flags() & Flags.ANNOTATION) == 0) {
log.error(a.annotationType.pos(),
"not.annotation.type", a.type.toString());
// Need to make sure nested (anno)trees does not have null as .type
attr.postAttr(a);
if (typeAnnotation) {
return new Attribute.TypeCompound(a.type, List.<Pair<MethodSymbol,Attribute>>nil(), null);
} else {
......@@ -278,7 +285,7 @@ public class Annotate {
Assign(make.Ident(names.value), args.head);
}
ListBuffer<Pair<MethodSymbol,Attribute>> buf =
new ListBuffer<Pair<MethodSymbol,Attribute>>();
new ListBuffer<>();
for (List<JCExpression> tl = args; tl.nonEmpty(); tl = tl.tail) {
JCExpression t = tl.head;
if (!t.hasTag(ASSIGN)) {
......@@ -304,8 +311,7 @@ public class Annotate {
Type result = method.type.getReturnType();
Attribute value = enterAttributeValue(result, assign.rhs, env);
if (!method.type.isErroneous())
buf.append(new Pair<MethodSymbol,Attribute>
((MethodSymbol)method, value));
buf.append(new Pair<>((MethodSymbol)method, value));
t.type = result;
}
if (typeAnnotation) {
......
......@@ -58,7 +58,6 @@ import static com.sun.tools.javac.code.Kinds.*;
import static com.sun.tools.javac.code.Kinds.ERRONEOUS;
import static com.sun.tools.javac.code.TypeTag.*;
import static com.sun.tools.javac.code.TypeTag.WILDCARD;
import static com.sun.tools.javac.code.TypeTag.ARRAY;
import static com.sun.tools.javac.tree.JCTree.Tag.*;
/** This is the main context-dependent analysis phase in GJC. It
......@@ -806,44 +805,33 @@ public class Attr extends JCTree.Visitor {
Type t = tree.type != null ?
tree.type :
attribType(tree, env);
return checkBase(t, tree, env, classExpected, interfaceExpected, false, checkExtensible);
return checkBase(t, tree, env, classExpected, interfaceExpected, checkExtensible);
}
Type checkBase(Type t,
JCTree tree,
Env<AttrContext> env,
boolean classExpected,
boolean interfacesOnlyExpected,
boolean interfacesOrArraysExpected,
boolean interfaceExpected,
boolean checkExtensible) {
if (t.isErroneous())
return t;
if (t.hasTag(TYPEVAR) && !classExpected &&
!interfacesOrArraysExpected && !interfacesOnlyExpected) {
if (t.hasTag(TYPEVAR) && !classExpected && !interfaceExpected) {
// check that type variable is already visible
if (t.getUpperBound() == null) {
log.error(tree.pos(), "illegal.forward.ref");
return types.createErrorType(t);
}
} else if (classExpected) {
t = chk.checkClassType(tree.pos(), t, checkExtensible|!allowGenerics);
} else {
t = chk.checkClassOrArrayType(tree.pos(), t,
checkExtensible|!allowGenerics);
t = chk.checkClassType(tree.pos(), t, checkExtensible|!allowGenerics);
}
if (interfacesOnlyExpected && !t.tsym.isInterface()) {
if (interfaceExpected && (t.tsym.flags() & INTERFACE) == 0) {
log.error(tree.pos(), "intf.expected.here");
// return errType is necessary since otherwise there might
// be undetected cycles which cause attribution to loop
return types.createErrorType(t);
} else if (interfacesOrArraysExpected &&
!(t.tsym.isInterface() || t.getTag() == ARRAY)) {
log.error(tree.pos(), "intf.or.array.expected.here");
// return errType is necessary since otherwise there might
// be undetected cycles which cause attribution to loop
return types.createErrorType(t);
} else if (checkExtensible &&
classExpected &&
t.tsym.isInterface()) {
(t.tsym.flags() & INTERFACE) != 0) {
log.error(tree.pos(), "no.intf.expected.here");
return types.createErrorType(t);
}
......@@ -855,12 +843,6 @@ public class Attr extends JCTree.Visitor {
chk.checkNonCyclic(tree.pos(), t);
return t;
}
//where
private Object asTypeParam(Type t) {
return (t.hasTag(TYPEVAR))
? diags.fragment("type.parameter", t)
: t;
}
Type attribIdentAsEnumType(Env<AttrContext> env, JCIdent id) {
Assert.check((env.enclClass.sym.flags() & ENUM) != 0);
......@@ -2254,7 +2236,8 @@ public class Attr extends JCTree.Visitor {
// empty annotations, if only declaration annotations were given.
// This method will raise an error for such a type.
for (JCAnnotation ai : annotations) {
if (typeAnnotations.annotationType(ai.attribute, sym) == TypeAnnotations.AnnotationType.DECLARATION) {
if (!ai.type.isErroneous() &&
typeAnnotations.annotationType(ai.attribute, sym) == TypeAnnotations.AnnotationType.DECLARATION) {
log.error(ai.pos(), "annotation.type.not.applicable");
}
}
......@@ -2714,9 +2697,10 @@ public class Attr extends JCTree.Visitor {
Pair<Symbol, Resolve.ReferenceLookupHelper> refResult = null;
List<Type> saved_undet = resultInfo.checkContext.inferenceContext().save();
try {
refResult = rs.resolveMemberReference(that.pos(), localEnv, that, that.expr.type,
that.name, argtypes, typeargtypes, true, referenceCheck,
resultInfo.checkContext.inferenceContext());
refResult = rs.resolveMemberReference(localEnv, that, that.expr.type,
that.name, argtypes, typeargtypes, referenceCheck,
resultInfo.checkContext.inferenceContext(),
resultInfo.checkContext.deferredAttrContext().mode);
} finally {
resultInfo.checkContext.inferenceContext().rollback(saved_undet);
}
......@@ -2736,6 +2720,7 @@ public class Attr extends JCTree.Visitor {
case HIDDEN:
case STATICERR:
case MISSING_ENCL:
case WRONG_STATICNESS:
targetError = true;
break;
default:
......@@ -2787,26 +2772,6 @@ public class Attr extends JCTree.Visitor {
chk.checkRaw(that.expr, localEnv);
}
if (!that.kind.isUnbound() &&
that.getMode() == ReferenceMode.INVOKE &&
TreeInfo.isStaticSelector(that.expr, names) &&
!that.sym.isStatic()) {
log.error(that.expr.pos(), "invalid.mref", Kinds.kindName(that.getMode()),
diags.fragment("non-static.cant.be.ref", Kinds.kindName(refSym), refSym));
result = that.type = types.createErrorType(target);
return;
}
if (that.kind.isUnbound() &&
that.getMode() == ReferenceMode.INVOKE &&
TreeInfo.isStaticSelector(that.expr, names) &&
that.sym.isStatic()) {
log.error(that.expr.pos(), "invalid.mref", Kinds.kindName(that.getMode()),
diags.fragment("static.method.in.unbound.lookup", Kinds.kindName(refSym), refSym));
result = that.type = types.createErrorType(target);
return;
}
if (that.sym.isStatic() && TreeInfo.isStaticSelector(that.expr, names) &&
exprType.getTypeArguments().nonEmpty()) {
//static ref with class type-args
......@@ -3984,7 +3949,7 @@ public class Attr extends JCTree.Visitor {
Set<Type> boundSet = new HashSet<Type>();
if (bounds.nonEmpty()) {
// accept class or interface or typevar as first bound.
bounds.head.type = checkBase(bounds.head.type, bounds.head, env, false, false, false, false);
bounds.head.type = checkBase(bounds.head.type, bounds.head, env, false, false, false);
boundSet.add(types.erasure(bounds.head.type));
if (bounds.head.type.isErroneous()) {
return bounds.head.type;
......@@ -4000,7 +3965,7 @@ public class Attr extends JCTree.Visitor {
// if first bound was a class or interface, accept only interfaces
// as further bounds.
for (JCExpression bound : bounds.tail) {
bound.type = checkBase(bound.type, bound, env, false, false, true, false);
bound.type = checkBase(bound.type, bound, env, false, true, false);
if (bound.type.isErroneous()) {
bounds = List.of(bound);
}
......@@ -4619,9 +4584,8 @@ public class Attr extends JCTree.Visitor {
validateAnnotatedType(t, t.type);
}
repeat = false;
} else if (enclTr.getKind() == JCTree.Kind.PRIMITIVE_TYPE) {
// This happens in test TargetTypeTest52.java
// Is there anything to do?
} else if (enclTr.getKind() == JCTree.Kind.PRIMITIVE_TYPE ||
enclTr.getKind() == JCTree.Kind.ERRONEOUS) {
repeat = false;
} else {
Assert.error("Unexpected tree: " + enclTr + " with kind: " + enclTr.getKind() +
......
......@@ -707,37 +707,6 @@ public class Check {
return t;
}
// Analog of checkClassType that calls checkClassOrArrayType instead
Type checkClassOrArrayType(DiagnosticPosition pos,
Type t, boolean noBounds) {
t = checkClassOrArrayType(pos, t);
if (noBounds && t.isParameterized()) {
List<Type> args = t.getTypeArguments();
while (args.nonEmpty()) {
if (args.head.hasTag(WILDCARD))
return typeTagError(pos,
diags.fragment("type.req.exact"),
args.head);
args = args.tail;
}
}
return t;
}
/** Check that type is a reifiable class, interface or array type.
* @param pos Position to be used for error reporting.
* @param t The type to be checked.
*/
Type checkReifiableReferenceType(DiagnosticPosition pos, Type t) {
t = checkClassOrArrayType(pos, t);
if (!t.isErroneous() && !types.isReifiable(t)) {
log.error(pos, "illegal.generic.type.for.instof");
return types.createErrorType(t);
} else {
return t;
}
}
/** Check that type is a reference type, i.e. a class, interface or array type
* or a type variable.
* @param pos Position to be used for error reporting.
......@@ -2253,9 +2222,6 @@ public class Check {
seen = seen.prepend(tv);
for (Type b : types.getBounds(tv))
checkNonCyclic1(pos, b, seen);
} else if (t.hasTag(ARRAY)) {
final ArrayType at = (ArrayType)t.unannotatedType();
checkNonCyclic1(pos, at.elemtype, seen);
}
}
......
......@@ -643,15 +643,16 @@ public class DeferredAttr extends JCTree.Visitor {
}
JCMemberReference mref2 = new TreeCopier<Void>(make).copy(tree);
mref2.expr = exprTree;
Pair<Symbol, ?> lookupRes =
rs.resolveMemberReference(tree, localEnv, mref2, exprTree.type,
tree.name, argtypes.toList(), null, true, rs.arityMethodCheck, inferenceContext);
switch (lookupRes.fst.kind) {
Symbol lookupSym =
rs.resolveMemberReferenceByArity(localEnv, mref2, exprTree.type,
tree.name, argtypes.toList(), inferenceContext);
switch (lookupSym.kind) {
//note: as argtypes are erroneous types, type-errors must
//have been caused by arity mismatch
case Kinds.ABSENT_MTH:
case Kinds.WRONG_MTH:
case Kinds.WRONG_MTHS:
case Kinds.WRONG_STATICNESS:
checkContext.report(tree, diags.fragment("incompatible.arg.types.in.mref"));
}
}
......@@ -1037,11 +1038,10 @@ public class DeferredAttr extends JCTree.Visitor {
attr.memberReferenceQualifierResult(tree));
JCMemberReference mref2 = new TreeCopier<Void>(make).copy(tree);
mref2.expr = exprTree;
Pair<Symbol, ReferenceLookupHelper> lookupRes =
rs.resolveMemberReference(tree, localEnv, mref2, exprTree.type,
tree.name, List.<Type>nil(), null, true, rs.nilMethodCheck,
infer.emptyContext);
Symbol res = tree.sym = lookupRes.fst;
Symbol res =
rs.getMemberReference(tree, localEnv, mref2,
exprTree.type, tree.name);
tree.sym = res;
if (res.kind >= Kinds.ERRONEOUS ||
res.type.hasTag(FORALL) ||
(res.flags() & Flags.VARARGS) != 0 ||
......
......@@ -1378,7 +1378,11 @@ public class Lower extends TreeTranslator {
ref = make.Ident(sym);
args = make.Idents(md.params);
} else {
ref = make.Select(make.Ident(md.params.head), sym);
Symbol msym = sym;
if (sym.owner.isInterface()) {
msym = msym.clone(types.supertype(accessor.owner.type).tsym);
}
ref = make.Select(make.Ident(md.params.head), msym);
args = make.Idents(md.params.tail);
}
JCStatement stat; // The statement accessing the private symbol.
......
......@@ -25,6 +25,7 @@
package com.sun.tools.javac.comp;
import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
import com.sun.tools.javac.api.Formattable.LocalizedString;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Symbol.*;
......@@ -110,6 +111,9 @@ public class Resolve {
SymbolNotFoundError(ABSENT_VAR);
methodNotFound = new
SymbolNotFoundError(ABSENT_MTH);
methodWithCorrectStaticnessNotFound = new
SymbolNotFoundError(WRONG_STATICNESS,
"method found has incorrect staticness");
typeNotFound = new
SymbolNotFoundError(ABSENT_TYP);
......@@ -144,6 +148,7 @@ public class Resolve {
*/
private final SymbolNotFoundError varNotFound;
private final SymbolNotFoundError methodNotFound;
private final SymbolNotFoundError methodWithCorrectStaticnessNotFound;
private final SymbolNotFoundError typeNotFound;
public static Resolve instance(Context context) {
......@@ -868,6 +873,12 @@ public class Resolve {
}
};
/**
* This class handles method reference applicability checks; since during
* these checks it's sometime possible to have inference variables on
* the actual argument types list, the method applicability check must be
* extended so that inference variables are 'opened' as needed.
*/
class MethodReferenceCheck extends AbstractMethodCheck {
InferenceContext pendingInferenceContext;
......@@ -2674,6 +2685,97 @@ public class Resolve {
return resolveOperator(pos, optag, env, List.of(left, right));
}
Symbol getMemberReference(DiagnosticPosition pos,
Env<AttrContext> env,
JCMemberReference referenceTree,
Type site,
Name name) {
site = types.capture(site);
ReferenceLookupHelper lookupHelper = makeReferenceLookupHelper(
referenceTree, site, name, List.<Type>nil(), null, VARARITY);
Env<AttrContext> newEnv = env.dup(env.tree, env.info.dup());
Symbol sym = lookupMethod(newEnv, env.tree.pos(), site.tsym,
nilMethodCheck, lookupHelper);
env.info.pendingResolutionPhase = newEnv.info.pendingResolutionPhase;
return sym;
}
ReferenceLookupHelper makeReferenceLookupHelper(JCMemberReference referenceTree,
Type site,
Name name,
List<Type> argtypes,
List<Type> typeargtypes,
MethodResolutionPhase maxPhase) {
ReferenceLookupHelper result;
if (!name.equals(names.init)) {
//method reference
result =
new MethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase);
} else {
if (site.hasTag(ARRAY)) {
//array constructor reference
result =
new ArrayConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase);
} else {
//class constructor reference
result =
new ConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase);
}
}
return result;
}
Symbol resolveMemberReferenceByArity(Env<AttrContext> env,
JCMemberReference referenceTree,
Type site,
Name name,
List<Type> argtypes,
InferenceContext inferenceContext) {
boolean isStaticSelector = TreeInfo.isStaticSelector(referenceTree.expr, names);
site = types.capture(site);
ReferenceLookupHelper boundLookupHelper = makeReferenceLookupHelper(
referenceTree, site, name, argtypes, null, VARARITY);
//step 1 - bound lookup
Env<AttrContext> boundEnv = env.dup(env.tree, env.info.dup());
Symbol boundSym = lookupMethod(boundEnv, env.tree.pos(), site.tsym,
arityMethodCheck, boundLookupHelper);
if (isStaticSelector &&
!name.equals(names.init) &&
!boundSym.isStatic() &&
boundSym.kind < ERRONEOUS) {
boundSym = methodNotFound;
}
//step 2 - unbound lookup
Symbol unboundSym = methodNotFound;
ReferenceLookupHelper unboundLookupHelper = null;
Env<AttrContext> unboundEnv = env.dup(env.tree, env.info.dup());
if (isStaticSelector) {
unboundLookupHelper = boundLookupHelper.unboundLookup(inferenceContext);
unboundSym = lookupMethod(unboundEnv, env.tree.pos(), site.tsym,
arityMethodCheck, unboundLookupHelper);
if (unboundSym.isStatic() &&
unboundSym.kind < ERRONEOUS) {
unboundSym = methodNotFound;
}
}
//merge results
Symbol bestSym = choose(boundSym, unboundSym);
env.info.pendingResolutionPhase = bestSym == unboundSym ?
unboundEnv.info.pendingResolutionPhase :
boundEnv.info.pendingResolutionPhase;
return bestSym;
}
/**
* Resolution of member references is typically done as a single
* overload resolution step, where the argument types A are inferred from
......@@ -2700,47 +2802,118 @@ public class Resolve {
* the type T might be dynamically inferred (i.e. if constructor reference
* has a raw qualifier).
*/
Pair<Symbol, ReferenceLookupHelper> resolveMemberReference(DiagnosticPosition pos,
Env<AttrContext> env,
Pair<Symbol, ReferenceLookupHelper> resolveMemberReference(Env<AttrContext> env,
JCMemberReference referenceTree,
Type site,
Name name, List<Type> argtypes,
Name name,
List<Type> argtypes,
List<Type> typeargtypes,
boolean boxingAllowed,
MethodCheck methodCheck,
InferenceContext inferenceContext) {
MethodResolutionPhase maxPhase = boxingAllowed ? VARARITY : BASIC;
InferenceContext inferenceContext,
AttrMode mode) {
site = types.capture(site);
ReferenceLookupHelper boundLookupHelper;
if (!name.equals(names.init)) {
//method reference
boundLookupHelper =
new MethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase);
} else if (site.hasTag(ARRAY)) {
//array constructor reference
boundLookupHelper =
new ArrayConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase);
} else {
//class constructor reference
boundLookupHelper =
new ConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase);
}
ReferenceLookupHelper boundLookupHelper = makeReferenceLookupHelper(
referenceTree, site, name, argtypes, typeargtypes, VARARITY);
//step 1 - bound lookup
Env<AttrContext> boundEnv = env.dup(env.tree, env.info.dup());
Symbol boundSym = lookupMethod(boundEnv, env.tree.pos(), site.tsym, methodCheck, boundLookupHelper);
Symbol origBoundSym;
boolean staticErrorForBound = false;
MethodResolutionContext boundSearchResolveContext = new MethodResolutionContext();
boundSearchResolveContext.methodCheck = methodCheck;
Symbol boundSym = origBoundSym = lookupMethod(boundEnv, env.tree.pos(),
site.tsym, boundSearchResolveContext, boundLookupHelper);
SearchResultKind boundSearchResultKind = SearchResultKind.NOT_APPLICABLE_MATCH;
boolean isStaticSelector = TreeInfo.isStaticSelector(referenceTree.expr, names);
boolean shouldCheckForStaticness = isStaticSelector &&
referenceTree.getMode() == ReferenceMode.INVOKE;
if (boundSym.kind != WRONG_MTHS && boundSym.kind != WRONG_MTH) {
if (shouldCheckForStaticness) {
if (!boundSym.isStatic()) {
staticErrorForBound = true;
if (hasAnotherApplicableMethod(
boundSearchResolveContext, boundSym, true)) {
boundSearchResultKind = SearchResultKind.BAD_MATCH_MORE_SPECIFIC;
} else {
boundSearchResultKind = SearchResultKind.BAD_MATCH;
if (boundSym.kind < ERRONEOUS) {
boundSym = methodWithCorrectStaticnessNotFound;
}
}
} else if (boundSym.kind < ERRONEOUS) {
boundSearchResultKind = SearchResultKind.GOOD_MATCH;
}
}
}
//step 2 - unbound lookup
ReferenceLookupHelper unboundLookupHelper = boundLookupHelper.unboundLookup(inferenceContext);
Symbol origUnboundSym = null;
Symbol unboundSym = methodNotFound;
ReferenceLookupHelper unboundLookupHelper = null;
Env<AttrContext> unboundEnv = env.dup(env.tree, env.info.dup());
Symbol unboundSym = lookupMethod(unboundEnv, env.tree.pos(), site.tsym, methodCheck, unboundLookupHelper);
SearchResultKind unboundSearchResultKind = SearchResultKind.NOT_APPLICABLE_MATCH;
boolean staticErrorForUnbound = false;
if (isStaticSelector) {
unboundLookupHelper = boundLookupHelper.unboundLookup(inferenceContext);
MethodResolutionContext unboundSearchResolveContext =
new MethodResolutionContext();
unboundSearchResolveContext.methodCheck = methodCheck;
unboundSym = origUnboundSym = lookupMethod(unboundEnv, env.tree.pos(),
site.tsym, unboundSearchResolveContext, unboundLookupHelper);
if (unboundSym.kind != WRONG_MTH && unboundSym.kind != WRONG_MTHS) {
if (shouldCheckForStaticness) {
if (unboundSym.isStatic()) {
staticErrorForUnbound = true;
if (hasAnotherApplicableMethod(
unboundSearchResolveContext, unboundSym, false)) {
unboundSearchResultKind = SearchResultKind.BAD_MATCH_MORE_SPECIFIC;
} else {
unboundSearchResultKind = SearchResultKind.BAD_MATCH;
if (unboundSym.kind < ERRONEOUS) {
unboundSym = methodWithCorrectStaticnessNotFound;
}
}
} else if (unboundSym.kind < ERRONEOUS) {
unboundSearchResultKind = SearchResultKind.GOOD_MATCH;
}
}
}
}
//merge results
Pair<Symbol, ReferenceLookupHelper> res;
Symbol bestSym = choose(boundSym, unboundSym);
res = new Pair<Symbol, ReferenceLookupHelper>(bestSym,
if (bestSym.kind < ERRONEOUS && (staticErrorForBound || staticErrorForUnbound)) {
if (staticErrorForBound) {
boundSym = methodWithCorrectStaticnessNotFound;
}
if (staticErrorForUnbound) {
unboundSym = methodWithCorrectStaticnessNotFound;
}
bestSym = choose(boundSym, unboundSym);
}
if (bestSym == methodWithCorrectStaticnessNotFound && mode == AttrMode.CHECK) {
Symbol symToPrint = origBoundSym;
String errorFragmentToPrint = "non-static.cant.be.ref";
if (staticErrorForBound && staticErrorForUnbound) {
if (unboundSearchResultKind == SearchResultKind.BAD_MATCH_MORE_SPECIFIC) {
symToPrint = origUnboundSym;
errorFragmentToPrint = "static.method.in.unbound.lookup";
}
} else {
if (!staticErrorForBound) {
symToPrint = origUnboundSym;
errorFragmentToPrint = "static.method.in.unbound.lookup";
}
}
log.error(referenceTree.expr.pos(), "invalid.mref",
Kinds.kindName(referenceTree.getMode()),
diags.fragment(errorFragmentToPrint,
Kinds.kindName(symToPrint), symToPrint));
}
res = new Pair<>(bestSym,
bestSym == unboundSym ? unboundLookupHelper : boundLookupHelper);
env.info.pendingResolutionPhase = bestSym == unboundSym ?
unboundEnv.info.pendingResolutionPhase :
......@@ -2748,18 +2921,42 @@ public class Resolve {
return res;
}
enum SearchResultKind {
GOOD_MATCH, //type I
BAD_MATCH_MORE_SPECIFIC, //type II
BAD_MATCH, //type III
NOT_APPLICABLE_MATCH //type IV
}
boolean hasAnotherApplicableMethod(MethodResolutionContext resolutionContext,
Symbol bestSoFar, boolean staticMth) {
for (Candidate c : resolutionContext.candidates) {
if (resolutionContext.step != c.step ||
!c.isApplicable() ||
c.sym == bestSoFar) {
continue;
} else {
if (c.sym.isStatic() == staticMth) {
return true;
}
}
}
return false;
}
//where
private Symbol choose(Symbol s1, Symbol s2) {
if (lookupSuccess(s1) && lookupSuccess(s2)) {
return ambiguityError(s1, s2);
} else if (lookupSuccess(s1) ||
(canIgnore(s2) && !canIgnore(s1))) {
return s1;
} else if (lookupSuccess(s2) ||
(canIgnore(s1) && !canIgnore(s2))) {
return s2;
private Symbol choose(Symbol boundSym, Symbol unboundSym) {
if (lookupSuccess(boundSym) && lookupSuccess(unboundSym)) {
return ambiguityError(boundSym, unboundSym);
} else if (lookupSuccess(boundSym) ||
(canIgnore(unboundSym) && !canIgnore(boundSym))) {
return boundSym;
} else if (lookupSuccess(unboundSym) ||
(canIgnore(boundSym) && !canIgnore(unboundSym))) {
return unboundSym;
} else {
return s1;
return boundSym;
}
}
......@@ -2780,6 +2977,8 @@ public class Resolve {
InapplicableSymbolsError errSyms =
(InapplicableSymbolsError)s;
return errSyms.filterCandidates(errSyms.mapCandidates()).isEmpty();
case WRONG_STATICNESS:
return false;
default:
return false;
}
......@@ -2894,7 +3093,6 @@ public class Resolve {
List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) {
super(name, site, argtypes, typeargtypes, maxPhase);
this.referenceTree = referenceTree;
}
/**
......@@ -3324,6 +3522,11 @@ public class Resolve {
return false;
}
@Override
public boolean isStatic() {
return false;
}
/**
* Create an external representation for this erroneous symbol to be
* used during attribution - by default this returns the symbol of a
......@@ -3398,7 +3601,11 @@ public class Resolve {
class SymbolNotFoundError extends ResolveError {
SymbolNotFoundError(int kind) {
super(kind, "symbol not found error");
this(kind, "symbol not found error");
}
SymbolNotFoundError(int kind, String debugName) {
super(kind, debugName);
}
@Override
......@@ -3436,7 +3643,8 @@ public class Resolve {
hasLocation = !location.name.equals(names._this) &&
!location.name.equals(names._super);
}
boolean isConstructor = kind == ABSENT_MTH && name == names.init;
boolean isConstructor = (kind == ABSENT_MTH || kind == WRONG_STATICNESS) &&
name == names.init;
KindName kindname = isConstructor ? KindName.CONSTRUCTOR : absentKind(kind);
Name idname = isConstructor ? site.tsym.name : name;
String errKey = getErrorKey(kindname, typeargtypes.nonEmpty(), hasLocation);
......
......@@ -483,17 +483,8 @@ public class Code {
/** Emit an invokedynamic instruction.
*/
public void emitInvokedynamic(int desc, Type mtype) {
// N.B. this format is under consideration by the JSR 292 EG
int argsize = width(mtype.getParameterTypes());
int prevPos = pendingStatPos;
try {
//disable line number generation (we could have used 'emit1', that
//bypasses stackmap generation - which is needed for indy calls)
pendingStatPos = Position.NOPOS;
emitop(invokedynamic);
} finally {
pendingStatPos = prevPos;
}
emitop(invokedynamic);
if (!alive) return;
emit2(desc);
emit2(0);
......@@ -1790,8 +1781,9 @@ public class Code {
void markInitialized(UninitializedType old) {
Type newtype = old.initializedType();
for (int i=0; i<stacksize; i++)
for (int i=0; i<stacksize; i++) {
if (stack[i] == old) stack[i] = newtype;
}
for (int i=0; i<lvar.length; i++) {
LocalVar lv = lvar[i];
if (lv != null && lv.sym.type == old) {
......@@ -2112,7 +2104,6 @@ public class Code {
private void endScope(int adr) {
LocalVar v = lvar[adr];
if (v != null) {
lvar[adr] = null;
if (v.isLastRangeInitialized()) {
char length = (char)(curCP() - v.lastRange().start_pc);
if (length < Character.MAX_VALUE) {
......@@ -2121,6 +2112,12 @@ public class Code {
fillLocalVarPosition(v);
}
}
/** the call to curCP() can implicitly adjust the current cp, if so
* the alive range of local variables may be modified. Thus we need
* all of them. For this reason assigning null to the given address
* should be the last action to do.
*/
lvar[adr] = null;
}
state.defined.excl(adr);
}
......
......@@ -575,9 +575,6 @@ compiler.err.intf.annotation.member.clash=\
compiler.err.intf.expected.here=\
interface expected here
compiler.err.intf.or.array.expected.here=\
interface or array type expected here
compiler.err.intf.meth.cant.have.body=\
interface abstract methods cannot have body
......
......@@ -73,15 +73,11 @@ public class ConstructorDocImpl
/**
* Get the name.
*
* @return the name of the member qualified by class (but not package)
* @return the name of the member.
*/
public String name() {
ClassSymbol c = sym.enclClass();
String n = c.name.toString();
for (c = c.owner.enclClass(); c != null; c = c.owner.enclClass()) {
n = c.name.toString() + "." + n;
}
return n;
return c.name.toString();
}
/**
......
......@@ -26,9 +26,11 @@ package com.sun.tools.jdeps;
import com.sun.tools.classfile.Dependency.Location;
import com.sun.tools.jdeps.PlatformClassPath.JDKArchive;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
......@@ -52,7 +54,7 @@ public class Analyzer {
private final Type type;
private final Map<Archive, ArchiveDeps> results = new HashMap<>();
private final Map<String, Archive> map = new HashMap<>();
private final Map<Location, Archive> map = new HashMap<>();
private final Archive NOT_FOUND
= new Archive(JdepsTask.getMessage("artifact.not.found"));
......@@ -69,6 +71,17 @@ public class Analyzer {
* Performs the dependency analysis on the given archives.
*/
public void run(List<Archive> archives) {
// build a map from Location to Archive
for (Archive archive: archives) {
for (Location l: archive.getClasses()) {
if (!map.containsKey(l)) {
map.put(l, archive);
} else {
// duplicated class warning?
}
}
}
// traverse and analyze all dependencies
for (Archive archive : archives) {
ArchiveDeps deps;
if (type == Type.CLASS || type == Type.VERBOSE) {
......@@ -76,33 +89,9 @@ public class Analyzer {
} else {
deps = new PackageVisitor(archive);
}
archive.visit(deps);
archive.visitDependences(deps);
results.put(archive, deps);
}
// set the required dependencies
for (ArchiveDeps result: results.values()) {
for (Set<String> set : result.deps.values()) {
for (String target : set) {
Archive source = getArchive(target);
if (result.archive != source) {
String profile = "";
if (source instanceof JDKArchive) {
profile = result.profile != null ? result.profile.toString() : "";
if (result.getTargetProfile(target) == null) {
profile += ", JDK internal API";
// override the value if it accesses any JDK internal
result.requireArchives.put(source, profile);
continue;
}
}
if (!result.requireArchives.containsKey(source)) {
result.requireArchives.put(source, profile);
}
}
}
}
}
}
public boolean hasDependences(Archive archive) {
......@@ -117,94 +106,143 @@ public class Analyzer {
* Visits the source archive to its destination archive of
* a recorded dependency.
*/
void visitArchiveDependence(Archive origin, Archive target, String profile);
void visitArchiveDependence(Archive origin, Archive target, Profile profile);
/**
* Visits a recorded dependency from origin to target which can be
* a fully-qualified classname, a package name, a profile or
* archive name depending on the Analyzer's type.
*/
void visitDependence(String origin, Archive source, String target, Archive archive, String profile);
void visitDependence(String origin, Archive source, String target, Archive archive, Profile profile);
}
public void visitArchiveDependences(Archive source, Visitor v) {
ArchiveDeps r = results.get(source);
for (Map.Entry<Archive,String> e : r.requireArchives.entrySet()) {
v.visitArchiveDependence(r.archive, e.getKey(), e.getValue());
for (ArchiveDeps.Dep d: r.requireArchives()) {
v.visitArchiveDependence(r.archive, d.archive, d.profile);
}
}
public void visitDependences(Archive source, Visitor v) {
ArchiveDeps r = results.get(source);
for (String origin : r.deps.keySet()) {
for (String target : r.deps.get(origin)) {
Archive archive = getArchive(target);
assert source == getArchive(origin);
Profile profile = r.getTargetProfile(target);
for (Map.Entry<String, SortedSet<ArchiveDeps.Dep>> e: r.deps.entrySet()) {
String origin = e.getKey();
for (ArchiveDeps.Dep d: e.getValue()) {
// filter intra-dependency unless in verbose mode
if (type == Type.VERBOSE || archive != source) {
v.visitDependence(origin, source, target, archive,
profile != null ? profile.toString() : "");
if (type == Type.VERBOSE || d.archive != source) {
v.visitDependence(origin, source, d.target, d.archive, d.profile);
}
}
}
}
public Archive getArchive(String name) {
return map.containsKey(name) ? map.get(name) : NOT_FOUND;
}
/**
* ArchiveDeps contains the dependencies for an Archive that
* can have one or more classes.
*/
private abstract class ArchiveDeps implements Archive.Visitor {
final Archive archive;
final Map<Archive,String> requireArchives;
final SortedMap<String, SortedSet<String>> deps;
Profile profile = null;
final SortedMap<String, SortedSet<Dep>> deps;
ArchiveDeps(Archive archive) {
this.archive = archive;
this.requireArchives = new HashMap<>();
this.deps = new TreeMap<>();
}
void add(String loc) {
Archive a = map.get(loc);
if (a == null) {
map.put(loc, archive);
} else if (a != archive) {
// duplicated class warning?
void add(String origin, String target, Archive targetArchive, String pkgName) {
SortedSet<Dep> set = deps.get(origin);
if (set == null) {
deps.put(origin, set = new TreeSet<>());
}
Profile p = targetArchive instanceof JDKArchive
? Profile.getProfile(pkgName) : null;
set.add(new Dep(target, targetArchive, p));
}
void add(String origin, String target) {
SortedSet<String> set = deps.get(origin);
if (set == null) {
deps.put(origin, set = new TreeSet<>());
/**
* Returns the list of Archive dependences. The returned
* list contains one {@code Dep} instance per one archive
* and with the minimum profile this archive depends on.
*/
List<Dep> requireArchives() {
Map<Archive,Profile> map = new HashMap<>();
for (Set<Dep> set: deps.values()) {
for (Dep d: set) {
if (this.archive != d.archive) {
Profile p = map.get(d.archive);
if (p == null || (d.profile != null && p.profile < d.profile.profile)) {
map.put(d.archive, d.profile);
}
}
}
}
List<Dep> list = new ArrayList<>();
for (Map.Entry<Archive,Profile> e: map.entrySet()) {
list.add(new Dep("", e.getKey(), e.getValue()));
}
return list;
}
/**
* Dep represents a dependence where the target can be
* a classname or packagename and the archive and profile
* the target belongs to.
*/
class Dep implements Comparable<Dep> {
final String target;
final Archive archive;
final Profile profile;
Dep(String target, Archive archive, Profile p) {
this.target = target;
this.archive = archive;
this.profile = p;
}
@Override
public boolean equals(Object o) {
if (o instanceof Dep) {
Dep d = (Dep)o;
return this.archive == d.archive && this.target.equals(d.target);
}
return false;
}
@Override
public int hashCode() {
int hash = 3;
hash = 17 * hash + Objects.hashCode(this.archive);
hash = 17 * hash + Objects.hashCode(this.target);
return hash;
}
if (!set.contains(target)) {
set.add(target);
// find the corresponding profile
Profile p = getTargetProfile(target);
if (profile == null || (p != null && profile.profile < p.profile)) {
profile = p;
@Override
public int compareTo(Dep o) {
if (this.target.equals(o.target)) {
if (this.archive == o.archive) {
return 0;
} else {
return this.archive.getFileName().compareTo(o.archive.getFileName());
}
}
return this.target.compareTo(o.target);
}
}
public abstract void visit(Location o, Location t);
public abstract Profile getTargetProfile(String target);
}
private class ClassVisitor extends ArchiveDeps {
ClassVisitor(Archive archive) {
super(archive);
}
public void visit(Location l) {
add(l.getClassName());
}
@Override
public void visit(Location o, Location t) {
add(o.getClassName(), t.getClassName());
}
public Profile getTargetProfile(String target) {
int i = target.lastIndexOf('.');
return (i > 0) ? Profile.getProfile(target.substring(0, i)) : null;
Archive targetArchive =
this.archive.getClasses().contains(t) ? this.archive : map.get(t);
if (targetArchive == null) {
map.put(t, targetArchive = NOT_FOUND);
}
String origin = o.getClassName();
String target = t.getClassName();
add(origin, target, targetArchive, t.getPackageName());
}
}
......@@ -212,18 +250,21 @@ public class Analyzer {
PackageVisitor(Archive archive) {
super(archive);
}
@Override
public void visit(Location o, Location t) {
add(packageOf(o), packageOf(t));
}
public void visit(Location l) {
add(packageOf(l));
Archive targetArchive =
this.archive.getClasses().contains(t) ? this.archive : map.get(t);
if (targetArchive == null) {
map.put(t, targetArchive = NOT_FOUND);
}
String origin = packageOf(o);
String target = packageOf(t);
add(origin, target, targetArchive, t.getPackageName());
}
private String packageOf(Location loc) {
String pkg = loc.getPackageName();
public String packageOf(Location o) {
String pkg = o.getPackageName();
return pkg.isEmpty() ? "<unnamed>" : pkg;
}
public Profile getTargetProfile(String target) {
return Profile.getProfile(target);
}
}
}
......@@ -67,6 +67,7 @@ public class Archive {
deps.put(origin, set);
}
}
public void addClass(Location origin, Location target) {
Set<Location> set = deps.get(origin);
if (set == null) {
......@@ -76,21 +77,27 @@ public class Archive {
set.add(target);
}
public void visit(Visitor v) {
public Set<Location> getClasses() {
return deps.keySet();
}
public void visitDependences(Visitor v) {
for (Map.Entry<Location,Set<Location>> e: deps.entrySet()) {
v.visit(e.getKey());
for (Location target : e.getValue()) {
v.visit(e.getKey(), target);
}
}
}
public String toString() {
public String getPathName() {
return path != null ? path.toString() : filename;
}
public String toString() {
return filename;
}
interface Visitor {
void visit(Location loc);
void visit(Location origin, Location target);
}
}
......@@ -190,6 +190,11 @@ class JdepsTask {
task.options.fullVersion = true;
}
},
new HiddenOption(false, "-showlabel") {
void process(JdepsTask task, String opt, String arg) {
task.options.showLabel = true;
}
},
new HiddenOption(true, "-depth") {
void process(JdepsTask task, String opt, String arg) throws BadArgs {
try {
......@@ -279,12 +284,21 @@ class JdepsTask {
private void generateDotFiles(Path dir, Analyzer analyzer) throws IOException {
Path summary = dir.resolve("summary.dot");
try (PrintWriter sw = new PrintWriter(Files.newOutputStream(summary));
DotFileFormatter formatter = new DotFileFormatter(sw, "summary")) {
for (Archive archive : sourceLocations) {
analyzer.visitArchiveDependences(archive, formatter);
boolean verbose = options.verbose == Analyzer.Type.VERBOSE;
DotGraph<?> graph = verbose ? new DotSummaryForPackage()
: new DotSummaryForArchive();
for (Archive archive : sourceLocations) {
analyzer.visitArchiveDependences(archive, graph);
if (verbose || options.showLabel) {
// traverse detailed dependences to generate package-level
// summary or build labels for edges
analyzer.visitDependences(archive, graph);
}
}
try (PrintWriter sw = new PrintWriter(Files.newOutputStream(summary))) {
graph.writeTo(sw);
}
// output individual .dot file for each archive
if (options.verbose != Analyzer.Type.SUMMARY) {
for (Archive archive : sourceLocations) {
if (analyzer.hasDependences(archive)) {
......@@ -365,17 +379,16 @@ class JdepsTask {
}
}
}
sourceLocations.addAll(archives);
List<Archive> classpaths = new ArrayList<>(); // for class file lookup
classpaths.addAll(getClassPathArchives(options.classpath));
if (options.includePattern != null) {
archives.addAll(getClassPathArchives(options.classpath));
} else {
classpaths.addAll(getClassPathArchives(options.classpath));
archives.addAll(classpaths);
}
classpaths.addAll(PlatformClassPath.getArchives());
// add all archives to the source locations for reporting
sourceLocations.addAll(archives);
// add all classpath archives to the source locations for reporting
sourceLocations.addAll(classpaths);
// Work queue of names of classfiles to be searched.
......@@ -557,6 +570,7 @@ class JdepsTask {
boolean showSummary;
boolean wildcard;
boolean apiOnly;
boolean showLabel;
String dotOutputDir;
String classpath = "";
int depth = 1;
......@@ -627,16 +641,34 @@ class JdepsTask {
return result;
}
/**
* If the given archive is JDK archive and non-null Profile,
* this method returns the profile name only if -profile option is specified;
* a null profile indicates it accesses a private JDK API and this method
* will return "JDK internal API".
*
* For non-JDK archives, this method returns the file name of the archive.
*/
private String getProfileArchiveInfo(Archive source, Profile profile) {
if (options.showProfile && profile != null)
return profile.toString();
if (source instanceof JDKArchive) {
return profile == null ? "JDK internal API (" + source.getFileName() + ")" : "";
}
return source.getFileName();
}
/**
* Returns the file name of the archive for non-JRE class or
* internal JRE classes. It returns empty string for SE API.
* Returns the profile name or "JDK internal API" for JDK archive;
* otherwise empty string.
*/
private static String getArchiveName(Archive source, String profile) {
String name = source.getFileName();
if (source instanceof JDKArchive)
return profile.isEmpty() ? "JDK internal API (" + name + ")" : "";
return name;
private String profileName(Archive archive, Profile profile) {
if (archive instanceof JDKArchive) {
return Objects.toString(profile, "JDK internal API");
} else {
return "";
}
}
class RawOutputFormatter implements Analyzer.Visitor {
......@@ -648,21 +680,18 @@ class JdepsTask {
private String pkg = "";
@Override
public void visitDependence(String origin, Archive source,
String target, Archive archive, String profile) {
String target, Archive archive, Profile profile) {
if (!origin.equals(pkg)) {
pkg = origin;
writer.format(" %s (%s)%n", origin, source.getFileName());
}
String name = (options.showProfile && !profile.isEmpty())
? profile
: getArchiveName(archive, profile);
writer.format(" -> %-50s %s%n", target, name);
writer.format(" -> %-50s %s%n", target, getProfileArchiveInfo(archive, profile));
}
@Override
public void visitArchiveDependence(Archive origin, Archive target, String profile) {
writer.format("%s -> %s", origin, target);
if (options.showProfile && !profile.isEmpty()) {
public void visitArchiveDependence(Archive origin, Archive target, Profile profile) {
writer.format("%s -> %s", origin.getPathName(), target.getPathName());
if (options.showProfile && profile != null) {
writer.format(" (%s)%n", profile);
} else {
writer.format("%n");
......@@ -670,19 +699,14 @@ class JdepsTask {
}
}
class DotFileFormatter implements Analyzer.Visitor, AutoCloseable {
class DotFileFormatter extends DotGraph<String> implements AutoCloseable {
private final PrintWriter writer;
private final String name;
DotFileFormatter(PrintWriter writer, String name) {
this.writer = writer;
this.name = name;
writer.format("digraph \"%s\" {%n", name);
}
DotFileFormatter(PrintWriter writer, Archive archive) {
this.writer = writer;
this.name = archive.getFileName();
writer.format("digraph \"%s\" {%n", name);
writer.format(" // Path: %s%n", archive.toString());
writer.format(" // Path: %s%n", archive.getPathName());
}
@Override
......@@ -690,39 +714,169 @@ class JdepsTask {
writer.println("}");
}
private final Set<String> edges = new HashSet<>();
private String node = "";
@Override
public void visitDependence(String origin, Archive source,
String target, Archive archive, String profile) {
if (!node.equals(origin)) {
edges.clear();
node = origin;
}
String target, Archive archive, Profile profile) {
// if -P option is specified, package name -> profile will
// be shown and filter out multiple same edges.
if (!edges.contains(target)) {
StringBuilder sb = new StringBuilder();
String name = options.showProfile && !profile.isEmpty()
? profile
: getArchiveName(archive, profile);
writer.format(" %-50s -> %s;%n",
String.format("\"%s\"", origin),
name.isEmpty() ? String.format("\"%s\"", target)
: String.format("\"%s (%s)\"", target, name));
edges.add(target);
String name = getProfileArchiveInfo(archive, profile);
writeEdge(writer, new Edge(origin, target, getProfileArchiveInfo(archive, profile)));
}
@Override
public void visitArchiveDependence(Archive origin, Archive target, Profile profile) {
throw new UnsupportedOperationException();
}
}
class DotSummaryForArchive extends DotGraph<Archive> {
@Override
public void visitDependence(String origin, Archive source,
String target, Archive archive, Profile profile) {
Edge e = findEdge(source, archive);
assert e != null;
// add the dependency to the label if enabled and not compact1
if (profile == Profile.COMPACT1) {
return;
}
e.addLabel(origin, target, profileName(archive, profile));
}
@Override
public void visitArchiveDependence(Archive origin, Archive target, Profile profile) {
// add an edge with the archive's name with no tag
// so that there is only one node for each JDK archive
// while there may be edges to different profiles
Edge e = addEdge(origin, target, "");
if (target instanceof JDKArchive) {
// add a label to print the profile
if (profile == null) {
e.addLabel("JDK internal API");
} else if (options.showProfile && !options.showLabel) {
e.addLabel(profile.toString());
}
}
}
}
// DotSummaryForPackage generates the summary.dot file for verbose mode
// (-v or -verbose option) that includes all class dependencies.
// The summary.dot file shows package-level dependencies.
class DotSummaryForPackage extends DotGraph<String> {
private String packageOf(String cn) {
int i = cn.lastIndexOf('.');
return i > 0 ? cn.substring(0, i) : "<unnamed>";
}
@Override
public void visitArchiveDependence(Archive origin, Archive target, String profile) {
String name = options.showProfile && !profile.isEmpty()
? profile : "";
writer.format(" %-30s -> \"%s\";%n",
String.format("\"%s\"", origin.getFileName()),
name.isEmpty()
? target.getFileName()
: String.format("%s (%s)", target.getFileName(), name));
public void visitDependence(String origin, Archive source,
String target, Archive archive, Profile profile) {
// add a package dependency edge
String from = packageOf(origin);
String to = packageOf(target);
Edge e = addEdge(from, to, getProfileArchiveInfo(archive, profile));
// add the dependency to the label if enabled and not compact1
if (!options.showLabel || profile == Profile.COMPACT1) {
return;
}
// trim the package name of origin to shorten the label
int i = origin.lastIndexOf('.');
String n1 = i < 0 ? origin : origin.substring(i+1);
e.addLabel(n1, target, profileName(archive, profile));
}
@Override
public void visitArchiveDependence(Archive origin, Archive target, Profile profile) {
// nop
}
}
abstract class DotGraph<T> implements Analyzer.Visitor {
private final Set<Edge> edges = new LinkedHashSet<>();
private Edge curEdge;
public void writeTo(PrintWriter writer) {
writer.format("digraph \"summary\" {%n");
for (Edge e: edges) {
writeEdge(writer, e);
}
writer.println("}");
}
void writeEdge(PrintWriter writer, Edge e) {
writer.format(" %-50s -> \"%s\"%s;%n",
String.format("\"%s\"", e.from.toString()),
e.tag.isEmpty() ? e.to
: String.format("%s (%s)", e.to, e.tag),
getLabel(e));
}
Edge addEdge(T origin, T target, String tag) {
Edge e = new Edge(origin, target, tag);
if (e.equals(curEdge)) {
return curEdge;
}
if (edges.contains(e)) {
for (Edge e1 : edges) {
if (e.equals(e1)) {
curEdge = e1;
}
}
} else {
edges.add(e);
curEdge = e;
}
return curEdge;
}
Edge findEdge(T origin, T target) {
for (Edge e : edges) {
if (e.from.equals(origin) && e.to.equals(target)) {
return e;
}
}
return null;
}
String getLabel(Edge e) {
String label = e.label.toString();
return label.isEmpty() ? "" : String.format("[label=\"%s\",fontsize=9]", label);
}
class Edge {
final T from;
final T to;
final String tag; // optional tag
final StringBuilder label = new StringBuilder();
Edge(T from, T to, String tag) {
this.from = from;
this.to = to;
this.tag = tag;
}
void addLabel(String s) {
label.append(s).append("\\n");
}
void addLabel(String origin, String target, String profile) {
label.append(origin).append(" -> ").append(target);
if (!profile.isEmpty()) {
label.append(" (" + profile + ")");
}
label.append("\\n");
}
@Override @SuppressWarnings("unchecked")
public boolean equals(Object o) {
if (o instanceof DotGraph<?>.Edge) {
DotGraph<?>.Edge e = (DotGraph<?>.Edge)o;
return this.from.equals(e.from) &&
this.to.equals(e.to) &&
this.tag.equals(e.tag);
}
return false;
}
@Override
public int hashCode() {
int hash = 7;
hash = 67 * hash + Objects.hashCode(this.from) +
Objects.hashCode(this.to) + Objects.hashCode(this.tag);
return hash;
}
}
}
}
......@@ -81,8 +81,12 @@ enum Profile {
}
static class PackageToProfile {
static String[] JAVAX_CRYPTO_PKGS = new String[] {
"javax.crypto",
"javax.crypto.interfaces",
"javax.crypto.spec"
};
static Map<String, Profile> map = initProfiles();
private static Map<String, Profile> initProfiles() {
try {
String profilesProps = System.getProperty("jdeps.profiles");
......@@ -103,6 +107,9 @@ enum Profile {
findProfile(cf);
}
}
// special case for javax.crypto.* classes that are not
// included in ct.sym since they are in jce.jar
Collections.addAll(Profile.COMPACT1.packages, JAVAX_CRYPTO_PKGS);
}
}
} catch (IOException | ConstantPoolException e) {
......
......@@ -27,6 +27,7 @@ package javax.lang.model.util;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.type.IntersectionType;
import static javax.lang.model.SourceVersion.*;
/**
......@@ -98,4 +99,17 @@ public class SimpleTypeVisitor8<R, P> extends SimpleTypeVisitor7<R, P> {
protected SimpleTypeVisitor8(R defaultValue){
super(defaultValue);
}
/**
* This implementation visits an {@code IntersectionType} by calling
* {@code defaultAction}.
*
* @param t {@inheritDoc}
* @param p {@inheritDoc}
* @return the result of {@code defaultAction}
*/
@Override
public R visitIntersection(IntersectionType t, P p){
return defaultAction(t, p);
}
}
......@@ -101,4 +101,17 @@ public class TypeKindVisitor8<R, P> extends TypeKindVisitor7<R, P> {
protected TypeKindVisitor8(R defaultValue) {
super(defaultValue);
}
/**
* This implementation visits an {@code IntersectionType} by calling
* {@code defaultAction}.
*
* @param t {@inheritDoc}
* @param p {@inheritDoc}
* @return the result of {@code defaultAction}
*/
@Override
public R visitIntersection(IntersectionType t, P p) {
return defaultAction(t, p);
}
}
......@@ -23,7 +23,7 @@
/*
* @test
* @bug 8025633
* @bug 8025633 8025524
* @summary Test for valid name attribute in HTML anchors.
* @author Bhavesh Patel
* @library ../lib/
......@@ -196,10 +196,10 @@ public class TestAnchorNames extends JavadocTester {
//Test nested class
{BUG_ID + FS + "pkg1" + FS + "RegClass._NestedClas$.html",
"<a name=\"RegClass._NestedClas:D--\">"
"<a name=\"Z:Z_NestedClas:D--\">"
},
{BUG_ID + FS + "pkg1" + FS + "RegClass._NestedClas$.html",
"<a href=\"../pkg1/RegClass._NestedClas$.html#RegClass._NestedClas:D--\">"
"<a href=\"../pkg1/RegClass._NestedClas$.html#Z:Z_NestedClas:D--\">"
},
//Test class use page
......
/*
* Copyright (c) 2013, 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 8025524
* @summary Test for constructor name which should be a non-qualified name.
* @author Bhavesh Patel
* @library ../lib/
* @build JavadocTester TestConstructors
* @run main TestConstructors
*/
public class TestConstructors extends JavadocTester {
private static final String BUG_ID = "8025524";
//Input for string search tests.
private static final String[][] TEST = {
{BUG_ID + FS + "pkg1" + FS + "Outer.html",
"<a href=\"../pkg1/Outer.html#Outer--\">Outer</a></span>()"
},
{BUG_ID + FS + "pkg1" + FS + "Outer.html",
"<a name=\"Outer--\">"
},
{BUG_ID + FS + "pkg1" + FS + "Outer.html",
"<a href=\"../pkg1/Outer.html#Outer-int-\">Outer</a></span>(int&nbsp;i)"
},
{BUG_ID + FS + "pkg1" + FS + "Outer.html",
"<a name=\"Outer-int-\">"
},
{BUG_ID + FS + "pkg1" + FS + "Outer.Inner.html",
"<a href=\"../pkg1/Outer.Inner.html#Inner--\">Inner</a></span>()"
},
{BUG_ID + FS + "pkg1" + FS + "Outer.Inner.html",
"<a name=\"Inner--\">"
},
{BUG_ID + FS + "pkg1" + FS + "Outer.Inner.html",
"<a href=\"../pkg1/Outer.Inner.html#Inner-int-\">Inner</a></span>(int&nbsp;i)"
},
{BUG_ID + FS + "pkg1" + FS + "Outer.Inner.html",
"<a name=\"Inner-int-\">"
},
{BUG_ID + FS + "pkg1" + FS + "Outer.Inner.NestedInner.html",
"<a href=\"../pkg1/Outer.Inner.NestedInner.html#NestedInner--\">NestedInner</a></span>()"
},
{BUG_ID + FS + "pkg1" + FS + "Outer.Inner.NestedInner.html",
"<a name=\"NestedInner--\">"
},
{BUG_ID + FS + "pkg1" + FS + "Outer.Inner.NestedInner.html",
"<a href=\"../pkg1/Outer.Inner.NestedInner.html#NestedInner-int-\">NestedInner</a></span>(int&nbsp;i)"
},
{BUG_ID + FS + "pkg1" + FS + "Outer.Inner.NestedInner.html",
"<a name=\"NestedInner-int-\">"
}
};
private static final String[][] NEGATED_TEST = {
{BUG_ID + FS + "pkg1" + FS + "Outer.Inner.html",
"Outer.Inner--"
},
{BUG_ID + FS + "pkg1" + FS + "Outer.Inner.html",
"Outer.Inner-int-"
},
{BUG_ID + FS + "pkg1" + FS + "Outer.Inner.NestedInner.html",
"Outer.Inner.NestedInner--"
},
{BUG_ID + FS + "pkg1" + FS + "Outer.Inner.NestedInner.html",
"Outer.Inner.NestedInner-int-"
}
};
private static final String[] ARGS = new String[] {
"-d", BUG_ID, "-sourcepath", SRC_DIR, "pkg1"
};
/**
* The entry point of the test.
* @param args the array of command line arguments.
*/
public static void main(String[] args) throws Exception {
TestConstructors tester = new TestConstructors();
run(tester, ARGS, TEST, NEGATED_TEST);
tester.printSummary();
}
/**
* {@inheritDoc}
*/
public String getBugId() {
return BUG_ID;
}
/**
* {@inheritDoc}
*/
public String getBugName() {
return getClass().getName();
}
}
/*
* Copyright (c) 2013, 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 pkg1;
public class Outer {
/**
* An outer constructor.
*/
public Outer() {
}
/**
* Another outer constructor.
*/
public Outer(int i) {
}
/**
* A nested class.
*/
public class Inner {
/**
* An inner constructor.
*/
public Inner() {
}
/**
* Another inner constructor.
*/
public Inner(int i) {
}
/**
* A nested inner class.
*/
public class NestedInner {
/**
* A nested inner constructor.
*/
public NestedInner() {
}
/**
* Another nested inner constructor.
*/
public NestedInner(int i) {
}
}
}
}
......@@ -112,11 +112,6 @@ public class ExtDirTest {
}
void createJars() throws Exception {
// for i in 1 2 3; do
// if test ! -d ext${i}; then mkdir ext${i}; fi
// cp ${TESTSRC}${FS}ext${i}${FS}*.jar ext${i}
// done
sun.tools.jar.Main jarGenerator =
new sun.tools.jar.Main(System.out, System.err, "jar");
......@@ -155,19 +150,19 @@ public class ExtDirTest {
void compileWithExtDirs() throws Exception {
//"$javac" ${TESTTOOLVMOPTS} -d . -extdirs ext1 "${TESTSRC}${FS}ExtDirTest_1.java"
//javac -extdirs ext1 ExtDirTest_1.java
ToolBox.JavaToolArgs params =
new ToolBox.JavaToolArgs()
.setOptions("-d", ".", "-extdirs", "ext1")
.setSources(ExtDirTest_1Src);
ToolBox.javac(params);
//"$javac" ${TESTTOOLVMOPTS} -d . -extdirs ext1${PS}ext2 "${TESTSRC}${FS}ExtDirTest_2.java"
//javac -extdirs ext1:ext2 ExtDirTest_2.java
params.setOptions("-d", ".", "-extdirs", "ext1" + File.pathSeparator + "ext2")
.setSources(ExtDirTest_2Src);
ToolBox.javac(params);
//"$javac" ${TESTTOOLVMOPTS} -d . -extdirs ext3 "${TESTSRC}${FS}ExtDirTest_3.java"
//javac -extdirs ext3 ExtDirTest_3.java
params.setOptions("-d", ".", "-extdirs", "ext3")
.setSources(ExtDirTest_3Src);
ToolBox.javac(params);
......
......@@ -2,7 +2,6 @@
* @test /nodynamiccopyright/
* @bug 7042623
* @summary Regression: javac silently crash when attributing non-existent annotation
* @ignore
* @compile/fail/ref=T7042623.out -XDrawDiagnostics -XDdev T7042623.java
*/
......
......@@ -25,7 +25,7 @@
/*
* @test
* @bug 8019486 8026861
* @bug 8019486 8026861 8027142
* @summary javac, generates erroneous LVT for a test case with lambda code
* @library /tools/javac/lib
* @build ToolBox
......@@ -68,7 +68,14 @@ public class WrongLNTForLambdaTest {
/* 22 */ " Runnable r4 = super :: notify;\n" +
/* 23 */ " }\n" +
/* 24 */ " private void foo() {}\n" +
/* 25 */ "}";
/* 25 */ " void assignLambda() {\n" +
/* 26 */ " Runnable r = () -> { };\n" +
/* 27 */ " }\n" +
/* 28 */ " void callLambda(int i, Runnable r) {\n" +
/* 29 */ " callLambda(0,\n" +
/* 30 */ " () -> { });\n" +
/* 31 */ " }\n" +
/* 32 */ "}";
static final int[][] simpleLambdaExpectedLNT = {
// {line-number, start-pc},
......@@ -102,6 +109,18 @@ public class WrongLNTForLambdaTest {
{22, 0}, //number -> number / 1
};
static final int[][] assignmentExpectedLNT = {
// {line-number, start-pc},
{26, 0}, //number -> number / 1
{27, 6}, //number -> number / 1
};
static final int[][] callExpectedLNT = {
// {line-number, start-pc},
{29, 0}, //number -> number / 1
{31, 10}, //number -> number / 1
};
public static void main(String[] args) throws Exception {
new WrongLNTForLambdaTest().run();
}
......@@ -120,6 +139,10 @@ public class WrongLNTForLambdaTest {
"Foo.class").toUri()), "$deserializeLambda$", deserializeExpectedLNT);
checkClassFile(new File(Paths.get(System.getProperty("user.dir"),
"Foo.class").toUri()), "lambda$MR$variablesInLambdas$notify$8bc4f5bd$1", lambdaBridgeExpectedLNT);
checkClassFile(new File(Paths.get(System.getProperty("user.dir"),
"Foo.class").toUri()), "assignLambda", assignmentExpectedLNT);
checkClassFile(new File(Paths.get(System.getProperty("user.dir"),
"Foo.class").toUri()), "callLambda", callExpectedLNT);
}
void compileTestClass() throws Exception {
......
/*
* @test /nodynamiccopyright/
* @bug 8026963
* @summary type annotations code crashes for lambdas with void argument
* @compile/fail/ref=TypeAnnotationsCrashWithErroneousTreeTest.out -XDrawDiagnostics -XDshouldStopPolicy=FLOW TypeAnnotationsCrashWithErroneousTreeTest.java
*/
public class TypeAnnotationsCrashWithErroneousTreeTest {
private void t(this) {}
}
TypeAnnotationsCrashWithErroneousTreeTest.java:9:20: compiler.err.illegal.start.of.type
1 error
/*
* @test /nodynamiccopyright/
* @bug 8025113
* @author sogoel
* @summary Resources cannot be declared outside t-w-r block
* @compile/fail/ref=ResDeclOutsideTry.out -XDrawDiagnostics ResDeclOutsideTry.java
*/
public class ResDeclOutsideTry implements AutoCloseable {
ResDeclOutsideTry tr1;
ResDeclOutsideTry tr2 = new ResDeclOutsideTry();
String test1() {
try (tr1 = new ResDeclOutsideTry(); tr2;) {
}
}
}
ResDeclOutsideTry.java:14:17: compiler.err.expected: token.identifier
ResDeclOutsideTry.java:14:48: compiler.err.expected: token.identifier
2 errors
/*
* Copyright (c) 2010, 2013, 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 8025113
* @author sogoel
* @summary Resource creation in nested expressions
*/
/**
* This test checks for resource creation in nested expressions.
* test1() - Create 3 resource in nested new expressions, style 1
* test2() - Create 3 resource in nested new expressions, style 2
* test3() - Create 4 resources with resources as parameters: new expression; typeid & new expression
*/
public class ResInNestedExpr {
static final int expected = 5;
static int closed = 0;
static void closing(String clazz) {
closed++;
}
static void checkClosedCount() {
if (expected != closed) {
throw new RuntimeException("Did not find enough closed resources."
+ "Expected " + expected + ", but found " + closed);
}
}
/**
* The "expected output" is each class name gotten with getSimpleName() to unclutter things.
* Each test method returns a classname of the resource and that is compared with
* values in this array.
*/
static String[] expectedOutput = {
"aResource::bResource::cResource", //test1
"aResource::bResource::cResource&aResource::cResource", //test3
"aResource::bResource::cResource&aResource::cResource"}; //test2
static void compare(String s1, String s2) {
if (s1.compareTo(s2) != 0) {
throw new RuntimeException(s1 + "!=" + s2);
}
}
String test1() {
String ret = null;
try (bResource br = new bResource(new cResource());
aResource ar = new aResource(br)) {
ret = ar.getClass().getSimpleName() + "::" +
ar.getB().getClass().getSimpleName() + "::" +
ar.getB().getC().getClass().getSimpleName();
}
return ret;
}
String test2() {
String ret = null;
try (aResource ar = new aResource(new bResource(new cResource()), new cResource())) {
String abc = ar.getClass().getSimpleName() + "::" +
ar.getB().getClass().getSimpleName() + "::" +
ar.getB().getC().getClass().getSimpleName();
String ac = ar.getClass().getSimpleName() + "::" +
ar.getC().getClass().getSimpleName();
ret = abc + "&" + ac;
}
return ret;
}
String test3() {
String ret = null;
try (bResource br = new bResource(new cResource());
aResource ar = new aResource(br, new cResource())) {
String abc = ar.getClass().getSimpleName() + "::" +
ar.getB().getClass().getSimpleName() + "::" +
ar.getB().getC().getClass().getSimpleName();
String ac = ar.getClass().getSimpleName() + "::" +
ar.getC().getClass().getSimpleName();
ret = abc + "&" + ac;
}
return ret;
}
public static void main(String... args) {
ResInNestedExpr t = new ResInNestedExpr();
int eo = 0;
compare(expectedOutput[eo++], t.test1());
compare(expectedOutput[eo++], t.test3());
compare(expectedOutput[eo++], t.test2());
ResInNestedExpr.checkClosedCount();
}
/**
* A resource to implement AutoCloseable
* Contains two other resources as data items.
*/
static class aResource implements AutoCloseable {
bResource bR;
cResource cR;
public aResource() {
bR = null;
cR = null;
}
public aResource(bResource br) {
bR = br;
}
public aResource(cResource cr) {
cR = cr;
}
public aResource(bResource br, cResource cr) {
bR = br;
cR = cr;
}
public bResource getB() {
return bR;
}
public cResource getC() {
return cR;
}
@Override
public void close() {
ResInNestedExpr.closing(this.getClass().getName());
}
}
/**
* A resource to implement AutoCloseable
* Contains one other resources as a data item.
*/
static class bResource implements AutoCloseable {
cResource cR;
public bResource() {
cR = null;
}
public bResource(cResource cr) {
cR = cr;
}
public cResource getC() {
return cR;
}
@Override
public void close() {
ResInNestedExpr.closing(this.getClass().getName());
}
}
/** A resource to implement AutoCloseable */
static class cResource implements AutoCloseable {
public cResource() {
}
@Override
public void close() {
ResInNestedExpr.closing(this.getClass().getName());
}
}
}
/*
* @test /nodynamiccopyright/
* @bug 8025113
* @author sogoel
* @summary Resource var cannot have same name as local variable
* @compile/fail/ref=ResourceNameConflict.out -XDrawDiagnostics ResourceNameConflict.java
*/
/**
* Test methods and their description
* test1() - negative test - local variable used as test resource
* test2() - negative test - test resource already defined in an enclosing for statement
*/
public class ResourceNameConflict implements AutoCloseable {
static final String str = "asdf";
void test1() {
String tr = "A resource spec var cannot have same name as local var.";
try (ResourceNameConflict tr = new ResourceNameConflict()) {
}
}
void test2(String... strArray) {
for (String str : strArray) {
try (ResourceNameConflict str = new ResourceNameConflict()) {
}
}
}
@Override
public void close() {
}
}
ResourceNameConflict.java:21:35: compiler.err.already.defined: kindname.variable, tr, kindname.method, test1()
ResourceNameConflict.java:27:39: compiler.err.already.defined: kindname.variable, str, kindname.method, test2(java.lang.String...)
2 errors
/*
* @test /nodynamiccopyright/
* @bug 8025113
* @author sogoel
* @summary Redeclaration of resource variables
* @compile/fail/ref=ResourceRedecl.out -XDrawDiagnostics ResourceRedecl.java
*/
import java.io.*;
public class ResourceRedecl {
public void test() {
// compiler error if name of an exception param is redeclared within the Block of the catch clause as a local var;
// or as an exception param of a catch clause in a try statement;
// or as a resource in a try-with-resources statement
try {
} catch (Exception exParam1) {
Object exParam1 = new Object();
try (java.io.FileInputStream exParam1 = new java.io.FileInputStream("foo.txt")) {
Object exParam1 = new Object();
} catch (IOException exParam1) {
}
}
// compiler error if resource is redeclared within the try Block as a local var
// or as an exception param of a catch clause in a try statement
try (java.io.FileInputStream exParam2 = new java.io.FileInputStream("bar.txt")) {
Object exParam2 = new Object();
try (BufferedReader br = new BufferedReader(new FileReader("zee.txt"))) {
} catch (IOException exParam2) {
}
} catch (Exception ex) {
}
}
}
ResourceRedecl.java:19:20: compiler.err.already.defined: kindname.variable, exParam1, kindname.method, test()
ResourceRedecl.java:20:42: compiler.err.already.defined: kindname.variable, exParam1, kindname.method, test()
ResourceRedecl.java:21:24: compiler.err.already.defined: kindname.variable, exParam1, kindname.method, test()
ResourceRedecl.java:22:34: compiler.err.already.defined: kindname.variable, exParam1, kindname.method, test()
ResourceRedecl.java:29:20: compiler.err.already.defined: kindname.variable, exParam2, kindname.method, test()
ResourceRedecl.java:31:34: compiler.err.already.defined: kindname.variable, exParam2, kindname.method, test()
6 errors
/*
* Copyright (c) 2010, 2013, 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 8025113
* @author sogoel
* @summary Test shadowing of resource variable
*/
/*
* "...a variable declared in a resource specification
* may be shadowed (6.3.1) anywhere inside a class declaration nested
* within the Block of the try."
*/
public class ResourceShadow {
static final String str = "asdf"; //this is okay
/**
* Resource variable shadows switch and case variables
*/
String test1() {
String ret = null;
switch (str) {
case str: //this is okay
try (SilentCloseable str = new SilentCloseable()) {
SilentCloseable tr = new SilentCloseable(str);
ret = str.getClass().getSimpleName();
}
break;
default:
ret = "";
}
return ret;
}
/**
* Resource variable may be shadowed (6.3.1) anywhere inside a class
* declaration nested within the Block of the try
*/
String test2() {
String ret = null;
try (SilentCloseable str = new SilentCloseable()) {
class temp {
String str = "I am not a SilentCloseable";
public void printSTR() {
System.out.println(str);
}
public String getSTR() {
return str;
}
}
temp tmp = new temp();
SilentCloseable tr = new SilentCloseable(tmp.getSTR());
ret = tr.getMsg();
}
return ret;
}
public static void main(String... args) {
ResourceShadow t = new ResourceShadow();
if (t.test1().compareTo("SilentCloseable") != 0) {
throw new RuntimeException("FAIL-test1");
}
if (t.test2().compareTo("I am not a SilentCloseable") != 0) {
throw new RuntimeException("FAIL-test2");
}
}
}
class SilentCloseable implements AutoCloseable {
SilentCloseable testres = null;
String msg = "default";
@Override
public void close() {
}
public SilentCloseable() {
}
public SilentCloseable(String s) {
msg = s;
}
public SilentCloseable(SilentCloseable tr) {
testres = tr;
}
public String getMsg() {
return msg;
}
}
/*
* Copyright (c) 2010, 2013, 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 8025113
* @author sogoel
* @summary t-w-r completes abruptly if the initialization of resource completes abruptly
*/
import java.io.FileInputStream;
import java.io.IOException;
import java.io.File;
/*
* If the initialization of the resource completes abruptly because of a
* throw of a value V ... and the automatic ->closing of the resource completes normally,
* then the try-with-resources statement completes abruptly because of the throw of value V.
*/
public class TestTwr09 {
/**
* throw from ctor of nested resource
* Check first resource is not open.
*/
String test1() {
String ret = null;
try (ResCloseable tr = new ResCloseable(new ResCloseable("throw from inner resource ctor",3))) {
ret = "FAIL";
} catch (RuntimeException re) {
ret = re.getMessage();
}
return ret;
}
/**
* throw from ctor of 2nd resource.
* 1st resource, FileInputStream should be automatically closed.
*/
String test2() {
String ret = null;
byte[] buf = new byte[1];
try (java.io.ByteArrayInputStream tr = new java.io.ByteArrayInputStream(buf);
ResCloseable str = new ResCloseable("throw from inner resource ctor",3)) {
ret = "FAIL";
} catch (final IOException fe) {
ret = "FAIL test2";
} catch (RuntimeException re) {
ret = "PASS test2";
}
System.out.println("Ret = " + ret);
return ret;
}
public static void main(String... args) {
TestTwr09 t = new TestTwr09();
if (t.test1().compareTo("throw from inner resource ctor") != 0) {
throw new RuntimeException("FAIL-test1");
}
if (t.test2().compareTo("PASS test2") != 0) {
throw new RuntimeException("FAIL-test2");
}
}
}
/** a simple resource the implements AutoCloseable so it can be used
* in twr's resource specification block.
*/
class ResCloseable implements AutoCloseable {
ResCloseable testres = null;
String msg = "default";
boolean bOpen = false;
public ResCloseable() {
bOpen = true;
}
public ResCloseable(ResCloseable tr) {
bOpen = true;
msg = tr.getMsg();
}
public ResCloseable(String s) {
bOpen = true;
msg = s;
}
public ResCloseable(String msg, int c) {
bOpen = true;
if (c == 3) {
throw new RuntimeException(msg);
}
}
@Override
public void close() {
bOpen = false;
}
public boolean isOpen() {
return bOpen;
}
public String getMsg() {
return msg;
}
}
/* @test /nodynamiccopyright/
* @bug 8027375
* @summary Test that javac doesn't assert/crash when there are what looks to
* be annotations nested inside erroneous annotations.
* @compile/fail/ref=TestCrashNestedAnnos.out -XDrawDiagnostics TestCrashNestedAnnos.java
*/
public class TestCrashNestedAnnos {
// A and B are not annotation types
@A(@A1()) int foo() {}
@B(@B1()) int bar() {}
}
class B {}
class B1 {}
TestCrashNestedAnnos.java:9:6: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.class, TestCrashNestedAnnos, null)
TestCrashNestedAnnos.java:10:6: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: B, java.lang.annotation.Annotation)
2 errors
/*
* Copyright (c) 2013, 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 8027281
* @summary As per JVMS 4.9.2, invokespecial can only refer to direct superinterfaces
* @compile TestDirectSuperInterfaceInvoke.java
* @run main TestDirectSuperInterfaceInvoke
*/
import java.io.File;
import com.sun.tools.classfile.Attribute;
import com.sun.tools.classfile.ClassFile;
import com.sun.tools.classfile.Code_attribute;
import com.sun.tools.classfile.ConstantPool.CPRefInfo;
import com.sun.tools.classfile.Instruction;
import com.sun.tools.classfile.Method;
import com.sun.tools.classfile.Opcode;
interface BaseInterface {
public default int testedMethod(){ return 1; }
}
interface IntermediateInterface extends BaseInterface {
}
interface TestInterface extends IntermediateInterface {
public default void test() {
IntermediateInterface.super.testedMethod();
}
}
abstract class BaseClass implements BaseInterface { }
class TestClass extends BaseClass implements BaseInterface {
public int testedMethod() {return 9;}
public void test() {
if (super.testedMethod() != 1)
throw new IllegalStateException();
if (TestClass.super.testedMethod() != 1)
throw new IllegalStateException();
new Runnable() {
public void run() {
if (TestClass.super.testedMethod() != 1)
throw new IllegalStateException();
}
}.run();
}
}
public class TestDirectSuperInterfaceInvoke {
public static void main(String... args) throws Exception {
new TestDirectSuperInterfaceInvoke().run();
}
public void run() throws Exception {
new TestClass().test();
verifyDefaultBody("TestClass.class");
new TestInterface() {}.test();
verifyDefaultBody("TestInterface.class");
}
void verifyDefaultBody(String classFile) {
String workDir = System.getProperty("test.classes");
File file = new File(workDir, classFile);
try {
final ClassFile cf = ClassFile.read(file);
for (Method m : cf.methods) {
Code_attribute codeAttr = (Code_attribute)m.attributes.get(Attribute.Code);
for (Instruction instr : codeAttr.getInstructions()) {
if (instr.getOpcode() == Opcode.INVOKESPECIAL) {
int pc_index = instr.getShort(1);
CPRefInfo ref = (CPRefInfo)cf.constant_pool.get(pc_index);
String className = ref.getClassName();
if (className.equals("BaseInterface"))
throw new IllegalStateException("Must not directly refer to TestedInterface");
}
}
}
} catch (Exception e) {
e.printStackTrace();
throw new Error("error reading " + file +": " + e);
}
}
}
......@@ -23,8 +23,10 @@
/*
* @test
* @bug 7047734
* @summary The LVT is not generated correctly during some try/catch scenarios
* @bug 7047734 8027660
* @summary The LVT is not generated correctly during some try/catch scenarios;
* javac crash while creating LVT entry for a local variable defined in
* an inner block
* @library /tools/javac/lib
* @build JavacTestingAbstractProcessor LVTHarness
* @run main LVTHarness
......
......@@ -21,19 +21,21 @@
* questions.
*/
/*
* @test
* @bug 8021339
* @summary Allow arrays in intersection types
* @compile ArraysInIntersections.java
*/
import java.io.Serializable;
public class TestCaseLocalInInnerBlock {
public class ArraysInIntersections<T extends Serializable & Integer[]> {
public <S extends Serializable & Integer[]> Object m() {
return (Serializable & Integer[]) new Integer[1];
@AliveRange(varName="fm", bytecodeStart=23, bytecodeLength=10)
@AliveRange(varName="newWidth", bytecodeStart=2, bytecodeLength=33)
@AliveRange(varName="tc", bytecodeStart=5, bytecodeLength=30)
int m() {
int newWidth = 0;
String tc = "b";
if (tc != null) {
String fm;
if (tc.trim() != null) {
} else if ((fm = "b") != null) {
newWidth += fm.length();
}
}
return newWidth;
}
}
T6680106.java:11:14: compiler.err.cyclic.inheritance: T
T6680106.java:12:14: compiler.err.cyclic.inheritance: T
T6680106.java:13:14: compiler.err.cyclic.inheritance: T
T6680106.java:14:14: compiler.err.cyclic.inheritance: T
T6680106.java:15:14: compiler.err.cyclic.inheritance: T
T6680106.java:16:14: compiler.err.cyclic.inheritance: T
6 errors
T6680106.java:11:25: compiler.err.type.found.req: T[], (compiler.misc.type.req.class)
T6680106.java:12:25: compiler.err.type.found.req: S[], (compiler.misc.type.req.class)
T6680106.java:12:40: compiler.err.type.found.req: T[], (compiler.misc.type.req.class)
T6680106.java:13:25: compiler.err.type.found.req: S[], (compiler.misc.type.req.class)
T6680106.java:13:40: compiler.err.type.found.req: U[], (compiler.misc.type.req.class)
T6680106.java:13:55: compiler.err.type.found.req: T[], (compiler.misc.type.req.class)
T6680106.java:14:30: compiler.err.type.found.req: T[], (compiler.misc.type.req.class)
T6680106.java:15:30: compiler.err.type.found.req: S[], (compiler.misc.type.req.class)
T6680106.java:15:50: compiler.err.type.found.req: T[], (compiler.misc.type.req.class)
T6680106.java:16:30: compiler.err.type.found.req: S[], (compiler.misc.type.req.class)
T6680106.java:16:50: compiler.err.type.found.req: U[], (compiler.misc.type.req.class)
T6680106.java:16:70: compiler.err.type.found.req: T[], (compiler.misc.type.req.class)
12 errors
......@@ -48,19 +48,19 @@ class MethodReference22 {
}
static void test2() {
SAM2 s1 = MethodReference22::m1; //ambiguous
call2(MethodReference22::m1); //ambiguous
SAM2 s2 = MethodReference22::m2; //ambiguous
call2(MethodReference22::m2); //ambiguous
SAM2 s3 = MethodReference22::m3; //ambiguous
call2(MethodReference22::m3); //ambiguous
SAM2 s4 = MethodReference22::m4; //ambiguous
call2(MethodReference22::m4); //ambiguous
SAM2 s1 = MethodReference22::m1; //ok
call2(MethodReference22::m1); //ok
SAM2 s2 = MethodReference22::m2; //ok
call2(MethodReference22::m2); //ok
SAM2 s3 = MethodReference22::m3; //fail
call2(MethodReference22::m3); //fail
SAM2 s4 = MethodReference22::m4; //fail
call2(MethodReference22::m4); //fail
}
static void test3() {
call3(MethodReference22::m1); //fail
call3(MethodReference22::m2); //ok
call3(MethodReference22::m1); //ok
call3(MethodReference22::m2); //ambiguous
call3(MethodReference22::m3); //ok
call3(MethodReference22::m4); //fail
}
......
MethodReference22.java:40:19: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, m1(java.lang.String))
MethodReference22.java:41:15: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, m1(java.lang.String))
MethodReference22.java:41:9: compiler.err.cant.apply.symbol: kindname.method, call1, MethodReference22.SAM1, @999, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.arg.types.in.mref))
MethodReference22.java:46:19: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, m4(java.lang.String))
MethodReference22.java:47:15: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, m4(java.lang.String))
MethodReference22.java:51:19: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m1, kindname.method, m1(MethodReference22,java.lang.String), MethodReference22, kindname.method, m1(java.lang.String), MethodReference22))
MethodReference22.java:52:14: compiler.err.cant.apply.symbol: kindname.method, call2, MethodReference22.SAM2, @1401, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m1, kindname.method, m1(MethodReference22,java.lang.String), MethodReference22, kindname.method, m1(java.lang.String), MethodReference22)))
MethodReference22.java:53:19: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m2, kindname.method, m2(MethodReference22,java.lang.String), MethodReference22, kindname.method, m2(java.lang.String), MethodReference22))
MethodReference22.java:54:14: compiler.err.cant.apply.symbol: kindname.method, call2, MethodReference22.SAM2, @1504, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m2, kindname.method, m2(MethodReference22,java.lang.String), MethodReference22, kindname.method, m2(java.lang.String), MethodReference22)))
MethodReference22.java:55:19: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m3, kindname.method, m3(MethodReference22,java.lang.String), MethodReference22, kindname.method, m3(java.lang.String), MethodReference22))
MethodReference22.java:56:14: compiler.err.cant.apply.symbol: kindname.method, call2, MethodReference22.SAM2, @1607, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m3, kindname.method, m3(MethodReference22,java.lang.String), MethodReference22, kindname.method, m3(java.lang.String), MethodReference22)))
MethodReference22.java:47:9: compiler.err.cant.apply.symbol: kindname.method, call1, MethodReference22.SAM1, @1270, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.arg.types.in.mref))
MethodReference22.java:55:19: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, m3(MethodReference22,java.lang.String))
MethodReference22.java:56:9: compiler.err.cant.apply.symbol: kindname.method, call2, MethodReference22.SAM2, @1574, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.arg.types.in.mref))
MethodReference22.java:57:19: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m4, kindname.method, m4(MethodReference22,java.lang.String), MethodReference22, kindname.method, m4(java.lang.String), MethodReference22))
MethodReference22.java:58:14: compiler.err.cant.apply.symbol: kindname.method, call2, MethodReference22.SAM2, @1710, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m4, kindname.method, m4(MethodReference22,java.lang.String), MethodReference22, kindname.method, m4(java.lang.String), MethodReference22)))
MethodReference22.java:62:9: compiler.err.ref.ambiguous: call3, kindname.method, call3(MethodReference22.SAM1), MethodReference22, kindname.method, call3(MethodReference22.SAM2), MethodReference22
MethodReference22.java:62:15: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, m1(java.lang.String))
MethodReference22.java:58:14: compiler.err.cant.apply.symbol: kindname.method, call2, MethodReference22.SAM2, @1667, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m4, kindname.method, m4(MethodReference22,java.lang.String), MethodReference22, kindname.method, m4(java.lang.String), MethodReference22)))
MethodReference22.java:63:9: compiler.err.ref.ambiguous: call3, kindname.method, call3(MethodReference22.SAM1), MethodReference22, kindname.method, call3(MethodReference22.SAM2), MethodReference22
MethodReference22.java:64:9: compiler.err.ref.ambiguous: call3, kindname.method, call3(MethodReference22.SAM1), MethodReference22, kindname.method, call3(MethodReference22.SAM2), MethodReference22
MethodReference22.java:65:9: compiler.err.ref.ambiguous: call3, kindname.method, call3(MethodReference22.SAM1), MethodReference22, kindname.method, call3(MethodReference22.SAM2), MethodReference22
MethodReference22.java:65:15: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, m4(java.lang.String))
18 errors
MethodReference22.java:65:14: compiler.err.cant.apply.symbol: kindname.method, call3, MethodReference22.SAM2, @1881, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m4, kindname.method, m4(MethodReference22,java.lang.String), MethodReference22, kindname.method, m4(java.lang.String), MethodReference22)))
10 errors
......@@ -36,11 +36,11 @@ class TestMethodReference51 {
static void test() {
IntSam s1 = MethodReference51::unknown; //method not found
IntSam s2 = MethodReference51::f; //inapplicable method
IntSam s3 = MethodReference51::g; //inapplicable methods
IntegerIntegerSam s4 = MethodReference51::g; //ambiguous
IntSam s5 = MethodReference51::h; //static error
IntSam s6 = MethodReference51.foo::j; //inaccessible method
IntSam s1 = MethodReference51::unknown; //fail
IntSam s2 = MethodReference51::f; //fail
IntSam s3 = MethodReference51::g; //fail
IntegerIntegerSam s4 = MethodReference51::g; //fail
IntSam s5 = MethodReference51::h; //fail
IntSam s6 = MethodReference51.foo::j; //fail
}
}
MethodReference68.java:21:10: compiler.err.cant.apply.symbol: kindname.method, g, MethodReference68.F<Z>,Z[], @493,int, kindname.class, MethodReference68, (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Integer, MethodReference68.Foo,java.lang.Object)
1 error
MethodReference68.java:21:12: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, getName())
2 errors
/*
* @test /nodynamiccopyright/
* @bug 8026231
* @summary Look at 'static' flag when checking method references
* @compile/fail/ref=MethodReference73.out -XDrawDiagnostics MethodReference73.java
*/
public class MethodReference73 {
interface SAM {
void m(MethodReference73 rec, String x);
}
void m1(MethodReference73 rec, String x) {}
static void m1(MethodReference73 rec, Object x) {}
void m1(String x) {}
static void m2(MethodReference73 rec, String x) {}
void m2(Object x) {}
static void m2(String x) {}
static void m3(MethodReference73 rec, String x) {}
void m3(String x) {}
void m4(MethodReference73 rec, String x) {}
static void m4(MethodReference73 rec, Object x) {}
static void m4(String x) {}
void m4(Object x) {}
static void m5(MethodReference73 rec, String x) {}
static void m5(String x) {}
static void m6(MethodReference73 rec, String x) {}
void m6(String x, int i) {}
void m7(MethodReference73 rec, String x) {}
void m7(String x) {}
static void m8(MethodReference73 rec, String x, int i) {}
void m8(String x) {}
void m9(MethodReference73 rec, String x) {}
static void m9(MethodReference73 rec, Object x) {}
static void m9(String x) {}
void m10(MethodReference73 rec, String x) {}
static void m10(MethodReference73 rec, Object x) {}
void m10(String x, int i) {}
void m11(MethodReference73 rec, String x) {}
void m11(Object x) {}
static void m11(String x) {}
static void m12(MethodReference73 rec, String x, int i) {}
void m12(Object x) {}
static void m12(String x) {}
void m13(MethodReference73 rec, String x) {}
void m13(String x, int i) {}
static void m14(MethodReference73 rec, String x, int i) {}
static void m14(String x) {}
void m15(MethodReference73 rec, String x) {}
static void m15(String x) {}
static void m16(MethodReference73 rec, String x, int i) {}
void m16(String x, int i) {}
/** For method references with a type selector two searches are performed.
* Each of them may yield one of the following results:
* I) a good match
* II) a bad match more specific than a good match
* III) a bad match with no good matches
* IV) no applicable method found
*
* Whether a match is considered to be good or not depends on the staticness
* of the matched method. The expected result of the first search is a static
* method. The expected result of the second search is an instance method.
*
* If the most specific method has the wrong staticness but there is an
* applicable method with the right staticness then we have the (II) case.
* The (III) case is reserved for those cases when the most specific method
* has the wrong staticness but there is no applicable method with the right
* staticness.
*/
static void test() {
SAM s1 = MethodReference73::m1; //(II, I) ambiguous
SAM s2 = MethodReference73::m2; //(I, II) ambiguous
SAM s3 = MethodReference73::m3; //(I, I) ambiguous
SAM s4 = MethodReference73::m4; //(II, II) ambiguous
SAM s5 = MethodReference73::m5; //(I, III) first search's result gets selected
SAM s6 = MethodReference73::m6; //(I, IV) first search's result gets selected
SAM s7 = MethodReference73::m7; //(III, I) second search's result gets selected
SAM s8 = MethodReference73::m8; //(IV, I) second search's result gets selected
SAM s9 = MethodReference73::m9; //(II, III) method matched by first search has the wrong staticness
SAM s10 = MethodReference73::m10; //(II, IV) method matched by first search has the wrong staticness
SAM s11 = MethodReference73::m11; //(III, II) method matched by second search has the wrong staticness
SAM s12 = MethodReference73::m12; //(IV, II) method matched by second search has the wrong staticness
SAM s13 = MethodReference73::m13; //(III, IV) method matched by first search has the wrong staticness
SAM s14 = MethodReference73::m14; //(IV, III) method matched by second search has the wrong staticness
SAM s15 = MethodReference73::m15; //(III, III) method matched by first search has the wrong staticness
SAM s16 = MethodReference73::m16; //(IV, IV) incompatible types, invalid method reference
}
}
MethodReference73.java:89:18: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m1, kindname.method, m1(MethodReference73,java.lang.String), MethodReference73, kindname.method, m1(java.lang.String), MethodReference73))
MethodReference73.java:90:18: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m2, kindname.method, m2(MethodReference73,java.lang.String), MethodReference73, kindname.method, m2(java.lang.String), MethodReference73))
MethodReference73.java:91:18: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m3, kindname.method, m3(MethodReference73,java.lang.String), MethodReference73, kindname.method, m3(java.lang.String), MethodReference73))
MethodReference73.java:92:18: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m4, kindname.method, m4(MethodReference73,java.lang.String), MethodReference73, kindname.method, m4(java.lang.String), MethodReference73))
MethodReference73.java:100:18: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, m9(MethodReference73,java.lang.String))
MethodReference73.java:101:19: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, m10(MethodReference73,java.lang.String))
MethodReference73.java:102:19: compiler.err.invalid.mref: kindname.method, (compiler.misc.static.method.in.unbound.lookup: kindname.method, m11(java.lang.String))
MethodReference73.java:103:19: compiler.err.invalid.mref: kindname.method, (compiler.misc.static.method.in.unbound.lookup: kindname.method, m12(java.lang.String))
MethodReference73.java:104:19: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, m13(MethodReference73,java.lang.String))
MethodReference73.java:105:19: compiler.err.invalid.mref: kindname.method, (compiler.misc.static.method.in.unbound.lookup: kindname.method, m14(java.lang.String))
MethodReference73.java:106:19: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, m15(MethodReference73,java.lang.String))
MethodReference73.java:108:19: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbols: kindname.method, m16, MethodReference73,java.lang.String,{(compiler.misc.inapplicable.method: kindname.method, MethodReference73, m16(MethodReference73,java.lang.String,int), (compiler.misc.arg.length.mismatch)),(compiler.misc.inapplicable.method: kindname.method, MethodReference73, m16(java.lang.String,int), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: MethodReference73, java.lang.String)))}))
12 errors
......@@ -57,7 +57,7 @@ class TargetType60 {
static void testUnbound() {
TargetType60 s1 = u(TargetType60::n0); //ok - resolves to u(Sam1)
TargetType60 s2 = u(TargetType60::n1); //ambiguous (u(Sam1), u(Sam2) apply)
TargetType60 s2 = u(TargetType60::n1); //ok - resolves to u(Sam2)
TargetType60 s3 = u(TargetType60::n2); //none is applicable
TargetType60 s4 = u(TargetType60::n01);//ambiguous (u(Sam1), u(Sam2) apply)
TargetType60 s5 = u(TargetType60::n012);//ambiguous (u(Sam1), u(Sam2) apply)
......
TargetType60.java:54:21: compiler.err.ref.ambiguous: g, kindname.method, g(TargetType60.Sam0), TargetType60, kindname.method, <U>g(TargetType60.Sam1<U>), TargetType60
TargetType60.java:55:21: compiler.err.ref.ambiguous: g, kindname.method, <U>g(TargetType60.Sam1<U>), TargetType60, kindname.method, <U>g(TargetType60.Sam2<U,java.lang.String>), TargetType60
TargetType60.java:60:27: compiler.err.ref.ambiguous: u, kindname.method, <U>u(TargetType60.Sam1<U>), TargetType60, kindname.method, <U>u(TargetType60.Sam2<U,java.lang.String>), TargetType60
TargetType60.java:60:29: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, n1(java.lang.String))
TargetType60.java:61:29: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, n2(TargetType60,java.lang.String))
TargetType60.java:61:27: compiler.err.cant.apply.symbols: kindname.method, u, @1639,{(compiler.misc.inapplicable.method: kindname.method, TargetType60, <U>u(TargetType60.Sam1<U>), (compiler.misc.infer.no.conforming.assignment.exists: U, (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, n2, TargetType60,java.lang.String, U, kindname.class, TargetType60, (compiler.misc.arg.length.mismatch))))),(compiler.misc.inapplicable.method: kindname.method, TargetType60, <U>u(TargetType60.Sam2<U,java.lang.String>), (compiler.misc.infer.no.conforming.assignment.exists: U, (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.resolve.location.args: kindname.method, n2, , U,java.lang.String, (compiler.misc.location: kindname.class, TargetType60, null)))))}
TargetType60.java:62:27: compiler.err.ref.ambiguous: u, kindname.method, <U>u(TargetType60.Sam1<U>), TargetType60, kindname.method, <U>u(TargetType60.Sam2<U,java.lang.String>), TargetType60
TargetType60.java:63:27: compiler.err.ref.ambiguous: u, kindname.method, <U>u(TargetType60.Sam1<U>), TargetType60, kindname.method, <U>u(TargetType60.Sam2<U,java.lang.String>), TargetType60
7 errors
5 errors
......@@ -356,7 +356,7 @@ public class TestInvokeDynamic
if (lnt == null) {
throw new Error("No LineNumberTable attribute");
}
if (lnt.line_number_table_length != 2) {
if (lnt.line_number_table_length != 3) {
throw new Error("Wrong number of entries in LineNumberTable");
}
} catch (Exception e) {
......
......@@ -46,7 +46,7 @@ public class Compiler {
USECACHE // Keeps results around for reuse. Only use this is
// you're sure that each compilation name maps to the
// same source code
};
}
private static final AtomicInteger counter = new AtomicInteger();
private static final String targetDir = "gen-separate";
......@@ -85,7 +85,7 @@ public class Compiler {
}
public void setFlags(Flags ... flags) {
this.flags = new HashSet<Flags>(Arrays.asList(flags));
this.flags = new HashSet<>(Arrays.asList(flags));
}
public void addPostprocessor(ClassFilePreprocessor cfp) {
......@@ -131,17 +131,10 @@ public class Compiler {
outputDirs.put(type.getName(), outDir);
Class superClass = type.getSuperclass();
if (superClass != null) {
for( Map.Entry<String,File> each : compileHierarchy(superClass).entrySet()) {
outputDirs.put(each.getKey(), each.getValue());
}
}
for (Extends ext : type.getSupertypes()) {
Type iface = ext.getType();
for( Map.Entry<String,File> each : compileHierarchy(iface).entrySet()) {
outputDirs.put(each.getKey(), each.getValue());
}
}
if (superClass != null)
outputDirs.putAll(compileHierarchy(superClass));
for (Extends ext : type.getSupertypes())
outputDirs.putAll(compileHierarchy(ext.getType()));
return outputDirs;
}
......@@ -157,8 +150,12 @@ public class Compiler {
SourceProcessor accum =
(name, src) -> { files.add(new SourceFile(name, src)); };
for (Type dep : type.typeDependencies()) {
dep.generateAsDependency(accum, type.methodDependencies());
Collection<Type> deps = type.typeDependencies(type.isFullCompilation());
for (Type dep : deps) {
if (type.isFullCompilation())
dep.generate(accum);
else
dep.generateAsDependency(accum, type.methodDependencies());
}
type.generate(accum);
......@@ -185,7 +182,7 @@ public class Compiler {
StandardLocation.CLASS_OUTPUT, Arrays.asList(destDir));
} catch (IOException e) {
throw new RuntimeException(
"IOException encountered during compilation");
"IOException encountered during compilation", e);
}
Boolean result = ct.call();
if (result == Boolean.FALSE) {
......
......@@ -48,7 +48,7 @@ public class SourceModel {
generate(pw);
return sw.toString();
}
};
}
public static class AccessFlag extends Element {
private String flag;
......@@ -125,6 +125,7 @@ public class SourceModel {
// (and thus will be present in stubs)
private Set<Method> methodDependencies;
private List<Type> typeDependencies;
private boolean fullCompilation;
protected Type(String name,
List<AccessFlag> flags, List<TypeParameter> params,
......@@ -214,6 +215,14 @@ public class SourceModel {
methodDependencies.add(m);
}
public boolean isFullCompilation() {
return fullCompilation;
}
public void setFullCompilation(boolean fullCompilation) {
this.fullCompilation = fullCompilation;
}
// Convenience method for creating an Extends object using this
// class and specified type arguments.
public Extends with(String ... args) {
......@@ -255,14 +264,23 @@ public class SourceModel {
pw.println("}");
}
public Collection<Type> typeDependencies() {
public Collection<Type> typeDependencies(boolean recursive) {
HashMap<String,Type> dependencies = new HashMap<>();
Type superclass = getSuperclass();
if (superclass != null) {
dependencies.put(superclass.getName(), superclass);
if (recursive) {
for (Type t : superclass.typeDependencies(true))
dependencies.put(t.getName(), t);
}
}
for (Extends e : getSupertypes())
for (Extends e : getSupertypes()) {
dependencies.put(e.getType().getName(), e.getType());
if (recursive) {
for (Type t : e.getType().typeDependencies(true))
dependencies.put(t.getName(), t);
}
}
// Do these last so that they override
for (Type t : this.typeDependencies)
dependencies.put(t.getName(), t);
......
......@@ -198,7 +198,7 @@ public class TestHarness {
assertEquals(res, value);
}
} catch (InvocationTargetException | IllegalAccessException e) {
fail("Unexpected exception thrown: " + e.getCause());
fail("Unexpected exception thrown: " + e.getCause(), e.getCause());
}
}
......@@ -227,8 +227,7 @@ public class TestHarness {
* a return type of 'int', and no arguments.
*/
public void assertInvokeVirtualEquals(int value, Class target) {
assertInvokeVirtualEquals(
new Integer(value), target, stdCM, "-1");
assertInvokeVirtualEquals(value, target, stdCM, "-1");
}
/**
......@@ -260,12 +259,31 @@ public class TestHarness {
Compiler compiler = compilerLocal.get();
compiler.setFlags(compilerFlags());
assertInvokeInterfaceEquals(
new Integer(value), target, new Extends(iface), stdAM);
assertInvokeInterfaceEquals(value, target, new Extends(iface), stdAM);
compiler.cleanup();
}
protected void assertInvokeInterfaceThrows(java.lang.Class<? extends Throwable> errorClass,
Class target, Extends iface, AbstractMethod method,
String... args) {
try {
assertInvokeInterfaceEquals(0, target, iface, method, args);
fail("Expected exception: " + errorClass);
}
catch (AssertionError e) {
Throwable cause = e.getCause();
if (cause == null)
throw e;
else if ((errorClass.isAssignableFrom(cause.getClass()))) {
// this is success
return;
}
else
throw e;
}
}
/**
* Creates a class which calls target::method(args) via invokevirtual,
* compiles and loads both the new class and 'target', and then invokes
......
......@@ -25,18 +25,22 @@
package org.openjdk.tests.vm;
import java.lang.reflect.*;
import java.util.*;
import java.io.File;
import java.io.IOException;
import org.testng.annotations.Test;
import org.openjdk.tests.separate.*;
import org.openjdk.tests.separate.Compiler;
import org.openjdk.tests.separate.TestHarness;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
import static org.openjdk.tests.separate.SourceModel.*;
import static org.openjdk.tests.separate.SourceModel.AbstractMethod;
import static org.openjdk.tests.separate.SourceModel.AccessFlag;
import static org.openjdk.tests.separate.SourceModel.Class;
import static org.openjdk.tests.separate.SourceModel.ConcreteMethod;
import static org.openjdk.tests.separate.SourceModel.DefaultMethod;
import static org.openjdk.tests.separate.SourceModel.Extends;
import static org.openjdk.tests.separate.SourceModel.Interface;
import static org.openjdk.tests.separate.SourceModel.MethodParameter;
import static org.openjdk.tests.separate.SourceModel.TypeParameter;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.fail;
@Test(groups = "vm")
public class DefaultMethodsTest extends TestHarness {
......@@ -186,7 +190,7 @@ public class DefaultMethodsTest extends TestHarness {
* TEST: D d = new D(); d.m() == 22;
* TEST: I i = new D(); i.m() == 22;
*/
void testExistingInheritedOverride() {
public void testExistingInheritedOverride() {
Interface I = new Interface("I", DefaultMethod.std("99"));
Class C = new Class("C", I, ConcreteMethod.std("11"));
Class D = new Class("D", C, ConcreteMethod.std("22"));
......@@ -258,7 +262,6 @@ public class DefaultMethodsTest extends TestHarness {
* TEST: C c = new C(); c.m() throws ICCE
*/
public void testConflict() {
// debugTest();
Interface I = new Interface("I", DefaultMethod.std("99"));
Interface J = new Interface("J", DefaultMethod.std("88"));
Class C = new Class("C", I, J);
......@@ -390,19 +393,16 @@ public class DefaultMethodsTest extends TestHarness {
/**
* interface I<T> { default int m(T t) { return 99; } }
* Class C implements I<String> { public int m() { return 88; } }
* Class C implements I<String> { public int m(String s) { return 88; } }
*
* TEST: C c = new C(); c.m() == 88;
* TEST: I i = new C(); i.m() == 88;
* TEST: C c = new C(); c.m("string") == 88;
* TEST: I i = new C(); i.m("string") == 88;
*/
@Test(enabled=false)
public void testSelfFill() {
// This test ensures that a concrete method overrides a default method
// that matches at the language-level, but has a different method
// signature due to erasure.
// debugTest();
DefaultMethod dm = new DefaultMethod(
"int", "m", "return 99;", new MethodParameter("T", "t"));
ConcreteMethod cm = new ConcreteMethod(
......@@ -415,9 +415,11 @@ public class DefaultMethodsTest extends TestHarness {
AbstractMethod pm = new AbstractMethod(
"int", "m", new MethodParameter("T", "t"));
assertInvokeVirtualEquals(new Integer(88), C, cm, "-1", "\"string\"");
assertInvokeInterfaceEquals(
new Integer(88), C, I.with("String"), pm, "\"string\"");
assertInvokeVirtualEquals(88, C, cm, "-1", "\"string\"");
assertInvokeInterfaceEquals(99, C, I.with("String"), pm, "\"string\"");
C.setFullCompilation(true); // Force full bridge generation
assertInvokeInterfaceEquals(88, C, I.with("String"), pm, "\"string\"");
}
/**
......@@ -485,7 +487,6 @@ public class DefaultMethodsTest extends TestHarness {
* TEST: J<String,String> j = new C(); j.m("A","B","C") == 88;
* TEST: K<String> k = new C(); k.m("A","B","C") == 88;
*/
@Test(enabled=false)
public void testBridges() {
DefaultMethod dm = new DefaultMethod("int", stdMethodName, "return 99;",
new MethodParameter("T", "t"), new MethodParameter("V", "v"),
......@@ -518,13 +519,17 @@ public class DefaultMethodsTest extends TestHarness {
J.with("String", "T"), pm2);
Class C = new Class("C", K.with("String"), cm);
// First, without compiler bridges
String[] args = new String[] { "\"A\"", "\"B\"", "\"C\"" };
assertInvokeInterfaceEquals(new Integer(88), C,
I.with("String", "String", "String"), pm0, args);
assertInvokeInterfaceEquals(new Integer(88), C,
J.with("String", "String"), pm1, args);
assertInvokeInterfaceEquals(new Integer(88), C,
K.with("String"), pm2, args);
assertInvokeInterfaceEquals(99, C, I.with("String", "String", "String"), pm0, args);
assertInvokeInterfaceThrows(AbstractMethodError.class, C, J.with("String", "String"), pm1, args);
assertInvokeInterfaceThrows(AbstractMethodError.class, C, K.with("String"), pm2, args);
// Then with compiler bridges
C.setFullCompilation(true);
assertInvokeInterfaceEquals(88, C, I.with("String", "String", "String"), pm0, args);
assertInvokeInterfaceEquals(88, C, J.with("String", "String"), pm1, args);
assertInvokeInterfaceEquals(88, C, K.with("String"), pm2, args);
}
/**
......@@ -536,8 +541,6 @@ public class DefaultMethodsTest extends TestHarness {
* TEST: I i = new C(); i.m() == 88;
*/
public void testSuperBasic() {
// debugTest();
Interface J = new Interface("J", DefaultMethod.std("88"));
Interface I = new Interface("I", J, new DefaultMethod(
"int", stdMethodName, "return J.super.m();"));
......@@ -559,8 +562,6 @@ public class DefaultMethodsTest extends TestHarness {
* TODO: add case for K k = new C(); k.m() throws ICCE
*/
public void testSuperConflict() {
// debugTest();
Interface K = new Interface("K", DefaultMethod.std("99"));
Interface L = new Interface("L", DefaultMethod.std("101"));
Interface J = new Interface("J", K, L);
......@@ -635,8 +636,7 @@ public class DefaultMethodsTest extends TestHarness {
AbstractMethod pm = new AbstractMethod("int", stdMethodName,
new MethodParameter("String", "s"));
assertInvokeInterfaceEquals(
new Integer(88), C, new Extends(I), pm, "\"\"");
assertInvokeInterfaceEquals(88, C, new Extends(I), pm, "\"\"");
}
/**
......@@ -674,7 +674,6 @@ public class DefaultMethodsTest extends TestHarness {
* class S { Object foo() { return (new D()).m(); } // link sig: ()LInteger;
* TEST: S s = new S(); s.foo() == new Integer(99)
*/
@Test(enabled=false)
public void testCovarBridge() {
Interface I = new Interface("I", new DefaultMethod(
"Integer", "m", "return new Integer(88);"));
......@@ -692,7 +691,8 @@ public class DefaultMethodsTest extends TestHarness {
S.addCompilationDependency(Dstub);
S.addCompilationDependency(DstubMethod);
assertInvokeVirtualEquals(new Integer(99), S, toCall, "null");
// NEGATIVE test for separate compilation -- dispatches to I, not C
assertInvokeVirtualEquals(88, S, toCall, "null");
}
/**
......@@ -719,7 +719,7 @@ public class DefaultMethodsTest extends TestHarness {
S.addCompilationDependency(Dstub);
S.addCompilationDependency(DstubMethod);
assertInvokeVirtualEquals(new Integer(88), S, toCall, "null");
assertInvokeVirtualEquals(88, S, toCall, "null");
}
/**
......@@ -757,7 +757,6 @@ public class DefaultMethodsTest extends TestHarness {
* Test that a erased-signature-matching method does not implement
* non-language-level matching methods
*/
@Test(enabled=false)
public void testNonConcreteFill() {
AbstractMethod ipm = new AbstractMethod("int", "m",
new MethodParameter("T", "t"),
......@@ -781,13 +780,14 @@ public class DefaultMethodsTest extends TestHarness {
new MethodParameter("T", "t"),
new MethodParameter("String", "s"),
new MethodParameter("String", "w"));
DefaultMethod kdm = new DefaultMethod("int", "m", "return 99;",
new MethodParameter("T", "t"),
new MethodParameter("String", "v"),
new MethodParameter("String", "w"));
Interface K = new Interface("K",
new TypeParameter("T"),
J.with("T", "String"),
new DefaultMethod("int", "m", "return 99;",
new MethodParameter("T", "t"),
new MethodParameter("String", "v"),
new MethodParameter("String", "w")));
kdm);
Class C = new Class("C",
K.with("String"),
......@@ -797,13 +797,18 @@ public class DefaultMethodsTest extends TestHarness {
new MethodParameter("Object", "v"),
new MethodParameter("String", "w")));
// First, without compiler bridges
String a = "\"\"";
assertInvokeInterfaceEquals(99, C,
K.with("String"), kpm, a, a, a);
assertInvokeInterfaceEquals(77, C,
J.with("String", "String"), jpm, a, a, a);
assertInvokeInterfaceEquals(99, C,
I.with("String", "String", "String"), ipm, a, a, a);
assertInvokeInterfaceEquals(99, C, K.with("String"), kpm, a, a, a);
assertInvokeInterfaceEquals(77, C, J.with("String", "String"), jpm, a, a, a);
assertInvokeInterfaceThrows(AbstractMethodError.class, C, I.with("String", "String", "String"), ipm, a, a, a);
// Now, with bridges
J.setFullCompilation(true);
K.setFullCompilation(true);
assertInvokeInterfaceEquals(99, C, K.with("String"), kpm, a, a, a);
assertInvokeInterfaceEquals(77, C, J.with("String", "String"), jpm, a, a, a);
assertInvokeInterfaceEquals(99, C, I.with("String", "String", "String"), ipm, a, a, a);
}
public void testStrictfpDefault() {
......
/*
* Copyright (c) 2013, 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.
*/
import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedOptions;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.DiagnosticListener;
import javax.tools.FileObject;
import javax.tools.ForwardingJavaFileManager;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind;
import javax.tools.SimpleJavaFileObject;
import com.sun.source.tree.AnnotationTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.LiteralTree;
import com.sun.source.util.JavacTask;
import com.sun.source.util.TreeScanner;
import com.sun.source.util.Trees;
import com.sun.tools.javac.api.JavacTool;
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.util.Assert;
@SupportedAnnotationTypes("*")
@SupportedOptions("target")
public class Processor extends AbstractProcessor {
private int round = 0;
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (round++ == 0) {
try (Writer out = processingEnv.getFiler()
.createSourceFile("Anno.java")
.openWriter()) {
String target = processingEnv.getOptions().get("target");
String code = "import java.lang.annotation.ElementType;\n" +
"import java.lang.annotation.Target;\n" +
"@Target(ElementType." + target + ")\n" +
"@interface Anno { public String value(); }\n";
out.write(code);
} catch (IOException exc) {
throw new IllegalStateException(exc);
}
}
return true;
}
public static void main(String... args) throws IOException, URISyntaxException {
if (args.length != 1) throw new IllegalStateException("Must provide class name!");
String testContent = null;
File testSrc = new File(System.getProperty("test.src"));
File testFile = new File(testSrc, args[0]);
if (!testFile.canRead()) throw new IllegalStateException("Cannot read the test source");
JavacTool compiler = JavacTool.create();
JavacFileManager fm = compiler.getStandardFileManager(null, null, null);
testContent = fm.getRegularFile(testFile).getCharContent(true).toString();
JavaFileObject testFileObject = new TestFO(new URI("mem://" + args[0]), testContent);
TestFM testFileManager = new TestFM(fm);
JavacTask task = compiler.getTask(null,
testFileManager,
new DiagnosticCollector<JavaFileObject>(),
null,
null,
Arrays.asList(testFileObject));
final Trees trees = Trees.instance(task);
final CompilationUnitTree cut = task.parse().iterator().next();
final Map<int[], String> annotation2Target = new TreeMap<>(new Comparator<int[]>() {
@Override public int compare(int[] o1, int[] o2) {
return o2[0] - o1[0];
}
});
new TreeScanner<Void, Void>() {
@Override
public Void visitAnnotation(AnnotationTree node, Void p) {
int endPos = (int) trees.getSourcePositions().getEndPosition(cut, node);
Assert.check(endPos >= 0);
int startPos = (int) trees.getSourcePositions().getStartPosition(cut, node);
String target = ((LiteralTree) node.getArguments().get(0)).getValue().toString();
annotation2Target.put(new int[] {startPos, endPos}, target);
return super.visitAnnotation(node, p);
}
}.scan(cut.getTypeDecls().get(0), null);
DiagnosticListener<JavaFileObject> noErrors = new DiagnosticListener<JavaFileObject>() {
@Override public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
throw new IllegalStateException(diagnostic.toString());
}
}
};
for (Entry<int[], String> e : annotation2Target.entrySet()) {
StringBuilder updatedContent = new StringBuilder();
int last = testContent.length();
for (int[] toRemove : annotation2Target.keySet()) {
if (toRemove == e.getKey()) continue;
updatedContent.insert(0, testContent.substring(toRemove[1], last));
last = toRemove[0];
}
updatedContent.insert(0, testContent.substring(0, last));
JavaFileObject updatedFile = new TestFO(new URI("mem://" + args[0]),
updatedContent.toString());
JavacTask testTask = compiler.getTask(null,
testFileManager,
noErrors,
Arrays.asList("-processor", "Processor",
"-Atarget=" + e.getValue()),
null,
Arrays.asList(updatedFile));
try {
testTask.analyze();
} catch (Throwable exc) {
System.out.println("error while processing:");
System.out.println(updatedContent);
throw exc;
}
JavacTask testTask2 = compiler.getTask(null,
testFileManager,
new DiagnosticCollector<JavaFileObject>(),
null,
null,
Arrays.asList(updatedFile));
try {
testTask2.analyze();
} catch (Throwable exc) {
System.out.println("error while processing:");
System.out.println(updatedContent);
throw exc;
}
}
}
private static final class TestFO extends SimpleJavaFileObject {
private final String content;
public TestFO(URI uri, String content) {
super(uri, Kind.SOURCE);
this.content = content;
}
@Override public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
return content;
}
@Override public boolean isNameCompatible(String simpleName, Kind kind) {
return true;
}
}
private static final class TestFM extends ForwardingJavaFileManager<JavaFileManager> {
public TestFM(JavaFileManager fileManager) {
super(fileManager);
}
@Override
public boolean isSameFile(FileObject a, FileObject b) {
return a.equals(b);
}
}
}
/*
* Copyright (c) 2013, 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 /nodynamiccopyright/
* @bug 8027310
* @summary Ensure no exceptions on unresolvable annotations
* @build Processor
* @run main Processor Source.java
*/
import java.util.List;
@Anno("TYPE")
public class Source {
@Anno("TYPE")
class Inner {
class InnerInner {
public @Anno("CONSTRUCTOR") InnerInner(@Anno("TYPE_USE") Source. @Anno("TYPE_USE") Inner Inner.this,
@Anno("PARAMETER") java.lang. @Anno("TYPE_USE") Runnable p) {
Runnable r = () -> {
@Anno("TYPE_USE") Object tested = null;
@Anno("TYPE_USE") boolean isAnnotated = tested instanceof @Anno("TYPE_USE") String;
};
@Anno("TYPE_USE") Object tested = (@Anno("TYPE_USE") String @Anno("TYPE_USE") []) null;
@Anno("TYPE_USE") boolean isAnnotated = tested instanceof@Anno("TYPE_USE") String;
tested = new java.lang. @Anno("TYPE_USE") Object();
tested = new @Anno("TYPE_USE") Object();
}
}
}
{
Runnable r = () -> {
@Anno("TYPE_USE") Object tested = null;
@Anno("TYPE_USE") boolean isAnnotated = tested instanceof @Anno("TYPE_USE") String;
};
@Anno("TYPE_USE") Object tested = (@Anno("TYPE_USE") String @Anno("TYPE_USE") []) null;
@Anno("TYPE_USE") boolean isAnnotated = tested instanceof@Anno("TYPE_USE") String;
tested = new java.lang. @Anno("TYPE_USE") Object();
tested = new @Anno("TYPE_USE") Object();
}
@Anno("TYPE")
@Anno("ANNOTATION_TYPE")
@interface A { }
abstract class Parameterized<@Anno("TYPE_PARAMETER") T extends @Anno("TYPE_USE") CharSequence &
@Anno("TYPE_USE") Runnable>
implements @Anno("TYPE_USE") List<@Anno("TYPE_USE") Runnable> { }
}
/*
* Copyright (c) 2013, 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 8027730
* @summary Test visitor support for intersection types
*/
import java.lang.annotation.Annotation;
import java.util.List;
import javax.lang.model.element.*;
import javax.lang.model.type.*;
import javax.lang.model.util.*;
public class TestIntersectionTypeVisitors {
public static void main(String... args) throws Exception {
IntersectionType it = new TestIntersectionType();
boolean result = it.accept(new TypeKindVisitor8Child(), null) &&
it.accept(new SimpleTypeVisitor8Child(), null) &&
it.accept(new SimpleTypeVisitor6Child(), null);
if (!result)
throw new RuntimeException();
}
static class TestIntersectionType implements IntersectionType {
TestIntersectionType() {}
@Override
public List<? extends TypeMirror> getBounds() {
throw new UnsupportedOperationException();
}
@Override
public <R,P> R accept(TypeVisitor<R,P> v,
P p) {
return v.visitIntersection(this, p);
}
@Override
public TypeKind getKind() {
return TypeKind.INTERSECTION;
}
@Override
public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
throw new UnsupportedOperationException();
}
@Override
public List<? extends AnnotationMirror> getAnnotationMirrors() {
throw new UnsupportedOperationException();
}
@Override
public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType) {
throw new UnsupportedOperationException();
}
}
static class TypeKindVisitor8Child extends TypeKindVisitor8<Boolean, Void> {
TypeKindVisitor8Child() {
super(false);
}
@Override
public Boolean visitIntersection(IntersectionType t, Void p) {
super.visitIntersection(t, p); // Make sure overridden method doesn't throw an exception
return true;
}
}
static class SimpleTypeVisitor8Child extends SimpleTypeVisitor8<Boolean, Void> {
SimpleTypeVisitor8Child() {
super(false);
}
@Override
public Boolean visitIntersection(IntersectionType t, Void p) {
super.visitIntersection(t, p); // Make sure overridden method doesn't throw an exception
return true;
}
}
static class SimpleTypeVisitor6Child extends SimpleTypeVisitor6<Boolean, Void> {
SimpleTypeVisitor6Child() {
super(false);
}
@Override
public Boolean visitIntersection(IntersectionType t, Void p) {
try {
super.visitIntersection(t, p);
return false;
} catch (UnknownTypeException ute) {
return true; // Expected
}
}
}
}
/*
* Copyright (c) 2013, 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 8025844
* @summary test DocumentationTool.Location methods
* @build APITest
* @run main DocumentationToolLocationTest
*/
import javax.tools.DocumentationTool;
import java.util.Objects;
/**
* Test for DocumentationTool.Location methods.
*/
public class DocumentationToolLocationTest extends APITest {
public static void main(String[] args) throws Exception {
new DocumentationToolLocationTest().run();
}
/**
* Test getName() method
*/
@Test
public void testGetName() throws Exception {
// getName() returns name(). This is for test coverage of getName.
for (DocumentationTool.Location dl: DocumentationTool.Location.values()) {
String expect = dl.name();
String found = dl.getName();
if (!Objects.equals(expect, found))
throw new Exception("mismatch for " + dl + "; expected " + expect + ", found " + found);
}
}
/**
* Test generated enum methods values() and valueOf()
*/
@Test
public void testEnumMethods() throws Exception {
DocumentationTool.Location[] values = DocumentationTool.Location.values();
if (values.length != 3)
throw new Exception("unexpected number of values returned");
for (DocumentationTool.Location dl: values) {
DocumentationTool.Location expect = dl;
DocumentationTool.Location found = DocumentationTool.Location.valueOf(dl.name());
if (!Objects.equals(expect, found))
throw new Exception("mismatch for " + dl + "; expected " + expect + ", found " + found);
}
}
}
......@@ -16,7 +16,7 @@ class pkg1.O<T>.I<S>
superclass:
java.lang.Object
constructors:
O.I()
I()
methods:
void m1(O<String>.I<Number>)
......@@ -36,7 +36,7 @@ class pkg1.X<T>.Y
superclass:
java.lang.Object
constructors:
X.Y()
Y()
class pkg1.X<T>.Y.Z<S>
name: Z / X.Y.Z / pkg1.X.Y.Z
......@@ -47,7 +47,7 @@ class pkg1.X<T>.Y.Z<S>
superclass:
java.lang.Object
constructors:
X.Y.Z()
Z()
methods:
void m1(X<String>.Y.Z<Number>)
/*
* Copyright (c) 2013, 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 8027530
* @summary test -public, -protected, -package, -private options
*/
import java.io.*;
import java.util.*;
import java.lang.StringBuilder;
public class AccessModifiers {
public int errorCount;
protected String protectedField;
String packageField;
private String privateField;
public static void main(String[] args) throws Exception {
new AccessModifiers().run();
}
private void run() throws Exception {
List<String> pubMembers = new ArrayList<String>();
pubMembers.add("public int errorCount");
pubMembers.add("public AccessModifiers");
pubMembers.add("public static void main");
List<String> proMembers = new ArrayList<String>();
proMembers.add("protected java.lang.String protectedField");
proMembers.add("protected java.lang.String runJavap");
List<String> pkgMembers = new ArrayList<String>();
pkgMembers.add("java.lang.String packageField");
pkgMembers.add("boolean verify");
pkgMembers.add("void error");
List<String> priMembers = new ArrayList<String>();
priMembers.add("private java.lang.String privateField");
priMembers.add("private void run() throws java.lang.Exception");
priMembers.add("private void test");
List<String> expectedList = new ArrayList<String>();
expectedList.addAll(pubMembers);
test("-public", expectedList);
expectedList.addAll(proMembers);
test("-protected", expectedList);
expectedList.addAll(pkgMembers);
test("-package", expectedList);
expectedList.addAll(priMembers);
test("-private", expectedList);
if (errorCount > 0)
throw new Exception(errorCount + " errors received");
}
private void test(String option, List<String> expectedStrs) throws Exception {
String output = runJavap(0, option);
if (verify(output, expectedStrs))
System.out.println(option + " test passed");
}
protected String runJavap(int expect, String... options) {
// convert the varargs to a list in order to add class name
List<String> optlist = new ArrayList<String>();
optlist.addAll(Arrays.asList(options));
optlist.add("AccessModifiers");
String[] newoptions = optlist.toArray(new String[optlist.size()]);
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
System.out.printf("\nRun javap " + optlist + "\n\n");
int rc = com.sun.tools.javap.Main.run(newoptions, pw);
pw.close();
System.out.println(sw);
if (rc != expect)
throw new Error("Expect to return " + expect + ", but return " + rc);
return sw.toString();
}
boolean verify(String output, List<String> expects) {
boolean pass = true;
for (String expect: expects) {
if (!output.contains(expect)) {
error(expect + " not found");
pass = false;
}
}
return pass;
}
void error(String msg) {
System.err.println(msg);
errorCount++;
}
}
/*
* Copyright (c) 2013, 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 8027411
* @summary test invalid options -h and -b
*/
import java.io.*;
import java.util.zip.*;
public class InvalidOptions {
int errorCount;
String log;
public static void main(String[] args) throws Exception {
new InvalidOptions().run();
}
void run() throws Exception {
test(2, "-h", "Error: -h is no longer available - use the javah program");
test(2, "-b", "Error: unknown option: -b",
"Usage: javap <options> <classes>",
"use -help for a list of possible options");
if (errorCount > 0)
throw new Exception(errorCount + " errors received");
}
void test(int expect, String option, String ... expectedOutput) {
String output = runJavap(expect, option);
verify(output, expectedOutput);
}
String runJavap(int expect, String... option) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
int rc = com.sun.tools.javap.Main.run(option, pw);
pw.close();
System.out.println("javap prints:");
System.out.println(sw);
if (rc != expect)
throw new Error("Expect to return " + expect + ", but return " + rc);
return sw.toString();
}
void verify(String output, String... expects) {
for (String expect: expects) {
if (!output.contains(expect))
error(expect + " not found");
}
}
void error(String msg) {
System.err.println(msg);
errorCount++;
}
}
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2013, 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,9 +23,9 @@
/*
* @test
* @bug 8003562 8005428 8015912
* @bug 8003562 8005428 8015912 8027481
* @summary Basic tests for jdeps tool
* @build Test p.Foo
* @build Test p.Foo p.Bar javax.activity.NotCompactProfile
* @run main Basic
*/
......@@ -33,10 +33,12 @@ import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.regex.*;
import static java.nio.file.StandardCopyOption.*;
public class Basic {
private static boolean symbolFileExist = initProfiles();
......@@ -74,23 +76,25 @@ public class Basic {
new String[] {"java.lang", "p"},
new String[] {"compact1", "not found"});
// test a directory
// also test non-SE javax.activity class dependency
test(new File(testDir, "p"),
new String[] {"java.lang", "java.util", "java.lang.management"},
new String[] {"compact1", "compact1", "compact3"});
new String[] {"java.lang", "java.util", "java.lang.management", "javax.activity", "javax.crypto"},
new String[] {"compact1", "compact1", "compact3", testDir.getName(), "compact1"},
new String[] {"-classpath", testDir.getPath()});
// test class-level dependency output
test(new File(testDir, "Test.class"),
new String[] {"java.lang.Object", "java.lang.String", "p.Foo"},
new String[] {"compact1", "compact1", "not found"},
new String[] {"java.lang.Object", "java.lang.String", "p.Foo", "p.Bar"},
new String[] {"compact1", "compact1", "not found", "not found"},
new String[] {"-verbose:class"});
// test -p option
test(new File(testDir, "Test.class"),
new String[] {"p.Foo"},
new String[] {"not found"},
new String[] {"p.Foo", "p.Bar"},
new String[] {"not found", "not found"},
new String[] {"-verbose:class", "-p", "p"});
// test -e option
test(new File(testDir, "Test.class"),
new String[] {"p.Foo"},
new String[] {"not found"},
new String[] {"p.Foo", "p.Bar"},
new String[] {"not found", "not found"},
new String[] {"-verbose:class", "-e", "p\\..*"});
test(new File(testDir, "Test.class"),
new String[] {"java.lang"},
......@@ -99,13 +103,34 @@ public class Basic {
// test -classpath and -include options
test(null,
new String[] {"java.lang", "java.util",
"java.lang.management"},
new String[] {"compact1", "compact1", "compact3"},
"java.lang.management", "javax.crypto"},
new String[] {"compact1", "compact1", "compact3", "compact1"},
new String[] {"-classpath", testDir.getPath(), "-include", "p.+|Test.class"});
test(new File(testDir, "Test.class"),
new String[] {"java.lang.Object", "java.lang.String", "p.Foo"},
new String[] {"compact1", "compact1", testDir.getName()},
new String[] {"java.lang.Object", "java.lang.String", "p.Foo", "p.Bar"},
new String[] {"compact1", "compact1", testDir.getName(), testDir.getName()},
new String[] {"-v", "-classpath", testDir.getPath(), "Test.class"});
// split package p - move p/Foo.class to dir1 and p/Bar.class to dir2
Path testClassPath = testDir.toPath();
Path dirP = testClassPath.resolve("p");
Path dir1 = testClassPath.resolve("dir1");
Path subdir1P = dir1.resolve("p");
Path dir2 = testClassPath.resolve("dir2");
Path subdir2P = dir2.resolve("p");
if (!Files.exists(subdir1P))
Files.createDirectories(subdir1P);
if (!Files.exists(subdir2P))
Files.createDirectories(subdir2P);
Files.move(dirP.resolve("Foo.class"), subdir1P.resolve("Foo.class"), REPLACE_EXISTING);
Files.move(dirP.resolve("Bar.class"), subdir2P.resolve("Bar.class"), REPLACE_EXISTING);
StringBuilder cpath = new StringBuilder(testDir.toString());
cpath.append(File.pathSeparator).append(dir1.toString());
cpath.append(File.pathSeparator).append(dir2.toString());
test(new File(testDir, "Test.class"),
new String[] {"java.lang.Object", "java.lang.String", "p.Foo", "p.Bar"},
new String[] {"compact1", "compact1", dir1.toFile().getName(), dir2.toFile().getName()},
new String[] {"-v", "-classpath", cpath.toString(), "Test.class"});
return errors;
}
......@@ -148,7 +173,7 @@ public class Basic {
// Use the linePattern to break the given String into lines, applying
// the pattern to each line to see if we have a match
private static Map<String,String> findDeps(String out) {
Map<String,String> result = new HashMap<>();
Map<String,String> result = new LinkedHashMap<>();
Matcher lm = linePattern.matcher(out); // Line matcher
Matcher pm = null; // Pattern matcher
int lines = 0;
......
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2013, 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 @@
public class Test {
public void test() {
p.Foo f = new p.Foo();
p.Bar b = new p.Bar();
}
private String name() {
return "this test";
......
......@@ -21,8 +21,10 @@
* questions.
*/
// key: compiler.err.intf.or.array.expected.here
package javax.activity;
import java.util.List;
class InterfaceExpected<T extends List & String> { }
public class NotCompactProfile {
public static String name() {
return "not Java SE API";
}
}
......@@ -21,18 +21,13 @@
* questions.
*/
/*
* @test
* @bug 8021339
* @summary Allow arrays in intersection types
* @compile -doe -XDrawDiagnostics InferArraysInIntersections.java
*/
import java.util.*;
class InferArraysInIntersections {
<T> T m(List<? super T> t) { return null; }
package p;
void test(List<char[]> lc) {
Runnable r = m(lc); //inference fails here
}
public class Bar extends javax.activity.NotCompactProfile {
public String bar() {
return "bar";
}
public javax.crypto.Cipher getCiper() {
return null;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册