Provides a workaround flag `incOptions :=
incOptions.value.withIncludeSynthToNameHashing(true)` for name hashing
not including synthetic methods. This will not be enabled by default in
sbt 0.13. It can also enabled by passing `sbt.inc.include_synth=true`
to JVM.
Add a new field in `Source` that indicates whether this `Source`
represents a package object. This field is used in the incrmental
compiler to perform recompilation of package objects rather than relying
on the file name being `package.scala`.
Mark pending test `source-dependencies/package-object-name` as passing.
Modify `invalidatedPackageObjects` to look for package objects that
transitively inherit from an invalidated class instead of just inheriting
directly. This is the correct behavior that should have been implemented
in the first place. The bug comes from a subtle copy&paste mistake. The old
implementation used `publicInherited` relation and new one looks identical
but uses `inheritance` relation. The difference is that `publicInherited`
was a relation that was expanded transitively along inheritance chain but
`inheritance` is not. We have to perform the transitive walk in
`IncrementalNameHashing.invalidatedPackageObjects` implementation.
Mark `pkg-self` test as passing.
Fixes#2326
To aid debugging, modify Relations.toString to include `inheritance` in
addition to already printed `memberRef` relation.
Modify it for both name hashing and old implementation.
Further categorize debug output as api diff ([diff]), and
invalidation ([inv]). Since we log a ton of diagnostics,
make it a bit easier to find the relevant bits.
Motivated because we want to make it more robust & configurable.
Original motivation was to diagnose a cyclic type representation,
likely due to an f-bounded existential type, as illustrated by the following:
```
class Dep {
// The API representation for `bla`'s result type contains a cycle
// (an existential's type variable's bound is the existential type itself)
// This results in a stack overflow while showing the API diff.
// Note that the actual result type in the compiler is not cyclic
// (the f-bounded existential for Comparable is truncated)
def bla(c: Boolean) = if (c) new Value else "bla"
}
class Value extends java.lang.Comparable[Value] { def compareTo(that: Value): Int = 1 }
```
Limit nesting (`-Dsbt.inc.apidiff.depth=N`, where N defaults to `2`),
and number of declarations shown for a class/structural type
(via `sbt.inc.apidiff.decls`, which defaults to `0` -- no limit).
Limiting nesting is crucial in keeping the size of api diffs of large programs
within a reasonable amount of RAM...
For example, compiling the Scala library, the API diff with nesting at `4`
exhausts 4G of RAM...
sbt 0.13.1 was changed so that products were invalidated
not just when they were deleted, but also when they were
modified, however the debug message was not updated to
reflect this, causing people to think invalidated class files
had been deleted.
* Split Java analyzing compile into its own class.
* MixedAnalyzingCompiler now only does the mixing
* Start moving methods around to more-final locations
* Static analyzingCompile method now constructs a MixedAnalyzingCOmpiler and delegates to incremental compile.
* Force CompileSetup Equiv typeclass to use Equiv relations defined locally.
* Add toString methods on many of the incremental compiler datatypes.
* Remove remaining binary compatibility issues in Defaults.scala.
Since `DependencyContext` is needed in the compiler interface
subproject, it has to be defined in this same subproject.
`DependencyContext` is needed in this subproject because the
`AnalysisCallback` interface uses it.
A new infrastructure to register sources and their dependencies has
been introduced in `c09a391`.
This commit brings the required modifications to `AnalysisTest`,
so that it uses it.
A new infrastructure to register sources and their dependencies has
been introduced in `c09a391`.
This commit brings the required modifications to `AnalysisCallback`,
so that it uses it.
This commit implements the abstraction over the dependency kinds and
deprecates the methods that were used to register files and their
dependencies.
Dependencies are now divided into two categories : Internal and
External dependencies. Moreover, each internal or external dependency
has a Context, which describes what introduced the dependency (for
instance, a dependency may be introduced by member reference or by
inheritance).
Dependencies must now be registered using the method `addSource` in
`Analysis` and in `Relations`. This method has the advantage of being
independent from the existing dependency contexts. That is, its
signature does not need to be modified whenever a new dependency
context is introduced.
This represents a sketch of the idea that we can abstract over details
of a specific dependency kind. The goal would that only a few
implementations of methods in incremental would be sensitive to specific
dependency kind:
1. Dependency extraction logic
2. Implementation of Relations which adds dependencies to specific
relations (or abstract over specific relations)
3. Invalidation algorithm (Incremental.scala) which has different
of each kind of dependency
4. TextAnalysisFormat
In particular, adding a new dependency kind would not affect signatures
of existing methods.
What needs to be done:
- finish refactoring so the code compiles again and previous semantics
are preserved
- introduce deprecated overloads that preserve old method signatures
(this is required for preserving binary compatibility)
The previous implementation of TextAnalysisFormat contained the list
of all the existing relations that sbt knew of, and used this
information to write to and read from the disk the persisted analyses.
In this knew implementation, TextAnalysisFormat gets from the
Relations object what are the existing relations, and then persists
them to disk.
The previous situation was not optimal since it meant that, in order
to add a new dependency kind, one had to modify both the Relations
and TextAnalysisFormat.
Using this new implementation, no change to TextAnalysisFormat is
required whenever a new dependency kind is added.
Unit tests in incremental-compiler subproject use a generator to
create random Analysis objects. This generator was unfortunately
not working properly and generated only empty Analyses (it failed
to generate any non-empty Analysis because of a bug in the `unique`
generator).
Name hashing is now turned on by default, so I’m changing the value for
inc.Relations.empty, so inc.Analysis.empty functions as expected when
it’s joined with name hashing analyses.
This commit changes the default value of `IncOptions.nameHashing` to be
set to true. It means, the improved incremental compilation algorithm
known as "name hashing" will be enabled by default.
In order to disable it, users should add this to their sbt configuration:
incOptions := incOptions.value.withNameHashing(false)
Number of tests has been cleaned up as part of this change. All tests
that were marked as name hashing specific are removed. The list includes:
* constants-name-hashing
* import-class-name-hashing
* java-static-name-hashing
* macro-name-hashing
* struct-name-hashing
We'll keep just regular version of those tests. The tests will just
exercise the default algorithm: name hashing. This is the first step
towards phasing out of the old incremental compilation algorithm.
Apart from that, a few tests changed its status due to enabling name
hashing algorithm.
The `constants` test has been marked pending due to issue described in
#1543.
The `import-class` test has been marked as passing because name hashing
tracks dependencies introduced by import statements correctly, now.
The `macro` test has been marked as pending due to issue described in
#1544.
The `struct` test has been marked as pending due to issue described in
#1545.
The `java-static` has been slightly modified to exercise just static field
and not run into the same issue as with `constants` test.
There are no other known issues related to name hashing so we conclude
that name hashing is ready to be shipped to all sbt, Scala IDE and zinc
users.
Incremental.scala contained all three strategies of incremental
compilation:
* ant-style
* the default one (before name hashing)
* name hashing
Let's move all those classes into separate files. Also, move common code
into a separate file.
This commit implements an Ant-style incremental compilation mode. This mode
emulates what Ant's scalac command does. It recompiles just changed source
files and does not perform any invalidation of dependencies.
This is a very naive mode of incremental compilation that very often leads
to broken binaries.
The Ant-style mode is being introduced because Scala team needs it for
migration of Scala compiler to sbt. The name hashing algorithm doesn't
work well with Scala compiler sources due to deep inheritance chains.
There's a plan to refactor compiler's code to use more composition instead
of inheritance.
Once Scala compiler sources are refactored to work well with name hashing
algorithm, Ant-style mode will be deleted immediately.
Add an option that enables (to be implemented) Ant-style mode of
incremental compilation.
This option is unsupported and may go away at any point in the future.
NOTE: Either `antStyle` or `nameHashing` mode can be enabled. This is
being enforced with runtime assertion.
Add logging of various operations the transactional class file manager is
doing. You can pass logger to be used by the transactional class file
manager by using overloaded definition of `ClassfileManager.transactional`
method. The old overload has been deprecated.
The factory methods for class file manager in IncOptions companion object
has been deprecated in favor of using ClassfileManager companion object
directly. The code in Defaults.scala has been updated to use non-deprecated
methods. The logging is turned off by default.
The canonical way of enabling transactional class file manager in sbt
project is:
```
incOptions := incOptions.value.withNewClassfileManager(
sbt.inc.ClassfileManager.transactional(
crossTarget.value / "classes.bak",
(streams in (compile, Compile)).value.log
)
)
```
It's a bit verbose which shows that the api for this is not the best.
However, I don't expect sbt users to need this code very often.
This patch should help debug the problem described in #1184
It should have been there from the beginning because NameHashing is tied
to internals of the API subproject.
It was added to incremental subproject by mistake.
The c7f435026f introduced a new parameter
to the constructor of `CompileSetup` but it turns out that this class
is being used in zinc. Introduce an overloaded variant of that constructor
that preserves backwards compatibility.
The CompileSetup class is being used to detect changes to arguments of
incremental compiler that affect result of compilation and trigger
recompilation. Examples of such arguments include, the target (output)
directory, Scala compiler options, Scala compiler version, etc.
By adding `nameHashing` to CompileSetup we have a chance to handle change
to that flag smoothly by throwing away old Analysis object and starting
with an empty one. That's implemented in AggressiveComile by extending
the logic that was responsible for detection of changes to CompileSetup
values. Thanks to this change we fix#1081.
Analysis formats has been updated to support persisting of newly added
value in CompileSetup. We used to not store the value of `nameHashing`
flag in persisted Analysis file and infer it from contents of relations
but that leads to issue #1071 when empty relations are involved. Given
the fact that CompileSetup stores `nameHashing` value now, we can just
use it when reading relations and fix#1071. This requires reading/writing
compile setup before reading relations. I decided to make that change even
if there's a comment saying that reading/writing relations first was done
intentionally.
The ae15eccd9c accidentally removed
`Incremental.incDebugProp` which broke Scala IDE build that relies on it.
We bring back that val but at the same time we deprecate it because we
have better mechanism for configuring incremental compiler now.
I also added a little comment with the history of `incDebugProp` which
explains proper migration path.