Commit Graph

918 Commits

Author SHA1 Message Date
Josh Suereth 9c23aca4bd Merge pull request #1166 from retronym/ticket/1150
Fix task macro's handling of Symbol owners in <qual>.value
2014-03-09 09:48:33 -04:00
Jason Zaugg ba2d12a46d Fix task macro's handling of Symbol owners in <qual>.value
The qualifier of the `.value` call may contain `DefTree`s (e.g.
vals, defs) or `Function` trees. When we snip them out of the
tree and graft them into a new context, we must also call
`changeOwner`, so that the symbol owner structure and the tree
structure are coherent.

Failure to do so resulted in a crash in the compiler backend.

Fixes #1150
2014-03-09 12:20:24 +01:00
Josh Suereth 44c3e27eb7 Revert "Fix task macro's handling of Symbol owners in <qual>.value"
This reverts commit 3017bfcd07.

This was causing sbt to be unable to compile.  Reverting temporarily until
we have a shot at a full fix.
2014-03-07 22:25:29 -05:00
Josh Suereth 14d2bdafd8 Merge pull request #1145 from sbt/wip/issue-1136
Fix #1136 - Ivy's + dependency ranges not converted appropriately to maven.
2014-03-07 17:22:29 -05:00
Josh Suereth 494cb518cb Merge pull request #1157 from retronym/ticket/1150
Fix task macro's handling of Symbol owners in <qual>.value
2014-03-07 12:02:04 -05:00
Jason Zaugg f2d6528c5c Fix task macro's handling of Symbol owners in <qual>.value
The qualifier of the `.value` call may contain `DefTree`s (e.g.
vals, defs) or `Function` trees. When we snip them out of the
tree and graft them into a new context, we must also call
`changeOwner`, so that the symbol owner structure and the tree
structure are coherent.

Failure to do so resulted in a crash in the compiler backend.

Fixes #1150
2014-03-07 17:53:14 +01:00
Josh Suereth 39ebcb177e Merge pull request #1115 from metasim/Structure-docs
Added basic documentation for DefinableSetting, inferring behavior from implementation.
2014-03-03 14:16:21 -05:00
Josh Suereth ff2553f49f Merge pull request #1127 from retronym/topic/2.11-2.10-source-compat
using compat._ to plug source compatibility breakages
2014-02-20 16:09:48 -05:00
Josh Suereth 2835ff9784 Merge pull request #1130 from sbt/wip/auto-plugins
AUTO PLUGIN FEATURE!!!!
2014-02-20 16:08:01 -05:00
Josh Suereth 4cd573c7b3 Merge pull request #1126 from jozic/no-def-package
explicitly disapprove plugins using default package
2014-02-19 09:13:39 -05:00
Jason Zaugg 3b24308396 using compat._ to plug source compatibility breakages
This commit makes the code source compatible across Scala 2.10.3
and https://github.com/scala/scala/pull/3452, which is proposed
for inclusion in Scala 2.11.0-RC1.

We only strictly need the incremental compiler to build on Scala
2.11, as that is integrated into the IDE. But we gain valuable
insight into compiler regressions by building *all* of SBT with
2.11.

We only got there recently (the 0.13 branch of SBT now fully cross
compiles with 2.10.3 and 2.11.0-SNAPSHOT), and this aims to keep
things that way.

Once 2.10 support is dropped, SBT macros will be able to exploit
the new reflection APIs in 2.11 to avoid the need for casting
to compiler internals, which aren't governed by binary compatibility.
This has been prototyped by @xeno-by: https://github.com/sbt/sbt/pull/1121
2014-02-17 14:53:59 +01:00
Jason Zaugg 38c85dff02 Merge pull request #1114 from gkossakowski/scala-2.11.0-M8
Remove work-arounds for Scala 2.11 problematic dependencies
2014-02-12 15:27:23 +01:00
Josh Suereth 209ce64136 Merge pull request #1111 from D-Roch/patch-1
Update Community-Plugins.rst
2014-02-12 08:23:49 -05:00
Grzegorz Kossakowski b257543719 Merge pull request #1113 from retronym/ticket/si-8263
Scala 2.11 compatibility
2014-02-12 14:05:47 +01:00
Jason Zaugg 489b48f736 SI-8263 Avoid SOE in Symbol#logicallyEnclosingMember under Scala 2.11
Since the fix for SI-2066, Scala 2.11 calls logicallyEnclosingMember on the
`x` in the expansion of the task macro:

    InitializeInstance.app[[T0[x]](T0[java.io.File], T0[java.io.File]), Seq[java.io.File]]

This exposed the fact that SBT has created `T0` with `NoSymbol` as
the owner. This led to the a SOE.

I will also change the compiler to be more tolerant of this, but we
can observe good discipline in the macro and pick a sensible owner.
2014-02-12 13:30:46 +01:00
Mark Harrah 01708c572e Convert logic system test cases into unit tests.
Still TODO for auto-plugins/logic:

 * property-based tests for logic system
 * user documentation
 * (optional) 'about plugins' or similar to show more information about the auto-plugins for a project
 * (deferred) allow AutoPlugin to inject Commands directly?
 * (deferred) provide AutoPlugin functionality to arbitrary scopes instead of just at the Project level?
2014-01-24 14:37:04 -05:00
Mark Harrah 7d03a9da99 API docs, better terminology for negative cycle checking in logic system. 2014-01-24 14:36:46 -05:00
Mark Harrah 3e1142843e Translate errors from logic system to Natures system. 2014-01-24 14:36:46 -05:00
Mark Harrah 6a2e8947bb Acyclic negation checking in logic system that backs auto-plugins. 2014-01-24 14:36:36 -05:00
Mark Harrah ca3877e138 Logic system supporting auto plugins and initial outline of AutoPlugin and Natures types.
* Not integrated into project loading
 * Doesn't yet check that negation is acyclic before execution
2014-01-24 14:30:12 -05:00
Grzegorz Kossakowski 27de5da9d4 Merge pull request #1069 from benjyw/0.13-format-v4-A
Make analysis file portable.
2014-01-07 15:50:23 -08:00
Grzegorz Kossakowski e858a82152 Merge pull request #1042 from gkossakowski/name-hashing
Implement name hashing algorithm in incremental compiler
2014-01-06 15:40:18 -08:00
Mark Harrah 5dcd8bd913 TaskKey[T].previous: Option[T], which returns the value of the task the last time it executed.
This requires a Format[T] to be implicitly available at the call site and requires the task
to be referenced statically (not in a settingDyn call).  References to previous task values
in the form of a ScopedKey[Task[T]] + Format[T] are collected at setting load time in the
'references' setting.  These are used to know which tasks should be persisted (the ScopedKey)
and how to persist them (the Format).

When checking/delegating previous references, rules are slightly different.

A normal reference from a task t in scope s cannot refer to t in s unless
there is an earlier definition of t in s.  However, a previous reference
does not have this restriction.  This commit modifies validateReferenced
to allow this.

TODO: user documentation
TODO: stable selection of the Format when there are multiple .previous calls on the same task
TODO: make it usable in InputTasks, specifically Parsers
2013-12-06 20:45:01 -05:00
Mark Harrah 105127c122 Merge remote-tracking branch 'gkossakowski/compute-name-hashes' into 0.13 2013-12-05 08:53:50 -05:00
Grzegorz Kossakowski f3c136df62 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 b81fc0b256 Merge pull request #1013 from gkossakowski/used-names-extraction
Used names extraction logic
2013-12-03 03:30:21 -08:00
Grzegorz Kossakowski 06b862db5f Add support for tracking names used in Scala source files.
Tracking of used names is a component needed by the name hashing
algorithm. The extraction and storage of used names is active only when
`AnalysisCallback.nameHashing` flag is enabled and it's disabled by
default.

This change constists of two parts:

  1. Modification of Relations to include a new `names` relation
     that allows us to track used names in Scala source files
  2. Implementation of logic that extracts used names from Scala
     compilation units (that correspond to Scala source files)

The first part is straightforward: add standard set of methods in
Relations (along with their implementation) and update the logic which
serializes and deserializes Relations.

The second part is implemented as tree walk that collects all symbols
associated with trees. For each symbol we extract a simple, decoded name
and add it to a set of extracted names. Check documentation of
`ExtractUsedNames` for discussion of implementation details.

The `ExtractUsedNames` comes with unit tests grouped in
`ExtractUsedNamesSpecification`. Check that class for details.

Given the fact that we fork while running tests in `compiler-interface`
subproject and tests are ran in parallel which involves allocating
multiple Scala compiler instances we had to bump the default memory limit.

This commit contains fixes for gkossakowski/sbt#3, gkossakowski/sbt#5 and
gkossakowski/sbt#6 issues.
2013-12-03 12:27:29 +01:00
Dan Sanduleac ee8089f4a9 Removed unnecessary catch for exception 2013-11-28 11:04:46 -05:00
Dan Sanduleac 9b1727889b Added test case for derived settings 2013-11-28 11:04:46 -05:00
Dan Sanduleac d1678e7cac Fix deriveAndLocal bug 2013-11-28 11:04:46 -05:00
Mark Harrah 29db06dcfa Merge remote-tracking branch 'gk/analysis-generator-fix' into 0.13 2013-11-28 11:03:16 -05:00
Grzegorz Kossakowski 7f04c14a12 Rename Relations.{memberRefAndInheritanceDeps => nameHashing}
The previous name of the flag was rather specific: it indicated
whether the new source dependency tracking is supported by given Relations
object. However, there will be more functionality added to Relations that
is specific to name hashing algorithm. Therefore it makes sense to name
the flag as just `nameHashing`.

I decided to rename Relations implementation classes to be more
consistent with the name of the flag and with the purpose they serve.

The flag in AnalysisCallback (and classes implementing it) has been
renamed as well.
2013-11-28 13:42:39 +01:00
Grzegorz Kossakowski ede5ebcef6 Merge pull request #1002 from gkossakowski/deps-by-treewalking
Extract dependencies by tree walking
2013-11-27 06:51:05 -08:00
Grzegorz Kossakowski 4da31cd27d Extract source code dependencies by tree walking.
Previously incremental compiler was extracting source code
dependencies by inspecting `CompilationUnit.depends` set. This set is
constructed by Scala compiler and it contains all symbols that given
compilation unit refers or even saw (in case of implicit search).
There are a few problems with this approach:

  * The contract for `CompilationUnit.depend` is not clearly defined
    in Scala compiler and there are no tests around it. Read: it's
    not an official, maintained API.
  * Improvements to incremental compiler require more context
    information about given dependency. For example, we want to
    distinguish between dependency on a class when you just select
    members from it or inherit from it. The other example is that
    we might want to know dependencies of a given class instead of
    the whole compilation unit to make the invalidation logic more
    precise.

That led to the idea of pushing dependency extracting logic to
incremental compiler side so it can evolve indepedently from Scala
compiler releases and can be refined as needed. We extract
dependencies of a compilation unit by walking a type-checked tree
and gathering symbols attached to them.

Specifically, the tree walk is implemented as a separate phase that
runs after pickler and extracts symbols from following tree nodes:

  * `Import` so we can track dependencies on unused imports
  * `Select` which is used for selecting all terms
  * `Ident` used for referring to local terms, package-local terms
            and top-level packages
  * `TypeTree` which is used for referring to all types

Note that we do not extract just a single symbol assigned to `TypeTree`
node because it might represent a complex type that mentions
several symbols. We collect all those symbols by traversing the type
with CollectTypeTraverser. The implementation of the traverser is inspired
by `CollectTypeCollector` from Scala 2.10. The
`source-dependencies/typeref-only` test covers a scenario where the
dependency is introduced through a TypeRef only.
2013-11-26 18:39:23 +01:00
Mark Harrah 8857a4fb9a Add -Dsbt.cli.nodelegation option to experiment with no delegation for running/showing tasks/settings from the command line.
With this set to true, the following is no longer allowed for example:

> compile:update
2013-11-25 21:03:40 -05:00
Mark Harrah 4ec88dba43 Remove the need for resetLocalAttrs. Fixes #994, #952.
The fix was made possible by the very helpful information provided by @retronym.

This commit does two key things:
 1. changes the owner when splicing original trees into new trees
 2. ensures the synthetic trees that get spliced into original trees do not need typechecking

Given this original source (from Defaults.scala):

  ...
  lazy val sourceConfigPaths = Seq(
    ...
    unmanagedSourceDirectories := Seq(scalaSource.value, javaSource.value),
    ...
  )
  ...

After expansion of .value, this looks something like:

    unmanagedSourceDirectories := Seq(
      InputWrapper.wrapInit[File](scalaSource),
      InputWrapper.wrapInit[File](javaSource)
    )

where wrapInit is something like:

    def wrapInit[T](a: Any): T

After expansion of := we have (approximately):

    unmanagedSourceDirectories <<=
      Instance.app( (scalaSource, javaSource) ) {
        $p1: (File, File) =>
          val $q4: File = $p1._1
          val $q3: File = $p1._2
          Seq($q3, $q4)
      }

So,

 a) `scalaSource` and `javaSource` are user trees that are spliced into a tuple constructor after being temporarily held in `InputWrapper.wrapInit`
 b) the constructed tuple `(scalaSource, javaSource)` is passed as an argument to another method call (without going through a val or anything) and shouldn't need owner changing
 c) the synthetic vals $q3 and $q4 need their owner properly set to the anonymous function
 d) the references (Idents) $q3 and $q4 are spliced into the user tree `Seq(..., ...)` and their symbols need to be the Symbol for the referenced vals
 e) generally, treeCopy needs to be used when substituting Trees in order to preserve attributes, like Types and Positions

changeOwner is called on the body `Seq($q3, $q4)` with the original owner sourceConfigPaths to be changed to the new anonymous function.
In this example, no owners are actually changed, but when the body contains vals or anonymous functions, they will.

An example of the compiler crash seen when the symbol of the references is not that of the vals:

symbol value $q3 does not exist in sbt.Defaults.sourceConfigPaths$lzycompute
	at scala.reflect.internal.SymbolTable.abort(SymbolTable.scala:49)
	at scala.tools.nsc.Global.abort(Global.scala:254)
	at scala.tools.nsc.backend.icode.GenICode$ICodePhase.genLoadIdent$1(GenICode.scala:1038)
	at scala.tools.nsc.backend.icode.GenICode$ICodePhase.scala$tools$nsc$backend$icode$GenICode$ICodePhase$$genLoad(GenICode.scala:1044)
	at scala.tools.nsc.backend.icode.GenICode$ICodePhase$$anonfun$genLoadArguments$1.apply(GenICode.scala:1246)
	at scala.tools.nsc.backend.icode.GenICode$ICodePhase$$anonfun$genLoadArguments$1.apply(GenICode.scala:1244)
   ...

Other problems with the synthetic tree when it is spliced under the original tree often result in type mismatches or some other compiler error that doesn't result in a crash.

If the owner is not changed correctly on the original tree that gets spliced under a synthetic tree, one way it can crash the compiler is:

java.lang.IllegalArgumentException: Could not find proxy for val $q23: java.io.File in List(value $q23, method apply, anonymous class $anonfun$globalCore$5, value globalCore, object Defaults, package sbt, package <root>) (currentOwner= value dir )
   ...
     while compiling: /home/mark/code/sbt/main/src/main/scala/sbt/Defaults.scala
        during phase: global=lambdalift, atPhase=constructors
   ...
  last tree to typer: term $outer
              symbol: value $outer (flags: <synthetic> <paramaccessor> <triedcooking> private[this])
   symbol definition: private[this] val $outer: sbt.BuildCommon
                 tpe: <notype>
       symbol owners: value $outer -> anonymous class $anonfun$87 -> value x$298 -> method derive -> class BuildCommon$class -> package sbt
      context owners: value dir -> value globalCore -> object Defaults -> package sbt
   ...

The problem here is the difference between context owners and the proxy search chain.
2013-11-22 13:08:10 -05:00
Mark Harrah cfe5f3cebc update to ScalaCheck 1.11.0 2013-11-04 11:28:40 -05:00
Benjy 57f87fe6c1 Fix implementation of Relation.size.
Nothing was actually using it yet, fortunately.
2013-11-04 09:29:38 -05:00
Bruno Bieth 9fefc18e2d avoid deadlock in ConsoleOut.systemOutOverwrite
System.out can be reset after being captured by `val lockObject`.
Then locking `lockObject` and calling `println()` could lead to a
deadlock.
2013-11-01 13:27:23 -04:00
Grzegorz Kossakowski effb255c97 Fix unstable existential type names bug.
Fix the problem with unstable names synthesized for existential
types (declared with underscore syntax) by renaming type variables
to a scheme that is guaranteed to be stable no matter where given
the existential type appears.

The sheme we use are De Bruijn-like indices that capture both position
of type variable declarion within single existential type and nesting
level of nested existential type. This way we properly support nested
existential types by avoiding name clashes.

In general, we can perform renamings like that because type variables
declared in existential types are scoped to those types so the renaming
operation is local.

There's a specs2 unit test covering instability of existential types.
The test is included in compiler-interface project and the build
definition has been modified to enable building and executing tests
in compiler-interface project. Some dependencies has been modified:

  * compiler-interface project depends on api project for testing
    (test makes us of SameAPI)
  * dependency on junit has been introduced because it's needed
    for `@RunWith` annotation which declares that specs2 unit
    test should be ran with JUnitRunner

SameAPI has been modified to expose a method that allows us to
compare two definitions.

This commit also adds `ScalaCompilerForUnitTesting` class that allows
to compile a piece of Scala code and inspect information recorded
callbacks defined in  `AnalysisCallback` interface. That class uses
existing ConsoleLogger for logging. I considered doing the same for
ConsoleReporter. There's LoggingReporter defined which would fit our
usecase but it's defined in compile subproject that compiler-interface
doesn't depend on so we roll our own.

ScalaCompilerForUnit testing uses TestCallback from compiler-interface
subproject for recording information passed to callbacks. In order
to be able to access TestCallback from compiler-interface
subproject I had to tweak dependencies between interface and
compiler-interface so test classes from the former are visible in the
latter. I also modified the TestCallback itself to accumulate apis in
a HashMap instead of a buffer of tuples for easier lookup.

An integration test has been added which tests scenario
mentioned in #823.

This commit fixes #823.
2013-10-29 16:39:50 +01:00
Grzegorz Kossakowski 18128d6146 Move TestCallback.scala to a directory matching its package name. 2013-10-29 16:39:50 +01:00
Grzegorz Kossakowski 785b750e47 Remove dead source file `F0.scala` from interface subproject.
It doesn't seem to be used anywhere.
2013-10-29 16:39:50 +01:00
Mark Harrah 59905741e1 Merge remote-tracking branch 'gkossakowski/separate-dependency-phase' into 0.13 2013-10-24 16:57:32 -04:00
Mark Harrah 10b5361e83 Merge remote-tracking branch 'benjy/interned_files' into 0.13 2013-10-24 16:55:16 -04:00
Mark Harrah cb7c12a4ad Transfer logging,trace levels from old to new global loggers. 2013-10-24 16:34:16 -04:00
Grzegorz Kossakowski 9c75143382 Remove AnalysisCallback.{beginSource, endSource} methods.
As pointed out by @harrah in #705, both beginSource and endSource are
not used in sbt internally for anything meaningful.

We've discussed an option of deprecating those methods but since they
are not doing anything meaningful Mark prefers to have compile-time
error in case somebody implements or calls those methods. I agree with
that hence removal.
2013-10-24 16:44:45 +02:00
Mark Harrah 8dc24826d3 shortcut heterogeneous AList to KList.toList 2013-10-23 09:46:43 -04:00
Mark Harrah a0540f5ce9 cleanups in Settings 2013-10-23 09:46:43 -04:00
Mark Harrah d30a3f3bfd drop view for iterator in IMap 2013-10-23 09:46:43 -04:00
Mark Harrah 4f422ccac7 Merge remote-tracking branch 'benjy/analysis_test' into 0.13 2013-10-17 15:17:57 -04:00