From 85d61915ee515bc123694b8b10c6f44d156db7e8 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Thu, 1 Dec 2016 09:29:05 +1000 Subject: [PATCH] Avoid false positives for classes defined in methods If a class has the `EnclosingMethod` attribute, we know it was defined in the body of a method (or a val/var initializer), and is not part of the API of a class. Fixes #147 --- .../main/scala/com/typesafe/tools/mima/core/ClassInfo.scala | 3 +++ .../scala/com/typesafe/tools/mima/core/ClassfileParser.scala | 2 ++ .../main/scala/com/typesafe/tools/mima/core/PackageInfo.scala | 2 +- .../src/test/class-added-local-class-ok/problems.txt | 0 .../src/test/class-added-local-class-ok/v1/A.scala | 1 + .../src/test/class-added-local-class-ok/v2/A.scala | 1 + .../src/test/class-changed-local-class-ok/problems.txt | 0 .../src/test/class-changed-local-class-ok/v1/A.scala | 1 + .../src/test/class-changed-local-class-ok/v2/A.scala | 1 + .../src/test/class-removed-local-class-ok/problems.txt | 0 .../src/test/class-removed-local-class-ok/v1/A.scala | 1 + .../src/test/class-removed-local-class-ok/v2/A.scala | 1 + 12 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 reporter/functional-tests/src/test/class-added-local-class-ok/problems.txt create mode 100644 reporter/functional-tests/src/test/class-added-local-class-ok/v1/A.scala create mode 100644 reporter/functional-tests/src/test/class-added-local-class-ok/v2/A.scala create mode 100644 reporter/functional-tests/src/test/class-changed-local-class-ok/problems.txt create mode 100644 reporter/functional-tests/src/test/class-changed-local-class-ok/v1/A.scala create mode 100644 reporter/functional-tests/src/test/class-changed-local-class-ok/v2/A.scala create mode 100644 reporter/functional-tests/src/test/class-removed-local-class-ok/problems.txt create mode 100644 reporter/functional-tests/src/test/class-removed-local-class-ok/v1/A.scala create mode 100644 reporter/functional-tests/src/test/class-removed-local-class-ok/v2/A.scala diff --git a/core/src/main/scala/com/typesafe/tools/mima/core/ClassInfo.scala b/core/src/main/scala/com/typesafe/tools/mima/core/ClassInfo.scala index 481248ae..0847f9be 100644 --- a/core/src/main/scala/com/typesafe/tools/mima/core/ClassInfo.scala +++ b/core/src/main/scala/com/typesafe/tools/mima/core/ClassInfo.scala @@ -59,6 +59,9 @@ abstract class ClassInfo(val owner: PackageInfo) extends HasDeclarationName with var _innerClasses: Seq[String] = Seq.empty def innerClasses = { ensureLoaded(); _innerClasses } + var _isLocalClass = false + def isLocalClass = { ensureLoaded(); _isLocalClass} + var _isTopLevel = true def isTopLevel = { ensureLoaded(); _isTopLevel } diff --git a/core/src/main/scala/com/typesafe/tools/mima/core/ClassfileParser.scala b/core/src/main/scala/com/typesafe/tools/mima/core/ClassfileParser.scala index 837f27a4..20fd67ec 100644 --- a/core/src/main/scala/com/typesafe/tools/mima/core/ClassfileParser.scala +++ b/core/src/main/scala/com/typesafe/tools/mima/core/ClassfileParser.scala @@ -278,6 +278,8 @@ abstract class ClassfileParser(definitions: Definitions) { if (pool.getClassName(outerIndex) == c.bytecodeName) n else "" } else "" }.filterNot(_.isEmpty) + } else if (attrName == "EnclosingMethod") { + c._isLocalClass = true } else if (attrName == "Scala" || attrName == "ScalaSig") { this.parsedClass.isScala = true } diff --git a/core/src/main/scala/com/typesafe/tools/mima/core/PackageInfo.scala b/core/src/main/scala/com/typesafe/tools/mima/core/PackageInfo.scala index 18e22b3c..4159f8e8 100644 --- a/core/src/main/scala/com/typesafe/tools/mima/core/PackageInfo.scala +++ b/core/src/main/scala/com/typesafe/tools/mima/core/PackageInfo.scala @@ -79,7 +79,7 @@ abstract class PackageInfo(val owner: PackageInfo) { else if (prefix.isEmpty) clazz.isTopLevel && !clazz.bytecodeName.contains("$$") else prefix.exists(_.innerClasses contains clazz.bytecodeName) } - clazz.isPublic && isReachable + clazz.isPublic && !clazz.isLocalClass && isReachable } accessibleClassesUnder(Set.empty, Set.empty) diff --git a/reporter/functional-tests/src/test/class-added-local-class-ok/problems.txt b/reporter/functional-tests/src/test/class-added-local-class-ok/problems.txt new file mode 100644 index 00000000..e69de29b diff --git a/reporter/functional-tests/src/test/class-added-local-class-ok/v1/A.scala b/reporter/functional-tests/src/test/class-added-local-class-ok/v1/A.scala new file mode 100644 index 00000000..0aa93b47 --- /dev/null +++ b/reporter/functional-tests/src/test/class-added-local-class-ok/v1/A.scala @@ -0,0 +1 @@ +class A { def f() = { class Local } } \ No newline at end of file diff --git a/reporter/functional-tests/src/test/class-added-local-class-ok/v2/A.scala b/reporter/functional-tests/src/test/class-added-local-class-ok/v2/A.scala new file mode 100644 index 00000000..db2c5423 --- /dev/null +++ b/reporter/functional-tests/src/test/class-added-local-class-ok/v2/A.scala @@ -0,0 +1 @@ +class A { def f() = { } } \ No newline at end of file diff --git a/reporter/functional-tests/src/test/class-changed-local-class-ok/problems.txt b/reporter/functional-tests/src/test/class-changed-local-class-ok/problems.txt new file mode 100644 index 00000000..e69de29b diff --git a/reporter/functional-tests/src/test/class-changed-local-class-ok/v1/A.scala b/reporter/functional-tests/src/test/class-changed-local-class-ok/v1/A.scala new file mode 100644 index 00000000..c44406ca --- /dev/null +++ b/reporter/functional-tests/src/test/class-changed-local-class-ok/v1/A.scala @@ -0,0 +1 @@ +class A { def f() = { class Local { def v1 = "v1"} } } \ No newline at end of file diff --git a/reporter/functional-tests/src/test/class-changed-local-class-ok/v2/A.scala b/reporter/functional-tests/src/test/class-changed-local-class-ok/v2/A.scala new file mode 100644 index 00000000..0aa93b47 --- /dev/null +++ b/reporter/functional-tests/src/test/class-changed-local-class-ok/v2/A.scala @@ -0,0 +1 @@ +class A { def f() = { class Local } } \ No newline at end of file diff --git a/reporter/functional-tests/src/test/class-removed-local-class-ok/problems.txt b/reporter/functional-tests/src/test/class-removed-local-class-ok/problems.txt new file mode 100644 index 00000000..e69de29b diff --git a/reporter/functional-tests/src/test/class-removed-local-class-ok/v1/A.scala b/reporter/functional-tests/src/test/class-removed-local-class-ok/v1/A.scala new file mode 100644 index 00000000..dc63f8ce --- /dev/null +++ b/reporter/functional-tests/src/test/class-removed-local-class-ok/v1/A.scala @@ -0,0 +1 @@ +class A { def f() = { } } diff --git a/reporter/functional-tests/src/test/class-removed-local-class-ok/v2/A.scala b/reporter/functional-tests/src/test/class-removed-local-class-ok/v2/A.scala new file mode 100644 index 00000000..8b1774d4 --- /dev/null +++ b/reporter/functional-tests/src/test/class-removed-local-class-ok/v2/A.scala @@ -0,0 +1 @@ +class A { def f() = { class Local } }