**Problem**
When a val definition in build.sbt changes and the user runs `reload`, sbt crashes with `NoClassDefFoundError: $Wrap<hash>$`.
```
java.lang.NoClassDefFoundError: $Wrape8743d4f36$
at $Wrap0b8ea34d40$.$anonfun$1(build.sbt:1)
```
The workaround was to delete `project/target` directory.
**Solution**
The root cause was that imports were not included in the hash calculation when evaluating build.sbt expressions. When a val definition changes:
1. Its `$Wrap` module gets a new hash
2. Settings that reference the val get new imports pointing to the new module
3. But if the setting expression didn't change, its hash was the same
4. The old cached class was loaded with bytecode referencing the old module
Fix: Include imports in the hash calculation in `Eval.evalCommon`. Also re-enable `cleanEvalClasses` in `Load.scala` which was disabled pending this fix.
Fixes#8511
When loading a cached build definition, the code checked if the .class
file exists but not the .cache file. If the .cache file was missing
(deleted, corrupted, or from a partial compilation), it threw
NoSuchFileException.
Now both files are checked before using the cache. If either is missing,
the build definition is recompiled.
When using a SNAPSHOT version of sbt, if the sbt jars are republished
with breaking binary changes, the build definition should be recompiled.
Previously, the cache key only considered the source content, not the
classpath, causing NoSuchMethodError when cached classes referenced
methods that no longer exist.
This fix includes a hash of SNAPSHOT and -bin- jars (including their
modification times) in the cache key. When these jars change, the build
definition is recompiled.
Fixes#7713
Previously, sbt would fail to load build.sbt files when they included
annotated definitions because the parser would not correctly recognize
those definitions as such. In sbt 1.x, this used to be fine, because
there was little use for annotations in build.sbt.
Starting with sbt 2, whether caching should be enabled for a task key
can be controlled via annotations on the task key definition. Because
these can appear in build.sbt, support for annotations in build.sbt
becomes more important.
This patch enhances parsing of build.sbt by keeping the parsed trees
around so that the AST can be used to determine whether a given line
represents a setting or a definition, rather than relying on string
matching.
Previously, sbt would crash when attempting to load a build where
projects had minus signs (`-`) in their name.
For instance, when trying to load a project defined like this:
lazy val `my-project` = project
After compilation, this definition looks somewhat like this
val my$minusproject$lzy1 = ...
sbt was attempting to retrieve the original definition (without the $lzy
suffix) by taking the mangled name up to the first `$`. Unfortunately,
this approach does not work when the name includes special characters
like a minus sign, because these will be prefixed with `$` as well. In
the current example, sbt would then try to find the member named `my`,
fail, and crash.
This patch fixes the issue by using the "underlying" name, which is the
name without the additional information.
**Problem**
Compiler warnings and errors is not correct for build.sbt.
**Solution**
This adds line offset to the synthetic Scala file
so the original line position is displayed in the errors.
**Problem**
Slash syntax is currently implemented via a series of implicit
converters (Conversion), which is not nice, partly because
the behavior is difficult to follow.
**Solution**
This removes all the implicit converters and moves the slashes
into:
1. / methods under Reference for subproject scoping.
2. / methods under ScopeAxis with Reference type constraint
for the initial Zero scoping.
3. Return RefThenConfig structure for intermediate config scoping.
4. / method under `Scoped`, which is base trait for the keys
to implement task scoping e.g. `compile / scalacOptions`.
5. Extension methods for ConfigKey.
6. Extension methods for AttributeKey.
Settings0 used to be a Map[Scope, AttributeMap], and is now a
Map[ScopedKey[x], x].
This is better because we don't need to decompose all ScopedKey[x]
into a Scope and an AttributeKey[x], for recomposing it back later,
which duplicates all ScopedKey[x]. It reduces the number of long-living
ScopedKey[x] by 8%, and the total number of instances by 1.4%.
Also it improves the performance of Settings0, which was responsible of
2.95% of the total CPU time, and is now responsible of 0.41%.
Problem
-------
By Typer phase it seems like lazy val is expanded out to
`def x(): Int` and synthetic `val x$lzy1`,
which results in NoSuchMethod `x$lzy1`.
Solution
--------
Assume the naming convention and grab the part before `$`.