mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-16 17:14:41 +02:00
7192246: Add type-checking support for default methods
Add type-checking support for default methods as per Featherweight-Defender document Reviewed-by: jjg, dlsmith
This commit is contained in:
parent
d50b720ecc
commit
d4be9a13c8
86 changed files with 3844 additions and 102 deletions
|
@ -67,7 +67,6 @@ public class Flags {
|
||||||
if ((mask&NATIVE) != 0) flags.add(Flag.NATIVE);
|
if ((mask&NATIVE) != 0) flags.add(Flag.NATIVE);
|
||||||
if ((mask&INTERFACE) != 0) flags.add(Flag.INTERFACE);
|
if ((mask&INTERFACE) != 0) flags.add(Flag.INTERFACE);
|
||||||
if ((mask&ABSTRACT) != 0) flags.add(Flag.ABSTRACT);
|
if ((mask&ABSTRACT) != 0) flags.add(Flag.ABSTRACT);
|
||||||
if ((mask&DEFAULT) != 0) flags.add(Flag.DEFAULT);
|
|
||||||
if ((mask&STRICTFP) != 0) flags.add(Flag.STRICTFP);
|
if ((mask&STRICTFP) != 0) flags.add(Flag.STRICTFP);
|
||||||
if ((mask&BRIDGE) != 0) flags.add(Flag.BRIDGE);
|
if ((mask&BRIDGE) != 0) flags.add(Flag.BRIDGE);
|
||||||
if ((mask&SYNTHETIC) != 0) flags.add(Flag.SYNTHETIC);
|
if ((mask&SYNTHETIC) != 0) flags.add(Flag.SYNTHETIC);
|
||||||
|
|
|
@ -206,6 +206,9 @@ public enum Source {
|
||||||
public boolean allowDefaultMethods() {
|
public boolean allowDefaultMethods() {
|
||||||
return compareTo(JDK1_8) >= 0;
|
return compareTo(JDK1_8) >= 0;
|
||||||
}
|
}
|
||||||
|
public boolean allowStrictMethodClashCheck() {
|
||||||
|
return compareTo(JDK1_8) >= 0;
|
||||||
|
}
|
||||||
public boolean allowEffectivelyFinalInInnerClasses() {
|
public boolean allowEffectivelyFinalInInnerClasses() {
|
||||||
return compareTo(JDK1_8) >= 0;
|
return compareTo(JDK1_8) >= 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1192,9 +1192,9 @@ public abstract class Symbol implements Element {
|
||||||
|
|
||||||
// check for an inherited implementation
|
// check for an inherited implementation
|
||||||
if ((flags() & ABSTRACT) != 0 ||
|
if ((flags() & ABSTRACT) != 0 ||
|
||||||
(other.flags() & ABSTRACT) == 0 ||
|
(other.flags() & ABSTRACT) == 0 ||
|
||||||
!other.isOverridableIn(origin) ||
|
!other.isOverridableIn(origin) ||
|
||||||
!this.isMemberOf(origin, types))
|
!this.isMemberOf(origin, types))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// assert types.asSuper(origin.type, other.owner) != null;
|
// assert types.asSuper(origin.type, other.owner) != null;
|
||||||
|
|
|
@ -75,6 +75,7 @@ public class Types {
|
||||||
final boolean allowBoxing;
|
final boolean allowBoxing;
|
||||||
final boolean allowCovariantReturns;
|
final boolean allowCovariantReturns;
|
||||||
final boolean allowObjectToPrimitiveCast;
|
final boolean allowObjectToPrimitiveCast;
|
||||||
|
final boolean allowDefaultMethods;
|
||||||
final ClassReader reader;
|
final ClassReader reader;
|
||||||
final Check chk;
|
final Check chk;
|
||||||
JCDiagnostic.Factory diags;
|
JCDiagnostic.Factory diags;
|
||||||
|
@ -98,6 +99,7 @@ public class Types {
|
||||||
allowBoxing = source.allowBoxing();
|
allowBoxing = source.allowBoxing();
|
||||||
allowCovariantReturns = source.allowCovariantReturns();
|
allowCovariantReturns = source.allowCovariantReturns();
|
||||||
allowObjectToPrimitiveCast = source.allowObjectToPrimitiveCast();
|
allowObjectToPrimitiveCast = source.allowObjectToPrimitiveCast();
|
||||||
|
allowDefaultMethods = source.allowDefaultMethods();
|
||||||
reader = ClassReader.instance(context);
|
reader = ClassReader.instance(context);
|
||||||
chk = Check.instance(context);
|
chk = Check.instance(context);
|
||||||
capturedName = names.fromString("<captured wildcard>");
|
capturedName = names.fromString("<captured wildcard>");
|
||||||
|
@ -2146,6 +2148,13 @@ public class Types {
|
||||||
return List.nil();
|
return List.nil();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public boolean isDirectSuperInterface(Type t, TypeSymbol tsym) {
|
||||||
|
for (Type t2 : interfaces(tsym.type)) {
|
||||||
|
if (isSameType(t, t2)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// </editor-fold>
|
// </editor-fold>
|
||||||
|
|
||||||
// <editor-fold defaultstate="collapsed" desc="isDerivedRaw">
|
// <editor-fold defaultstate="collapsed" desc="isDerivedRaw">
|
||||||
|
@ -2310,6 +2319,10 @@ public class Types {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean overridesObjectMethod(Symbol msym) {
|
||||||
|
return ((MethodSymbol)msym).implementation(syms.objectType.tsym, this, true) != null;
|
||||||
|
}
|
||||||
|
|
||||||
// <editor-fold defaultstate="collapsed" desc="Determining method implementation in given site">
|
// <editor-fold defaultstate="collapsed" desc="Determining method implementation in given site">
|
||||||
class ImplementationCache {
|
class ImplementationCache {
|
||||||
|
|
||||||
|
@ -2455,6 +2468,70 @@ public class Types {
|
||||||
}
|
}
|
||||||
// </editor-fold>
|
// </editor-fold>
|
||||||
|
|
||||||
|
|
||||||
|
//where
|
||||||
|
public List<MethodSymbol> interfaceCandidates(Type site, MethodSymbol ms) {
|
||||||
|
return interfaceCandidates(site, ms, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<MethodSymbol> interfaceCandidates(Type site, MethodSymbol ms, boolean intfOnly) {
|
||||||
|
Filter<Symbol> filter = new MethodFilter(ms, site, intfOnly);
|
||||||
|
List<MethodSymbol> candidates = List.nil();
|
||||||
|
for (Symbol s : membersClosure(site, false).getElements(filter)) {
|
||||||
|
if (!site.tsym.isInterface() && !s.owner.isInterface()) {
|
||||||
|
return List.of((MethodSymbol)s);
|
||||||
|
} else if (!candidates.contains(s)) {
|
||||||
|
candidates = candidates.prepend((MethodSymbol)s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return prune(candidates, ownerComparator);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<MethodSymbol> prune(List<MethodSymbol> methods, Comparator<MethodSymbol> cmp) {
|
||||||
|
ListBuffer<MethodSymbol> methodsMin = ListBuffer.lb();
|
||||||
|
for (MethodSymbol m1 : methods) {
|
||||||
|
boolean isMin_m1 = true;
|
||||||
|
for (MethodSymbol m2 : methods) {
|
||||||
|
if (m1 == m2) continue;
|
||||||
|
if (cmp.compare(m2, m1) < 0) {
|
||||||
|
isMin_m1 = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isMin_m1)
|
||||||
|
methodsMin.append(m1);
|
||||||
|
}
|
||||||
|
return methodsMin.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
Comparator<MethodSymbol> ownerComparator = new Comparator<MethodSymbol>() {
|
||||||
|
public int compare(MethodSymbol s1, MethodSymbol s2) {
|
||||||
|
return s1.owner.isSubClass(s2.owner, Types.this) ? -1 : 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// where
|
||||||
|
private class MethodFilter implements Filter<Symbol> {
|
||||||
|
|
||||||
|
Symbol msym;
|
||||||
|
Type site;
|
||||||
|
boolean intfOnly;
|
||||||
|
|
||||||
|
MethodFilter(Symbol msym, Type site, boolean intfOnly) {
|
||||||
|
this.msym = msym;
|
||||||
|
this.site = site;
|
||||||
|
this.intfOnly = intfOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean accepts(Symbol s) {
|
||||||
|
return s.kind == Kinds.MTH &&
|
||||||
|
(!intfOnly || s.owner.isInterface()) &&
|
||||||
|
s.name == msym.name &&
|
||||||
|
s.isInheritedIn(site.tsym, Types.this) &&
|
||||||
|
overrideEquivalent(memberType(site, s), memberType(site, msym));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// </editor-fold>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does t have the same arguments as s? It is assumed that both
|
* Does t have the same arguments as s? It is assumed that both
|
||||||
* types are (possibly polymorphic) method types. Monomorphic
|
* types are (possibly polymorphic) method types. Monomorphic
|
||||||
|
|
|
@ -135,6 +135,7 @@ public class Attr extends JCTree.Visitor {
|
||||||
allowStringsInSwitch = source.allowStringsInSwitch();
|
allowStringsInSwitch = source.allowStringsInSwitch();
|
||||||
allowPoly = source.allowPoly() && options.isSet("allowPoly");
|
allowPoly = source.allowPoly() && options.isSet("allowPoly");
|
||||||
allowLambda = source.allowLambda();
|
allowLambda = source.allowLambda();
|
||||||
|
allowDefaultMethods = source.allowDefaultMethods();
|
||||||
sourceName = source.name;
|
sourceName = source.name;
|
||||||
relax = (options.isSet("-retrofit") ||
|
relax = (options.isSet("-retrofit") ||
|
||||||
options.isSet("-relax"));
|
options.isSet("-relax"));
|
||||||
|
@ -178,6 +179,10 @@ public class Attr extends JCTree.Visitor {
|
||||||
*/
|
*/
|
||||||
boolean allowCovariantReturns;
|
boolean allowCovariantReturns;
|
||||||
|
|
||||||
|
/** Switch: support default methods ?
|
||||||
|
*/
|
||||||
|
boolean allowDefaultMethods;
|
||||||
|
|
||||||
/** Switch: support lambda expressions ?
|
/** Switch: support lambda expressions ?
|
||||||
*/
|
*/
|
||||||
boolean allowLambda;
|
boolean allowLambda;
|
||||||
|
@ -898,6 +903,10 @@ public class Attr extends JCTree.Visitor {
|
||||||
|
|
||||||
localEnv.info.lint = lint;
|
localEnv.info.lint = lint;
|
||||||
|
|
||||||
|
if (isDefaultMethod && types.overridesObjectMethod(m)) {
|
||||||
|
log.error(tree, "default.overrides.object.member", m.name, Kinds.kindName(m.location()), m.location());
|
||||||
|
}
|
||||||
|
|
||||||
// Enter all type parameters into the local method scope.
|
// Enter all type parameters into the local method scope.
|
||||||
for (List<JCTypeParameter> l = tree.typarams; l.nonEmpty(); l = l.tail)
|
for (List<JCTypeParameter> l = tree.typarams; l.nonEmpty(); l = l.tail)
|
||||||
localEnv.info.scope.enterIfAbsent(l.head.type.tsym);
|
localEnv.info.scope.enterIfAbsent(l.head.type.tsym);
|
||||||
|
@ -961,10 +970,12 @@ public class Attr extends JCTree.Visitor {
|
||||||
log.error(tree.pos(),
|
log.error(tree.pos(),
|
||||||
"default.allowed.in.intf.annotation.member");
|
"default.allowed.in.intf.annotation.member");
|
||||||
}
|
}
|
||||||
} else if ((owner.flags() & INTERFACE) != 0 && !isDefaultMethod) {
|
} else if ((tree.sym.flags() & ABSTRACT) != 0 && !isDefaultMethod) {
|
||||||
log.error(tree.body.pos(), "intf.meth.cant.have.body");
|
if ((owner.flags() & INTERFACE) != 0) {
|
||||||
} else if ((tree.mods.flags & ABSTRACT) != 0) {
|
log.error(tree.body.pos(), "intf.meth.cant.have.body");
|
||||||
log.error(tree.pos(), "abstract.meth.cant.have.body");
|
} else {
|
||||||
|
log.error(tree.pos(), "abstract.meth.cant.have.body");
|
||||||
|
}
|
||||||
} else if ((tree.mods.flags & NATIVE) != 0) {
|
} else if ((tree.mods.flags & NATIVE) != 0) {
|
||||||
log.error(tree.pos(), "native.meth.cant.have.body");
|
log.error(tree.pos(), "native.meth.cant.have.body");
|
||||||
} else {
|
} else {
|
||||||
|
@ -3281,6 +3292,23 @@ public class Attr extends JCTree.Visitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (env.info.defaultSuperCallSite != null &&
|
||||||
|
!types.interfaceCandidates(env.enclClass.type, (MethodSymbol)sym, true).contains(sym)) {
|
||||||
|
Symbol ovSym = null;
|
||||||
|
for (MethodSymbol msym : types.interfaceCandidates(env.enclClass.type, (MethodSymbol)sym, true)) {
|
||||||
|
if (msym.overrides(sym, msym.enclClass(), types, true)) {
|
||||||
|
for (Type i : types.interfaces(env.enclClass.type)) {
|
||||||
|
if (i.tsym.isSubClass(msym.owner, types)) {
|
||||||
|
ovSym = i.tsym;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.error(env.tree.pos(), "illegal.default.super.call", env.info.defaultSuperCallSite,
|
||||||
|
diags.fragment("overridden.default", sym, ovSym));
|
||||||
|
}
|
||||||
|
|
||||||
// Compute the identifier's instantiated type.
|
// Compute the identifier's instantiated type.
|
||||||
// For methods, we need to compute the instance type by
|
// For methods, we need to compute the instance type by
|
||||||
// Resolve.instantiate from the symbol's type as well as
|
// Resolve.instantiate from the symbol's type as well as
|
||||||
|
@ -3700,6 +3728,9 @@ public class Attr extends JCTree.Visitor {
|
||||||
// are compatible (i.e. no two define methods with same arguments
|
// are compatible (i.e. no two define methods with same arguments
|
||||||
// yet different return types). (JLS 8.4.6.3)
|
// yet different return types). (JLS 8.4.6.3)
|
||||||
chk.checkCompatibleSupertypes(tree.pos(), c.type);
|
chk.checkCompatibleSupertypes(tree.pos(), c.type);
|
||||||
|
if (allowDefaultMethods) {
|
||||||
|
chk.checkDefaultMethodClashes(tree.pos(), c.type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that class does not import the same parameterized interface
|
// Check that class does not import the same parameterized interface
|
||||||
|
|
|
@ -72,6 +72,10 @@ public class AttrContext {
|
||||||
*/
|
*/
|
||||||
Attr.ResultInfo returnResult = null;
|
Attr.ResultInfo returnResult = null;
|
||||||
|
|
||||||
|
/** Symbol corresponding to the site of a qualified default super call
|
||||||
|
*/
|
||||||
|
Type defaultSuperCallSite = null;
|
||||||
|
|
||||||
/** Duplicate this context, replacing scope field and copying all others.
|
/** Duplicate this context, replacing scope field and copying all others.
|
||||||
*/
|
*/
|
||||||
AttrContext dup(Scope scope) {
|
AttrContext dup(Scope scope) {
|
||||||
|
@ -84,6 +88,7 @@ public class AttrContext {
|
||||||
info.lint = lint;
|
info.lint = lint;
|
||||||
info.enclVar = enclVar;
|
info.enclVar = enclVar;
|
||||||
info.returnResult = returnResult;
|
info.returnResult = returnResult;
|
||||||
|
info.defaultSuperCallSite = defaultSuperCallSite;
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -119,6 +119,9 @@ public class Check {
|
||||||
allowAnnotations = source.allowAnnotations();
|
allowAnnotations = source.allowAnnotations();
|
||||||
allowCovariantReturns = source.allowCovariantReturns();
|
allowCovariantReturns = source.allowCovariantReturns();
|
||||||
allowSimplifiedVarargs = source.allowSimplifiedVarargs();
|
allowSimplifiedVarargs = source.allowSimplifiedVarargs();
|
||||||
|
allowDefaultMethods = source.allowDefaultMethods();
|
||||||
|
allowStrictMethodClashCheck = source.allowStrictMethodClashCheck() &&
|
||||||
|
options.isSet("strictMethodClashCheck"); //pre-lambda guard
|
||||||
complexInference = options.isSet("complexinference");
|
complexInference = options.isSet("complexinference");
|
||||||
warnOnSyntheticConflicts = options.isSet("warnOnSyntheticConflicts");
|
warnOnSyntheticConflicts = options.isSet("warnOnSyntheticConflicts");
|
||||||
suppressAbortOnBadClassFile = options.isSet("suppressAbortOnBadClassFile");
|
suppressAbortOnBadClassFile = options.isSet("suppressAbortOnBadClassFile");
|
||||||
|
@ -162,6 +165,14 @@ public class Check {
|
||||||
*/
|
*/
|
||||||
boolean allowSimplifiedVarargs;
|
boolean allowSimplifiedVarargs;
|
||||||
|
|
||||||
|
/** Switch: default methods enabled?
|
||||||
|
*/
|
||||||
|
boolean allowDefaultMethods;
|
||||||
|
|
||||||
|
/** Switch: should unrelated return types trigger a method clash?
|
||||||
|
*/
|
||||||
|
boolean allowStrictMethodClashCheck;
|
||||||
|
|
||||||
/** Switch: -complexinference option set?
|
/** Switch: -complexinference option set?
|
||||||
*/
|
*/
|
||||||
boolean complexInference;
|
boolean complexInference;
|
||||||
|
@ -1114,7 +1125,7 @@ public class Check {
|
||||||
} else if ((sym.owner.flags_field & INTERFACE) != 0) {
|
} else if ((sym.owner.flags_field & INTERFACE) != 0) {
|
||||||
if ((flags & DEFAULT) != 0) {
|
if ((flags & DEFAULT) != 0) {
|
||||||
mask = InterfaceDefaultMethodMask;
|
mask = InterfaceDefaultMethodMask;
|
||||||
implicit = PUBLIC;
|
implicit = PUBLIC | ABSTRACT;
|
||||||
} else {
|
} else {
|
||||||
mask = implicit = InterfaceMethodFlags;
|
mask = implicit = InterfaceMethodFlags;
|
||||||
}
|
}
|
||||||
|
@ -2047,11 +2058,21 @@ public class Check {
|
||||||
undef == null && e != null;
|
undef == null && e != null;
|
||||||
e = e.sibling) {
|
e = e.sibling) {
|
||||||
if (e.sym.kind == MTH &&
|
if (e.sym.kind == MTH &&
|
||||||
(e.sym.flags() & (ABSTRACT|IPROXY)) == ABSTRACT) {
|
(e.sym.flags() & (ABSTRACT|IPROXY|DEFAULT)) == ABSTRACT) {
|
||||||
MethodSymbol absmeth = (MethodSymbol)e.sym;
|
MethodSymbol absmeth = (MethodSymbol)e.sym;
|
||||||
MethodSymbol implmeth = absmeth.implementation(impl, types, true);
|
MethodSymbol implmeth = absmeth.implementation(impl, types, true);
|
||||||
if (implmeth == null || implmeth == absmeth)
|
if (implmeth == null || implmeth == absmeth) {
|
||||||
|
//look for default implementations
|
||||||
|
if (allowDefaultMethods) {
|
||||||
|
MethodSymbol prov = types.interfaceCandidates(impl.type, absmeth).head;
|
||||||
|
if (prov != null && prov.overrides(absmeth, impl, types, true)) {
|
||||||
|
implmeth = prov;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (implmeth == null || implmeth == absmeth) {
|
||||||
undef = absmeth;
|
undef = absmeth;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (undef == null) {
|
if (undef == null) {
|
||||||
|
@ -2354,7 +2375,7 @@ public class Check {
|
||||||
if (m2 == m1) continue;
|
if (m2 == m1) continue;
|
||||||
//if (i) the signature of 'sym' is not a subsignature of m1 (seen as
|
//if (i) the signature of 'sym' is not a subsignature of m1 (seen as
|
||||||
//a member of 'site') and (ii) m1 has the same erasure as m2, issue an error
|
//a member of 'site') and (ii) m1 has the same erasure as m2, issue an error
|
||||||
if (!types.isSubSignature(sym.type, types.memberType(site, m2), false) &&
|
if (!types.isSubSignature(sym.type, types.memberType(site, m2), allowStrictMethodClashCheck) &&
|
||||||
types.hasSameArgs(m2.erasure(types), m1.erasure(types))) {
|
types.hasSameArgs(m2.erasure(types), m1.erasure(types))) {
|
||||||
sym.flags_field |= CLASH;
|
sym.flags_field |= CLASH;
|
||||||
String key = m1 == sym ?
|
String key = m1 == sym ?
|
||||||
|
@ -2386,7 +2407,7 @@ public class Check {
|
||||||
for (Symbol s : types.membersClosure(site, true).getElementsByName(sym.name, cf)) {
|
for (Symbol s : types.membersClosure(site, true).getElementsByName(sym.name, cf)) {
|
||||||
//if (i) the signature of 'sym' is not a subsignature of m1 (seen as
|
//if (i) the signature of 'sym' is not a subsignature of m1 (seen as
|
||||||
//a member of 'site') and (ii) 'sym' has the same erasure as m1, issue an error
|
//a member of 'site') and (ii) 'sym' has the same erasure as m1, issue an error
|
||||||
if (!types.isSubSignature(sym.type, types.memberType(site, s), false) &&
|
if (!types.isSubSignature(sym.type, types.memberType(site, s), allowStrictMethodClashCheck) &&
|
||||||
types.hasSameArgs(s.erasure(types), sym.erasure(types))) {
|
types.hasSameArgs(s.erasure(types), sym.erasure(types))) {
|
||||||
log.error(pos,
|
log.error(pos,
|
||||||
"name.clash.same.erasure.no.hide",
|
"name.clash.same.erasure.no.hide",
|
||||||
|
@ -2420,6 +2441,62 @@ public class Check {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void checkDefaultMethodClashes(DiagnosticPosition pos, Type site) {
|
||||||
|
DefaultMethodClashFilter dcf = new DefaultMethodClashFilter(site);
|
||||||
|
for (Symbol m : types.membersClosure(site, false).getElements(dcf)) {
|
||||||
|
Assert.check(m.kind == MTH);
|
||||||
|
List<MethodSymbol> prov = types.interfaceCandidates(site, (MethodSymbol)m);
|
||||||
|
if (prov.size() > 1) {
|
||||||
|
ListBuffer<Symbol> abstracts = ListBuffer.lb();
|
||||||
|
ListBuffer<Symbol> defaults = ListBuffer.lb();
|
||||||
|
for (MethodSymbol provSym : prov) {
|
||||||
|
if ((provSym.flags() & DEFAULT) != 0) {
|
||||||
|
defaults = defaults.append(provSym);
|
||||||
|
} else if ((provSym.flags() & ABSTRACT) != 0) {
|
||||||
|
abstracts = abstracts.append(provSym);
|
||||||
|
}
|
||||||
|
if (defaults.nonEmpty() && defaults.size() + abstracts.size() >= 2) {
|
||||||
|
//strong semantics - issue an error if two sibling interfaces
|
||||||
|
//have two override-equivalent defaults - or if one is abstract
|
||||||
|
//and the other is default
|
||||||
|
String errKey;
|
||||||
|
Symbol s1 = defaults.first();
|
||||||
|
Symbol s2;
|
||||||
|
if (defaults.size() > 1) {
|
||||||
|
errKey = "types.incompatible.unrelated.defaults";
|
||||||
|
s2 = defaults.toList().tail.head;
|
||||||
|
} else {
|
||||||
|
errKey = "types.incompatible.abstract.default";
|
||||||
|
s2 = abstracts.first();
|
||||||
|
}
|
||||||
|
log.error(pos, errKey,
|
||||||
|
Kinds.kindName(site.tsym), site,
|
||||||
|
m.name, types.memberType(site, m).getParameterTypes(),
|
||||||
|
s1.location(), s2.location());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//where
|
||||||
|
private class DefaultMethodClashFilter implements Filter<Symbol> {
|
||||||
|
|
||||||
|
Type site;
|
||||||
|
|
||||||
|
DefaultMethodClashFilter(Type site) {
|
||||||
|
this.site = site;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean accepts(Symbol s) {
|
||||||
|
return s.kind == MTH &&
|
||||||
|
(s.flags() & DEFAULT) != 0 &&
|
||||||
|
s.isInheritedIn(site.tsym, types) &&
|
||||||
|
!s.isConstructor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Report a conflict between a user symbol and a synthetic symbol.
|
/** Report a conflict between a user symbol and a synthetic symbol.
|
||||||
*/
|
*/
|
||||||
private void syntheticError(DiagnosticPosition pos, Symbol sym) {
|
private void syntheticError(DiagnosticPosition pos, Symbol sym) {
|
||||||
|
|
|
@ -3631,15 +3631,26 @@ public class Lower extends TreeTranslator {
|
||||||
|
|
||||||
public void visitSelect(JCFieldAccess tree) {
|
public void visitSelect(JCFieldAccess tree) {
|
||||||
// need to special case-access of the form C.super.x
|
// need to special case-access of the form C.super.x
|
||||||
// these will always need an access method.
|
// these will always need an access method, unless C
|
||||||
|
// is a default interface subclassed by the current class.
|
||||||
boolean qualifiedSuperAccess =
|
boolean qualifiedSuperAccess =
|
||||||
tree.selected.hasTag(SELECT) &&
|
tree.selected.hasTag(SELECT) &&
|
||||||
TreeInfo.name(tree.selected) == names._super;
|
TreeInfo.name(tree.selected) == names._super &&
|
||||||
|
!types.isDirectSuperInterface(((JCFieldAccess)tree.selected).selected.type, currentClass);
|
||||||
tree.selected = translate(tree.selected);
|
tree.selected = translate(tree.selected);
|
||||||
if (tree.name == names._class)
|
if (tree.name == names._class) {
|
||||||
result = classOf(tree.selected);
|
result = classOf(tree.selected);
|
||||||
else if (tree.name == names._this || tree.name == names._super)
|
}
|
||||||
|
else if (tree.name == names._super &&
|
||||||
|
types.isDirectSuperInterface(tree.selected.type, currentClass)) {
|
||||||
|
//default super call!! Not a classic qualified super call
|
||||||
|
TypeSymbol supSym = tree.selected.type.tsym;
|
||||||
|
Assert.checkNonNull(types.asSuper(currentClass.type, supSym));
|
||||||
|
result = tree;
|
||||||
|
}
|
||||||
|
else if (tree.name == names._this || tree.name == names._super) {
|
||||||
result = makeThis(tree.pos(), tree.selected.type.tsym);
|
result = makeThis(tree.pos(), tree.selected.type.tsym);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
result = access(tree.sym, tree, enclOp, qualifiedSuperAccess);
|
result = access(tree.sym, tree, enclOp, qualifiedSuperAccess);
|
||||||
}
|
}
|
||||||
|
|
|
@ -560,6 +560,12 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||||
MethodSymbol m = new MethodSymbol(0, tree.name, null, enclScope.owner);
|
MethodSymbol m = new MethodSymbol(0, tree.name, null, enclScope.owner);
|
||||||
m.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, m, tree);
|
m.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, m, tree);
|
||||||
tree.sym = m;
|
tree.sym = m;
|
||||||
|
|
||||||
|
//if this is a default method, add the DEFAULT flag to the enclosing interface
|
||||||
|
if ((tree.mods.flags & DEFAULT) != 0) {
|
||||||
|
m.enclClass().flags_field |= DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
Env<AttrContext> localEnv = methodEnv(tree, env);
|
Env<AttrContext> localEnv = methodEnv(tree, env);
|
||||||
|
|
||||||
DeferredLintHandler prevLintHandler =
|
DeferredLintHandler prevLintHandler =
|
||||||
|
@ -677,7 +683,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||||
localEnv.info.scope.owner = tree.sym;
|
localEnv.info.scope.owner = tree.sym;
|
||||||
}
|
}
|
||||||
if ((tree.mods.flags & STATIC) != 0 ||
|
if ((tree.mods.flags & STATIC) != 0 ||
|
||||||
(env.enclClass.sym.flags() & INTERFACE) != 0)
|
((env.enclClass.sym.flags() & INTERFACE) != 0 && env.enclMethod == null))
|
||||||
localEnv.info.staticLevel++;
|
localEnv.info.staticLevel++;
|
||||||
return localEnv;
|
return localEnv;
|
||||||
}
|
}
|
||||||
|
@ -1001,20 +1007,19 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is a class, enter symbols for this and super into
|
// enter symbols for 'this' into current scope.
|
||||||
// current scope.
|
VarSymbol thisSym =
|
||||||
if ((c.flags_field & INTERFACE) == 0) {
|
new VarSymbol(FINAL | HASINIT, names._this, c.type, c);
|
||||||
VarSymbol thisSym =
|
thisSym.pos = Position.FIRSTPOS;
|
||||||
new VarSymbol(FINAL | HASINIT, names._this, c.type, c);
|
env.info.scope.enter(thisSym);
|
||||||
thisSym.pos = Position.FIRSTPOS;
|
// if this is a class, enter symbol for 'super' into current scope.
|
||||||
env.info.scope.enter(thisSym);
|
if ((c.flags_field & INTERFACE) == 0 &&
|
||||||
if (ct.supertype_field.hasTag(CLASS)) {
|
ct.supertype_field.hasTag(CLASS)) {
|
||||||
VarSymbol superSym =
|
VarSymbol superSym =
|
||||||
new VarSymbol(FINAL | HASINIT, names._super,
|
new VarSymbol(FINAL | HASINIT, names._super,
|
||||||
ct.supertype_field, c);
|
ct.supertype_field, c);
|
||||||
superSym.pos = Position.FIRSTPOS;
|
superSym.pos = Position.FIRSTPOS;
|
||||||
env.info.scope.enter(superSym);
|
env.info.scope.enter(superSym);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check that no package exists with same fully qualified name,
|
// check that no package exists with same fully qualified name,
|
||||||
|
|
|
@ -52,6 +52,7 @@ import java.util.EnumMap;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.lang.model.element.ElementVisitor;
|
import javax.lang.model.element.ElementVisitor;
|
||||||
|
|
||||||
|
@ -88,6 +89,7 @@ public class Resolve {
|
||||||
public final boolean boxingEnabled; // = source.allowBoxing();
|
public final boolean boxingEnabled; // = source.allowBoxing();
|
||||||
public final boolean varargsEnabled; // = source.allowVarargs();
|
public final boolean varargsEnabled; // = source.allowVarargs();
|
||||||
public final boolean allowMethodHandles;
|
public final boolean allowMethodHandles;
|
||||||
|
public final boolean allowDefaultMethods;
|
||||||
private final boolean debugResolve;
|
private final boolean debugResolve;
|
||||||
final EnumSet<VerboseResolutionMode> verboseResolutionMode;
|
final EnumSet<VerboseResolutionMode> verboseResolutionMode;
|
||||||
|
|
||||||
|
@ -122,6 +124,7 @@ public class Resolve {
|
||||||
verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options);
|
verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options);
|
||||||
Target target = Target.instance(context);
|
Target target = Target.instance(context);
|
||||||
allowMethodHandles = target.hasMethodHandles();
|
allowMethodHandles = target.hasMethodHandles();
|
||||||
|
allowDefaultMethods = source.allowDefaultMethods();
|
||||||
polymorphicSignatureScope = new Scope(syms.noSymbol);
|
polymorphicSignatureScope = new Scope(syms.noSymbol);
|
||||||
|
|
||||||
inapplicableMethodException = new InapplicableMethodException(diags);
|
inapplicableMethodException = new InapplicableMethodException(diags);
|
||||||
|
@ -1327,6 +1330,42 @@ public class Resolve {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Symbol lookupMethod(Env<AttrContext> env,
|
||||||
|
Type site,
|
||||||
|
Name name,
|
||||||
|
List<Type> argtypes,
|
||||||
|
List<Type> typeargtypes,
|
||||||
|
Scope sc,
|
||||||
|
Symbol bestSoFar,
|
||||||
|
boolean allowBoxing,
|
||||||
|
boolean useVarargs,
|
||||||
|
boolean operator,
|
||||||
|
boolean abstractok) {
|
||||||
|
for (Symbol s : sc.getElementsByName(name, new LookupFilter(abstractok))) {
|
||||||
|
bestSoFar = selectBest(env, site, argtypes, typeargtypes, s,
|
||||||
|
bestSoFar, allowBoxing, useVarargs, operator);
|
||||||
|
}
|
||||||
|
return bestSoFar;
|
||||||
|
}
|
||||||
|
//where
|
||||||
|
class LookupFilter implements Filter<Symbol> {
|
||||||
|
|
||||||
|
boolean abstractOk;
|
||||||
|
|
||||||
|
LookupFilter(boolean abstractOk) {
|
||||||
|
this.abstractOk = abstractOk;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean accepts(Symbol s) {
|
||||||
|
long flags = s.flags();
|
||||||
|
return s.kind == MTH &&
|
||||||
|
(flags & SYNTHETIC) == 0 &&
|
||||||
|
(abstractOk ||
|
||||||
|
(flags & DEFAULT) != 0 ||
|
||||||
|
(flags & ABSTRACT) == 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/** Find best qualified method matching given name, type and value
|
/** Find best qualified method matching given name, type and value
|
||||||
* arguments.
|
* arguments.
|
||||||
* @param env The current environment.
|
* @param env The current environment.
|
||||||
|
@ -1371,49 +1410,76 @@ public class Resolve {
|
||||||
boolean allowBoxing,
|
boolean allowBoxing,
|
||||||
boolean useVarargs,
|
boolean useVarargs,
|
||||||
boolean operator) {
|
boolean operator) {
|
||||||
boolean abstractOk = true;
|
@SuppressWarnings({"unchecked","rawtypes"})
|
||||||
List<Type> itypes = List.nil();
|
List<Type>[] itypes = (List<Type>[])new List[] { List.<Type>nil(), List.<Type>nil() };
|
||||||
|
InterfaceLookupPhase iphase = InterfaceLookupPhase.ABSTRACT_OK;
|
||||||
for (TypeSymbol s : superclasses(intype)) {
|
for (TypeSymbol s : superclasses(intype)) {
|
||||||
bestSoFar = lookupMethod(env, site, name, argtypes, typeargtypes,
|
bestSoFar = lookupMethod(env, site, name, argtypes, typeargtypes,
|
||||||
s.members(), bestSoFar, allowBoxing, useVarargs, operator, true);
|
s.members(), bestSoFar, allowBoxing, useVarargs, operator, true);
|
||||||
//We should not look for abstract methods if receiver is a concrete class
|
if (name == names.init) return bestSoFar;
|
||||||
//(as concrete classes are expected to implement all abstracts coming
|
iphase = (iphase == null) ? null : iphase.update(s, this);
|
||||||
//from superinterfaces)
|
if (iphase != null) {
|
||||||
abstractOk &= (s.flags() & (ABSTRACT | INTERFACE | ENUM)) != 0;
|
|
||||||
if (abstractOk) {
|
|
||||||
for (Type itype : types.interfaces(s.type)) {
|
for (Type itype : types.interfaces(s.type)) {
|
||||||
itypes = types.union(types.closure(itype), itypes);
|
itypes[iphase.ordinal()] = types.union(types.closure(itype), itypes[iphase.ordinal()]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (name == names.init) break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Symbol concrete = bestSoFar.kind < ERR &&
|
Symbol concrete = bestSoFar.kind < ERR &&
|
||||||
(bestSoFar.flags() & ABSTRACT) == 0 ?
|
(bestSoFar.flags() & ABSTRACT) == 0 ?
|
||||||
bestSoFar : methodNotFound;
|
bestSoFar : methodNotFound;
|
||||||
|
|
||||||
if (name != names.init) {
|
for (InterfaceLookupPhase iphase2 : InterfaceLookupPhase.values()) {
|
||||||
|
if (iphase2 == InterfaceLookupPhase.DEFAULT_OK && !allowDefaultMethods) break;
|
||||||
//keep searching for abstract methods
|
//keep searching for abstract methods
|
||||||
for (Type itype : itypes) {
|
for (Type itype : itypes[iphase2.ordinal()]) {
|
||||||
if (!itype.isInterface()) continue; //skip j.l.Object (included by Types.closure())
|
if (!itype.isInterface()) continue; //skip j.l.Object (included by Types.closure())
|
||||||
|
if (iphase2 == InterfaceLookupPhase.DEFAULT_OK &&
|
||||||
|
(itype.tsym.flags() & DEFAULT) == 0) continue;
|
||||||
bestSoFar = lookupMethod(env, site, name, argtypes, typeargtypes,
|
bestSoFar = lookupMethod(env, site, name, argtypes, typeargtypes,
|
||||||
itype.tsym.members(), bestSoFar, allowBoxing, useVarargs, operator, true);
|
itype.tsym.members(), bestSoFar, allowBoxing, useVarargs, operator, true);
|
||||||
if (concrete != bestSoFar &&
|
if (concrete != bestSoFar &&
|
||||||
concrete.kind < ERR && bestSoFar.kind < ERR &&
|
concrete.kind < ERR && bestSoFar.kind < ERR &&
|
||||||
types.isSubSignature(concrete.type, bestSoFar.type)) {
|
types.isSubSignature(concrete.type, bestSoFar.type)) {
|
||||||
//this is an hack - as javac does not do full membership checks
|
//this is an hack - as javac does not do full membership checks
|
||||||
//most specific ends up comparing abstract methods that might have
|
//most specific ends up comparing abstract methods that might have
|
||||||
//been implemented by some concrete method in a subclass and,
|
//been implemented by some concrete method in a subclass and,
|
||||||
//because of raw override, it is possible for an abstract method
|
//because of raw override, it is possible for an abstract method
|
||||||
//to be more specific than the concrete method - so we need
|
//to be more specific than the concrete method - so we need
|
||||||
//to explicitly call that out (see CR 6178365)
|
//to explicitly call that out (see CR 6178365)
|
||||||
bestSoFar = concrete;
|
bestSoFar = concrete;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return bestSoFar;
|
return bestSoFar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum InterfaceLookupPhase {
|
||||||
|
ABSTRACT_OK() {
|
||||||
|
@Override
|
||||||
|
InterfaceLookupPhase update(Symbol s, Resolve rs) {
|
||||||
|
//We should not look for abstract methods if receiver is a concrete class
|
||||||
|
//(as concrete classes are expected to implement all abstracts coming
|
||||||
|
//from superinterfaces)
|
||||||
|
if ((s.flags() & (ABSTRACT | INTERFACE | ENUM)) != 0) {
|
||||||
|
return this;
|
||||||
|
} else if (rs.allowDefaultMethods) {
|
||||||
|
return DEFAULT_OK;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
DEFAULT_OK() {
|
||||||
|
@Override
|
||||||
|
InterfaceLookupPhase update(Symbol s, Resolve rs) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
abstract InterfaceLookupPhase update(Symbol s, Resolve rs);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an Iterable object to scan the superclasses of a given type.
|
* Return an Iterable object to scan the superclasses of a given type.
|
||||||
* It's crucial that the scan is done lazily, as we don't want to accidentally
|
* It's crucial that the scan is done lazily, as we don't want to accidentally
|
||||||
|
@ -1467,34 +1533,6 @@ public class Resolve {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Lookup a method with given name and argument types in a given scope
|
|
||||||
*/
|
|
||||||
Symbol lookupMethod(Env<AttrContext> env,
|
|
||||||
Type site,
|
|
||||||
Name name,
|
|
||||||
List<Type> argtypes,
|
|
||||||
List<Type> typeargtypes,
|
|
||||||
Scope sc,
|
|
||||||
Symbol bestSoFar,
|
|
||||||
boolean allowBoxing,
|
|
||||||
boolean useVarargs,
|
|
||||||
boolean operator,
|
|
||||||
boolean abstractok) {
|
|
||||||
for (Symbol s : sc.getElementsByName(name, lookupFilter)) {
|
|
||||||
bestSoFar = selectBest(env, site, argtypes, typeargtypes, s,
|
|
||||||
bestSoFar, allowBoxing, useVarargs, operator);
|
|
||||||
}
|
|
||||||
return bestSoFar;
|
|
||||||
}
|
|
||||||
//where
|
|
||||||
Filter<Symbol> lookupFilter = new Filter<Symbol>() {
|
|
||||||
public boolean accepts(Symbol s) {
|
|
||||||
return s.kind == MTH &&
|
|
||||||
(s.flags() & SYNTHETIC) == 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Find unqualified method matching given name, type and value arguments.
|
/** Find unqualified method matching given name, type and value arguments.
|
||||||
* @param env The current environment.
|
* @param env The current environment.
|
||||||
* @param name The method's name.
|
* @param name The method's name.
|
||||||
|
@ -1920,7 +1958,7 @@ public class Resolve {
|
||||||
/** Check that sym is not an abstract method.
|
/** Check that sym is not an abstract method.
|
||||||
*/
|
*/
|
||||||
void checkNonAbstract(DiagnosticPosition pos, Symbol sym) {
|
void checkNonAbstract(DiagnosticPosition pos, Symbol sym) {
|
||||||
if ((sym.flags() & ABSTRACT) != 0)
|
if ((sym.flags() & ABSTRACT) != 0 && (sym.flags() & DEFAULT) == 0)
|
||||||
log.error(pos, "abstract.cant.be.accessed.directly",
|
log.error(pos, "abstract.cant.be.accessed.directly",
|
||||||
kindName(sym), sym, sym.location());
|
kindName(sym), sym, sym.location());
|
||||||
}
|
}
|
||||||
|
@ -2744,9 +2782,47 @@ public class Resolve {
|
||||||
if ((env1.enclClass.sym.flags() & STATIC) != 0) staticOnly = true;
|
if ((env1.enclClass.sym.flags() & STATIC) != 0) staticOnly = true;
|
||||||
env1 = env1.outer;
|
env1 = env1.outer;
|
||||||
}
|
}
|
||||||
|
if (allowDefaultMethods && c.isInterface() &&
|
||||||
|
name == names._super && !isStatic(env) &&
|
||||||
|
types.isDirectSuperInterface(c.type, env.enclClass.sym)) {
|
||||||
|
//this might be a default super call if one of the superinterfaces is 'c'
|
||||||
|
for (Type t : pruneInterfaces(env.enclClass.type)) {
|
||||||
|
if (t.tsym == c) {
|
||||||
|
env.info.defaultSuperCallSite = t;
|
||||||
|
return new VarSymbol(0, names._super,
|
||||||
|
types.asSuper(env.enclClass.type, c), env.enclClass.sym);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//find a direct superinterface that is a subtype of 'c'
|
||||||
|
for (Type i : types.interfaces(env.enclClass.type)) {
|
||||||
|
if (i.tsym.isSubClass(c, types) && i.tsym != c) {
|
||||||
|
log.error(pos, "illegal.default.super.call", c,
|
||||||
|
diags.fragment("redundant.supertype", c, i));
|
||||||
|
return syms.errSymbol;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Assert.error();
|
||||||
|
}
|
||||||
log.error(pos, "not.encl.class", c);
|
log.error(pos, "not.encl.class", c);
|
||||||
return syms.errSymbol;
|
return syms.errSymbol;
|
||||||
}
|
}
|
||||||
|
//where
|
||||||
|
private List<Type> pruneInterfaces(Type t) {
|
||||||
|
ListBuffer<Type> result = ListBuffer.lb();
|
||||||
|
for (Type t1 : types.interfaces(t)) {
|
||||||
|
boolean shouldAdd = true;
|
||||||
|
for (Type t2 : types.interfaces(t)) {
|
||||||
|
if (t1 != t2 && types.isSubtypeNoCapture(t2, t1)) {
|
||||||
|
shouldAdd = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (shouldAdd) {
|
||||||
|
result.append(t1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve `c.this' for an enclosing class c that contains the
|
* Resolve `c.this' for an enclosing class c that contains the
|
||||||
|
|
|
@ -115,6 +115,9 @@ public class ClassReader implements Completer {
|
||||||
*/
|
*/
|
||||||
boolean lintClassfile;
|
boolean lintClassfile;
|
||||||
|
|
||||||
|
/** Switch: allow default methods
|
||||||
|
*/
|
||||||
|
boolean allowDefaultMethods;
|
||||||
|
|
||||||
/** Switch: preserve parameter names from the variable table.
|
/** Switch: preserve parameter names from the variable table.
|
||||||
*/
|
*/
|
||||||
|
@ -279,6 +282,7 @@ public class ClassReader implements Completer {
|
||||||
allowVarargs = source.allowVarargs();
|
allowVarargs = source.allowVarargs();
|
||||||
allowAnnotations = source.allowAnnotations();
|
allowAnnotations = source.allowAnnotations();
|
||||||
allowSimplifiedVarargs = source.allowSimplifiedVarargs();
|
allowSimplifiedVarargs = source.allowSimplifiedVarargs();
|
||||||
|
allowDefaultMethods = source.allowDefaultMethods();
|
||||||
saveParameterNames = options.isSet("save-parameter-names");
|
saveParameterNames = options.isSet("save-parameter-names");
|
||||||
cacheCompletionFailure = options.isUnset("dev");
|
cacheCompletionFailure = options.isUnset("dev");
|
||||||
preferSource = "source".equals(options.get("-Xprefer"));
|
preferSource = "source".equals(options.get("-Xprefer"));
|
||||||
|
@ -937,6 +941,18 @@ public class ClassReader implements Completer {
|
||||||
|
|
||||||
new AttributeReader(names.Code, V45_3, MEMBER_ATTRIBUTE) {
|
new AttributeReader(names.Code, V45_3, MEMBER_ATTRIBUTE) {
|
||||||
protected void read(Symbol sym, int attrLen) {
|
protected void read(Symbol sym, int attrLen) {
|
||||||
|
if (currentOwner.isInterface() &&
|
||||||
|
(sym.flags_field & ABSTRACT) == 0 && !name.equals(names.clinit)) {
|
||||||
|
if (majorVersion > Target.JDK1_8.majorVersion ||
|
||||||
|
//todo replace with Target.Version when available
|
||||||
|
(majorVersion == Target.JDK1_8.majorVersion && minorVersion >= Target.JDK1_8.minorVersion)) {
|
||||||
|
currentOwner.flags_field |= DEFAULT;
|
||||||
|
sym.flags_field |= DEFAULT | ABSTRACT;
|
||||||
|
} else {
|
||||||
|
//protect against ill-formed classfiles
|
||||||
|
throw new CompletionFailure(currentOwner, "default method found in pre JDK 8 classfile");
|
||||||
|
}
|
||||||
|
}
|
||||||
if (readAllOfClassFile || saveParameterNames)
|
if (readAllOfClassFile || saveParameterNames)
|
||||||
((MethodSymbol)sym).code = readCode(sym);
|
((MethodSymbol)sym).code = readCode(sym);
|
||||||
else
|
else
|
||||||
|
|
|
@ -1540,7 +1540,7 @@ public class ClassWriter extends ClassFile {
|
||||||
List<Type> interfaces = types.interfaces(c.type);
|
List<Type> interfaces = types.interfaces(c.type);
|
||||||
List<Type> typarams = c.type.getTypeArguments();
|
List<Type> typarams = c.type.getTypeArguments();
|
||||||
|
|
||||||
int flags = adjustFlags(c.flags());
|
int flags = adjustFlags(c.flags() & ~DEFAULT);
|
||||||
if ((flags & PROTECTED) != 0) flags |= PUBLIC;
|
if ((flags & PROTECTED) != 0) flags |= PUBLIC;
|
||||||
flags = flags & ClassFlags & ~STRICTFP;
|
flags = flags & ClassFlags & ~STRICTFP;
|
||||||
if ((flags & INTERFACE) == 0) flags |= ACC_SUPER;
|
if ((flags & INTERFACE) == 0) flags |= ACC_SUPER;
|
||||||
|
@ -1676,6 +1676,8 @@ public class ClassWriter extends ClassFile {
|
||||||
result |= ACC_BRIDGE;
|
result |= ACC_BRIDGE;
|
||||||
if ((flags & VARARGS) != 0 && target.useVarargsFlag())
|
if ((flags & VARARGS) != 0 && target.useVarargsFlag())
|
||||||
result |= ACC_VARARGS;
|
result |= ACC_VARARGS;
|
||||||
|
if ((flags & DEFAULT) != 0)
|
||||||
|
result &= ~ABSTRACT;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -523,7 +523,7 @@ public class Items {
|
||||||
Item invoke() {
|
Item invoke() {
|
||||||
MethodType mtype = (MethodType)member.externalType(types);
|
MethodType mtype = (MethodType)member.externalType(types);
|
||||||
int rescode = Code.typecode(mtype.restype);
|
int rescode = Code.typecode(mtype.restype);
|
||||||
if ((member.owner.flags() & Flags.INTERFACE) != 0) {
|
if ((member.owner.flags() & Flags.INTERFACE) != 0 && !nonvirtual) {
|
||||||
code.emitInvokeinterface(pool.put(member), mtype);
|
code.emitInvokeinterface(pool.put(member), mtype);
|
||||||
} else if (nonvirtual) {
|
} else if (nonvirtual) {
|
||||||
code.emitInvokespecial(pool.put(member), mtype);
|
code.emitInvokespecial(pool.put(member), mtype);
|
||||||
|
|
|
@ -574,7 +574,7 @@ compiler.err.intf.expected.here=\
|
||||||
interface expected here
|
interface expected here
|
||||||
|
|
||||||
compiler.err.intf.meth.cant.have.body=\
|
compiler.err.intf.meth.cant.have.body=\
|
||||||
interface methods cannot have body
|
interface abstract methods cannot have body
|
||||||
|
|
||||||
compiler.err.invalid.annotation.member.type=\
|
compiler.err.invalid.annotation.member.type=\
|
||||||
invalid type for annotation member
|
invalid type for annotation member
|
||||||
|
@ -941,6 +941,31 @@ compiler.err.type.var.more.than.once.in.result=\
|
||||||
compiler.err.types.incompatible.diff.ret=\
|
compiler.err.types.incompatible.diff.ret=\
|
||||||
types {0} and {1} are incompatible; both define {2}, but with unrelated return types
|
types {0} and {1} are incompatible; both define {2}, but with unrelated return types
|
||||||
|
|
||||||
|
# 0: kind, 1: type, 2: name, 3: list of type, 4: symbol, 5: symbol
|
||||||
|
compiler.err.types.incompatible.unrelated.defaults=\
|
||||||
|
{0} {1} inherits unrelated defaults for {2}({3}) from types {4} and {5}
|
||||||
|
|
||||||
|
# 0: kind, 1: type, 2: name, 3: list of type, 4: symbol, 5: symbol
|
||||||
|
compiler.err.types.incompatible.abstract.default=\
|
||||||
|
{0} {1} inherits abstract and default for {2}({3}) from types {4} and {5}
|
||||||
|
|
||||||
|
# 0: name, 1: kind, 2: symbol
|
||||||
|
compiler.err.default.overrides.object.member=\
|
||||||
|
default method {0} in {1} {2} overrides a member of java.lang.Object
|
||||||
|
|
||||||
|
# 0: type, 1: message segment
|
||||||
|
compiler.err.illegal.default.super.call=\
|
||||||
|
bad type qualifier {0} in default super call\n\
|
||||||
|
{1}
|
||||||
|
|
||||||
|
# 0: symbol, 1: type
|
||||||
|
compiler.misc.overridden.default=\
|
||||||
|
method {0} is overridden in {2}
|
||||||
|
|
||||||
|
# 0: symbol, 1: symbol
|
||||||
|
compiler.misc.redundant.supertype=\
|
||||||
|
redundant interface {0} is extended by {1}
|
||||||
|
|
||||||
compiler.err.unclosed.char.lit=\
|
compiler.err.unclosed.char.lit=\
|
||||||
unclosed character literal
|
unclosed character literal
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2011, 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
|
||||||
|
* @summary check that default methods don't cause ClassReader to complete classes recursively
|
||||||
|
* @author Maurizio Cimadamore
|
||||||
|
* @compile -XDallowDefaultMethods pkg/Foo.java
|
||||||
|
* @compile ClassReaderTest.java
|
||||||
|
*/
|
||||||
|
|
||||||
|
abstract class ClassReaderTest implements pkg.Foo {}
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2011, 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 pkg;
|
||||||
|
|
||||||
|
public interface Foo {
|
||||||
|
default void m1() { Impl.m1(this); }
|
||||||
|
default void m2() { Impl.m2(this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
class Impl {
|
||||||
|
static void m1(Foo f) { }
|
||||||
|
static void m2(Foo f) { }
|
||||||
|
}
|
18
langtools/test/tools/javac/defaultMethods/Neg01.java
Normal file
18
langtools/test/tools/javac/defaultMethods/Neg01.java
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
* @test /nodynamiccopyright/
|
||||||
|
* @summary negative test for ambiguous defaults
|
||||||
|
* @compile/fail/ref=Neg01.out -XDallowDefaultMethods -XDrawDiagnostics Neg01.java
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Neg01 {
|
||||||
|
interface IA { default int m() { return Neg01.m1(this); } }
|
||||||
|
interface IB { default int m() { return Neg01.m2(this); } }
|
||||||
|
|
||||||
|
static class A implements IA {}
|
||||||
|
static class B implements IB {}
|
||||||
|
|
||||||
|
static class AB implements IA, IB {}
|
||||||
|
|
||||||
|
static int m1(IA a) { return 0; }
|
||||||
|
static int m2(IB b) { return 0; }
|
||||||
|
}
|
2
langtools/test/tools/javac/defaultMethods/Neg01.out
Normal file
2
langtools/test/tools/javac/defaultMethods/Neg01.out
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Neg01.java:14:12: compiler.err.types.incompatible.unrelated.defaults: kindname.class, Neg01.AB, m, , Neg01.IA, Neg01.IB
|
||||||
|
1 error
|
26
langtools/test/tools/javac/defaultMethods/Neg02.java
Normal file
26
langtools/test/tools/javac/defaultMethods/Neg02.java
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* @test /nodynamiccopyright/
|
||||||
|
* @summary check that ill-formed MI hierarchies do not compile
|
||||||
|
* @compile/fail/ref=Neg02.out -XDallowDefaultMethods -XDrawDiagnostics Neg02.java
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Neg02 {
|
||||||
|
interface A {
|
||||||
|
default void m() { Neg02.impl(this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
interface B {
|
||||||
|
default void m() { Neg02.impl(this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static class X implements A, B { } //error
|
||||||
|
|
||||||
|
void test(X x) {
|
||||||
|
x.m();
|
||||||
|
((A)x).m();
|
||||||
|
((B)x).m();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void impl(A a) { }
|
||||||
|
static void impl(B b) { }
|
||||||
|
}
|
2
langtools/test/tools/javac/defaultMethods/Neg02.out
Normal file
2
langtools/test/tools/javac/defaultMethods/Neg02.out
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Neg02.java:16:13: compiler.err.types.incompatible.unrelated.defaults: kindname.class, Neg02.X, m, , Neg02.A, Neg02.B
|
||||||
|
1 error
|
38
langtools/test/tools/javac/defaultMethods/Neg03.java
Normal file
38
langtools/test/tools/javac/defaultMethods/Neg03.java
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* @test /nodynamiccopyright/
|
||||||
|
* @summary check that re-abstraction works properly
|
||||||
|
* @compile/fail/ref=Neg03.out -XDallowDefaultMethods -XDrawDiagnostics Neg03.java
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Neg03 {
|
||||||
|
interface A {
|
||||||
|
default void m() { Neg03.one(this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
interface B {
|
||||||
|
default void m() { Neg03.two(this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
interface C extends A, B {
|
||||||
|
default void m() { Neg03.one(this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static class X implements C, A { } //ok - ignore extraneous remix of A
|
||||||
|
|
||||||
|
interface D extends A, B {
|
||||||
|
void m(); // ok - m() is not reabstracted!
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Y implements D, A { } // invalid - abstract D.m()
|
||||||
|
|
||||||
|
interface E extends A {
|
||||||
|
void m(); // reabstraction of m()
|
||||||
|
}
|
||||||
|
|
||||||
|
static class W implements D, E { } // invalid - abstracts D.m()/E.m()
|
||||||
|
|
||||||
|
static class Z implements D, A, B { } // invalid - abstract D.m()
|
||||||
|
|
||||||
|
static void one(Object a) { }
|
||||||
|
static void two(Object a) { }
|
||||||
|
}
|
4
langtools/test/tools/javac/defaultMethods/Neg03.out
Normal file
4
langtools/test/tools/javac/defaultMethods/Neg03.out
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
Neg03.java:26:12: compiler.err.does.not.override.abstract: Neg03.Y, m(), Neg03.D
|
||||||
|
Neg03.java:32:12: compiler.err.does.not.override.abstract: Neg03.W, m(), Neg03.D
|
||||||
|
Neg03.java:34:12: compiler.err.does.not.override.abstract: Neg03.Z, m(), Neg03.D
|
||||||
|
3 errors
|
14
langtools/test/tools/javac/defaultMethods/Neg04.java
Normal file
14
langtools/test/tools/javac/defaultMethods/Neg04.java
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
/*
|
||||||
|
* @test /nodynamiccopyright/
|
||||||
|
* @summary check that default method must have most specific return type
|
||||||
|
* @compile/fail/ref=Neg04.out -XDallowDefaultMethods -XDrawDiagnostics Neg04.java
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Neg04 {
|
||||||
|
interface IA1 { Integer m(); }
|
||||||
|
interface IA2 extends IA1 { default Number m() { return Neg04.m(this); } } //error
|
||||||
|
|
||||||
|
abstract class C implements IA1, IA2 {}
|
||||||
|
|
||||||
|
static int m(IA2 a) { return 0; }
|
||||||
|
}
|
2
langtools/test/tools/javac/defaultMethods/Neg04.out
Normal file
2
langtools/test/tools/javac/defaultMethods/Neg04.out
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Neg04.java:9:48: compiler.err.override.incompatible.ret: (compiler.misc.clashes.with: m(), Neg04.IA2, m(), Neg04.IA1), java.lang.Number, java.lang.Integer
|
||||||
|
1 error
|
16
langtools/test/tools/javac/defaultMethods/Neg05.java
Normal file
16
langtools/test/tools/javac/defaultMethods/Neg05.java
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* @test /nodynamiccopyright/
|
||||||
|
* @summary check that abstract methods are compatible with inherited defaults
|
||||||
|
* @compile/fail/ref=Neg05.out -XDallowDefaultMethods -XDrawDiagnostics Neg05.java
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Neg05 {
|
||||||
|
interface IA1 { default Number m() { return Neg05.m1(this); } }
|
||||||
|
interface IA2 extends IA1 { default Integer m() { return Neg05.m2(this); } }
|
||||||
|
interface IA3 extends IA2 { Number m(); } //error
|
||||||
|
|
||||||
|
static class C implements IA3{}
|
||||||
|
|
||||||
|
static int m1(IA1 a) { return 0; }
|
||||||
|
static int m2(IA2 b) { return 0; }
|
||||||
|
}
|
3
langtools/test/tools/javac/defaultMethods/Neg05.out
Normal file
3
langtools/test/tools/javac/defaultMethods/Neg05.out
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
Neg05.java:10:40: compiler.err.override.incompatible.ret: (compiler.misc.clashes.with: m(), Neg05.IA3, m(), Neg05.IA2), java.lang.Number, java.lang.Integer
|
||||||
|
Neg05.java:12:12: compiler.err.does.not.override.abstract: Neg05.C, m(), Neg05.IA3
|
||||||
|
2 errors
|
16
langtools/test/tools/javac/defaultMethods/Neg06.java
Normal file
16
langtools/test/tools/javac/defaultMethods/Neg06.java
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* @test /nodynamiccopyright/
|
||||||
|
* @summary flow analysis is not run on inlined default bodies
|
||||||
|
* @compile/fail/ref=Neg06.out -XDallowDefaultMethods -XDrawDiagnostics Neg06.java
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Neg06 {
|
||||||
|
|
||||||
|
interface A {
|
||||||
|
default String m() { C.m(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static class C {
|
||||||
|
static String m() { return ""; }
|
||||||
|
}
|
||||||
|
}
|
2
langtools/test/tools/javac/defaultMethods/Neg06.out
Normal file
2
langtools/test/tools/javac/defaultMethods/Neg06.out
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Neg06.java:10:37: compiler.err.missing.ret.stmt
|
||||||
|
1 error
|
21
langtools/test/tools/javac/defaultMethods/Neg07.java
Normal file
21
langtools/test/tools/javac/defaultMethods/Neg07.java
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* @test /nodynamiccopyright/
|
||||||
|
* @summary check that default overrides are properly type-checked
|
||||||
|
* @compile/fail/ref=Neg07.out -XDallowDefaultMethods -XDrawDiagnostics Neg07.java
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Neg07 {
|
||||||
|
interface I {
|
||||||
|
default int m() { return 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
static class C1 {
|
||||||
|
public void m() { } //incompatible return
|
||||||
|
}
|
||||||
|
|
||||||
|
static class C2 extends C1 implements I { }
|
||||||
|
|
||||||
|
static class C3 implements I {
|
||||||
|
public void m() { } //incompatible return
|
||||||
|
}
|
||||||
|
}
|
3
langtools/test/tools/javac/defaultMethods/Neg07.out
Normal file
3
langtools/test/tools/javac/defaultMethods/Neg07.out
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
Neg07.java:16:12: compiler.err.override.incompatible.ret: (compiler.misc.cant.implement: m(), Neg07.C1, m(), Neg07.I), void, int
|
||||||
|
Neg07.java:19:21: compiler.err.override.incompatible.ret: (compiler.misc.cant.implement: m(), Neg07.C3, m(), Neg07.I), void, int
|
||||||
|
2 errors
|
20
langtools/test/tools/javac/defaultMethods/Neg08.java
Normal file
20
langtools/test/tools/javac/defaultMethods/Neg08.java
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
* @test /nodynamiccopyright/
|
||||||
|
* @summary check that default overrides are properly type-checked
|
||||||
|
* @compile/fail/ref=Neg08.out -XDallowDefaultMethods -XDrawDiagnostics Neg08.java
|
||||||
|
*/
|
||||||
|
class Neg08 {
|
||||||
|
interface I {
|
||||||
|
default void m() { }
|
||||||
|
}
|
||||||
|
|
||||||
|
static class C1 {
|
||||||
|
void m() { } //weaker modifier
|
||||||
|
}
|
||||||
|
|
||||||
|
static class C2 extends C1 implements I { }
|
||||||
|
|
||||||
|
static class C3 implements I {
|
||||||
|
void m() { } //weaker modifier
|
||||||
|
}
|
||||||
|
}
|
3
langtools/test/tools/javac/defaultMethods/Neg08.out
Normal file
3
langtools/test/tools/javac/defaultMethods/Neg08.out
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
Neg08.java:15:12: compiler.err.override.weaker.access: (compiler.misc.cant.implement: m(), Neg08.C1, m(), Neg08.I), public
|
||||||
|
Neg08.java:18:14: compiler.err.override.weaker.access: (compiler.misc.cant.implement: m(), Neg08.C3, m(), Neg08.I), public
|
||||||
|
2 errors
|
22
langtools/test/tools/javac/defaultMethods/Neg09.java
Normal file
22
langtools/test/tools/javac/defaultMethods/Neg09.java
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* @test /nodynamiccopyright/
|
||||||
|
* @summary check that default overrides are properly type-checked
|
||||||
|
* @compile/fail/ref=Neg09.out -Werror -Xlint:unchecked -XDallowDefaultMethods -XDrawDiagnostics Neg09.java
|
||||||
|
*/
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
class Neg09 {
|
||||||
|
interface I {
|
||||||
|
default List<String> m() { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
static class C1 {
|
||||||
|
public List m() { return null; } //unchecked (return) override
|
||||||
|
}
|
||||||
|
|
||||||
|
static class C2 extends C1 implements I { }
|
||||||
|
|
||||||
|
static class C3 implements I {
|
||||||
|
public List m() { return null; } //unchecked (return) override
|
||||||
|
}
|
||||||
|
}
|
5
langtools/test/tools/javac/defaultMethods/Neg09.out
Normal file
5
langtools/test/tools/javac/defaultMethods/Neg09.out
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
Neg09.java:17:12: compiler.warn.override.unchecked.ret: (compiler.misc.unchecked.implement: m(), Neg09.C1, m(), Neg09.I), java.util.List, java.util.List<java.lang.String>
|
||||||
|
Neg09.java:20:21: compiler.warn.override.unchecked.ret: (compiler.misc.unchecked.implement: m(), Neg09.C3, m(), Neg09.I), java.util.List, java.util.List<java.lang.String>
|
||||||
|
- compiler.err.warnings.and.werror
|
||||||
|
1 error
|
||||||
|
2 warnings
|
20
langtools/test/tools/javac/defaultMethods/Neg10.java
Normal file
20
langtools/test/tools/javac/defaultMethods/Neg10.java
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
* @test /nodynamiccopyright/
|
||||||
|
* @summary check that default overrides are properly type-checked
|
||||||
|
* @compile/fail/ref=Neg10.out -Werror -Xlint:unchecked -XDallowDefaultMethods -XDrawDiagnostics Neg10.java
|
||||||
|
*/
|
||||||
|
class Neg10 {
|
||||||
|
interface I<X extends Exception> {
|
||||||
|
default void m() throws X { }
|
||||||
|
}
|
||||||
|
|
||||||
|
static class C1 {
|
||||||
|
public void m() throws Exception { } //unchecked (throws) override
|
||||||
|
}
|
||||||
|
|
||||||
|
static class C2<Z extends Exception> extends C1 implements I<Z> { }
|
||||||
|
|
||||||
|
static class C3<Z extends Exception> implements I<Z> {
|
||||||
|
public void m() throws Exception { } //unchecked (throws) override
|
||||||
|
}
|
||||||
|
}
|
5
langtools/test/tools/javac/defaultMethods/Neg10.out
Normal file
5
langtools/test/tools/javac/defaultMethods/Neg10.out
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
Neg10.java:15:12: compiler.warn.override.unchecked.thrown: (compiler.misc.cant.implement: m(), Neg10.C1, m(), Neg10.I), java.lang.Exception
|
||||||
|
Neg10.java:18:21: compiler.warn.override.unchecked.thrown: (compiler.misc.cant.implement: m(), Neg10.C3, m(), Neg10.I), java.lang.Exception
|
||||||
|
- compiler.err.warnings.and.werror
|
||||||
|
1 error
|
||||||
|
2 warnings
|
20
langtools/test/tools/javac/defaultMethods/Neg11.java
Normal file
20
langtools/test/tools/javac/defaultMethods/Neg11.java
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
* @test /nodynamiccopyright/
|
||||||
|
* @summary check that default overrides are properly type-checked
|
||||||
|
* @compile/fail/ref=Neg11.out -XDallowDefaultMethods -XDrawDiagnostics Neg11.java
|
||||||
|
*/
|
||||||
|
class Neg11 {
|
||||||
|
interface I {
|
||||||
|
default void m() { }
|
||||||
|
}
|
||||||
|
|
||||||
|
static class C1 {
|
||||||
|
public void m() throws Exception { } //bad throws
|
||||||
|
}
|
||||||
|
|
||||||
|
static class C2 extends C1 implements I { }
|
||||||
|
|
||||||
|
static class C3 implements I {
|
||||||
|
public void m() throws Exception { } //bad throws
|
||||||
|
}
|
||||||
|
}
|
3
langtools/test/tools/javac/defaultMethods/Neg11.out
Normal file
3
langtools/test/tools/javac/defaultMethods/Neg11.out
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
Neg11.java:15:12: compiler.err.override.meth.doesnt.throw: (compiler.misc.cant.implement: m(), Neg11.C1, m(), Neg11.I), java.lang.Exception
|
||||||
|
Neg11.java:18:21: compiler.err.override.meth.doesnt.throw: (compiler.misc.cant.implement: m(), Neg11.C3, m(), Neg11.I), java.lang.Exception
|
||||||
|
2 errors
|
27
langtools/test/tools/javac/defaultMethods/Neg12.java
Normal file
27
langtools/test/tools/javac/defaultMethods/Neg12.java
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* @test /nodynamiccopyright/
|
||||||
|
* @summary check that abstract methods are discarded in overload resolution diags
|
||||||
|
* @compile/fail/ref=Neg12.out -XDallowDefaultMethods -XDrawDiagnostics Neg12.java
|
||||||
|
*/
|
||||||
|
class Neg12 {
|
||||||
|
|
||||||
|
interface I1 {
|
||||||
|
default void m(String s) {};
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I2 {
|
||||||
|
void m(String s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static class B {
|
||||||
|
void m(Integer i) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
static class C extends B implements I1 { }
|
||||||
|
static class D extends B implements I2 { }
|
||||||
|
|
||||||
|
void test(C c, D d) {
|
||||||
|
c.m();
|
||||||
|
d.m();
|
||||||
|
}
|
||||||
|
}
|
4
langtools/test/tools/javac/defaultMethods/Neg12.out
Normal file
4
langtools/test/tools/javac/defaultMethods/Neg12.out
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
Neg12.java:21:12: compiler.err.does.not.override.abstract: Neg12.D, m(java.lang.String), Neg12.I2
|
||||||
|
Neg12.java:24:10: compiler.err.cant.apply.symbols: kindname.method, m, ,{(compiler.misc.inapplicable.method: kindname.method, Neg12.B, m(java.lang.Integer), (compiler.misc.arg.length.mismatch)),(compiler.misc.inapplicable.method: kindname.method, Neg12.I1, m(java.lang.String), (compiler.misc.arg.length.mismatch))}
|
||||||
|
Neg12.java:25:10: compiler.err.cant.apply.symbol: kindname.method, m, java.lang.Integer, compiler.misc.no.args, kindname.class, Neg12.B, (compiler.misc.arg.length.mismatch)
|
||||||
|
3 errors
|
18
langtools/test/tools/javac/defaultMethods/Neg13.java
Normal file
18
langtools/test/tools/javac/defaultMethods/Neg13.java
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
* @test /nodynamiccopyright/
|
||||||
|
* @summary check that default method overriding object members are flagged as error
|
||||||
|
* @compile/fail/ref=Neg13.out -XDallowDefaultMethods -XDrawDiagnostics Neg13.java
|
||||||
|
*/
|
||||||
|
interface Neg13 {
|
||||||
|
default protected Object clone() { return null; } //protected not allowed here
|
||||||
|
default boolean equals(Object obj) { return false; }
|
||||||
|
default protected void finalize() { } //protected not allowed here
|
||||||
|
default Class<?> getClass() { return null; }
|
||||||
|
default int hashCode() { return 0; }
|
||||||
|
default void notify() { }
|
||||||
|
default void notifyAll() { }
|
||||||
|
default String toString() { return null; }
|
||||||
|
default void wait() { }
|
||||||
|
default void wait(long timeout) { }
|
||||||
|
default void wait(long timeout, int nanos) { }
|
||||||
|
}
|
12
langtools/test/tools/javac/defaultMethods/Neg13.out
Normal file
12
langtools/test/tools/javac/defaultMethods/Neg13.out
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
Neg13.java:7:30: compiler.err.mod.not.allowed.here: protected
|
||||||
|
Neg13.java:9:28: compiler.err.mod.not.allowed.here: protected
|
||||||
|
Neg13.java:8:21: compiler.err.default.overrides.object.member: equals, kindname.interface, Neg13
|
||||||
|
Neg13.java:10:22: compiler.err.override.meth: (compiler.misc.cant.override: getClass(), Neg13, getClass(), java.lang.Object), final
|
||||||
|
Neg13.java:11:17: compiler.err.default.overrides.object.member: hashCode, kindname.interface, Neg13
|
||||||
|
Neg13.java:12:18: compiler.err.override.meth: (compiler.misc.cant.override: notify(), Neg13, notify(), java.lang.Object), final
|
||||||
|
Neg13.java:13:18: compiler.err.override.meth: (compiler.misc.cant.override: notifyAll(), Neg13, notifyAll(), java.lang.Object), final
|
||||||
|
Neg13.java:14:20: compiler.err.default.overrides.object.member: toString, kindname.interface, Neg13
|
||||||
|
Neg13.java:15:18: compiler.err.override.meth: (compiler.misc.cant.override: wait(), Neg13, wait(), java.lang.Object), final
|
||||||
|
Neg13.java:16:18: compiler.err.override.meth: (compiler.misc.cant.override: wait(long), Neg13, wait(long), java.lang.Object), final
|
||||||
|
Neg13.java:17:18: compiler.err.override.meth: (compiler.misc.cant.override: wait(long,int), Neg13, wait(long,int), java.lang.Object), final
|
||||||
|
11 errors
|
11
langtools/test/tools/javac/defaultMethods/Neg14.java
Normal file
11
langtools/test/tools/javac/defaultMethods/Neg14.java
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
/*
|
||||||
|
* @test /nodynamiccopyright/
|
||||||
|
* @summary check that a class cannot have two sibling interfaces with a default and abstract method
|
||||||
|
* @compile/fail/ref=Neg14.out -XDallowDefaultMethods -XDrawDiagnostics Neg14.java
|
||||||
|
*/
|
||||||
|
class Neg14 {
|
||||||
|
interface IA { int m(); }
|
||||||
|
interface IB { default int m() { return 1; } }
|
||||||
|
|
||||||
|
abstract class AB implements IA, IB {}
|
||||||
|
}
|
2
langtools/test/tools/javac/defaultMethods/Neg14.out
Normal file
2
langtools/test/tools/javac/defaultMethods/Neg14.out
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Neg14.java:10:14: compiler.err.types.incompatible.abstract.default: kindname.class, Neg14.AB, m, , Neg14.IB, Neg14.IA
|
||||||
|
1 error
|
14
langtools/test/tools/javac/defaultMethods/Neg15.java
Normal file
14
langtools/test/tools/javac/defaultMethods/Neg15.java
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
/*
|
||||||
|
* @test /nodynamiccopyright/
|
||||||
|
* @summary check that level skipping in default super calls is correctly rejected
|
||||||
|
* @compile/fail/ref=Neg15.out -XDallowDefaultMethods -XDrawDiagnostics Neg15.java
|
||||||
|
*/
|
||||||
|
class Neg15 {
|
||||||
|
interface I { default void m() { } }
|
||||||
|
interface J extends I { default void m() { } }
|
||||||
|
interface K extends I {}
|
||||||
|
|
||||||
|
static class C implements J, K {
|
||||||
|
void foo() { K.super.m(); }
|
||||||
|
}
|
||||||
|
}
|
2
langtools/test/tools/javac/defaultMethods/Neg15.out
Normal file
2
langtools/test/tools/javac/defaultMethods/Neg15.out
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Neg15.java:12:31: compiler.err.illegal.default.super.call: Neg15.K, (compiler.misc.overridden.default: m(), Neg15.J)
|
||||||
|
1 error
|
13
langtools/test/tools/javac/defaultMethods/Neg16.java
Normal file
13
langtools/test/tools/javac/defaultMethods/Neg16.java
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
/*
|
||||||
|
* @test /nodynamiccopyright/
|
||||||
|
* @summary check that level skipping in default super calls is correctly rejected
|
||||||
|
* @compile/fail/ref=Neg16.out -XDallowDefaultMethods -XDrawDiagnostics Neg16.java
|
||||||
|
*/
|
||||||
|
class Neg16 {
|
||||||
|
interface I { default void m() { } }
|
||||||
|
interface J extends I { default void m() { } }
|
||||||
|
|
||||||
|
static class C implements I, J {
|
||||||
|
void foo() { I.super.m(); }
|
||||||
|
}
|
||||||
|
}
|
2
langtools/test/tools/javac/defaultMethods/Neg16.out
Normal file
2
langtools/test/tools/javac/defaultMethods/Neg16.out
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Neg16.java:11:23: compiler.err.illegal.default.super.call: Neg16.I, (compiler.misc.redundant.supertype: Neg16.I, Neg16.J)
|
||||||
|
1 error
|
61
langtools/test/tools/javac/defaultMethods/Pos01.java
Normal file
61
langtools/test/tools/javac/defaultMethods/Pos01.java
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2011, 2012, 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
|
||||||
|
* @summary basic test for default methods
|
||||||
|
* @ignore awaits lambda support
|
||||||
|
* @author Maurizio Cimadamore
|
||||||
|
* @compile -XDallowLambda -XDallowPoly -XDallowDefaultMethods Pos01.java
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
class Pos01 {
|
||||||
|
|
||||||
|
interface Mapper<T> {
|
||||||
|
T map(T in);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ExtendedList<T> extends List<T> {
|
||||||
|
default List<T> testMap(Mapper<T> r) {
|
||||||
|
return Pos01.<T>listMapper(this, r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class MyList<E> extends ArrayList<E> implements ExtendedList<E> {}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
MyList<Integer> l = new MyList<Integer>();
|
||||||
|
l.add(1); l.add(2); l.add(3);
|
||||||
|
l.testMap((Integer x) -> x * x );
|
||||||
|
}
|
||||||
|
|
||||||
|
static <T> List<T> listMapper(List<T> l, Mapper<T> mapper) {
|
||||||
|
MyList<T> new_list = new MyList<T>();
|
||||||
|
for (T el : l) {
|
||||||
|
new_list.add(mapper.map(el));
|
||||||
|
}
|
||||||
|
return new_list;
|
||||||
|
}
|
||||||
|
}
|
48
langtools/test/tools/javac/defaultMethods/Pos02.java
Normal file
48
langtools/test/tools/javac/defaultMethods/Pos02.java
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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
|
||||||
|
* @summary test for explicit resolution of ambiguous default methods
|
||||||
|
* @author Maurizio Cimadamore
|
||||||
|
* @compile -XDallowDefaultMethods Pos02.java
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Pos02 {
|
||||||
|
interface IA { default int m() { return Pos02.m1(this); } }
|
||||||
|
interface IB { default int m() { return Pos02.m2(this); } }
|
||||||
|
|
||||||
|
static class A implements IA {}
|
||||||
|
static class B implements IB {}
|
||||||
|
|
||||||
|
static class AB implements IA, IB {
|
||||||
|
public int m() { return 0; }
|
||||||
|
void test() {
|
||||||
|
AB.this.m();
|
||||||
|
IA.super.m();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int m1(IA a) { return 0; }
|
||||||
|
static int m2(IB b) { return 0; }
|
||||||
|
}
|
43
langtools/test/tools/javac/defaultMethods/Pos04.java
Normal file
43
langtools/test/tools/javac/defaultMethods/Pos04.java
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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
|
||||||
|
* @summary test for overriding with default method
|
||||||
|
* @author Maurizio Cimadamore
|
||||||
|
* @compile -XDallowDefaultMethods Pos04.java
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Pos04 {
|
||||||
|
interface A { default int m() { return Pos04.m(this); } }
|
||||||
|
static abstract class B { public int m() { return 0; } }
|
||||||
|
|
||||||
|
static class C extends B implements A {
|
||||||
|
void test() {
|
||||||
|
C.this.m();
|
||||||
|
A.super.m();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int m(A a) { return 0; }
|
||||||
|
}
|
45
langtools/test/tools/javac/defaultMethods/Pos05.java
Normal file
45
langtools/test/tools/javac/defaultMethods/Pos05.java
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010, 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
|
||||||
|
* @summary check that indirectly inherited default methods are discovered during resolution
|
||||||
|
* @author Maurizio Cimadamore
|
||||||
|
* @compile -XDallowDefaultMethods Pos05.java
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Pos05 {
|
||||||
|
interface A {
|
||||||
|
default void m() { Pos05.impl(this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
interface B extends A { }
|
||||||
|
|
||||||
|
static class E implements B { }
|
||||||
|
|
||||||
|
void test(E e) {
|
||||||
|
e.m();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void impl(A a) { }
|
||||||
|
}
|
49
langtools/test/tools/javac/defaultMethods/Pos06.java
Normal file
49
langtools/test/tools/javac/defaultMethods/Pos06.java
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010, 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
|
||||||
|
* @summary check that well-formed MI hierarchies behaves well w.r.t. method resolution (i.e. no ambiguities)
|
||||||
|
* @author Maurizio Cimadamore
|
||||||
|
* @compile -XDallowDefaultMethods Pos06.java
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Pos06 {
|
||||||
|
interface A {
|
||||||
|
default void m() { Pos06.impl(this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
interface B extends A {
|
||||||
|
default void m() { Pos06.impl(this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static class X implements A, B { }
|
||||||
|
|
||||||
|
void test(X x) {
|
||||||
|
x.m();
|
||||||
|
((A)x).m();
|
||||||
|
((B)x).m();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void impl(Object a) { }
|
||||||
|
}
|
44
langtools/test/tools/javac/defaultMethods/Pos07.java
Normal file
44
langtools/test/tools/javac/defaultMethods/Pos07.java
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010, 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
|
||||||
|
* @summary check that compilation order does not matter
|
||||||
|
* @author Maurizio Cimadamore
|
||||||
|
* @compile -XDallowDefaultMethods Pos07.java
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Pos07 {
|
||||||
|
interface A {
|
||||||
|
default void foo() { Pos07.impl(this); }
|
||||||
|
default void bar() { Pos07.impl(this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static class C implements B, A {}
|
||||||
|
|
||||||
|
interface B extends A {
|
||||||
|
default void foo() { Pos07.impl(this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static void impl(A a) {}
|
||||||
|
}
|
46
langtools/test/tools/javac/defaultMethods/Pos08.java
Normal file
46
langtools/test/tools/javac/defaultMethods/Pos08.java
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010, 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
|
||||||
|
* @summary check that common overrider solves default method conflicts
|
||||||
|
* @author Maurizio Cimadamore
|
||||||
|
* @compile -XDallowDefaultMethods Pos08.java
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Pos08 {
|
||||||
|
interface A {
|
||||||
|
default void m() { Pos08.a(this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
interface B {
|
||||||
|
default void m() { Pos08.b(this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
interface C extends A, B {
|
||||||
|
default void m() { Pos08.b(this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static void a(A o) { }
|
||||||
|
static void b(B o) { }
|
||||||
|
}
|
43
langtools/test/tools/javac/defaultMethods/Pos10.java
Normal file
43
langtools/test/tools/javac/defaultMethods/Pos10.java
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010, 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
|
||||||
|
* @summary check that type-variables in generic extension decl can be accessed from default impl
|
||||||
|
* @author Maurizio Cimadamore
|
||||||
|
* @compile -XDallowDefaultMethods Pos10.java
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Pos10 {
|
||||||
|
interface Function<X,Y> {
|
||||||
|
Y apply(X x);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface A<T> {
|
||||||
|
default <R> void m(Function<T,R> f) { Impl.<T,R>m(this, f); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Impl {
|
||||||
|
static <T,R> void m(A<T> a, Function<T,R> f) { }
|
||||||
|
}
|
||||||
|
}
|
56
langtools/test/tools/javac/defaultMethods/Pos11.java
Normal file
56
langtools/test/tools/javac/defaultMethods/Pos11.java
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010, 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
|
||||||
|
* @summary complex test with conflict resolution via overriding
|
||||||
|
* @author Brian Goetz
|
||||||
|
* @compile -XDallowDefaultMethods Pos11.java
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Pos11 {
|
||||||
|
interface A {
|
||||||
|
default void get() { Pos11.one(this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
interface B {
|
||||||
|
default void get() { Pos11.two(this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
interface C extends A {
|
||||||
|
default void get() { Pos11.two(this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
interface D extends A, B {
|
||||||
|
default void get() { Pos11.two(this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static class X implements C { }
|
||||||
|
|
||||||
|
static class Y implements C, A { }
|
||||||
|
|
||||||
|
static class Z implements D, A, B { }
|
||||||
|
|
||||||
|
static void one(Object a) { }
|
||||||
|
static void two(Object a) { }
|
||||||
|
}
|
39
langtools/test/tools/javac/defaultMethods/Pos12.java
Normal file
39
langtools/test/tools/javac/defaultMethods/Pos12.java
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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
|
||||||
|
* @summary check that 'this' can be used from within an extension method
|
||||||
|
* @compile -XDallowDefaultMethods Pos12.java
|
||||||
|
*/
|
||||||
|
|
||||||
|
interface Pos12 {
|
||||||
|
|
||||||
|
default Object m() {
|
||||||
|
Object o = this;
|
||||||
|
f(this);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void f(Object o);
|
||||||
|
}
|
62
langtools/test/tools/javac/defaultMethods/Pos13.java
Normal file
62
langtools/test/tools/javac/defaultMethods/Pos13.java
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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
|
||||||
|
* @summary qualified 'this' inside default method causes StackOverflowException
|
||||||
|
* @compile -XDallowDefaultMethods Pos13.java
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Pos13 {
|
||||||
|
|
||||||
|
static int assertionCount = 0;
|
||||||
|
|
||||||
|
static void assertTrue(boolean cond) {
|
||||||
|
assertionCount++;
|
||||||
|
if (!cond)
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Outer {
|
||||||
|
abstract void doSomething();
|
||||||
|
|
||||||
|
default void m() {
|
||||||
|
new SubOuter() {
|
||||||
|
public void doSomething() {
|
||||||
|
Outer.this.doSomething();
|
||||||
|
}
|
||||||
|
}.doSomething();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SubOuter extends Outer { }
|
||||||
|
|
||||||
|
static class E implements Outer {
|
||||||
|
public void doSomething() { assertTrue(true); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
new E().m();
|
||||||
|
assertTrue(assertionCount == 1);
|
||||||
|
}
|
||||||
|
}
|
39
langtools/test/tools/javac/defaultMethods/Pos14.java
Normal file
39
langtools/test/tools/javac/defaultMethods/Pos14.java
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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
|
||||||
|
* @summary check that overload resolution selects most specific signature
|
||||||
|
* @compile -XDallowDefaultMethods Pos14.java
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Pos14 {
|
||||||
|
interface A { default Object m() { return null; } }
|
||||||
|
static abstract class B { abstract public String m(); }
|
||||||
|
|
||||||
|
static abstract class C extends B implements A {
|
||||||
|
void test() {
|
||||||
|
m().length();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
39
langtools/test/tools/javac/defaultMethods/Pos15.java
Normal file
39
langtools/test/tools/javac/defaultMethods/Pos15.java
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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
|
||||||
|
* @summary check that overload resolution selects most specific signature
|
||||||
|
* @compile -XDallowDefaultMethods Pos15.java
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Pos15 {
|
||||||
|
interface A { default String m() { return null; } }
|
||||||
|
static abstract class B { abstract public Object m(); }
|
||||||
|
|
||||||
|
static abstract class C extends B implements A {
|
||||||
|
void test() {
|
||||||
|
m().length();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
42
langtools/test/tools/javac/defaultMethods/Pos16.java
Normal file
42
langtools/test/tools/javac/defaultMethods/Pos16.java
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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
|
||||||
|
* @summary 'class wins' should not short-circuit overload resolution
|
||||||
|
* @compile -XDallowDefaultMethods Pos16.java
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Pos16 {
|
||||||
|
interface I {
|
||||||
|
default String m(Integer i) { return ""; }
|
||||||
|
}
|
||||||
|
|
||||||
|
class C implements I {
|
||||||
|
Integer m(Object o) { return 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
void test(C c) {
|
||||||
|
c.m(1).length();
|
||||||
|
}
|
||||||
|
}
|
125
langtools/test/tools/javac/defaultMethods/TestDefaultBody.java
Normal file
125
langtools/test/tools/javac/defaultMethods/TestDefaultBody.java
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2011, 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
|
||||||
|
* @ignore awaits for VM support
|
||||||
|
* @summary check that code attributed for default methods is correctly generated
|
||||||
|
* @compile -XDallowDefaultMethods TestDefaultBody.java
|
||||||
|
* @run main TestDefaultBody
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.sun.tools.classfile.AccessFlags;
|
||||||
|
import com.sun.tools.classfile.Attribute;
|
||||||
|
import com.sun.tools.classfile.ClassFile;
|
||||||
|
import com.sun.tools.classfile.ConstantPool.*;
|
||||||
|
import com.sun.tools.classfile.Code_attribute;
|
||||||
|
import com.sun.tools.classfile.Instruction;
|
||||||
|
import com.sun.tools.classfile.Method;
|
||||||
|
|
||||||
|
import com.sun.tools.classfile.Opcode;
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public class TestDefaultBody {
|
||||||
|
|
||||||
|
interface TestInterface {
|
||||||
|
int no_default(int i);
|
||||||
|
default int yes_default(int i) { return impl(this, i); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static int impl(TestInterface ti, int i) { return 0; }
|
||||||
|
|
||||||
|
static final String TARGET_CLASS_NAME = "TestDefaultBody";
|
||||||
|
static final String TARGET_NAME = "impl";
|
||||||
|
static final String TARGET_TYPE = "(LTestDefaultBody$TestInterface;I)I";
|
||||||
|
static final String SUBTEST_NAME = TestInterface.class.getName() + ".class";
|
||||||
|
static final String TEST_METHOD_NAME = "yes_default";
|
||||||
|
|
||||||
|
public static void main(String... args) throws Exception {
|
||||||
|
new TestDefaultBody().run();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() throws Exception {
|
||||||
|
String workDir = System.getProperty("test.classes");
|
||||||
|
File compiledTest = new File(workDir, SUBTEST_NAME);
|
||||||
|
verifyDefaultBody(compiledTest);
|
||||||
|
}
|
||||||
|
|
||||||
|
void verifyDefaultBody(File f) {
|
||||||
|
System.err.println("verify: " + f);
|
||||||
|
try {
|
||||||
|
ClassFile cf = ClassFile.read(f);
|
||||||
|
Method testMethod = null;
|
||||||
|
Code_attribute codeAttr = null;
|
||||||
|
for (Method m : cf.methods) {
|
||||||
|
codeAttr = (Code_attribute)m.attributes.get(Attribute.Code);
|
||||||
|
String mname = m.getName(cf.constant_pool);
|
||||||
|
if (mname.equals(TEST_METHOD_NAME)) {
|
||||||
|
testMethod = m;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
codeAttr = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (testMethod == null) {
|
||||||
|
throw new Error("Test method not found");
|
||||||
|
}
|
||||||
|
if (testMethod.access_flags.is(AccessFlags.ACC_ABSTRACT)) {
|
||||||
|
throw new Error("Test method is abstract");
|
||||||
|
}
|
||||||
|
if (codeAttr == null) {
|
||||||
|
throw new Error("Code attribute in test method not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean found = false;
|
||||||
|
for (Instruction instr : codeAttr.getInstructions()) {
|
||||||
|
if (instr.getOpcode() == Opcode.INVOKESTATIC) {
|
||||||
|
found = true;
|
||||||
|
int pc_index = instr.getShort(1);
|
||||||
|
CONSTANT_Methodref_info mref = (CONSTANT_Methodref_info)cf.constant_pool.get(pc_index);
|
||||||
|
String className = mref.getClassName();
|
||||||
|
String targetName = mref.getNameAndTypeInfo().getName();
|
||||||
|
String targetType = mref.getNameAndTypeInfo().getType();
|
||||||
|
|
||||||
|
if (!className.equals(TARGET_CLASS_NAME)) {
|
||||||
|
throw new Error("unexpected class in default method body " + className);
|
||||||
|
}
|
||||||
|
if (!targetName.equals(TARGET_NAME)) {
|
||||||
|
throw new Error("unexpected method name in default method body " + targetName);
|
||||||
|
}
|
||||||
|
if (!targetType.equals(TARGET_TYPE)) {
|
||||||
|
throw new Error("unexpected method type in default method body " + targetType);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
throw new Error("no invokestatic found in default method body");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new Error("error reading " + f +": " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2011, 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
|
||||||
|
* @ignore awaits for VM support
|
||||||
|
* @summary check that javac does not generate bridge methods for defaults
|
||||||
|
* @compile -XDallowDefaultMethods TestNoBridgeOnDefaults.java
|
||||||
|
* @run main TestNoBridgeOnDefaults
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.sun.tools.classfile.ClassFile;
|
||||||
|
import com.sun.tools.classfile.ConstantPool.*;
|
||||||
|
import com.sun.tools.classfile.Method;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public class TestNoBridgeOnDefaults {
|
||||||
|
|
||||||
|
interface A<X> {
|
||||||
|
default <Y> A<X> m(X x, Y y) { return Impl.<X,Y>m1(this, x, y); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static abstract class B<X> implements A<X> { }
|
||||||
|
|
||||||
|
interface C<X> extends A<X> {
|
||||||
|
default <Y> C<X> m(X x, Y y) { return Impl.<X,Y>m2(this, x, y); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static abstract class D<X> extends B<X> implements C<X> { }
|
||||||
|
|
||||||
|
static class Impl {
|
||||||
|
static <X, Y> A<X> m1(A<X> rec, X x, Y y) { return null; }
|
||||||
|
static <X, Y> C<X> m2(C<X> rec, X x, Y y) { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
static final String[] SUBTEST_NAMES = { B.class.getName() + ".class", D.class.getName() + ".class" };
|
||||||
|
static final String TEST_METHOD_NAME = "m";
|
||||||
|
|
||||||
|
public static void main(String... args) throws Exception {
|
||||||
|
new TestNoBridgeOnDefaults().run();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() throws Exception {
|
||||||
|
String workDir = System.getProperty("test.classes");
|
||||||
|
for (int i = 0 ; i < SUBTEST_NAMES.length ; i ++) {
|
||||||
|
File compiledTest = new File(workDir, SUBTEST_NAMES[i]);
|
||||||
|
checkNoBridgeOnDefaults(compiledTest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkNoBridgeOnDefaults(File f) {
|
||||||
|
System.err.println("check: " + f);
|
||||||
|
try {
|
||||||
|
ClassFile cf = ClassFile.read(f);
|
||||||
|
for (Method m : cf.methods) {
|
||||||
|
String mname = m.getName(cf.constant_pool);
|
||||||
|
if (mname.equals(TEST_METHOD_NAME)) {
|
||||||
|
throw new Error("unexpected bridge method found " + m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new Error("error reading " + f +": " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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.
|
||||||
|
*/
|
||||||
|
interface Clinit {
|
||||||
|
String s = Inner.m();
|
||||||
|
|
||||||
|
static class Inner {
|
||||||
|
static String m() { return ""; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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
|
||||||
|
* @summary check that clinit in interface doesn't cause spurious default method diagnostics
|
||||||
|
* @compile -source 1.4 -target 1.4 Clinit.java
|
||||||
|
* @compile CrossCompile.java
|
||||||
|
*/
|
||||||
|
class CrossCompile {
|
||||||
|
void test() {
|
||||||
|
String s = Clinit.s;
|
||||||
|
}
|
||||||
|
}
|
147
langtools/test/tools/javac/defaultMethods/fd/FDTest.java
Normal file
147
langtools/test/tools/javac/defaultMethods/fd/FDTest.java
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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
|
||||||
|
* @summary Automatic test for checking correctness of default resolution
|
||||||
|
*/
|
||||||
|
|
||||||
|
import shapegen.*;
|
||||||
|
|
||||||
|
import com.sun.source.util.JavacTask;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.tools.Diagnostic;
|
||||||
|
import javax.tools.JavaCompiler;
|
||||||
|
import javax.tools.JavaFileObject;
|
||||||
|
import javax.tools.SimpleJavaFileObject;
|
||||||
|
import javax.tools.StandardJavaFileManager;
|
||||||
|
import javax.tools.ToolProvider;
|
||||||
|
|
||||||
|
public class FDTest {
|
||||||
|
|
||||||
|
enum TestKind {
|
||||||
|
POSITIVE,
|
||||||
|
NEGATIVE;
|
||||||
|
|
||||||
|
Collection<Hierarchy> getHierarchy(HierarchyGenerator hg) {
|
||||||
|
return this == POSITIVE ?
|
||||||
|
hg.getOK() : hg.getErr();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
//create default shared JavaCompiler - reused across multiple compilations
|
||||||
|
JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
|
||||||
|
StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
|
||||||
|
|
||||||
|
HierarchyGenerator hg = new HierarchyGenerator();
|
||||||
|
for (TestKind tk : TestKind.values()) {
|
||||||
|
for (Hierarchy hs : tk.getHierarchy(hg)) {
|
||||||
|
new FDTest(tk, hs).run(comp, fm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestKind tk;
|
||||||
|
Hierarchy hs;
|
||||||
|
DefenderTestSource source;
|
||||||
|
DiagnosticChecker diagChecker;
|
||||||
|
|
||||||
|
FDTest(TestKind tk, Hierarchy hs) {
|
||||||
|
this.tk = tk;
|
||||||
|
this.hs = hs;
|
||||||
|
this.source = new DefenderTestSource();
|
||||||
|
this.diagChecker = new DiagnosticChecker();
|
||||||
|
}
|
||||||
|
|
||||||
|
void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
|
||||||
|
JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
|
||||||
|
Arrays.asList("-XDallowDefaultMethods"), null, Arrays.asList(source));
|
||||||
|
try {
|
||||||
|
ct.analyze();
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
throw new AssertionError("Error thrown when analyzing the following source:\n" + source.getCharContent(true));
|
||||||
|
}
|
||||||
|
check();
|
||||||
|
}
|
||||||
|
|
||||||
|
void check() {
|
||||||
|
boolean errorExpected = tk == TestKind.NEGATIVE;
|
||||||
|
if (errorExpected != diagChecker.errorFound) {
|
||||||
|
throw new AssertionError("problem in source: \n" +
|
||||||
|
"\nerror found = " + diagChecker.errorFound +
|
||||||
|
"\nerror expected = " + errorExpected +
|
||||||
|
"\n" + dumpHierarchy() +
|
||||||
|
"\n" + source.getCharContent(true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String dumpHierarchy() {
|
||||||
|
StringBuilder buf = new StringBuilder();
|
||||||
|
buf.append("root = " + hs.root + "\n");
|
||||||
|
for (ClassCase cc : hs.all) {
|
||||||
|
buf.append(" class name = " + cc.getName() + "\n");
|
||||||
|
buf.append(" class OK = " + cc.get_OK() + "\n");
|
||||||
|
buf.append(" prov = " + cc.get_mprov() + "\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
return buf.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
class DefenderTestSource extends SimpleJavaFileObject {
|
||||||
|
|
||||||
|
String source;
|
||||||
|
|
||||||
|
public DefenderTestSource() {
|
||||||
|
super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
|
||||||
|
StringBuilder buf = new StringBuilder();
|
||||||
|
List<ClassCase> defaultRef = new ArrayList<>();
|
||||||
|
for (ClassCase cc : hs.all) {
|
||||||
|
hs.genClassDef(buf, cc, null, defaultRef);
|
||||||
|
}
|
||||||
|
source = buf.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
|
||||||
|
|
||||||
|
boolean errorFound;
|
||||||
|
|
||||||
|
public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
|
||||||
|
if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
|
||||||
|
errorFound = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,310 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package shapegen;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Robert Field
|
||||||
|
*/
|
||||||
|
public class ClassCase {
|
||||||
|
|
||||||
|
public enum Kind {
|
||||||
|
IVAC (true, "v"),
|
||||||
|
IPRESENT (true, "p"),
|
||||||
|
IDEFAULT (true, "d"),
|
||||||
|
CNONE (false, "n"),
|
||||||
|
CABSTRACT (false, "a"),
|
||||||
|
CCONCRETE (false, "c");
|
||||||
|
|
||||||
|
private final String prefix;
|
||||||
|
public final boolean isInterface;
|
||||||
|
|
||||||
|
Kind(boolean isInterface, String prefix) {
|
||||||
|
this.isInterface = isInterface;
|
||||||
|
this.prefix = prefix;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public final Kind kind;
|
||||||
|
private final ClassCase superclass;
|
||||||
|
private final List<ClassCase> supertypes;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private boolean _OK;
|
||||||
|
private boolean _HasClassMethod;
|
||||||
|
private Set<ClassCase> _mprov;
|
||||||
|
private boolean _IsConcrete;
|
||||||
|
private boolean _HasDefault;
|
||||||
|
private ClassCase _mres;
|
||||||
|
private ClassCase _mdefend;
|
||||||
|
|
||||||
|
private Set<RuleGroup> executed = new HashSet<RuleGroup>() {};
|
||||||
|
|
||||||
|
public ClassCase(Kind kind, ClassCase superclass, List<ClassCase> interfaces) {
|
||||||
|
this.kind = kind;
|
||||||
|
this.superclass = superclass;
|
||||||
|
|
||||||
|
// Set supertypes from superclass (if any) and interfaces
|
||||||
|
List<ClassCase> lc;
|
||||||
|
if (superclass == null) {
|
||||||
|
lc = interfaces;
|
||||||
|
} else {
|
||||||
|
lc = new ArrayList<>();
|
||||||
|
lc.add(superclass);
|
||||||
|
lc.addAll(interfaces);
|
||||||
|
}
|
||||||
|
this.supertypes = lc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final boolean isInterface() { return kind.isInterface; }
|
||||||
|
public final boolean isClass() { return !kind.isInterface; }
|
||||||
|
|
||||||
|
public Set<ClassCase> get_mprov() {
|
||||||
|
exec(RuleGroup.PROVENENCE);
|
||||||
|
return _mprov;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set_mprov(ClassCase cc) {
|
||||||
|
Set<ClassCase> s = new HashSet<>();
|
||||||
|
s.add(cc);
|
||||||
|
_mprov = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set_mprov(Set<ClassCase> s) {
|
||||||
|
_mprov = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassCase get_mres() {
|
||||||
|
exec(RuleGroup.RESOLUTION);
|
||||||
|
return _mres;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set_mres(ClassCase cc) {
|
||||||
|
_mres = cc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassCase get_mdefend() {
|
||||||
|
exec(RuleGroup.DEFENDER);
|
||||||
|
return _mdefend;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set_mdefend(ClassCase cc) {
|
||||||
|
_mdefend = cc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean get_HasClassMethod() {
|
||||||
|
exec(RuleGroup.PROVENENCE);
|
||||||
|
return _HasClassMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set_HasClassMethod(boolean bool) {
|
||||||
|
_HasClassMethod = bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean get_HasDefault() {
|
||||||
|
exec(RuleGroup.MARKER);
|
||||||
|
return _HasDefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set_HasDefault(boolean bool) {
|
||||||
|
_HasDefault = bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean get_IsConcrete() {
|
||||||
|
exec(RuleGroup.MARKER);
|
||||||
|
return _IsConcrete;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set_IsConcrete(boolean bool) {
|
||||||
|
_IsConcrete = bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean get_OK() {
|
||||||
|
exec(RuleGroup.CHECKING);
|
||||||
|
return _OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set_OK(boolean bool) {
|
||||||
|
_OK = bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMethodDefined() {
|
||||||
|
for (ClassCase cc : supertypes) {
|
||||||
|
if (cc.isMethodDefined()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (kind) {
|
||||||
|
case CCONCRETE:
|
||||||
|
case CABSTRACT:
|
||||||
|
case IPRESENT:
|
||||||
|
case IDEFAULT:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAbstract() {
|
||||||
|
return isMethodDefined() && (get_mres()==null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasSuperclass() {
|
||||||
|
return superclass != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassCase getSuperclass() {
|
||||||
|
return superclass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ClassCase> getSupertypes() {
|
||||||
|
return supertypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ClassCase> getInterfaces() {
|
||||||
|
if (superclass != null) {
|
||||||
|
if (supertypes.get(0) != superclass) {
|
||||||
|
throw new AssertionError("superclass missing from supertypes");
|
||||||
|
}
|
||||||
|
return supertypes.subList(1, supertypes.size());
|
||||||
|
} else {
|
||||||
|
return supertypes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSubtypeOf(ClassCase cc) {
|
||||||
|
// S-Refl
|
||||||
|
if (cc.equals(this)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// S-Def
|
||||||
|
for (ClassCase sp : getSupertypes()) {
|
||||||
|
if (cc.equals(sp)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// _S-Trans
|
||||||
|
for (ClassCase sp : getSupertypes()) {
|
||||||
|
if (sp.isSubtypeOf(cc)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init(Map<String, Integer> namingContext) {
|
||||||
|
if (name != null) {
|
||||||
|
return; // Already inited
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ClassCase sup : supertypes) {
|
||||||
|
sup.init(namingContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build name
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
if (!supertypes.isEmpty()) {
|
||||||
|
sb.append(isInterface() ? "I" : "C");
|
||||||
|
for (ClassCase cc : supertypes) {
|
||||||
|
sb.append(cc.getName());
|
||||||
|
}
|
||||||
|
sb.append(kind.isInterface ? "i" : "c");
|
||||||
|
}
|
||||||
|
sb.append(kind.prefix);
|
||||||
|
String pname = sb.toString();
|
||||||
|
Integer icnt = namingContext.get(pname);
|
||||||
|
int cnt = icnt == null ? 0 : icnt;
|
||||||
|
++cnt;
|
||||||
|
namingContext.put(pname, cnt);
|
||||||
|
if (cnt > 1) {
|
||||||
|
sb.append(cnt);
|
||||||
|
}
|
||||||
|
this.name = sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isa(Kind... kinds) {
|
||||||
|
for (Kind k : kinds) {
|
||||||
|
if (kind == k) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void exec(RuleGroup rg ) {
|
||||||
|
if (!executed.contains(rg)) {
|
||||||
|
rg.exec(this);
|
||||||
|
executed.add(rg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void collectClasses(Set<ClassCase> seen) {
|
||||||
|
seen.add(this);
|
||||||
|
for (ClassCase cc : supertypes) {
|
||||||
|
cc.collectClasses(seen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getID() {
|
||||||
|
if (name == null) {
|
||||||
|
throw new Error("Access to uninitialized ClassCase");
|
||||||
|
} else {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public final String getName() {
|
||||||
|
if (name == null) {
|
||||||
|
return "ClassCase uninited@" + hashCode();
|
||||||
|
} else {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
return obj instanceof ClassCase && getID().equals(((ClassCase)obj).getID());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return getID().hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getName();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,143 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package shapegen;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static shapegen.ClassCase.Kind.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Robert Field
|
||||||
|
*/
|
||||||
|
public class Hierarchy {
|
||||||
|
|
||||||
|
public final ClassCase root;
|
||||||
|
public final Set<ClassCase> all;
|
||||||
|
|
||||||
|
public Hierarchy(ClassCase root) {
|
||||||
|
this.root = root;
|
||||||
|
root.init(new HashMap<String,Integer>());
|
||||||
|
Set<ClassCase> allClasses = new HashSet<>();
|
||||||
|
root.collectClasses(allClasses);
|
||||||
|
this.all = allClasses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean anyDefaults() {
|
||||||
|
for (ClassCase cc : all) {
|
||||||
|
if (cc.kind == IDEFAULT) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean get_OK() {
|
||||||
|
return root.get_OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String testName() {
|
||||||
|
return root + "Test";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void genInterfaceList(StringBuilder buf, String prefix, List<ClassCase> interfaces) {
|
||||||
|
if (!interfaces.isEmpty()) {
|
||||||
|
buf.append(" ");
|
||||||
|
buf.append(prefix);
|
||||||
|
buf.append(" ");
|
||||||
|
buf.append(interfaces.get(0));
|
||||||
|
for (int i = 1; i < interfaces.size(); ++i) {
|
||||||
|
buf.append(", " + interfaces.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void genClassDef(StringBuilder buf, ClassCase cc, String implClass, List<ClassCase> defaultRef) {
|
||||||
|
if (cc.isInterface()) {
|
||||||
|
buf.append("interface ");
|
||||||
|
buf.append(cc.getName() + " ");
|
||||||
|
genInterfaceList(buf, "extends", cc.getInterfaces());
|
||||||
|
buf.append(" {\n");
|
||||||
|
|
||||||
|
switch (cc.kind) {
|
||||||
|
case IDEFAULT:
|
||||||
|
buf.append(" default String m() { return \"\"; }\n");
|
||||||
|
defaultRef.add(cc);
|
||||||
|
break;
|
||||||
|
case IPRESENT:
|
||||||
|
buf.append(" String m();\n");
|
||||||
|
break;
|
||||||
|
case IVAC:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new AssertionError("Unexpected kind");
|
||||||
|
}
|
||||||
|
buf.append("}\n\n");
|
||||||
|
} else {
|
||||||
|
buf.append((cc.isAbstract()? "abstract " : ""));
|
||||||
|
buf.append(" class " + cc.getName());
|
||||||
|
if (cc.getSuperclass() != null) {
|
||||||
|
buf.append(" extends " + cc.getSuperclass());
|
||||||
|
}
|
||||||
|
|
||||||
|
genInterfaceList(buf, "implements", cc.getInterfaces());
|
||||||
|
buf.append(" {\n");
|
||||||
|
|
||||||
|
switch (cc.kind) {
|
||||||
|
case CCONCRETE:
|
||||||
|
buf.append(" public String m() { return \"\"; }\n");
|
||||||
|
break;
|
||||||
|
case CABSTRACT:
|
||||||
|
buf.append(" public abstract String m();\n");
|
||||||
|
break;
|
||||||
|
case CNONE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new AssertionError("Unexpected kind");
|
||||||
|
}
|
||||||
|
buf.append("}\n\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
return obj instanceof Hierarchy && root.getID().equals(((Hierarchy)obj).root.getID());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return root.getID().hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return root.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,190 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package shapegen;
|
||||||
|
|
||||||
|
import shapegen.ClassCase.Kind;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static shapegen.ClassCase.Kind.*;
|
||||||
|
|
||||||
|
import static java.lang.Math.pow;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Robert Field
|
||||||
|
*/
|
||||||
|
public final class HierarchyGenerator {
|
||||||
|
|
||||||
|
private static int okcnt = 0;
|
||||||
|
private static int errcnt = 0;
|
||||||
|
private static Set<Hierarchy> uniqueOK = new HashSet<>();
|
||||||
|
private static Set<Hierarchy> uniqueErr = new HashSet<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param args the command line arguments
|
||||||
|
*/
|
||||||
|
public HierarchyGenerator() {
|
||||||
|
organize("exhaustive interface", iExhaustive(2));
|
||||||
|
organize("exhaustive class", cExhaustive());
|
||||||
|
organize("shapes interface", iShapes());
|
||||||
|
organize("shapes class/interface", ciShapes());
|
||||||
|
|
||||||
|
System.out.printf("\nExpect OK: %d -- unique %d", okcnt, uniqueOK.size());
|
||||||
|
System.out.printf("\nExpect Error: %d -- unique %d\n", errcnt, uniqueErr.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Hierarchy> getOK() {
|
||||||
|
return uniqueOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Hierarchy> getErr() {
|
||||||
|
return uniqueErr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void organize(String tname, List<Hierarchy> totest) {
|
||||||
|
System.out.printf("\nTesting %s....\n", tname);
|
||||||
|
int nodefault = 0;
|
||||||
|
List<Hierarchy> ok = new ArrayList<>();
|
||||||
|
List<Hierarchy> err = new ArrayList<>();
|
||||||
|
for (Hierarchy cc : totest) {
|
||||||
|
if (cc.anyDefaults()) {
|
||||||
|
//System.out.printf(" %s\n", cc);
|
||||||
|
if (cc.get_OK()) {
|
||||||
|
ok.add(cc);
|
||||||
|
} else {
|
||||||
|
err.add(cc);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
++nodefault;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
errcnt += err.size();
|
||||||
|
okcnt += ok.size();
|
||||||
|
uniqueErr.addAll(err);
|
||||||
|
uniqueOK.addAll(ok);
|
||||||
|
|
||||||
|
System.out.printf(" %5d No default\n %5d Error\n %5d OK\n %5d Total\n",
|
||||||
|
nodefault, err.size(), ok.size(), totest.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Hierarchy> iExhaustive(int idepth) {
|
||||||
|
List<ClassCase> current = new ArrayList<>();
|
||||||
|
for (int i = 0; i < idepth; ++i) {
|
||||||
|
current = ilayer(current);
|
||||||
|
}
|
||||||
|
return wrapInClassAndHierarchy(current);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ClassCase> ilayer(List<ClassCase> srcLayer) {
|
||||||
|
List<ClassCase> lay = new ArrayList<>();
|
||||||
|
for (int i = (int) pow(2, srcLayer.size()) - 1; i >= 0; --i) {
|
||||||
|
List<ClassCase> itfs = new ArrayList<>();
|
||||||
|
for (int b = srcLayer.size() - 1; b >= 0; --b) {
|
||||||
|
if ((i & (1<<b)) != 0) {
|
||||||
|
itfs.add(srcLayer.get(b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lay.add(new ClassCase(IVAC, null, itfs));
|
||||||
|
lay.add(new ClassCase(IPRESENT, null, itfs));
|
||||||
|
lay.add(new ClassCase(IDEFAULT, null, itfs));
|
||||||
|
lay.add(new ClassCase(IDEFAULT, null, itfs));
|
||||||
|
}
|
||||||
|
return lay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Hierarchy> cExhaustive() {
|
||||||
|
final Kind[] iKinds = new Kind[]{IDEFAULT, IVAC, IPRESENT, null};
|
||||||
|
final Kind[] cKinds = new Kind[]{CNONE, CABSTRACT, CCONCRETE};
|
||||||
|
List<Hierarchy> totest = new ArrayList<>();
|
||||||
|
for (int i1 = 0; i1 < iKinds.length; ++i1) {
|
||||||
|
for (int i2 = 0; i2 < iKinds.length; ++i2) {
|
||||||
|
for (int i3 = 0; i3 < iKinds.length; ++i3) {
|
||||||
|
for (int c1 = 0; c1 < cKinds.length; ++c1) {
|
||||||
|
for (int c2 = 0; c2 < cKinds.length; ++c2) {
|
||||||
|
for (int c3 = 0; c3 < cKinds.length; ++c3) {
|
||||||
|
totest.add( new Hierarchy(
|
||||||
|
new ClassCase(cKinds[c1],
|
||||||
|
new ClassCase(cKinds[c2],
|
||||||
|
new ClassCase(cKinds[c3],
|
||||||
|
null,
|
||||||
|
iList(iKinds[i1])
|
||||||
|
),
|
||||||
|
iList(iKinds[i2])
|
||||||
|
),
|
||||||
|
iList(iKinds[i3])
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return totest;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ClassCase> iList(Kind kind) {
|
||||||
|
if (kind == null) {
|
||||||
|
return Collections.EMPTY_LIST;
|
||||||
|
} else {
|
||||||
|
List<ClassCase> itfs = new ArrayList<>();
|
||||||
|
itfs.add(new ClassCase(kind, null, Collections.EMPTY_LIST));
|
||||||
|
return itfs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Hierarchy> ciShapes() {
|
||||||
|
return wrapInHierarchy(TTShape.allCases(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Hierarchy> iShapes() {
|
||||||
|
return wrapInClassAndHierarchy(TTShape.allCases(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Hierarchy> wrapInClassAndHierarchy(List<ClassCase> ihs) {
|
||||||
|
List<Hierarchy> totest = new ArrayList<>();
|
||||||
|
for (ClassCase cc : ihs) {
|
||||||
|
List<ClassCase> interfaces = new ArrayList<>();
|
||||||
|
interfaces.add(cc);
|
||||||
|
totest.add(new Hierarchy(new ClassCase(CNONE, null, interfaces)));
|
||||||
|
}
|
||||||
|
return totest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Hierarchy> wrapInHierarchy(List<ClassCase> ihs) {
|
||||||
|
List<Hierarchy> totest = new ArrayList<>();
|
||||||
|
for (ClassCase cc : ihs) {
|
||||||
|
totest.add(new Hierarchy(cc));
|
||||||
|
}
|
||||||
|
return totest;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package shapegen;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Robert Field
|
||||||
|
*/
|
||||||
|
public abstract class Rule {
|
||||||
|
|
||||||
|
public final String name;
|
||||||
|
|
||||||
|
public Rule(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract boolean guard(ClassCase cc);
|
||||||
|
|
||||||
|
abstract void eval(ClassCase cc);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,206 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package shapegen;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static shapegen.ClassCase.Kind.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Robert Field
|
||||||
|
*/
|
||||||
|
public class RuleGroup {
|
||||||
|
|
||||||
|
final String name;
|
||||||
|
private final Rule[] rules;
|
||||||
|
|
||||||
|
public RuleGroup(String name, Rule[] rules) {
|
||||||
|
this.name = name;
|
||||||
|
this.rules = rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean exec(ClassCase cc) {
|
||||||
|
boolean found = false;
|
||||||
|
for (Rule rule : rules) {
|
||||||
|
if (rule.guard(cc)) {
|
||||||
|
if (found) {
|
||||||
|
throw new RuntimeException("Bad rules -- multiple matches " + toString() + " for " + cc);
|
||||||
|
} else {
|
||||||
|
rule.eval(cc);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RuleGroup PROVENENCE = new RuleGroup("Provenence", new Rule[] {
|
||||||
|
new Rule("P-CDeclare") {
|
||||||
|
boolean guard(ClassCase cc) {
|
||||||
|
return cc.isa(CCONCRETE, CABSTRACT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void eval(ClassCase cc) {
|
||||||
|
cc.set_mprov(cc);
|
||||||
|
cc.set_HasClassMethod(true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
new Rule("P-IDeclare") {
|
||||||
|
boolean guard(ClassCase cc) {
|
||||||
|
return cc.isa(IDEFAULT, IPRESENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void eval(ClassCase cc) {
|
||||||
|
cc.set_mprov(cc);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
new Rule("P-IntfInh") {
|
||||||
|
boolean guard(ClassCase cc) {
|
||||||
|
return cc.isa(IVAC, CNONE) && !(cc.hasSuperclass() && cc.getSuperclass().get_HasClassMethod());
|
||||||
|
}
|
||||||
|
|
||||||
|
void eval(ClassCase cc) {
|
||||||
|
Set<ClassCase> _S = new HashSet<>();
|
||||||
|
for (ClassCase t : cc.getSupertypes()) {
|
||||||
|
_S.addAll(t.get_mprov());
|
||||||
|
}
|
||||||
|
Set<ClassCase> tops = new HashSet<>();
|
||||||
|
for (ClassCase _W : _S) {
|
||||||
|
for (ClassCase _V : _S) {
|
||||||
|
if (_V.equals(_W) || !(_V.isSubtypeOf(_W))) {
|
||||||
|
tops.add(_W);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cc.set_mprov(tops);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
new Rule("P-ClassInh") {
|
||||||
|
boolean guard(ClassCase cc) {
|
||||||
|
return cc.isa(CNONE) && (cc.hasSuperclass() && cc.getSuperclass().get_HasClassMethod());
|
||||||
|
}
|
||||||
|
|
||||||
|
void eval(ClassCase cc) {
|
||||||
|
cc.set_mprov(cc.getSuperclass());
|
||||||
|
cc.set_HasClassMethod(true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
public static RuleGroup MARKER = new RuleGroup("Marker", new Rule[] {
|
||||||
|
new Rule("M-Default") {
|
||||||
|
boolean guard(ClassCase cc) {
|
||||||
|
return cc.isa(IDEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void eval(ClassCase cc) {
|
||||||
|
cc.set_HasDefault(true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
new Rule("M-Conc") {
|
||||||
|
boolean guard(ClassCase cc) {
|
||||||
|
return cc.isa(CCONCRETE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void eval(ClassCase cc) {
|
||||||
|
cc.set_IsConcrete(true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
public static RuleGroup RESOLUTION = new RuleGroup("Resolution", new Rule[] {
|
||||||
|
new Rule("R-Resolve") {
|
||||||
|
boolean guard(ClassCase cc) {
|
||||||
|
if (!(cc.isClass() && cc.get_mprov().size() == 1)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ClassCase _V = cc.get_mprov().iterator().next();
|
||||||
|
return _V.get_IsConcrete() || _V.get_HasDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
void eval(ClassCase cc) {
|
||||||
|
ClassCase _V = cc.get_mprov().iterator().next();
|
||||||
|
cc.set_mres(_V);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
public static RuleGroup DEFENDER = new RuleGroup("Defender", new Rule[] {
|
||||||
|
new Rule("D-Defend") {
|
||||||
|
boolean guard(ClassCase cc) {
|
||||||
|
ClassCase mresSuper = cc.hasSuperclass() ? cc.getSuperclass().get_mres() : null;
|
||||||
|
boolean eq = cc.get_mres() == null ? mresSuper == null : cc.get_mres().equals(mresSuper);
|
||||||
|
return cc.isa(CNONE) && !eq;
|
||||||
|
}
|
||||||
|
|
||||||
|
void eval(ClassCase cc) {
|
||||||
|
cc.set_mdefend(cc.get_mres());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
public static RuleGroup CHECKING = new RuleGroup("Checking", new Rule[] {
|
||||||
|
new Rule("C-Check") {
|
||||||
|
boolean guard(ClassCase cc) {
|
||||||
|
for (ClassCase t : cc.getSupertypes()) {
|
||||||
|
if (! t.get_OK()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int defenderCount = 0;
|
||||||
|
int provCount = 0;
|
||||||
|
for (ClassCase prov : cc.get_mprov()) {
|
||||||
|
if (prov.get_HasDefault()) {
|
||||||
|
defenderCount++;
|
||||||
|
}
|
||||||
|
provCount++;
|
||||||
|
}
|
||||||
|
return provCount <= 1 || defenderCount == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void eval(ClassCase cc) {
|
||||||
|
cc.set_OK(true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,126 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package shapegen;
|
||||||
|
|
||||||
|
import shapegen.ClassCase.Kind;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static shapegen.ClassCase.Kind.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type Template Node
|
||||||
|
*
|
||||||
|
* @author Robert Field
|
||||||
|
*/
|
||||||
|
public class TTNode {
|
||||||
|
|
||||||
|
final List<TTNode> supertypes;
|
||||||
|
final boolean canBeClass;
|
||||||
|
|
||||||
|
private int currentKindIndex;
|
||||||
|
private Kind[] kinds;
|
||||||
|
|
||||||
|
public TTNode(List<TTNode> subtypes, boolean canBeClass) {
|
||||||
|
this.supertypes = subtypes;
|
||||||
|
this.canBeClass = canBeClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start(boolean includeClasses) {
|
||||||
|
kinds =
|
||||||
|
supertypes.isEmpty()?
|
||||||
|
(new Kind[]{IDEFAULT, IPRESENT})
|
||||||
|
: ((includeClasses && canBeClass)?
|
||||||
|
new Kind[]{CNONE, IVAC, IDEFAULT, IPRESENT}
|
||||||
|
: new Kind[]{IVAC, IDEFAULT, IPRESENT});
|
||||||
|
currentKindIndex = 0;
|
||||||
|
|
||||||
|
for (TTNode sub : supertypes) {
|
||||||
|
sub.start(includeClasses);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean next() {
|
||||||
|
++currentKindIndex;
|
||||||
|
if (currentKindIndex >= kinds.length) {
|
||||||
|
currentKindIndex = 0;
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void collectAllSubtypes(Set<TTNode> subs) {
|
||||||
|
subs.add(this);
|
||||||
|
for (TTNode n : supertypes) {
|
||||||
|
n.collectAllSubtypes(subs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Kind getKind() {
|
||||||
|
return kinds[currentKindIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isInterface() {
|
||||||
|
return getKind().isInterface;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isClass() {
|
||||||
|
return !isInterface();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hasDefault() {
|
||||||
|
return getKind() == IDEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isValid() {
|
||||||
|
for (TTNode n : supertypes) {
|
||||||
|
if (!n.isValid() || (isInterface() && n.isClass())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassCase genCase() {
|
||||||
|
ClassCase subclass;
|
||||||
|
List<TTNode> ttintfs;
|
||||||
|
if (isClass() && !supertypes.isEmpty() && supertypes.get(0).isClass()) {
|
||||||
|
subclass = supertypes.get(0).genCase();
|
||||||
|
ttintfs = supertypes.subList(1, supertypes.size());
|
||||||
|
} else {
|
||||||
|
subclass = null;
|
||||||
|
ttintfs = supertypes;
|
||||||
|
}
|
||||||
|
List<ClassCase> intfs = new ArrayList<>();
|
||||||
|
for (TTNode node : ttintfs) {
|
||||||
|
intfs.add(node.genCase());
|
||||||
|
}
|
||||||
|
return new ClassCase(getKind(), subclass, intfs);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,100 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package shapegen;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.StringReader;
|
||||||
|
|
||||||
|
import static java.lang.Character.isLetter;
|
||||||
|
import static java.lang.Character.isUpperCase;
|
||||||
|
import static java.lang.Character.isWhitespace;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a type template definition string
|
||||||
|
*
|
||||||
|
* input :: classDef
|
||||||
|
* classDef :: letter [ ( classDef* ) ]
|
||||||
|
*
|
||||||
|
* @author Robert Field
|
||||||
|
*/
|
||||||
|
public class TTParser extends StringReader {
|
||||||
|
|
||||||
|
private Map<Character, TTNode> letterMap = new HashMap<>();
|
||||||
|
private char ch;
|
||||||
|
|
||||||
|
private final String def;
|
||||||
|
|
||||||
|
public TTParser(String s) {
|
||||||
|
super(s);
|
||||||
|
this.def = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void advance() throws IOException {
|
||||||
|
do {
|
||||||
|
ch = (char)read();
|
||||||
|
} while (isWhitespace(ch));
|
||||||
|
}
|
||||||
|
|
||||||
|
public TTNode parse() {
|
||||||
|
try {
|
||||||
|
advance();
|
||||||
|
return classDef();
|
||||||
|
} catch (IOException t) {
|
||||||
|
throw new RuntimeException(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private TTNode classDef() throws IOException {
|
||||||
|
if (!isLetter(ch)) {
|
||||||
|
if (ch == (char)-1) {
|
||||||
|
throw new IOException("Unexpected end of type template in " + def);
|
||||||
|
} else {
|
||||||
|
throw new IOException("Unexpected character in type template: " + (Character)ch + " in " + def);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
char nodeCh = ch;
|
||||||
|
TTNode node = letterMap.get(nodeCh);
|
||||||
|
boolean canBeClass = isUpperCase(nodeCh);
|
||||||
|
advance();
|
||||||
|
if (node == null) {
|
||||||
|
List<TTNode> subtypes = new ArrayList<>();
|
||||||
|
if (ch == '(') {
|
||||||
|
advance();
|
||||||
|
while (ch != ')') {
|
||||||
|
subtypes.add(classDef());
|
||||||
|
}
|
||||||
|
advance();
|
||||||
|
}
|
||||||
|
node = new TTNode(subtypes, canBeClass);
|
||||||
|
letterMap.put(nodeCh, node);
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package shapegen;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Robert Field
|
||||||
|
*/
|
||||||
|
public class TTShape {
|
||||||
|
|
||||||
|
private final TTNode root;
|
||||||
|
private final TTNode[] nodes;
|
||||||
|
|
||||||
|
TTShape(TTNode root) {
|
||||||
|
this.root = root;
|
||||||
|
Set<TTNode> subs = new HashSet<>();
|
||||||
|
root.collectAllSubtypes(subs);
|
||||||
|
nodes = subs.toArray(new TTNode[subs.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ClassCase> toCases(boolean includeClasses) {
|
||||||
|
List<ClassCase> ccs = new ArrayList<>();
|
||||||
|
root.start(includeClasses);
|
||||||
|
int i;
|
||||||
|
outer:
|
||||||
|
while (true) {
|
||||||
|
if (root.isValid()) {
|
||||||
|
ClassCase cc = root.genCase();
|
||||||
|
//System.out.println(cc);
|
||||||
|
ccs.add(cc);
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
do {
|
||||||
|
if (i >= nodes.length) {
|
||||||
|
break outer;
|
||||||
|
}
|
||||||
|
} while(!nodes[i++].next());
|
||||||
|
}
|
||||||
|
return ccs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<ClassCase> allCases(boolean includeClasses) {
|
||||||
|
List<ClassCase> ccs = new ArrayList<>();
|
||||||
|
for (TTShape shape : SHAPES) {
|
||||||
|
ccs.addAll(shape.toCases(includeClasses));
|
||||||
|
}
|
||||||
|
return ccs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TTShape parse(String s) {
|
||||||
|
return new TTShape(new TTParser(s).parse());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final TTShape[] SHAPES = new TTShape[] {
|
||||||
|
parse("a"),
|
||||||
|
parse("a(b)"),
|
||||||
|
parse("A(bb)"),
|
||||||
|
parse("A(B(d)c(d))"),
|
||||||
|
parse("A(b(c))"),
|
||||||
|
parse("A(B(cd)d)"),
|
||||||
|
parse("A(B(c)c)"),
|
||||||
|
parse("A(B(Ce)d(e))"),
|
||||||
|
parse("A(B(C)d(e))"),
|
||||||
|
parse("A(Bc(d))"),
|
||||||
|
parse("A(B(d)dc)"),
|
||||||
|
parse("A(B(dc)dc)"),
|
||||||
|
parse("A(B(c(d))d)"),
|
||||||
|
parse("A(B(C(d))d)"),
|
||||||
|
parse("A(B(C(e)d(e))e)"),
|
||||||
|
parse("A(B(c(d))c)"),
|
||||||
|
parse("A(B(dc(d))c)"),
|
||||||
|
parse("A(B(C(d))d)"),
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010, 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
|
||||||
|
* @summary smoke test for separate compilation of default methods
|
||||||
|
* @author Maurizio Cimadamore
|
||||||
|
* @compile -XDallowDefaultMethods pkg1/A.java
|
||||||
|
* @compile -XDallowDefaultMethods Separate.java
|
||||||
|
*/
|
||||||
|
|
||||||
|
import pkg1.A;
|
||||||
|
|
||||||
|
class Separate {
|
||||||
|
interface B extends A.I {
|
||||||
|
default void m() { A.m(this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
interface C extends A.I, B { }
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010, 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 A {
|
||||||
|
public interface I {
|
||||||
|
default void m() { A.m(this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void m(Object o) {}
|
||||||
|
}
|
|
@ -0,0 +1,406 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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
|
||||||
|
* @summary Automatic test for checking correctness of default super/this resolution
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.sun.source.util.JavacTask;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.tools.Diagnostic;
|
||||||
|
import javax.tools.JavaCompiler;
|
||||||
|
import javax.tools.JavaFileObject;
|
||||||
|
import javax.tools.SimpleJavaFileObject;
|
||||||
|
import javax.tools.StandardJavaFileManager;
|
||||||
|
import javax.tools.ToolProvider;
|
||||||
|
|
||||||
|
public class TestDefaultSuperCall {
|
||||||
|
|
||||||
|
static int checkCount = 0;
|
||||||
|
|
||||||
|
enum InterfaceKind {
|
||||||
|
DEFAULT("interface A extends B { default void m() { } }"),
|
||||||
|
ABSTRACT("interface A extends B { void m(); }"),
|
||||||
|
NONE("interface A extends B { }");
|
||||||
|
|
||||||
|
String interfaceStr;
|
||||||
|
|
||||||
|
InterfaceKind(String interfaceStr) {
|
||||||
|
this.interfaceStr = interfaceStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean methodDefined() {
|
||||||
|
return this == DEFAULT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum PruneKind {
|
||||||
|
NO_PRUNE("interface C { }"),
|
||||||
|
PRUNE("interface C extends A { }");
|
||||||
|
|
||||||
|
boolean methodDefined(InterfaceKind ik) {
|
||||||
|
return this == PRUNE &&
|
||||||
|
ik.methodDefined();
|
||||||
|
}
|
||||||
|
|
||||||
|
String interfaceStr;
|
||||||
|
|
||||||
|
PruneKind(String interfaceStr) {
|
||||||
|
this.interfaceStr = interfaceStr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum QualifierKind {
|
||||||
|
DIRECT_1("C"),
|
||||||
|
DIRECT_2("A"),
|
||||||
|
INDIRECT("B"),
|
||||||
|
UNRELATED("E"),
|
||||||
|
ENCLOSING_1(null),
|
||||||
|
ENCLOSING_2(null);
|
||||||
|
|
||||||
|
String qualifierStr;
|
||||||
|
|
||||||
|
QualifierKind(String qualifierStr) {
|
||||||
|
this.qualifierStr = qualifierStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getQualifier(Shape sh) {
|
||||||
|
switch (this) {
|
||||||
|
case ENCLOSING_1: return sh.enclosingAt(0);
|
||||||
|
case ENCLOSING_2: return sh.enclosingAt(1);
|
||||||
|
default:
|
||||||
|
return qualifierStr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isEnclosing() {
|
||||||
|
return this == ENCLOSING_1 ||
|
||||||
|
this == ENCLOSING_2;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean allowSuperCall(InterfaceKind ik, PruneKind pk) {
|
||||||
|
switch (this) {
|
||||||
|
case DIRECT_1:
|
||||||
|
return pk.methodDefined(ik);
|
||||||
|
case DIRECT_2:
|
||||||
|
return ik.methodDefined() && pk == PruneKind.NO_PRUNE;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ExprKind {
|
||||||
|
THIS("this"),
|
||||||
|
SUPER("super");
|
||||||
|
|
||||||
|
String exprStr;
|
||||||
|
|
||||||
|
ExprKind(String exprStr) {
|
||||||
|
this.exprStr = exprStr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ElementKind {
|
||||||
|
INTERFACE("interface #N { #B }", true),
|
||||||
|
INTERFACE_EXTENDS("interface #N extends A, C { #B }", true),
|
||||||
|
CLASS("class #N { #B }", false),
|
||||||
|
CLASS_EXTENDS("abstract class #N implements A, C { #B }", false),
|
||||||
|
STATIC_CLASS("static class #N { #B }", true),
|
||||||
|
STATIC_CLASS_EXTENDS("abstract static class #N implements A, C { #B }", true),
|
||||||
|
ANON_CLASS("new Object() { #B };", false),
|
||||||
|
METHOD("void test() { #B }", false),
|
||||||
|
STATIC_METHOD("static void test() { #B }", true),
|
||||||
|
DEFAULT_METHOD("default void test() { #B }", false);
|
||||||
|
|
||||||
|
String templateDecl;
|
||||||
|
boolean isStatic;
|
||||||
|
|
||||||
|
ElementKind(String templateDecl, boolean isStatic) {
|
||||||
|
this.templateDecl = templateDecl;
|
||||||
|
this.isStatic = isStatic;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isClassDecl() {
|
||||||
|
switch(this) {
|
||||||
|
case METHOD:
|
||||||
|
case STATIC_METHOD:
|
||||||
|
case DEFAULT_METHOD:
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isAllowedEnclosing(ElementKind ek, boolean isTop) {
|
||||||
|
switch (this) {
|
||||||
|
case CLASS:
|
||||||
|
case CLASS_EXTENDS:
|
||||||
|
//class is implicitly static inside interface, so skip this combo
|
||||||
|
return ek.isClassDecl() &&
|
||||||
|
ek != INTERFACE && ek != INTERFACE_EXTENDS;
|
||||||
|
case ANON_CLASS:
|
||||||
|
return !ek.isClassDecl();
|
||||||
|
case METHOD:
|
||||||
|
return ek == CLASS || ek == CLASS_EXTENDS ||
|
||||||
|
ek == STATIC_CLASS || ek == STATIC_CLASS_EXTENDS ||
|
||||||
|
ek == ANON_CLASS;
|
||||||
|
case INTERFACE:
|
||||||
|
case INTERFACE_EXTENDS:
|
||||||
|
case STATIC_CLASS:
|
||||||
|
case STATIC_CLASS_EXTENDS:
|
||||||
|
case STATIC_METHOD:
|
||||||
|
return (isTop && (ek == CLASS || ek == CLASS_EXTENDS)) ||
|
||||||
|
ek == STATIC_CLASS || ek == STATIC_CLASS_EXTENDS;
|
||||||
|
case DEFAULT_METHOD:
|
||||||
|
return ek == INTERFACE || ek == INTERFACE_EXTENDS;
|
||||||
|
default:
|
||||||
|
throw new AssertionError("Bad enclosing element kind" + this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isAllowedTop() {
|
||||||
|
switch (this) {
|
||||||
|
case CLASS:
|
||||||
|
case CLASS_EXTENDS:
|
||||||
|
case INTERFACE:
|
||||||
|
case INTERFACE_EXTENDS:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hasSuper() {
|
||||||
|
return this == INTERFACE_EXTENDS ||
|
||||||
|
this == STATIC_CLASS_EXTENDS ||
|
||||||
|
this == CLASS_EXTENDS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Shape {
|
||||||
|
|
||||||
|
String shapeStr;
|
||||||
|
List<ElementKind> enclosingElements;
|
||||||
|
List<String> enclosingNames;
|
||||||
|
List<String> elementsWithMethod;
|
||||||
|
|
||||||
|
Shape(ElementKind... elements) {
|
||||||
|
System.err.println("elements = " + Arrays.toString(elements));
|
||||||
|
enclosingElements = new ArrayList<>();
|
||||||
|
enclosingNames = new ArrayList<>();
|
||||||
|
elementsWithMethod = new ArrayList<>();
|
||||||
|
int count = 0;
|
||||||
|
String prevName = null;
|
||||||
|
for (ElementKind ek : elements) {
|
||||||
|
String name = "name"+count++;
|
||||||
|
if (ek.isStatic) {
|
||||||
|
enclosingElements = new ArrayList<>();
|
||||||
|
enclosingNames = new ArrayList<>();
|
||||||
|
}
|
||||||
|
if (ek.isClassDecl()) {
|
||||||
|
enclosingElements.add(ek);
|
||||||
|
enclosingNames.add(name);
|
||||||
|
} else {
|
||||||
|
elementsWithMethod.add(prevName);
|
||||||
|
}
|
||||||
|
String element = ek.templateDecl.replaceAll("#N", name);
|
||||||
|
shapeStr = shapeStr == null ? element : shapeStr.replaceAll("#B", element);
|
||||||
|
prevName = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String getShape(QualifierKind qk, ExprKind ek) {
|
||||||
|
String methName = ek == ExprKind.THIS ? "test" : "m";
|
||||||
|
String call = qk.getQualifier(this) + "." + ek.exprStr + "." + methName + "();";
|
||||||
|
return shapeStr.replaceAll("#B", call);
|
||||||
|
}
|
||||||
|
|
||||||
|
String enclosingAt(int index) {
|
||||||
|
return index < enclosingNames.size() ? enclosingNames.get(index) : "BAD";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String... args) throws Exception {
|
||||||
|
|
||||||
|
//create default shared JavaCompiler - reused across multiple compilations
|
||||||
|
JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
|
||||||
|
StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
|
||||||
|
|
||||||
|
for (InterfaceKind ik : InterfaceKind.values()) {
|
||||||
|
for (PruneKind pk : PruneKind.values()) {
|
||||||
|
for (ElementKind ek1 : ElementKind.values()) {
|
||||||
|
if (!ek1.isAllowedTop()) continue;
|
||||||
|
for (ElementKind ek2 : ElementKind.values()) {
|
||||||
|
if (!ek2.isAllowedEnclosing(ek1, true)) continue;
|
||||||
|
for (ElementKind ek3 : ElementKind.values()) {
|
||||||
|
if (!ek3.isAllowedEnclosing(ek2, false)) continue;
|
||||||
|
for (ElementKind ek4 : ElementKind.values()) {
|
||||||
|
if (!ek4.isAllowedEnclosing(ek3, false)) continue;
|
||||||
|
for (ElementKind ek5 : ElementKind.values()) {
|
||||||
|
if (!ek5.isAllowedEnclosing(ek4, false) || ek5.isClassDecl()) continue;
|
||||||
|
for (QualifierKind qk : QualifierKind.values()) {
|
||||||
|
for (ExprKind ek : ExprKind.values()) {
|
||||||
|
new TestDefaultSuperCall(ik, pk, new Shape(ek1, ek2, ek3, ek4, ek5), qk, ek).run(comp, fm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println("Total check executed: " + checkCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
InterfaceKind ik;
|
||||||
|
PruneKind pk;
|
||||||
|
Shape sh;
|
||||||
|
QualifierKind qk;
|
||||||
|
ExprKind ek;
|
||||||
|
JavaSource source;
|
||||||
|
DiagnosticChecker diagChecker;
|
||||||
|
|
||||||
|
TestDefaultSuperCall(InterfaceKind ik, PruneKind pk, Shape sh, QualifierKind qk, ExprKind ek) {
|
||||||
|
this.ik = ik;
|
||||||
|
this.pk = pk;
|
||||||
|
this.sh = sh;
|
||||||
|
this.qk = qk;
|
||||||
|
this.ek = ek;
|
||||||
|
this.source = new JavaSource();
|
||||||
|
this.diagChecker = new DiagnosticChecker();
|
||||||
|
}
|
||||||
|
|
||||||
|
class JavaSource extends SimpleJavaFileObject {
|
||||||
|
|
||||||
|
String template = "interface E {}\n" +
|
||||||
|
"interface B { }\n" +
|
||||||
|
"#I\n" +
|
||||||
|
"#P\n" +
|
||||||
|
"#C";
|
||||||
|
|
||||||
|
String source;
|
||||||
|
|
||||||
|
public JavaSource() {
|
||||||
|
super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
|
||||||
|
source = template.replaceAll("#I", ik.interfaceStr)
|
||||||
|
.replaceAll("#P", pk.interfaceStr)
|
||||||
|
.replaceAll("#C", sh.getShape(qk, ek));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
|
||||||
|
JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
|
||||||
|
Arrays.asList("-XDallowDefaultMethods"), null, Arrays.asList(source));
|
||||||
|
try {
|
||||||
|
ct.analyze();
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
throw new AssertionError("Error thrown when analyzing the following source:\n" + source.getCharContent(true));
|
||||||
|
}
|
||||||
|
check();
|
||||||
|
}
|
||||||
|
|
||||||
|
void check() {
|
||||||
|
boolean errorExpected = false;
|
||||||
|
|
||||||
|
boolean badEnclosing = false;
|
||||||
|
boolean badThis = false;
|
||||||
|
boolean badSuper = false;
|
||||||
|
|
||||||
|
if (qk == QualifierKind.ENCLOSING_1 &&
|
||||||
|
sh.enclosingNames.size() < 1) {
|
||||||
|
errorExpected |= true;
|
||||||
|
badEnclosing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qk == QualifierKind.ENCLOSING_2 &&
|
||||||
|
sh.enclosingNames.size() < 2) {
|
||||||
|
errorExpected |= true;
|
||||||
|
badEnclosing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ek == ExprKind.THIS) {
|
||||||
|
boolean found = false;
|
||||||
|
for (int i = 0; i < sh.enclosingElements.size(); i++) {
|
||||||
|
if (sh.enclosingElements.get(i) == ElementKind.ANON_CLASS) continue;
|
||||||
|
if (sh.enclosingNames.get(i).equals(qk.getQualifier(sh))) {
|
||||||
|
found = sh.elementsWithMethod.contains(sh.enclosingNames.get(i));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
errorExpected |= !found;
|
||||||
|
if (!found) {
|
||||||
|
badThis = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ek == ExprKind.SUPER) {
|
||||||
|
|
||||||
|
int lastIdx = sh.enclosingElements.size() - 1;
|
||||||
|
boolean found = lastIdx == -1 ? false :
|
||||||
|
sh.enclosingElements.get(lastIdx).hasSuper() && qk.allowSuperCall(ik, pk);
|
||||||
|
|
||||||
|
errorExpected |= !found;
|
||||||
|
if (!found) {
|
||||||
|
badSuper = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkCount++;
|
||||||
|
if (diagChecker.errorFound != errorExpected) {
|
||||||
|
throw new AssertionError("Problem when compiling source:\n" + source.getCharContent(true) +
|
||||||
|
"\nenclosingElems: " + sh.enclosingElements +
|
||||||
|
"\nenclosingNames: " + sh.enclosingNames +
|
||||||
|
"\nelementsWithMethod: " + sh.elementsWithMethod +
|
||||||
|
"\nbad encl: " + badEnclosing +
|
||||||
|
"\nbad this: " + badThis +
|
||||||
|
"\nbad super: " + badSuper +
|
||||||
|
"\nqual kind: " + qk +
|
||||||
|
"\nfound error: " + diagChecker.errorFound);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
|
||||||
|
|
||||||
|
boolean errorFound;
|
||||||
|
|
||||||
|
public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
|
||||||
|
if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
|
||||||
|
System.err.println(diagnostic.getMessage(Locale.getDefault()));
|
||||||
|
errorFound = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// key: compiler.err.default.overrides.object.member
|
||||||
|
// options: -XDallowDefaultMethods
|
||||||
|
|
||||||
|
interface DefaultOverridesObjectMember {
|
||||||
|
default String toString() { return ""; }
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// key: compiler.err.illegal.default.super.call
|
||||||
|
// key: compiler.misc.overridden.default
|
||||||
|
// options: -XDallowDefaultMethods
|
||||||
|
|
||||||
|
class OverriddenDefault {
|
||||||
|
interface I { default void m() { } }
|
||||||
|
interface J extends I { default void m() { } }
|
||||||
|
interface K extends I {}
|
||||||
|
|
||||||
|
static class C implements J, K {
|
||||||
|
void foo() { K.super.m(); }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// key: compiler.err.illegal.default.super.call
|
||||||
|
// key: compiler.misc.redundant.supertype
|
||||||
|
// options: -XDallowDefaultMethods
|
||||||
|
|
||||||
|
class RedundantSupertype {
|
||||||
|
interface I { default void m() { } }
|
||||||
|
interface J extends I { default void m() { } }
|
||||||
|
|
||||||
|
static class C implements I, J {
|
||||||
|
void foo() { I.super.m(); }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// key: compiler.err.types.incompatible.abstract.default
|
||||||
|
// options: -XDallowDefaultMethods
|
||||||
|
|
||||||
|
class TypesIncompatibleAbstractDefault {
|
||||||
|
interface A {
|
||||||
|
default void m() { }
|
||||||
|
}
|
||||||
|
|
||||||
|
interface B {
|
||||||
|
void m();
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AB extends A, B { }
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// key: compiler.err.types.incompatible.unrelated.defaults
|
||||||
|
// options: -XDallowDefaultMethods
|
||||||
|
|
||||||
|
class TypesIncompatibleUnrelatedDefaults {
|
||||||
|
interface A {
|
||||||
|
default void m() { }
|
||||||
|
}
|
||||||
|
|
||||||
|
interface B {
|
||||||
|
default void m() { }
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AB extends A, B { }
|
||||||
|
}
|
|
@ -26,7 +26,8 @@
|
||||||
* @bug 7022054
|
* @bug 7022054
|
||||||
*
|
*
|
||||||
* @summary Invalid compiler error on covariant overriding methods with the same erasure
|
* @summary Invalid compiler error on covariant overriding methods with the same erasure
|
||||||
* @compile T7022054pos1.java
|
* @compile -source 7 T7022054pos1.java
|
||||||
|
* @compile/fail -XDstrictMethodClashCheck T7022054pos1.java
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -26,8 +26,8 @@
|
||||||
* @bug 7022054
|
* @bug 7022054
|
||||||
*
|
*
|
||||||
* @summary Invalid compiler error on covariant overriding methods with the same erasure
|
* @summary Invalid compiler error on covariant overriding methods with the same erasure
|
||||||
* @compile T7022054pos2.java
|
* @compile -source 7 T7022054pos2.java
|
||||||
*
|
* @compile/fail -XDstrictMethodClashCheck T7022054pos2.java
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class T7022054pos2 {
|
class T7022054pos2 {
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import javax.tools.Diagnostic;
|
import javax.tools.Diagnostic;
|
||||||
import javax.tools.DiagnosticListener;
|
import javax.tools.DiagnosticListener;
|
||||||
|
@ -43,13 +44,15 @@ public class EagerInterfaceCompletionTest {
|
||||||
|
|
||||||
JavaCompiler javacTool;
|
JavaCompiler javacTool;
|
||||||
File testDir;
|
File testDir;
|
||||||
|
VersionKind versionKind;
|
||||||
HierarchyKind hierarchyKind;
|
HierarchyKind hierarchyKind;
|
||||||
TestKind testKind;
|
TestKind testKind;
|
||||||
ActionKind actionKind;
|
ActionKind actionKind;
|
||||||
|
|
||||||
EagerInterfaceCompletionTest(JavaCompiler javacTool, File testDir,
|
EagerInterfaceCompletionTest(JavaCompiler javacTool, File testDir, VersionKind versionKind,
|
||||||
HierarchyKind hierarchyKind, TestKind testKind, ActionKind actionKind) {
|
HierarchyKind hierarchyKind, TestKind testKind, ActionKind actionKind) {
|
||||||
this.javacTool = javacTool;
|
this.javacTool = javacTool;
|
||||||
|
this.versionKind = versionKind;
|
||||||
this.hierarchyKind = hierarchyKind;
|
this.hierarchyKind = hierarchyKind;
|
||||||
this.testDir = testDir;
|
this.testDir = testDir;
|
||||||
this.testKind = testKind;
|
this.testKind = testKind;
|
||||||
|
@ -62,7 +65,7 @@ public class EagerInterfaceCompletionTest {
|
||||||
actionKind.doAction(this);
|
actionKind.doAction(this);
|
||||||
DiagnosticChecker dc = new DiagnosticChecker();
|
DiagnosticChecker dc = new DiagnosticChecker();
|
||||||
compile(dc, testKind.source);
|
compile(dc, testKind.source);
|
||||||
if (testKind.completionFailure(actionKind, hierarchyKind) != dc.errorFound) {
|
if (testKind.completionFailure(versionKind, actionKind, hierarchyKind) != dc.errorFound) {
|
||||||
if (dc.errorFound) {
|
if (dc.errorFound) {
|
||||||
error("Unexpected completion failure" +
|
error("Unexpected completion failure" +
|
||||||
"\nhierarhcyKind " + hierarchyKind +
|
"\nhierarhcyKind " + hierarchyKind +
|
||||||
|
@ -80,7 +83,8 @@ public class EagerInterfaceCompletionTest {
|
||||||
void compile(DiagnosticChecker dc, JavaSource... sources) {
|
void compile(DiagnosticChecker dc, JavaSource... sources) {
|
||||||
try {
|
try {
|
||||||
CompilationTask ct = javacTool.getTask(null, null, dc,
|
CompilationTask ct = javacTool.getTask(null, null, dc,
|
||||||
Arrays.asList("-d", testDir.getAbsolutePath(), "-cp", testDir.getAbsolutePath()),
|
Arrays.asList("-d", testDir.getAbsolutePath(), "-cp",
|
||||||
|
testDir.getAbsolutePath(), versionKind.optsArr[0], versionKind.optsArr[1]),
|
||||||
null, Arrays.asList(sources));
|
null, Arrays.asList(sources));
|
||||||
ct.call();
|
ct.call();
|
||||||
}
|
}
|
||||||
|
@ -108,12 +112,25 @@ public class EagerInterfaceCompletionTest {
|
||||||
boolean errorFound = false;
|
boolean errorFound = false;
|
||||||
|
|
||||||
public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
|
public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
|
||||||
errorFound = true;
|
if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
|
||||||
|
errorFound = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//global declarations
|
//global declarations
|
||||||
|
|
||||||
|
enum VersionKind {
|
||||||
|
PRE_LAMBDA("-source", "7"),
|
||||||
|
LAMBDA("-source", "8");
|
||||||
|
|
||||||
|
String[] optsArr;
|
||||||
|
|
||||||
|
VersionKind(String... optsArr) {
|
||||||
|
this.optsArr = optsArr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum HierarchyKind {
|
enum HierarchyKind {
|
||||||
INTERFACE("interface A { boolean f = false; void m(); }\n" +
|
INTERFACE("interface A { boolean f = false; void m(); }\n" +
|
||||||
"class B implements A { public void m() {} }"),
|
"class B implements A { public void m() {} }"),
|
||||||
|
@ -157,13 +174,14 @@ public class EagerInterfaceCompletionTest {
|
||||||
this.source = new JavaSource("Test2.java", code);
|
this.source = new JavaSource("Test2.java", code);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean completionFailure(ActionKind ak, HierarchyKind hk) {
|
boolean completionFailure(VersionKind vk, ActionKind ak, HierarchyKind hk) {
|
||||||
switch (this) {
|
switch (this) {
|
||||||
case ACCESS_ONLY:
|
case ACCESS_ONLY:
|
||||||
case CONSTR: return ak == ActionKind.REMOVE_B;
|
case CONSTR: return ak == ActionKind.REMOVE_B;
|
||||||
case FIELD:
|
case FIELD:
|
||||||
case SUPER: return true;
|
case SUPER: return true;
|
||||||
case METHOD: return hk != HierarchyKind.INTERFACE || ak == ActionKind.REMOVE_B;
|
case METHOD: return hk != HierarchyKind.INTERFACE || ak == ActionKind.REMOVE_B ||
|
||||||
|
(hk == HierarchyKind.INTERFACE && ak == ActionKind.REMOVE_A && vk == VersionKind.LAMBDA);
|
||||||
default: throw new AssertionError("Unexpected test kind " + this);
|
default: throw new AssertionError("Unexpected test kind " + this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -173,12 +191,15 @@ public class EagerInterfaceCompletionTest {
|
||||||
String SCRATCH_DIR = System.getProperty("user.dir");
|
String SCRATCH_DIR = System.getProperty("user.dir");
|
||||||
JavaCompiler javacTool = ToolProvider.getSystemJavaCompiler();
|
JavaCompiler javacTool = ToolProvider.getSystemJavaCompiler();
|
||||||
int n = 0;
|
int n = 0;
|
||||||
for (HierarchyKind hierarchyKind : HierarchyKind.values()) {
|
for (VersionKind versionKind : VersionKind.values()) {
|
||||||
for (TestKind testKind : TestKind.values()) {
|
for (HierarchyKind hierarchyKind : HierarchyKind.values()) {
|
||||||
for (ActionKind actionKind : ActionKind.values()) {
|
for (TestKind testKind : TestKind.values()) {
|
||||||
File testDir = new File(SCRATCH_DIR, "test"+n);
|
for (ActionKind actionKind : ActionKind.values()) {
|
||||||
new EagerInterfaceCompletionTest(javacTool, testDir, hierarchyKind, testKind, actionKind).test();
|
File testDir = new File(SCRATCH_DIR, "test"+n);
|
||||||
n++;
|
new EagerInterfaceCompletionTest(javacTool, testDir, versionKind,
|
||||||
|
hierarchyKind, testKind, actionKind).test();
|
||||||
|
n++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue