Skip to content

Commit

Permalink
Subsume extraHooks into ExternalHooks
Browse files Browse the repository at this point in the history
* add GetProvenance
* implement "quickAPI" in LookupImpl#lookupAnalyzedClass
  • Loading branch information
dwijnand committed May 26, 2020
1 parent 0160854 commit fc38079
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,25 @@

package xsbti.compile;

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

public class DefaultExternalHooks implements ExternalHooks {
private Optional<ExternalHooks.Lookup> lookup = Optional.empty();
private Optional<ClassFileManager> classFileManager = Optional.empty();
private GetProvenance getProvenance = NoProvenance.INSTANCE;

public DefaultExternalHooks(Optional<ExternalHooks.Lookup> lookup, Optional<ClassFileManager> classFileManager) {
public DefaultExternalHooks(
Optional<ExternalHooks.Lookup> lookup,
Optional<ClassFileManager> classFileManager,
GetProvenance getProvenance
) {
this.lookup = lookup;
this.classFileManager = classFileManager;
this.getProvenance = getProvenance;
}

public DefaultExternalHooks(Optional<ExternalHooks.Lookup> lookup, Optional<ClassFileManager> classFileManager) {
this(lookup, classFileManager, NoProvenance.INSTANCE);
}

@Override
Expand All @@ -35,22 +42,25 @@ public Optional<ClassFileManager> getExternalClassFileManager() {
return classFileManager;
}

@Override public GetProvenance getProvenance() { return getProvenance; }

@Override
public ExternalHooks withExternalClassFileManager(ClassFileManager externalClassFileManager) {
Optional<ClassFileManager> external = Optional.of(externalClassFileManager);
Optional<ClassFileManager> mixedManager = classFileManager.isPresent()
? Optional.of(WrappedClassFileManager.of(classFileManager.get(), external))
: external;
return new DefaultExternalHooks(lookup, mixedManager);
return new DefaultExternalHooks(lookup, mixedManager, getProvenance);
}

@Override
public ExternalHooks withExternalLookup(ExternalHooks.Lookup externalLookup) {
return new DefaultExternalHooks(Optional.of(externalLookup), classFileManager);
Optional<Lookup> externalLookup1 = Optional.of(externalLookup);
return new DefaultExternalHooks(externalLookup1, classFileManager, getProvenance);
}

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

package xsbti.compile;

import java.util.Map;
import java.nio.file.Path;
import java.util.Optional;
import java.util.Set;
import xsbti.VirtualFileRef;
Expand Down Expand Up @@ -61,6 +61,15 @@ interface Lookup {
Optional<FileHash[]> hashClasspath(VirtualFile[] classpath);
}

interface GetProvenance {
String get(Path path);
}

enum NoProvenance implements GetProvenance {
INSTANCE;
@Override public String get(Path path) { return ""; }
}

/**
* Returns the implementation of a lookup mechanism to be used instead of
* the internal lookup provided by the default implementation.
Expand All @@ -76,6 +85,8 @@ interface Lookup {
*/
Optional<ClassFileManager> getExternalClassFileManager();

default GetProvenance getProvenance() { return NoProvenance.INSTANCE; }

/**
* Returns an instance of hooks that executes the external passed class file manager.
*
Expand All @@ -95,8 +106,5 @@ interface Lookup {
*/
ExternalHooks withExternalLookup(Lookup externalLookup);

/**
* Until interface stabilizes, park experimental hooks here.
*/
Map<String, Object> extraHooks();
default ExternalHooks withGetProvenance(GetProvenance getProvenance) { return this; }
}
54 changes: 0 additions & 54 deletions internal/zinc-core/src/main/scala/sbt/internal/inc/Hooks.scala

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import xsbti.api._
import xsbti.compile.{
CompileAnalysis,
DependencyChanges,
ExternalHooks,
IncOptions,
Output,
ClassFileManager => XClassFileManager
Expand Down Expand Up @@ -81,13 +80,12 @@ 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(externalHooks, lookup)
val externalAPI = getExternalAPI(lookup)
try {
incrementalCompile(
sources,
Expand Down Expand Up @@ -167,9 +165,8 @@ 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, hooks, output)
incremental.detectInitialChanges(sources, previous, current, lookup, converter, output)
log.debug(s"> initialChanges = $initialChanges")
val binaryChanges = new DependencyChanges {
val modifiedLibraries = initialChanges.libraryDeps.toArray
Expand Down Expand Up @@ -318,9 +315,7 @@ private final class AnalysisCallback(
private[this] val compilation: Compilation = Compilation(compileStartTime, output)

private val hooks = options.externalHooks

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

override def toString =
(List("Class APIs", "Object APIs", "Library deps", "Products", "Source deps") zip
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ import xsbt.api.APIUtil
import xsbti.api.AnalyzedClass
import xsbti.compile.{
Changes,
CompileAnalysis,
DependencyChanges,
ExternalHooks,
IncOptions,
Output,
ClassFileManager => XClassFileManager
Expand Down Expand Up @@ -325,14 +323,12 @@ 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 @@ -379,12 +375,7 @@ private[inc] abstract class IncrementalCommon(
val externalApiChanges: APIChanges = {
val incrementalExternalChanges = {
val previousAPIs = previousAnalysis.apis
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)
val externalFinder = lookupAnalyzedClass(_: String).getOrElse(APIs.emptyAnalyzedClass)
detectAPIChanges(previousAPIs.allExternals, previousAPIs.externalAPI, externalFinder)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ trait Lookup extends ExternalLookup {
def lookupAnalysis(binaryClassName: String): Option[CompileAnalysis]

def lookupAnalyzedClass(binaryClassName: String): Option[AnalyzedClass] = {
// This is the default, slow, route, via Analysis; overridden in LookupImpl for the fast-track.
for {
analysis0 <- lookupAnalysis(binaryClassName)
analysis = analysis0 match { case a: Analysis => a }
Expand All @@ -71,6 +72,9 @@ trait ExternalLookup extends ExternalHooks.Lookup {
* Find the external `AnalyzedClass` (from another analysis) given a class name.
*
* @return The `AnalyzedClass` associated with the given class name, if one is found.
* Optional.empty() => Found class somewhere outside of project. No analysis possible.
* Optional.of(analyzed) if analyzed.provenance.isEmpty => Couldn't find it.
* Optional.of(analyzed) => good
*/
def lookupAnalyzedClass(binaryClassName: String): Option[AnalyzedClass]

Expand Down
9 changes: 7 additions & 2 deletions zinc/src/main/scala/sbt/internal/inc/LookupImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,13 @@ class LookupImpl(compileConfiguration: CompileConfiguration, previousSetup: Opti

override def lookupAnalyzedClass(binaryClassName: String): Option[AnalyzedClass] = {
externalLookup match { // not flatMap so that external lookup can fast-track returning None
case Some(externalLookup) => externalLookup.lookupAnalyzedClass(binaryClassName)
case _ => super.lookupAnalyzedClass(binaryClassName)
case Some(externalLookup) =>
externalLookup.lookupAnalyzedClass(binaryClassName) match {
case Some(api) if api.provenance.isEmpty => // found but w/o provenance, so go slow route
super.lookupAnalyzedClass(binaryClassName)
case x => x // fast-track success: either found w/ provenance or not found at all
}
case _ => super.lookupAnalyzedClass(binaryClassName)
}
}

Expand Down

0 comments on commit fc38079

Please sign in to comment.