Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding an abstract method is a binary compatible evolution. Fix #69 #70

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
public abstract class A {}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
public class B extends A {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
public abstract class A {
public abstract String foo();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
public class B extends A {
public String foo() {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
public interface A {}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
public class B implements A {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
public interface A {
public String foo();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
public class B implements A {
public String foo() {
return null;
}
}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
public interface A {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
public interface A {
public default String foo() {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
synthetic method A$_setter_$foo_=(Int)Unit in trait A does not have a correspondent in old version

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
method foo()Int in trait A does not have a correspondent in new version
method foo()Int in trait B does not have a correspondent in old version
method foo()Int in trait A does not have a correspondent in new version
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,3 @@ trait A {
def bar = 2
def foo = 2
}

trait B

class C extends A with B
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
trait A {
def bar = 2
}

trait B {
def foo = 2
}

class C extends A with B
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -78,18 +78,14 @@ private[analyze] class ClassAnalyzer extends Analyzer {
override def analyzeNewClassMethods(oldclazz: ClassInfo, newclazz: ClassInfo): List[Problem] = {
for (newAbstrMeth <- newclazz.deferredMethods) yield {
oldclazz.lookupMethods(newAbstrMeth.bytecodeName).find(_.sig == newAbstrMeth.sig) match {
case None =>
val p = MissingMethodProblem(newAbstrMeth)
p.affectedVersion = Problem.ClassVersion.Old
Some(p)
case Some(found) =>
if(found.isConcrete) {
val p = AbstractMethodProblem(newAbstrMeth)
p.affectedVersion = Problem.ClassVersion.Old
Some(p)
}
else
None
if (found.isConcrete) {
val p = AbstractMethodProblem(newAbstrMeth)
p.affectedVersion = Problem.ClassVersion.Old
Some(p)
} else
None
case _ => None
}
}
}
Expand All @@ -103,33 +99,19 @@ private[analyze] class TraitAnalyzer extends Analyzer {
protected val methodChecker = new TraitMethodChecker

override def analyzeNewClassMethods(oldclazz: ClassInfo, newclazz: ClassInfo): List[Problem] = {
val res = collection.mutable.ListBuffer.empty[Problem]

for (newmeth <- newclazz.concreteMethods if !oldclazz.hasStaticImpl(newmeth)) {
if (!oldclazz.lookupMethods(newmeth.bytecodeName).exists(_.sig == newmeth.sig)) {
// this means that the method is brand new and therefore the implementation
// has to be injected
val problem = MissingMethodProblem(newmeth)
problem.affectedVersion = Problem.ClassVersion.Old
res += problem
}
for {
newmeth <- newclazz.concreteMethods if !oldclazz.hasStaticImpl(newmeth)
if !oldclazz.lookupMethods(newmeth.bytecodeName).exists(_.sig == newmeth.sig)
// else a static implementation for the same method existed already, therefore
// class that mixed-in the trait already have a forwarder to the implementation
// class. Mind that, despite no binary incompatibility arises, program's
// semantic may be severely affected.
} yield {
// this means that the method is brand new and therefore the implementation
// has to be injected
val problem = MissingMethodProblem(newmeth)
problem.affectedVersion = Problem.ClassVersion.Old
problem
}

for (newmeth <- newclazz.deferredMethods) {
val oldmeths = oldclazz.lookupMethods(newmeth.bytecodeName)
oldmeths find (_.sig == newmeth.sig) match {
case Some(oldmeth) => ()
case _ =>
val problem = MissingMethodProblem(newmeth)
problem.affectedVersion = Problem.ClassVersion.Old
res += problem
}
}

res.toList
}
}