diff --git a/internal/compiler-bridge/src/main/scala/xsbt/Dependency.scala b/internal/compiler-bridge/src/main/scala/xsbt/Dependency.scala index 20ce91c9d6..1bad94f944 100644 --- a/internal/compiler-bridge/src/main/scala/xsbt/Dependency.scala +++ b/internal/compiler-bridge/src/main/scala/xsbt/Dependency.scala @@ -92,16 +92,21 @@ final class Dependency(val global: CallbackGlobal) extends LocateClassFile with } // Define processor reusing `processDependency` definition - val memberRef = processDependency(DependencyByMemberRef) _ - val inheritance = processDependency(DependencyByInheritance) _ - val localInheritance = processDependency(LocalDependencyByInheritance) _ + val memberRef = processDependency(DependencyByMemberRef, false) _ + val inheritance = processDependency(DependencyByInheritance, true) _ + val localInheritance = processDependency(LocalDependencyByInheritance, true) _ + + @deprecated("Use processDependency that takes allowLocal.", "1.1.0") + def processDependency(context: DependencyContext)(dep: ClassDependency): Unit = + processDependency(context, true)(dep) /* * Handles dependency on given symbol by trying to figure out if represents a term * that is coming from either source code (not necessarily compiled in this compilation * run) or from class file and calls respective callback method. */ - def processDependency(context: DependencyContext)(dep: ClassDependency): Unit = { + def processDependency(context: DependencyContext, allowLocal: Boolean)( + dep: ClassDependency): Unit = { val fromClassName = classNameAsString(dep.from) def binaryDependency(file: File, binaryClassName: String) = @@ -133,11 +138,12 @@ final class Dependency(val global: CallbackGlobal) extends LocateClassFile with case None => debuglog(Feedback.noOriginFileForExternalSymbol(dep.to)) } - } else if (onSource.file != sourceFile) { - // Dependency is internal -- but from other file / compilation unit + } else if (onSource.file != sourceFile || allowLocal) { + // We cannot ignore dependencies coming from the same source file because + // the dependency info needs to propagate. See source-dependencies/trait-trait-211. val onClassName = classNameAsString(dep.to) callback.classDependency(onClassName, fromClassName, context) - } else () // Comes from the same file, ignore + } } } @@ -227,7 +233,6 @@ final class Dependency(val global: CallbackGlobal) extends LocateClassFile with val depClass = enclOrModuleClass(dep) val dependency = ClassDependency(fromClass, depClass) if (!cache.contains(dependency) && - fromClass.associatedFile != depClass.associatedFile && !depClass.isRefinementClass) { process(dependency) cache.add(dependency) diff --git a/internal/zinc-core/src/main/scala/sbt/internal/inc/Relations.scala b/internal/zinc-core/src/main/scala/sbt/internal/inc/Relations.scala index 16318212f6..6f78eb1524 100644 --- a/internal/zinc-core/src/main/scala/sbt/internal/inc/Relations.scala +++ b/internal/zinc-core/src/main/scala/sbt/internal/inc/Relations.scala @@ -275,6 +275,7 @@ object Relations { case o: ClassDependencies => internal == o.internal && external == o.external case _ => false } + override def toString: String = s"ClassDependencies(internal = $internal, external = $external)" override def hashCode = (internal, external).hashCode } @@ -661,26 +662,23 @@ private class MRelationsNameHashing( override def hashCode = (srcProd :: libraryDep :: libraryClassName :: memberRef :: inheritance :: classes :: Nil).hashCode - override def toString = ( - """ + override def toString: String = { + val internalDepsStr = (internalDependencies.dependencies map { + case (k, vs) => k + " " + relation_s(vs) + }).mkString("\n ", "\n ", "") + val externalDepsStr = (externalDependencies.dependencies map { + case (k, vs) => k + " " + relation_s(vs) + }).mkString("\n ", "\n ", "") + s""" |Relations (with name hashing enabled): - | products: %s - | library deps: %s - | library class names: %s - | class deps: %s - | ext deps: %s - | class names: %s - | used names: %s - | product class names: %s - """.trim.stripMargin.format( - List(srcProd, - libraryDep, - libraryClassName, - internalClassDep, - externalClassDep, - classes, - names, - productClassName) map relation_s: _*) - ) - + | products: ${relation_s(srcProd)} + | library deps: ${relation_s(libraryDep)} + | library class names: ${relation_s(libraryClassName)} + | internalDependencies: $internalDepsStr + | externalDependencies: $externalDepsStr + | class names: ${relation_s(classes)} + | used names: ${relation_s(names)} + | product class names: ${relation_s(productClassName)} + """.trim.stripMargin + } } diff --git a/zinc/src/sbt-test/source-dependencies/patMat-scope/src/main/scala/foo/Bar.scala b/zinc/src/sbt-test/source-dependencies/patMat-scope/src/main/scala/foo/Bar.scala new file mode 100644 index 0000000000..5553bbb07e --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/patMat-scope/src/main/scala/foo/Bar.scala @@ -0,0 +1,6 @@ +package foo + +// This class is used to pad the number of source code. +class Bar { + def bar: Unit = ??? +} diff --git a/zinc/src/sbt-test/source-dependencies/patMat-scope/src/main/scala/foo/Foo.scala b/zinc/src/sbt-test/source-dependencies/patMat-scope/src/main/scala/foo/Foo.scala new file mode 100644 index 0000000000..0941e4e3f4 --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/patMat-scope/src/main/scala/foo/Foo.scala @@ -0,0 +1,6 @@ +package foo + +// This class is used to pad the number of source code. +class Foo { + def foo: Unit = ??? +} diff --git a/zinc/src/sbt-test/source-dependencies/sealed/incOptions.properties b/zinc/src/sbt-test/source-dependencies/sealed/incOptions.properties new file mode 100644 index 0000000000..26949ab5dd --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/sealed/incOptions.properties @@ -0,0 +1 @@ +scalac.options = -Xfatal-warnings diff --git a/zinc/src/sbt-test/source-dependencies/sealed/test b/zinc/src/sbt-test/source-dependencies/sealed/test index 412e495308..7253703737 100644 --- a/zinc/src/sbt-test/source-dependencies/sealed/test +++ b/zinc/src/sbt-test/source-dependencies/sealed/test @@ -5,5 +5,4 @@ $ copy-file changes/A.scala A.scala # D.scala needs recompiling because the pattern match in D # is no longer exhaustive, which emits a warning -> checkRecompilations 1 A B C E -> checkRecompilations 2 D +-> compile diff --git a/zinc/src/sbt-test/source-dependencies/trait-trait-211/build.json b/zinc/src/sbt-test/source-dependencies/trait-trait-211/build.json new file mode 100644 index 0000000000..e2b0035d3b --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/trait-trait-211/build.json @@ -0,0 +1,8 @@ +{ + "projects": [ + { + "name": "mirtest", + "scalaVersion": "2.11.8" + } + ] +} diff --git a/zinc/src/sbt-test/source-dependencies/trait-trait-211/changes/A1.scala b/zinc/src/sbt-test/source-dependencies/trait-trait-211/changes/A1.scala new file mode 100644 index 0000000000..a68e162077 --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/trait-trait-211/changes/A1.scala @@ -0,0 +1,12 @@ +package gg +package table + +trait A { + def transform: Unit = { + // the use site is updated + buildNonemptyObjects(0, 1) + } + + // add extra parameter here + def buildNonemptyObjects(a: Int, b: Int): Unit = () +} diff --git a/zinc/src/sbt-test/source-dependencies/trait-trait-211/mirtest/A.scala b/zinc/src/sbt-test/source-dependencies/trait-trait-211/mirtest/A.scala new file mode 100644 index 0000000000..5414fa1748 --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/trait-trait-211/mirtest/A.scala @@ -0,0 +1,10 @@ +package gg +package table + +trait A { + def transform: Unit = { + buildNonemptyObjects(0) + } + + def buildNonemptyObjects(a: Int): Unit = () +} diff --git a/zinc/src/sbt-test/source-dependencies/trait-trait-211/mirtest/B.scala b/zinc/src/sbt-test/source-dependencies/trait-trait-211/mirtest/B.scala new file mode 100644 index 0000000000..3378a548af --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/trait-trait-211/mirtest/B.scala @@ -0,0 +1,9 @@ +package xx + +import gg.table._ + +trait C extends B { +} + +trait B extends A { +} diff --git a/zinc/src/sbt-test/source-dependencies/trait-trait-211/mirtest/Hello.scala b/zinc/src/sbt-test/source-dependencies/trait-trait-211/mirtest/Hello.scala new file mode 100644 index 0000000000..c416916e23 --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/trait-trait-211/mirtest/Hello.scala @@ -0,0 +1,8 @@ +package xx + +object Hello extends App { + val consumer = new Foo + consumer.transform +} + +class Foo extends C diff --git a/zinc/src/sbt-test/source-dependencies/trait-trait-211/mirtest/incOptions.properties b/zinc/src/sbt-test/source-dependencies/trait-trait-211/mirtest/incOptions.properties new file mode 100644 index 0000000000..adfc92c361 --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/trait-trait-211/mirtest/incOptions.properties @@ -0,0 +1 @@ +relationsDebug = true diff --git a/zinc/src/sbt-test/source-dependencies/trait-trait-211/test b/zinc/src/sbt-test/source-dependencies/trait-trait-211/test new file mode 100644 index 0000000000..fe0b9a28b2 --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/trait-trait-211/test @@ -0,0 +1,5 @@ +> mirtest/run + +## After copying the Good implementation, we should be able to run successfully. +$ copy-file changes/A1.scala mirtest/A.scala +> mirtest/run diff --git a/zinc/src/sbt-test/source-dependencies/trait-trait-212/build.json b/zinc/src/sbt-test/source-dependencies/trait-trait-212/build.json new file mode 100644 index 0000000000..c925de7e82 --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/trait-trait-212/build.json @@ -0,0 +1,8 @@ +{ + "projects": [ + { + "name": "mirtest", + "scalaVersion": "2.12.3" + } + ] +} diff --git a/zinc/src/sbt-test/source-dependencies/trait-trait-212/changes/A1.scala b/zinc/src/sbt-test/source-dependencies/trait-trait-212/changes/A1.scala new file mode 100644 index 0000000000..a68e162077 --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/trait-trait-212/changes/A1.scala @@ -0,0 +1,12 @@ +package gg +package table + +trait A { + def transform: Unit = { + // the use site is updated + buildNonemptyObjects(0, 1) + } + + // add extra parameter here + def buildNonemptyObjects(a: Int, b: Int): Unit = () +} diff --git a/zinc/src/sbt-test/source-dependencies/trait-trait-212/mirtest/A.scala b/zinc/src/sbt-test/source-dependencies/trait-trait-212/mirtest/A.scala new file mode 100644 index 0000000000..5414fa1748 --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/trait-trait-212/mirtest/A.scala @@ -0,0 +1,10 @@ +package gg +package table + +trait A { + def transform: Unit = { + buildNonemptyObjects(0) + } + + def buildNonemptyObjects(a: Int): Unit = () +} diff --git a/zinc/src/sbt-test/source-dependencies/trait-trait-212/mirtest/B.scala b/zinc/src/sbt-test/source-dependencies/trait-trait-212/mirtest/B.scala new file mode 100644 index 0000000000..3378a548af --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/trait-trait-212/mirtest/B.scala @@ -0,0 +1,9 @@ +package xx + +import gg.table._ + +trait C extends B { +} + +trait B extends A { +} diff --git a/zinc/src/sbt-test/source-dependencies/trait-trait-212/mirtest/Hello.scala b/zinc/src/sbt-test/source-dependencies/trait-trait-212/mirtest/Hello.scala new file mode 100644 index 0000000000..c416916e23 --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/trait-trait-212/mirtest/Hello.scala @@ -0,0 +1,8 @@ +package xx + +object Hello extends App { + val consumer = new Foo + consumer.transform +} + +class Foo extends C diff --git a/zinc/src/sbt-test/source-dependencies/trait-trait-212/mirtest/incOptions.properties b/zinc/src/sbt-test/source-dependencies/trait-trait-212/mirtest/incOptions.properties new file mode 100644 index 0000000000..adfc92c361 --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/trait-trait-212/mirtest/incOptions.properties @@ -0,0 +1 @@ +relationsDebug = true diff --git a/zinc/src/sbt-test/source-dependencies/trait-trait-212/test b/zinc/src/sbt-test/source-dependencies/trait-trait-212/test new file mode 100644 index 0000000000..fe0b9a28b2 --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/trait-trait-212/test @@ -0,0 +1,5 @@ +> mirtest/run + +## After copying the Good implementation, we should be able to run successfully. +$ copy-file changes/A1.scala mirtest/A.scala +> mirtest/run diff --git a/zinc/src/sbt-test/source-dependencies/transitive-class/A.scala b/zinc/src/sbt-test/source-dependencies/transitive-class/A.scala new file mode 100644 index 0000000000..68c5796a7c --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/transitive-class/A.scala @@ -0,0 +1 @@ +abstract class A diff --git a/zinc/src/sbt-test/source-dependencies/transitive-class/BC.scala b/zinc/src/sbt-test/source-dependencies/transitive-class/BC.scala new file mode 100644 index 0000000000..150a8f195a --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/transitive-class/BC.scala @@ -0,0 +1,2 @@ +class B extends A +class C extends B diff --git a/zinc/src/sbt-test/source-dependencies/transitive-class/D.scala b/zinc/src/sbt-test/source-dependencies/transitive-class/D.scala new file mode 100644 index 0000000000..08ebf2e960 --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/transitive-class/D.scala @@ -0,0 +1,4 @@ +class D extends C +object Hello extends App { + new D +} diff --git a/zinc/src/sbt-test/source-dependencies/transitive-class/changes/A.scala b/zinc/src/sbt-test/source-dependencies/transitive-class/changes/A.scala new file mode 100644 index 0000000000..a02e9e5db4 --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/transitive-class/changes/A.scala @@ -0,0 +1,3 @@ +abstract class A { + def foo: String = "" +} diff --git a/zinc/src/sbt-test/source-dependencies/transitive-class/test b/zinc/src/sbt-test/source-dependencies/transitive-class/test new file mode 100644 index 0000000000..b4847740f4 --- /dev/null +++ b/zinc/src/sbt-test/source-dependencies/transitive-class/test @@ -0,0 +1,3 @@ +> compile +$ copy-file changes/A.scala A.scala +> checkRecompilations 2 A B C D Hello