From f3c136df62f46b140b73960c9a01dd7d778efd1d Mon Sep 17 00:00:00 2001 From: Grzegorz Kossakowski Date: Wed, 4 Dec 2013 01:34:18 +0100 Subject: [PATCH] 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 --- interface/other | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/interface/other b/interface/other index 111896f0b..68e4c3a50 100644 --- a/interface/other +++ b/interface/other @@ -3,8 +3,17 @@ Source hash: Byte* api: SourceAPI apiHash: Int + _internalOnly_nameHashes: _internalOnly_NameHashes hasMacro: Boolean +_internalOnly_NameHashes + regularMembers: _internalOnly_NameHash* + implicitMembers: _internalOnly_NameHash* + +_internalOnly_NameHash + name: String + hash: Int + SourceAPI packages : Package* definitions: Definition*