Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the first iteration of the Zinc API 1.0 #304

Merged
merged 51 commits into from
May 26, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
8a86b55
Remove deprecated compatibility stubs
jvican May 15, 2017
e39dd51
Make Zinc `Global` implementations independent
jvican May 15, 2017
2609a34
Hide `compilation` from `AnalysisCallback`
jvican May 15, 2017
e519c08
Port `CompileAnalysis` from contraband to Java
jvican May 16, 2017
ae6381c
Change `Stamps` interface and functionality
jvican May 16, 2017
8834f0b
Remove unused stamp `Exists`
jvican May 16, 2017
ad5e59a
Turn `CompileAnalysis` to an interface
jvican May 16, 2017
529c709
Add `ReadStamps` to `CompileAnalysis`
jvican May 16, 2017
8cde423
Create a `SourceInfo` API to be consumed from Java
jvican May 16, 2017
1d5da03
Create `ReadSourceInfos` & add to `CompileAnalysis`
jvican May 17, 2017
df4d222
Clarify `Stamp` documentation for empty value
jvican May 17, 2017
1f2d12c
Replace `OutputSetting` by `OutputGroup`
jvican May 17, 2017
761ea0e
Fix `Output` and `Compilation` API
jvican May 17, 2017
73ff81a
Remove `apiNote` since Javadoc doesn't accept it
jvican May 17, 2017
df6f5a4
Make the Output API more Java friendly
jvican May 17, 2017
4850acf
Add `ReadCompilations` to `CompileAnalysis`
jvican May 17, 2017
9eea8bd
Add `CompilerBridgeProvider` interface and misc.
jvican May 18, 2017
8381e29
Move `constant` to static in `CompilerBridgeProvider`
jvican May 18, 2017
d061e9e
Add headers to files that don't have them
jvican May 18, 2017
4b475b1
Rename `getCompilerSources` to `getCompiledBridge`
jvican May 18, 2017
b48a783
Fix oversight in InvalidComponent message
jvican May 18, 2017
f1fc0d5
Add `getScalaInstance` to `CompilerBridgeProvider`
jvican May 19, 2017
ae88038
Remove custom `getScalaInstance` and use default
jvican May 19, 2017
7903c60
Test `getScalaInstance` & `getCompiledBridge`
jvican May 19, 2017
3bac784
Compile bridge for 2.12.x and other Scala versions
jvican May 19, 2017
182aec7
Fix error when showing unresolved warning lines
jvican May 19, 2017
55583d7
Add Java API for Zinc Ivy integration
jvican May 19, 2017
b1eac04
Add public method to get a local ivy resolver
jvican May 19, 2017
0bf12de
Add public method to get no-op global lock
jvican May 19, 2017
af702ae
Remove verbose Java global lock implementation
jvican May 20, 2017
6391ae7
Add public method to get default component provider
jvican May 20, 2017
436a985
Remove the use of `BaseIvySpecification`
jvican May 20, 2017
4452126
Move IncOptionsUtil to zincCore project
jvican May 20, 2017
14d37d8
Format `IncOptionsUtil`
jvican May 20, 2017
5590cc5
Fix `fromStringMap` for classfile manager key
jvican May 21, 2017
9c53bf0
Add docs to `IncToolOptionsUtil`
jvican May 21, 2017
686b6bb
Fix #302: Migrate from Maybe to Optional
jvican May 21, 2017
d13928f
Make the equiv for stamp public
jvican May 22, 2017
f984ed9
Add interface for external Lookup
jvican May 22, 2017
bd23a51
Replace null by Optional in ExternalHooks
jvican May 22, 2017
e6eb0b0
Fix #125: Get default classfile manager for inc
jvican May 22, 2017
f49e945
Remove deprecated `transactional`
jvican May 22, 2017
7ee4c9d
Remove `allInternalSrcDeps` from Relations
jvican May 22, 2017
d1a4627
Add `ZincCompilerUtil` to get the Scalac compiler
jvican May 22, 2017
f98c221
Hide Zinc Compilation implementation
jvican May 22, 2017
d00234d
Move formats away from public API
jvican May 22, 2017
df5915f
Move ZincBridgeProvider to `xsbti.compile`
jvican May 22, 2017
3c846ad
Move `ClasspathOptionsUtil` to the Java public API
jvican May 22, 2017
a4f877e
Add headers to files missing it
jvican May 22, 2017
293c400
Make `CompilerCache` public
jvican May 22, 2017
e6cbee2
Rename `getXXX` by `fetchXXX`
jvican May 26, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,8 @@ lazy val zincCore = (project in internalPath / "zinc-core")
// needed because we fork tests and tests are ran in parallel so we have multiple Scala
// compiler instances that are memory hungry
javaOptions in Test += "-Xmx1G",
name := "zinc Core"
name := "zinc Core",
compileOrder := sbt.CompileOrder.Mixed
)
.configure(addSbtIO, addSbtUtilLogging, addSbtUtilRelation)

Expand All @@ -243,7 +244,8 @@ lazy val zincIvyIntegration = (project in internalPath / "zinc-ivy-integration")
.dependsOn(zincCompileCore, zincTesting % Test)
.settings(
baseSettings,
name := "zinc Ivy Integration"
name := "zinc Ivy Integration",
compileOrder := sbt.CompileOrder.ScalaThenJava
)
.configure(addSbtLm)

Expand Down
170 changes: 170 additions & 0 deletions internal/compiler-bridge/src/main/scala/xsbt/CallbackGlobal.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
/*
* Zinc - The incremental compiler for Scala.
* Copyright 2011 - 2017, Lightbend, Inc.
* Copyright 2008 - 2010, Mark Harrah
* This software is released under the terms written in LICENSE.
*/

package xsbt

import xsbti.{ AnalysisCallback, Severity }
import xsbti.compile._

import scala.tools.nsc._
import io.AbstractFile
import java.io.File

/** Defines the interface of the incremental compiler hiding implementation details. */
sealed abstract class CallbackGlobal(settings: Settings,
reporter: reporters.Reporter,
output: Output)
extends Global(settings, reporter) {

def callback: AnalysisCallback
def findClass(name: String): Option[(AbstractFile, Boolean)]

lazy val outputDirs: Iterable[File] = {
output match {
case single: SingleOutput => List(single.getOutputDirectory)
// Use Stream instead of List because Analyzer maps intensively over the directories
case multi: MultipleOutput => multi.getOutputGroups.toStream map (_.getOutputDirectory)
}
}

/**
* Defines the sbt phase in which the dependency analysis is performed.
* The reason why this is exposed in the callback global is because it's used
* in [[xsbt.LocalToNonLocalClass]] to make sure the we don't resolve local
* classes before we reach this phase.
*/
private[xsbt] val sbtDependency: SubComponent

/**
* A map from local classes to non-local class that contains it.
*
* This map is used by both Dependency and Analyzer phase so it has to be
* exposed here. The Analyzer phase uses the cached lookups performed by
* the Dependency phase. By the time Analyzer phase is run (close to backend
* phases), original owner chains are lost so Analyzer phase relies on
* information saved before.
*
* The LocalToNonLocalClass duplicates the tracking that Scala compiler does
* internally for backed purposes (generation of EnclosingClass attributes) but
* that internal mapping doesn't have a stable interface we could rely on.
*/
private[xsbt] val localToNonLocalClass = new LocalToNonLocalClass[this.type](this)
}

/** Defines the implementation of Zinc with all its corresponding phases. */
sealed class ZincCompiler(settings: Settings, dreporter: DelegatingReporter, output: Output)
extends CallbackGlobal(settings, dreporter, output)
with ZincGlobalCompat {

final class ZincRun(compileProgress: CompileProgress) extends Run {
override def informUnitStarting(phase: Phase, unit: CompilationUnit): Unit =
compileProgress.startUnit(phase.name, unit.source.path)
override def progress(current: Int, total: Int): Unit =
if (!compileProgress.advance(current, total)) cancel else ()
}

object dummy // temporary fix for #4426

/** Phase that analyzes the generated class files and maps them to sources. */
object sbtAnalyzer extends {
val global: ZincCompiler.this.type = ZincCompiler.this
val phaseName = Analyzer.name
val runsAfter = List("jvm")
override val runsBefore = List("terminal")
val runsRightAfter = None
} with SubComponent {
val analyzer = new Analyzer(global)
def newPhase(prev: Phase) = analyzer.newPhase(prev)
def name = phaseName
}

/** Phase that extracts dependency information */
object sbtDependency extends {
val global: ZincCompiler.this.type = ZincCompiler.this
val phaseName = Dependency.name
val runsAfter = List(API.name)
override val runsBefore = List("refchecks")
// Keep API and dependency close to each other -- we may want to merge them in the future.
override val runsRightAfter = Some(API.name)
} with SubComponent {
val dependency = new Dependency(global)
def newPhase(prev: Phase) = dependency.newPhase(prev)
def name = phaseName
}

/**
* Phase that walks the trees and constructs a representation of the public API.
*
* @note It extracts the API information after picklers to see the same symbol information
* irrespective of whether we typecheck from source or unpickle previously compiled classes.
*/
object apiExtractor extends {
val global: ZincCompiler.this.type = ZincCompiler.this
val phaseName = API.name
val runsAfter = List("typer")
override val runsBefore = List("erasure")
// TODO: Consider migrating to "uncurry" for `runsBefore`.
// TODO: Consider removing the system property to modify which phase is used for API extraction.
val runsRightAfter = Option(System.getProperty("sbt.api.phase")) orElse Some("pickler")
} with SubComponent {
val api = new API(global)
def newPhase(prev: Phase) = api.newPhase(prev)
def name = phaseName
}

override lazy val phaseDescriptors = {
phasesSet += sbtAnalyzer
if (callback.enabled()) {
phasesSet += sbtDependency
phasesSet += apiExtractor
}
this.computePhaseDescriptors
}

/** Returns the class file location of a fully qualified name and whether it's on the classpath. */
def findClass(fqn: String): Option[(AbstractFile, Boolean)] = {
def getOutputClass(name: String): Option[AbstractFile] = {
// This could be improved if a hint where to look is given.
val className = name.replace('.', '/') + ".class"
outputDirs.map(new File(_, className)).find((_.exists)).map((AbstractFile.getFile(_)))
}

def findOnClassPath(name: String): Option[AbstractFile] =
classPath.findClass(name).flatMap(_.binary.asInstanceOf[Option[AbstractFile]])

getOutputClass(fqn).map(f => (f, true)).orElse(findOnClassPath(fqn).map(f => (f, false)))
}

private[this] var callback0: AnalysisCallback = null

/** Returns the active analysis callback, set by [[set]] and cleared by [[clear]]. */
def callback: AnalysisCallback = callback0

final def set(callback: AnalysisCallback, dreporter: DelegatingReporter): Unit = {
this.callback0 = callback
reporter = dreporter
}

final def clear(): Unit = {
callback0 = null
superDropRun()
reporter = null
}

// Scala 2.10.x and later
private[xsbt] def logUnreportedWarnings(seq: Seq[(String, List[(Position, String)])]): Unit = {
val drep = reporter.asInstanceOf[DelegatingReporter]
for ((what, warnings) <- seq; (pos, msg) <- warnings)
yield callback.problem(what, drep.convert(pos), msg, Severity.Warn, false)
()
}
}

import scala.tools.nsc.interactive.RangePositions
final class ZincCompilerRangePos(settings: Settings, dreporter: DelegatingReporter, output: Output)
extends ZincCompiler(settings, dreporter, output)
with RangePositions
Loading