Skip to content

Commit

Permalink
Wire provenance to a new "quickAPI"
Browse files Browse the repository at this point in the history
  • Loading branch information
dwijnand committed May 26, 2020
1 parent df017bf commit 0160854
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@

package xsbti.compile;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

public class DefaultExternalHooks implements ExternalHooks {
Expand Down Expand Up @@ -45,4 +48,9 @@ public ExternalHooks withExternalClassFileManager(ClassFileManager externalClass
public ExternalHooks withExternalLookup(ExternalHooks.Lookup externalLookup) {
return new DefaultExternalHooks(Optional.of(externalLookup), classFileManager);
}

@Override
public Map<String, Object> extraHooks() {
return Collections.unmodifiableMap(new HashMap<>());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

package xsbti.compile;

import java.util.Map;
import java.util.Optional;
import java.util.Set;
import xsbti.VirtualFileRef;
Expand Down Expand Up @@ -93,4 +94,9 @@ interface Lookup {
* @return An instance of {@link ExternalHooks} with the specified lookup.
*/
ExternalHooks withExternalLookup(Lookup externalLookup);

/**
* Until interface stabilizes, park experimental hooks here.
*/
Map<String, Object> extraHooks();
}
54 changes: 54 additions & 0 deletions internal/zinc-core/src/main/scala/sbt/internal/inc/Hooks.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Zinc - The incremental compiler for Scala.
* Copyright Lightbend, Inc. and Mark Harrah
*
* Licensed under Apache License 2.0
* (http://www.apache.org/licenses/LICENSE-2.0).
*
* See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*/

package sbt
package internal
package inc

import java.nio.file.Path
import java.util.{ Map => jMap }
import java.util.Optional

import sbt.util.InterfaceUtil
import xsbti.api.AnalyzedClass
import xsbti.compile.ExternalHooks

object Hooks {
private val QUICK_API = "QUICKAPI"
private val GET_PROVENANCE = "GETPROVENANCE"

/**
* None => Found class somewhere outside of project. No analysis possible.
* Some(analyzed) if analyzed.provenance.isEmpty => Couldn't find it.
* Some(analyzed) => good
*/
private[sbt] def quickAPI(hooks: ExternalHooks): String => Option[AnalyzedClass] = {
val f = getOrElse(hooks, QUICK_API, (_: String) => Optional.empty[AnalyzedClass])
c => InterfaceUtil.toOption(f(c))
}

def addQuickAPI(m: jMap[String, Object], f: String => Optional[AnalyzedClass]): Unit = {
m.put(QUICK_API, f)
()
}

private[sbt] def getProvenance(hooks: ExternalHooks): Path => String = {
getOrElse(hooks, GET_PROVENANCE, (_: Path) => "")
}

def addGetProvenance(m: jMap[String, Object], f: Path => String): Unit = {
m.put(GET_PROVENANCE, f)
()
}

private def getOrElse[A <: AnyRef](hooks: ExternalHooks, key: String, alt: A): A =
hooks.extraHooks().getOrDefault(key, alt).asInstanceOf[A]
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import xsbti.api._
import xsbti.compile.{
CompileAnalysis,
DependencyChanges,
ExternalHooks,
IncOptions,
Output,
ClassFileManager => XClassFileManager
Expand Down Expand Up @@ -80,12 +81,13 @@ object Incremental {
): (Boolean, Analysis) = {
log.debug(s"[zinc] IncrementalCompile -----------")
val previous = previous0 match { case a: Analysis => a }
val externalHooks = options.externalHooks()
val currentStamper = Stamps.initial(stamper)
val internalBinaryToSourceClassName = (binaryClassName: String) =>
previous.relations.productClassName.reverse(binaryClassName).headOption
val internalSourceToClassNamesMap: VirtualFile => Set[String] = (f: VirtualFile) =>
previous.relations.classNames(f)
val externalAPI = getExternalAPI(lookup)
val externalAPI = getExternalAPI(externalHooks, lookup)
try {
incrementalCompile(
sources,
Expand Down Expand Up @@ -165,8 +167,9 @@ object Incremental {
val previous = previous0 match { case a: Analysis => a }
val runProfiler = profiler.profileRun
val incremental: IncrementalCommon = new IncrementalNameHashing(log, options, runProfiler)
val hooks = options.externalHooks
val initialChanges =
incremental.detectInitialChanges(sources, previous, current, lookup, converter, output)
incremental.detectInitialChanges(sources, previous, current, lookup, converter, hooks, output)
log.debug(s"> initialChanges = $initialChanges")
val binaryChanges = new DependencyChanges {
val modifiedLibraries = initialChanges.libraryDeps.toArray
Expand Down Expand Up @@ -314,6 +317,11 @@ private final class AnalysisCallback(
private[this] val compileStartTime: Long = System.currentTimeMillis()
private[this] val compilation: Compilation = Compilation(compileStartTime, output)

private val hooks = options.externalHooks

private val provenance =
jo2o(output.getSingleOutput).fold("")(Hooks.getProvenance(hooks)(_)).intern

override def toString =
(List("Class APIs", "Object APIs", "Library deps", "Products", "Source deps") zip
List(classApis, objectApis, libraryDeps, nonLocalClasses, intSrcDeps))
Expand Down Expand Up @@ -581,7 +589,8 @@ private final class AnalysisCallback(
apiHash,
nameHashes,
hasMacro,
extraHash
extraHash,
provenance
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ import xsbt.api.APIUtil
import xsbti.api.AnalyzedClass
import xsbti.compile.{
Changes,
CompileAnalysis,
DependencyChanges,
ExternalHooks,
IncOptions,
Output,
ClassFileManager => XClassFileManager
Expand Down Expand Up @@ -323,12 +325,14 @@ private[inc] abstract class IncrementalCommon(
stamps: ReadStamps,
lookup: Lookup,
converter: FileConverter,
hooks: ExternalHooks,
output: Output
)(implicit equivS: Equiv[XStamp]): InitialChanges = {
import IncrementalCommon.isLibraryModified
import lookup.lookupAnalyzedClass
val previous = previousAnalysis.stamps
val previousRelations = previousAnalysis.relations
val quickAPI: String => Option[AnalyzedClass] = Hooks.quickAPI(hooks)

val sourceChanges: Changes[VirtualFileRef] = lookup.changedSources(previousAnalysis).getOrElse {
val previousSources: Set[VirtualFileRef] = previous.allSources.toSet
Expand Down Expand Up @@ -375,7 +379,12 @@ private[inc] abstract class IncrementalCommon(
val externalApiChanges: APIChanges = {
val incrementalExternalChanges = {
val previousAPIs = previousAnalysis.apis
val externalFinder = lookupAnalyzedClass(_: String).getOrElse(APIs.emptyAnalyzedClass)
val externalFinder = (binaryClassName: String) =>
(quickAPI(binaryClassName) match {
case Some(api) if api.provenance.isEmpty =>
lookupAnalyzedClass(binaryClassName) // found without a provenance, so looking it up
case x => x // fast-track success: either found w/ provenance or not found at all
}).getOrElse(APIs.emptyAnalyzedClass)
detectAPIChanges(previousAPIs.allExternals, previousAPIs.externalAPI, externalFinder)
}

Expand Down

0 comments on commit 0160854

Please sign in to comment.