Skip to content

Commit

Permalink
Merge pull request #2 from caarmen/issue-109-fix
Browse files Browse the repository at this point in the history
Issue luontola#109: Prevent child lambdas overriding parent lambdas.
  • Loading branch information
caarmen authored Sep 19, 2016
2 parents 88cb0a9 + 83b6766 commit 03843e7
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,19 @@ public Collection<MethodInfo> getMethods(Type type) {
return methods.values();
}

public boolean isMethodInSuperClass(Type type, MethodSignature methodSignature) {
ClassInfo c = getClass(type);
if (c.superclass != null) {
Collection<MethodInfo> superClassMethods = getMethods(c.superclass);
for (MethodInfo superClassMethod : superClassMethods) {
if (superClassMethod.signature.equals(methodSignature)) {
return true;
}
}
}
return false;
}

private boolean isAlreadyInherited(MethodInfo subject, Map<MethodSignature, MethodInfo> existingMethods) {
MethodInfo existing = existingMethods.get(subject.signature);
return existing != null && getAllInterfaces(existing.owner).contains(subject.owner);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ private static void resetLambdaClassSequenceNumber() {

@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
if (LambdaNaming.isBodyMethod(access, name)) {
if (LambdaNaming.isBodyMethod(access, name)
&& !analyzer.isMethodInSuperClass(Type.getObjectType(className), new MethodSignature(name, desc))) {
// Ensure our generated lambda class is able to call this method.
access &= ~ACC_PRIVATE;
}
Expand All @@ -75,7 +76,7 @@ Handle getLambdaAccessMethod(Handle implMethod) {
// The method is visible to the companion class and therefore doesn't need an accessor.
return implMethod;
}
if (LambdaNaming.isBodyMethodName(implMethod.getName())) {
if (LambdaNaming.isBodyMethodName(implMethod.getName()) && !isMethodInSuperClass(implMethod)) {
if (implMethod.getTag() == H_INVOKESPECIAL) {
// The private body method is now package so switch its invocation from special to virtual.
return new Handle(H_INVOKEVIRTUAL, implMethod.getOwner(), implMethod.getName(), implMethod.getDesc(), false);
Expand Down Expand Up @@ -103,6 +104,11 @@ private boolean isOwnedMethodVisible(Handle implMethod) {
throw new IllegalStateException("Non-analyzed method " + implMethod + ". Report this as a bug.");
}

private boolean isMethodInSuperClass(Handle implMethod) {
MethodSignature implSignature = new MethodSignature(implMethod.getName(), implMethod.getDesc());
return analyzer.isMethodInSuperClass(Type.getObjectType(implMethod.getOwner()), implSignature);
}

private boolean isNonOwnedMethodVisible(Handle implMethod) {
String classPackage = className.substring(0, className.lastIndexOf('/'));
String implPackage = implMethod.getOwner().substring(0, implMethod.getOwner().lastIndexOf('/'));
Expand Down

0 comments on commit 03843e7

Please sign in to comment.