Commit Graph

150 Commits

Author SHA1 Message Date
James Roper 18fb684143 Update incremental compile debug message
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.
2015-04-15 14:29:10 +10:00
eugene yokota be78b7fc4c Merge pull request #1759 from jedesah/topic/minor_cleanup
Minor code cleanup
2015-01-14 16:13:06 -05:00
Jean-Rémi Desjardins ca736e55d3 Minor code cleanup 2014-12-03 09:56:34 -08:00
eugene yokota 7df9802f0c Merge pull request #1714 from sbt/wip/bytecode-enhancement
Expose mechanism whereby bytecode enhancement can be run *before* saving incremental compiler hashes.
2014-12-03 08:46:52 -05:00
Josh Suereth 3c4bc23cdb First set of refactorings from review.
* 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.
2014-12-01 13:35:51 -05:00
Josh Suereth ae4721aba0 Adding more scaladoc to incremental compiler library. 2014-12-01 13:35:51 -05:00
Josh Suereth 067479f59e Debug issues with implicit usage for CompileSetup.
* 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.
2014-12-01 13:35:51 -05:00
Martin Duhem 98c789b826 Abstract over dependency context in Compile
This commit completes the abstraction over dependency kinds in the
incremental compiler, started with #1340.
2014-11-19 10:35:07 +01:00
Martin Duhem deda8eee70 Remove trait `DependencyContext` in favor of enum
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.
2014-11-19 10:35:07 +01:00
Martin Duhem 191c3ed675 Use new infrastructure in `AnalysisTest`
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.
2014-11-18 13:09:07 +01:00
Martin Duhem b1a608cf1d Use new infrastructure in `AnalysisCallback`
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.
2014-11-18 13:08:51 +01:00
Martin Duhem c09a3912d1 Implement abstraction over dependency kinds
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.
2014-11-18 13:07:58 +01:00
Grzegorz Kossakowski f7c00ab581 Sketch of abstracting over dependency details in incremental compiler
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)
2014-09-12 08:52:06 +02:00
Martin Duhem 82152b8905 Don't hardcode existing relations in TextAnalysisFormat
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.
2014-09-11 14:45:47 +02:00
Martin Duhem c55ae4fd18 Fix random Analysis generator for ScalaCheck
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).
2014-09-03 23:10:22 +02:00
Eugene Yokota bb20310922 Run AnalysisTest without name hashing 2014-08-23 02:58:44 -04:00
Eugene Yokota 112052241c #1550. Fixes scripted/join that broke with #1546
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.
2014-08-22 19:12:27 -04:00
Grzegorz Kossakowski c440c578fc Enable name hashing incremental compilation by default.
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.
2014-08-22 02:08:07 +02:00
Grzegorz Kossakowski 129c870a1d Break Incremental.scala into smaller files.
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.
2014-05-21 16:23:55 +02:00
Grzegorz Kossakowski 7849361c82 Remove stale, commented out code from Incremental.scala
The commented out code was sitting here since 2010. It bit-rotted to the
point of not being useful anymore. Let's remove it.
2014-05-20 19:51:28 +02:00
Grzegorz Kossakowski 680713f666 Add Ant-style incremental compilation mode.
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.
2014-05-08 20:29:02 +02:00
Grzegorz Kossakowski ba88236b31 Add `antStyle` to IncOptions.
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.
2014-05-08 20:28:16 +02:00
Josh Suereth 244abd3b6f Scalariforming test code 2014-05-07 11:52:23 -04:00
Eugene Yokota adb41611cf added scalariform 2014-05-01 12:50:07 -04:00
Grzegorz Kossakowski d27a699715 Merge pull request #1250 from gkossakowski/namehashing-cleanup
Move NameHashing from incremental to api subproject.
2014-04-16 00:18:27 +02:00
Grzegorz Kossakowski a7fb54e4df Add debug logging in ClassfileManager
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
2014-04-11 13:42:21 +02:00
Grzegorz Kossakowski 36db1207cf Move NameHashing from incremental to api subproject.
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.
2014-04-10 20:21:42 +02:00
Grzegorz Kossakowski 3673f53119 Clarify the role and uses cases of Analysis.compilations.
It's mainly debugging tool. I added documentation describing the intent
of Analysis.compilations field.
2014-04-08 23:26:39 +02:00
Grzegorz Kossakowski 19ca7a1edc Make change to CompileSetup backwards compatible.
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.
2014-02-18 12:18:07 +01:00
Grzegorz Kossakowski c7f435026f Include value of `nameHashing` flag in `CompileSetup`.
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.
2014-02-17 17:00:19 +01:00
Grzegorz Kossakowski 9e7e93c632 Bring back and deprecate `Incremental.incDebugProp`.
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.
2014-01-13 16:29:16 +01:00
Grzegorz Kossakowski dcb327e6f4 Do not compute name hashes when name hashing is disabled
We should compute name hashes only when name hashing is enabled.
Otherwise, we just store an empty value for name hashes.
2014-01-08 17:37:43 -05:00
Grzegorz Kossakowski b581b60aa4 Merge pull request #1069 from benjyw/0.13-format-v4-A
Make analysis file portable.
2014-01-07 15:50:23 -08:00
Benjy 2e1809e17e Make analysis file portable.
Serializes CompileSetup as text instead of base64-encoded
binary-serialized object.

This is necessary so that file paths in the CompileSetup can be
rebased when porting analysis files between systems.
2014-01-07 22:39:47 +00:00
Grzegorz Kossakowski f4940df48d Make all APIChange subclasses final.
They should have been final from the beginning. We are fixing that
omission now.
2014-01-07 00:20:17 +01:00
Grzegorz Kossakowski a48ab0d38b Implement name hashing algorithm in incremental compiler.
Provide implementation of invalidation logic that takes computed
name hashes into account. The implementation is spread amongst two
classes:

  1. `IncrementalNameHashing` which implements a variant of
     incremental compilation algorithm that computes modified
     names and delegates to `MemberReferenceInvalidationStrategy`
     when invalidating member reference dependencies
  2. `MemberReferenceInvalidationStrategy` which implements the
     core logic of dealing with dependencies introduced by member
     reference. See documentation of that class for details.

The name hashing optimization is applied when invalidating source files
having both internal and external dependencies (in initial iteration),
check `invalidateByExternal` and `invalidateSource` methods for details.

As seen in implementation of `MemberReferenceInvalidationStrategy`
the name hashing optimization is not applied when implicit members
change.

NOTE: All functionality introduced in this commit is enabled only
when `IncOptions.nameHashing` flag is set to true.

The `source-dependencies/transitive-memberRef` test has been changed
to test name hashing variant of incremental compilation. The change
to invalidated files reflects the difference between the old and the
new algorithm.

Also, there a few new tests added that cover issues previously found
while testing name hashing algorithm and are fixed in this commit.
Each paragraph describes a single test.

Add a test case which shows that detect properly changes to type aliases
in the name hashing algorithm. See gkossakowski/sbt#6 for details.

Add test covering bug with use of symbolic names (issue
gkossakowski/sbt#5).

Add a test which covers the case where we refer to a name that is
declared in the same file. See issue gkossakowski/sbt#3 for details.
2014-01-07 00:20:17 +01:00
Grzegorz Kossakowski d70bc51b6d Use `nameHashing` option throughout incremental compiler
There are two categories of places in the code that need to refer to
`nameHashing` option:

  * places where Analysis object is created so it gets proper
    implementation of underlying Relations object
  * places with logic that is specifically designed to be enabled by
    that option

This commit covers both cases.
2013-12-15 18:40:46 +01:00
Grzegorz Kossakowski cacb17fb2e Add `nameHashing` option to IncOptions
This option is not used anywhere yet. This commit just contains all
the boilerplate needed in order to introduce a new field to IncOptions
class.
2013-12-15 18:40:46 +01:00
Grzegorz Kossakowski 88528a43cb Fix a few mistakes related to IncOptions.recompileOnMacroDef
The 39036e7c20 introduced
`recompileOnMacroDef` option to IncOptions. However, not all necessary
logic has been changed. This commit fixes that:

  * `copy` method does not forget the value of the `recompileOnMacroDef`
    flag
  * `productArity` has been increased to match the arity of the class
  * `productElement` returns the value of `recompileOnMacroDef` flag
  * `hashCode` and `equals` methods take into account value of
    `recompileOnMacroDef` flag
  * fix the name of the key for `recompileOnMacroDef` flag
2013-12-15 18:40:46 +01:00
Grzegorz Kossakowski 4ebbf3fb8b Refactor code in IncrementalCommon and IncrementalDefaultImpl
Move implementation of the following methods from IncrementalCommon
to IncrementalDefaultImpl:

  * invalidatedPackageObjects
  * sameAPI
  * invalidateByExternal
  * allDeps
  * invalidateSource

These are the methods that are expected to have different implementation
in the name hashing algorithm. Hence, we make them abstract in
IncrementalCommon so they can be implemented differently in subclasses.
2013-12-15 18:40:46 +01:00
Grzegorz Kossakowski fdc72f3744 The invalidateByExternal takes single external api change.
Refactor the `invalidateByExternal` method to take single, external
api change. Introduce `invalidateByAllExternal` that takes all APIChanges
object.

This way `invalidateByExternal` will have an access to APIChange object
that represents changed name hashes once name hashing is merged.
2013-12-15 18:40:46 +01:00
Grzegorz Kossakowski 3643419e7c Make `invalidateSource` to take Relations.
This way we'll be able to have a polymorphic implementation of this
method in the future. One implementation will use the old dependency
tracking mechanism and the other will use the new one (implemented
for name hashing).
2013-12-15 18:40:46 +01:00
Grzegorz Kossakowski 83a131e4f5 Introduce `IncrementalCommon.invalidateSource` method.
In addition to `invalidateSources` we introduce `invalidateSource`
that invalidates dependencies of a single source. This is needed
for the name hashing algorithm because its invalidation logic
depends on information about API changes of each source file
individually.

The refactoring is done in `IncrementalCommon` class so it affects
the default implementation as well. However, this refactoring does
not affect the result of invalidation in the default implementation.
2013-12-15 18:32:49 +01:00
Grzegorz Kossakowski 946fd53a73 Introduce abstract `IncrementalCommon` class.
Introduce an abstract `IncrementalCommon class that holds the
implementation of incremental compiler that was previously done in
`Incremental` class. Also, introduce `IncrementalDefaultImpl` that
inherits from IncrementalCommon.

This is the first step to introduce a design where most of incremental
compiler's logic lives in IncrementalCommon and we have two subclasses:

  1. Default, which holds implementation specific to the old algorithm
     known from sbt 0.13.0
  2. NameHashing, which holds implementation specific to the name
     hashing algorithm

This commit is purely a refactoring and does not change any behavior.
2013-12-15 18:32:09 +01:00
Grzegorz Kossakowski 1de2900a67 Add Logger and IncOptions as Incremental class constructor args
Both Logger and IncOptions instances were passed around Incremental class
implementation unmodified. Given the fact that entire implementation of
the class uses exactly the same values for those types it makes sense
to extract them as constructor arguments so they are accessible everywhere.

This helps reducing signatures of other methods to more essential
parameters that are more specific to given method.
2013-12-15 18:32:09 +01:00
Grzegorz Kossakowski ae15eccd9c Introduce a companion `Incremental` class.
Move most of the functionality from `Incremental` object to its
companion class.

This commit is a preparation for making it possible to have
two different implementation of logic in `Incremental` object.
2013-12-15 18:30:59 +01:00
Mark Harrah d8c15bb80e Merge remote-tracking branch 'gkossakowski/compute-name-hashes' into 0.13 2013-12-05 08:53:50 -05:00
Grzegorz Kossakowski 50528e6000 Push down `toString` implementation in Relations hierarchy.
Each of Relations implementation should have specific `toString`
implementation. For example, only `MRelationsNameHashing` implementation
should be printing used names in toString representation.
2013-12-05 08:00:13 +01:00
Grzegorz Kossakowski a9a709ccc0 Add hashing of public names defined in a source file.
A hash for given name in a source file is computed by combining
hashes of all definitions with given name. When hashing a single
definition we take into account all information about it except nested
definitions. For example, if we have following definition

class Foo[T] {
  def bar(x: Int): Int = ???
}

hash sum for `Foo` will include the fact that we have a class with
a single type parameter but it won't include hash sum of `bar` method.

Computed hash sums are location-sensitive. Each definition is hashed along
with its location so we properly detect cases when definition's signature
stays the same but it's moved around in the same compilation unit.

The location is defined as sequence of selections. Each selection consists
of a name and name type. The name type is either term name or type name.
Scala specification (9.2) guarantees that each publicly visible definition
is uniquely identified by a sequence of such selectors.

For example, if we have:

object Foo {
  class Bar { def abc: Int }
}

then location of `abc` is Seq((TermName, Foo), (TypeName, Bar))

It's worth mentioning that we track name-hash pairs separately for
regular (non implicit) and implicit members. That's required for name
hashing algorithm because it does not apply its heuristic when implicit
members are being modified.

Another important characteristic is that we include all inherited members
when computing name hashes.

Here comes the detailed list of changes made in this commit:

  * HashAPI has new parameter `includeDefinitions` that allows
    shallow hashing of Structures (where we do not compute hashes
    recursively)
  * HashAPI exposes `finalizeHash` method that allow one to capture
    current hash at any time. This is useful if you want to hash a list of
    definitions and not just whole `SourceAPI`.
  * NameHashing implements actual extraction of public definitions,
    grouping them by simple name and computing hash sums for each group
    using HashAPI
  * `Source` class (defined in interface/other file) has been extended to
    include `_internalOnly_nameHashes` field. This field stores
    NameHashes data structure for given source file. The NameHashes
    stores two separate collections of name-hash pairs for regular and
    implicit members.
    The prefix `_internalOnly_` is used to indicate that this is not an
    official incremental compiler's or sbt's API and it's for use by
    incremental compiler internals only. We had to use such a prefix
    because the `datatype` code generator doesn't support emitting access
    modifiers
  * `AnalysisCallback` implementation has been modified to gather all
    name hashes and store them in the Source object
  * TestCaseGenerators has been modified to implement generation of
    NameHashes
  * The NameHashingSpecification contains a few unit tests that make sure
    that the basic functionality works properly
2013-12-04 01:34:18 +01:00
Grzegorz Kossakowski ec40eab92d Merge pull request #1013 from gkossakowski/used-names-extraction
Used names extraction logic
2013-12-03 03:30:21 -08:00