mirror of https://github.com/sbt/sbt.git
drop 2.7 support, fix fatal warnings support. fixes #153
This commit is contained in:
parent
50a3f616ca
commit
ff95799af7
|
|
@ -14,11 +14,7 @@ import xsbti.api.{ClassLike, DefinitionType, PathComponent, SimpleType}
|
|||
object API
|
||||
{
|
||||
val name = "xsbt-api"
|
||||
// for 2.7 compatibility: this class was removed in 2.8
|
||||
type ImplicitMethodType = AnyRef
|
||||
}
|
||||
// imports ImplicitMethodType, which will preserve source compatibility in 2.7 for defDef
|
||||
import API._
|
||||
|
||||
final class API(val global: Global, val callback: xsbti.AnalysisCallback) extends Compat
|
||||
{
|
||||
|
|
@ -116,7 +112,7 @@ final class API(val global: Global, val callback: xsbti.AnalysisCallback) extend
|
|||
if(pre == NoPrefix)
|
||||
{
|
||||
if(sym.isLocalClass || sym.isRoot || sym.isRootPackage) Constants.emptyType
|
||||
else if(sym.isTypeParameterOrSkolem || isExistential(sym)) reference(sym)
|
||||
else if(sym.isTypeParameterOrSkolem || sym.isExistentiallyBound) reference(sym)
|
||||
else {
|
||||
// this appears to come from an existential type in an inherited member- not sure why isExistential is false here
|
||||
/*println("Warning: Unknown prefixless type: " + sym + " in " + sym.owner + " in " + sym.enclClass)
|
||||
|
|
@ -145,26 +141,19 @@ final class API(val global: Global, val callback: xsbti.AnalysisCallback) extend
|
|||
{
|
||||
def build(t: Type, typeParams: Array[xsbti.api.TypeParameter], valueParameters: List[xsbti.api.ParameterList]): xsbti.api.Def =
|
||||
{
|
||||
// 2.8 compatibility
|
||||
implicit def symbolsToParameters(syms: List[Symbol]): xsbti.api.ParameterList =
|
||||
def parameterList(syms: List[Symbol]): xsbti.api.ParameterList =
|
||||
{
|
||||
val isImplicitList = syms match { case head :: _ => isImplicit(head); case _ => false }
|
||||
new xsbti.api.ParameterList(syms.map(parameterS).toArray, isImplicitList)
|
||||
}
|
||||
// 2.7 compatibility
|
||||
implicit def typesToParameters(syms: List[Type]): xsbti.api.ParameterList =
|
||||
{
|
||||
val isImplicitList = t.isInstanceOf[ImplicitMethodType]
|
||||
new xsbti.api.ParameterList(syms.map(parameterT).toArray, isImplicitList)
|
||||
}
|
||||
t match
|
||||
{
|
||||
case PolyType(typeParams0, base) =>
|
||||
assert(typeParams.isEmpty)
|
||||
assert(valueParameters.isEmpty)
|
||||
build(base, typeParameters(in, typeParams0), Nil)
|
||||
case MethodType(params, resultType) => // in 2.7, params is of type List[Type], in 2.8 it is List[Symbol]
|
||||
build(resultType, typeParams, (params: xsbti.api.ParameterList) :: valueParameters)
|
||||
case MethodType(params, resultType) =>
|
||||
build(resultType, typeParams, parameterList(params) :: valueParameters)
|
||||
case Nullary(resultType) => // 2.9 and later
|
||||
build(resultType, typeParams, valueParameters)
|
||||
case returnType =>
|
||||
|
|
@ -175,9 +164,6 @@ final class API(val global: Global, val callback: xsbti.AnalysisCallback) extend
|
|||
def parameterS(s: Symbol): xsbti.api.MethodParameter =
|
||||
makeParameter(s.nameString, s.info, s.info.typeSymbol, s)
|
||||
|
||||
def parameterT(t: Type): xsbti.api.MethodParameter =
|
||||
makeParameter("", t, t.typeSymbol, NoSymbol)
|
||||
|
||||
// paramSym is only for 2.8 and is to determine if the parameter has a default
|
||||
def makeParameter(name: String, tpe: Type, ts: Symbol, paramSym: Symbol): xsbti.api.MethodParameter =
|
||||
{
|
||||
|
|
@ -194,13 +180,7 @@ final class API(val global: Global, val callback: xsbti.AnalysisCallback) extend
|
|||
val t = viewer(in).memberInfo(s)
|
||||
build(t, Array(), Nil)
|
||||
}
|
||||
private def hasDefault(s: Symbol) =
|
||||
{
|
||||
// 2.7 compatibility
|
||||
implicit def flagsWithDefault(f: AnyRef): WithDefault = new WithDefault
|
||||
class WithDefault { val DEFAULTPARAM = 0x00000000 }
|
||||
s != NoSymbol && s.hasFlag(Flags.DEFAULTPARAM)
|
||||
}
|
||||
private def hasDefault(s: Symbol) = s != NoSymbol && s.hasFlag(Flags.DEFAULTPARAM)
|
||||
private def fieldDef[T](in: Symbol, s: Symbol, keepConst: Boolean, create: (xsbti.api.Type, String, xsbti.api.Access, xsbti.api.Modifiers, Array[xsbti.api.Annotation]) => T): T =
|
||||
{
|
||||
val t = dropNullary(viewer(in).memberType(s))
|
||||
|
|
@ -266,7 +246,7 @@ final class API(val global: Global, val callback: xsbti.AnalysisCallback) extend
|
|||
def mkVal = Some(fieldDef(in, sym, true, new xsbti.api.Val(_,_,_,_,_)))
|
||||
if(sym.isClass || sym.isModule)
|
||||
if(ignoreClass(sym)) None else Some(classLike(in, sym))
|
||||
else if(isNonClassType(sym))
|
||||
else if(sym.isNonClassType)
|
||||
Some(typeDef(in, sym))
|
||||
else if(sym.isVariable)
|
||||
if(isSourceField(sym)) mkVar else None
|
||||
|
|
@ -278,7 +258,7 @@ final class API(val global: Global, val callback: xsbti.AnalysisCallback) extend
|
|||
None
|
||||
}
|
||||
private def ignoreClass(sym: Symbol): Boolean =
|
||||
sym.isLocalClass || sym.isAnonymousClass || fullName(sym).endsWith(LocalChild)
|
||||
sym.isLocalClass || sym.isAnonymousClass || sym.fullName.endsWith(LocalChild)
|
||||
|
||||
// This filters private[this] vals/vars that were not in the original source.
|
||||
// The getter will be used for processing instead.
|
||||
|
|
@ -305,7 +285,7 @@ final class API(val global: Global, val callback: xsbti.AnalysisCallback) extend
|
|||
else
|
||||
{
|
||||
val within = c.privateWithin
|
||||
val qualifier = if(within == NoSymbol) Constants.unqualified else new xsbti.api.IdQualifier(fullName(within))
|
||||
val qualifier = if(within == NoSymbol) Constants.unqualified else new xsbti.api.IdQualifier(within.fullName)
|
||||
if(c.hasFlag(Flags.PROTECTED)) new xsbti.api.Protected(qualifier)
|
||||
else new xsbti.api.Private(qualifier)
|
||||
}
|
||||
|
|
@ -354,7 +334,7 @@ final class API(val global: Global, val callback: xsbti.AnalysisCallback) extend
|
|||
private def classLike(in: Symbol, c: Symbol): ClassLike = classLikeCache.getOrElseUpdate( (in,c), mkClassLike(in, c))
|
||||
private def mkClassLike(in: Symbol, c: Symbol): ClassLike =
|
||||
{
|
||||
val name = fullName(c)
|
||||
val name = c.fullName
|
||||
val isModule = c.isModuleClass || c.isModule
|
||||
val struct = if(isModule) c.moduleClass else c
|
||||
val defType =
|
||||
|
|
@ -379,7 +359,7 @@ final class API(val global: Global, val callback: xsbti.AnalysisCallback) extend
|
|||
()
|
||||
else
|
||||
{
|
||||
packages += fullName(p)
|
||||
packages += p.fullName
|
||||
`package`(p.enclosingPackage)
|
||||
}
|
||||
}
|
||||
|
|
@ -414,10 +394,6 @@ final class API(val global: Global, val callback: xsbti.AnalysisCallback) extend
|
|||
(sym ne null) && (sym != NoSymbol) && !sym.isImplClass && !sym.isNestedClass && sym.isStatic &&
|
||||
!sym.hasFlag(Flags.SYNTHETIC) && !sym.hasFlag(Flags.JAVA)
|
||||
}
|
||||
|
||||
// In 2.8, attributes is renamed to annotations
|
||||
implicit def compat(a: AnyRef): WithAnnotations = new WithAnnotations(a)
|
||||
class WithAnnotations(a: AnyRef) { def attributes = a.getClass.getMethod("annotations").invoke(a).asInstanceOf[List[AnnotationInfo]] }
|
||||
|
||||
private def annotations(in: Symbol, s: Symbol): Array[xsbti.api.Annotation] =
|
||||
atPhase(currentRun.typerPhase) {
|
||||
|
|
@ -427,14 +403,13 @@ final class API(val global: Global, val callback: xsbti.AnalysisCallback) extend
|
|||
// a) they are recorded as normal source methods anyway
|
||||
// b) there is no way to distinguish them from user-defined methods
|
||||
val associated = List(b, b.getter(b.enclClass), b.setter(b.enclClass)).filter(_ != NoSymbol)
|
||||
associated.flatMap( ss => annotations(in, ss.attributes) ).removeDuplicates.toArray ;
|
||||
associated.flatMap( ss => annotations(in, ss.annotations) ).distinct.toArray ;
|
||||
}
|
||||
private def annotatedType(in: Symbol, at: AnnotatedType): xsbti.api.Type =
|
||||
{
|
||||
val annots = at.attributes
|
||||
val annots = at.annotations
|
||||
if(annots.isEmpty) processType(in, at.underlying) else annotated(in, annots, at.underlying)
|
||||
}
|
||||
private def fullName(s: Symbol): String = nameString(s)
|
||||
private def simpleName(s: Symbol): String =
|
||||
{
|
||||
val n = s.originalName
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ final class Analyzer(val global: Global, val callback: AnalysisCallback) extends
|
|||
case Some((f,className)) =>
|
||||
f match
|
||||
{
|
||||
case ze: ZipArchive#Entry => binaryDependency(new File(archive(ze).getName), className)
|
||||
case ze: ZipArchive#Entry => for(zip <- ze.underlyingSource; zipFile <- Option(zip.file) ) binaryDependency(zipFile, className)
|
||||
case pf: PlainFile => binaryDependency(pf.file, className)
|
||||
case _ => ()
|
||||
}
|
||||
|
|
@ -69,7 +69,7 @@ final class Analyzer(val global: Global, val callback: AnalysisCallback) extends
|
|||
}
|
||||
if(sym.isModuleClass && !sym.isImplClass)
|
||||
{
|
||||
if(isTopLevelModule(sym) && linkedClass(sym) == NoSymbol)
|
||||
if(isTopLevelModule(sym) && sym.companionClass == NoSymbol)
|
||||
addGenerated(false)
|
||||
addGenerated(true)
|
||||
}
|
||||
|
|
@ -81,14 +81,16 @@ final class Analyzer(val global: Global, val callback: AnalysisCallback) extends
|
|||
}
|
||||
}
|
||||
|
||||
private def classFile(sym: Symbol): Option[(AbstractFile, String)] =
|
||||
private[this] final val classSeparator = '.'
|
||||
private[this] def findClass(name: String): Option[AbstractFile] = classPath.findClass(name).flatMap(_.binary.asInstanceOf[Option[AbstractFile]])
|
||||
private[this] def classFile(sym: Symbol): Option[(AbstractFile, String)] =
|
||||
{
|
||||
import scala.tools.nsc.symtab.Flags
|
||||
val name = flatname(sym, finder.classSeparator) + moduleSuffix(sym)
|
||||
finder.findClass(name).map(file => (file, name)) orElse {
|
||||
val name = flatname(sym, classSeparator) + moduleSuffix(sym)
|
||||
findClass(name).map(file => (file, name)) orElse {
|
||||
if(isTopLevelModule(sym))
|
||||
{
|
||||
val linked = linkedClass(sym)
|
||||
val linked = sym.companionClass
|
||||
if(linked == NoSymbol)
|
||||
None
|
||||
else
|
||||
|
|
@ -102,7 +104,7 @@ final class Analyzer(val global: Global, val callback: AnalysisCallback) extends
|
|||
private def moduleSuffix(sym: Symbol) =
|
||||
if (sym.hasFlag(Flags.MODULE) && !sym.isMethod && !sym.isImplClass && !sym.hasFlag(Flags.JAVA)) "$" else "";
|
||||
private def flatname(s: Symbol, separator: Char) =
|
||||
atPhase(currentRun.flattenPhase.next) { nameString(s, separator) }
|
||||
atPhase(currentRun.flattenPhase.next) { s fullName separator }
|
||||
|
||||
private def isTopLevelModule(sym: Symbol): Boolean =
|
||||
atPhase (currentRun.picklerPhase.next) {
|
||||
|
|
@ -112,70 +114,14 @@ final class Analyzer(val global: Global, val callback: AnalysisCallback) extends
|
|||
flatname(s, sep) + (if(dollarRequired) "$" else "")
|
||||
private def fileForClass(outputDirectory: File, s: Symbol, separatorRequired: Boolean): File =
|
||||
new File(outputDirectory, className(s, File.separatorChar, separatorRequired) + ".class")
|
||||
|
||||
// required because the 2.8 way to find a class is:
|
||||
// classPath.findClass(name).flatMap(_.binary)
|
||||
// and the 2.7 way is:
|
||||
// val entry = classPath.root.find(name, false)
|
||||
// if(entry eq null) None else Some(entry.classFile)
|
||||
private lazy val finder = try { new LegacyFinder } catch { case _ => new NewFinder }
|
||||
private trait ClassFinder
|
||||
{
|
||||
def classSeparator: Char
|
||||
def findClass(name: String): Option[AbstractFile]
|
||||
}
|
||||
private class NewFinder extends ClassFinder
|
||||
{
|
||||
private class Compat27 { def findClass(name: String) = this; def flatMap(f: Compat27 => AnyRef) = Predef.error("Should never be called"); def binary = None }
|
||||
private implicit def compat27(any: AnyRef): Compat27 = new Compat27
|
||||
|
||||
def classSeparator = '.' // 2.8 uses . when searching for classes
|
||||
def findClass(name: String): Option[AbstractFile] =
|
||||
classPath.findClass(name).flatMap(_.binary.asInstanceOf[Option[AbstractFile]])
|
||||
}
|
||||
private class LegacyFinder extends ClassFinder
|
||||
{
|
||||
private class Compat28 { def root: Compat28 = invalid; def find(n: String, b: Boolean) = this; def classFile = invalid; def invalid = Predef.error("Should never be called") }
|
||||
private implicit def compat28(any: AnyRef): Compat28 = new Compat28
|
||||
|
||||
def classSeparator = File.separatorChar // 2.7 uses / or \ when searching for classes
|
||||
private val root = classPath.root
|
||||
def findClass(name: String): Option[AbstractFile] =
|
||||
{
|
||||
val entry = root.find(name, false)
|
||||
if(entry eq null) None else Some(entry.classFile)
|
||||
}
|
||||
}
|
||||
}
|
||||
abstract class Compat
|
||||
{
|
||||
val global: Global
|
||||
import global._
|
||||
def archive(s: ZipArchive#Entry): ZipFile = s.getArchive
|
||||
def nameString(s: Symbol): String = s.fullNameString
|
||||
def nameString(s: Symbol, sep: Char): String = s.fullNameString(sep)
|
||||
def isExistential(s: Symbol): Boolean = s.isExistential
|
||||
def isNonClassType(s: Symbol): Boolean = s.isTypeMember
|
||||
val LocalChild = global.tpnme.LOCAL_CHILD
|
||||
val Nullary = global.NullaryMethodType
|
||||
|
||||
def linkedClass(s: Symbol): Symbol = s.linkedClassOfModule
|
||||
|
||||
/** After 2.8.0.Beta1, fullNameString was renamed fullName.
|
||||
* linkedClassOfModule was renamed companionClass. */
|
||||
private[this] implicit def symCompat(sym: Symbol): SymCompat = new SymCompat(sym)
|
||||
private[this] final class SymCompat(s: Symbol)
|
||||
{
|
||||
def fullNameString = s.fullName; def fullName = sourceCompatibilityOnly
|
||||
def fullNameString(sep: Char) = s.fullName(sep); def fullName(sep: Char) = sourceCompatibilityOnly
|
||||
|
||||
def isExistential: Boolean = s.isExistentiallyBound; def isExistentiallyBound = sourceCompatibilityOnly
|
||||
def isTypeMember: Boolean = s.isNonClassType; def isNonClassType = sourceCompatibilityOnly
|
||||
|
||||
def linkedClassOfModule = s.companionClass; def companionClass = sourceCompatibilityOnly
|
||||
// In 2.8, hasAttribute is renamed to hasAnnotation
|
||||
def hasAnnotation(a: Symbol) = s.hasAttribute(a); def hasAttribute(a: Symbol) = sourceCompatibilityOnly
|
||||
}
|
||||
private[this] final class MiscCompat
|
||||
{
|
||||
// in 2.9, nme.LOCALCHILD was renamed to tpnme.LOCAL_CHILD
|
||||
|
|
@ -190,14 +136,6 @@ abstract class Compat
|
|||
def unapply(t: Type): Option[Type] = None
|
||||
}
|
||||
|
||||
final def hasAnnotation(s: Symbol)(ann: Symbol) = atPhase(currentRun.typerPhase) { s.hasAnnotation(ann) }
|
||||
|
||||
/** After 2.8.0.Beta1, getArchive was renamed archive.*/
|
||||
private[this] implicit def zipCompat(z: ZipArchive#Entry): ZipCompat = new ZipCompat(z)
|
||||
private[this] final class ZipCompat(z: ZipArchive#Entry)
|
||||
{
|
||||
def getArchive = z.archive; def archive = sourceCompatibilityOnly
|
||||
}
|
||||
private[this] def sourceCompatibilityOnly: Nothing = throw new RuntimeException("For source compatibility only: should not get here.")
|
||||
|
||||
private[this] final implicit def miscCompat(n: AnyRef): MiscCompat = new MiscCompat
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ private final class DelegatingReporter(warnFatal: Boolean, delegate: xsbti.Repor
|
|||
protected def info0(pos: Position, msg: String, rawSeverity: Severity, force: Boolean)
|
||||
{
|
||||
val severity = if(warnFatal && rawSeverity == WARNING) ERROR else rawSeverity
|
||||
delegate.log(convert(pos), msg, convert(rawSeverity))
|
||||
delegate.log(convert(pos), msg, convert(severity))
|
||||
}
|
||||
private[this] def convert(posIn: Position): xsbti.Position =
|
||||
{
|
||||
|
|
|
|||
|
|
@ -85,7 +85,9 @@ object Sbt extends Build
|
|||
// Compiler-side interface to compiler that is compiled against the compiler being used either in advance or on the fly.
|
||||
// Includes API and Analyzer phases that extract source API and relationships.
|
||||
lazy val compileInterfaceSub = baseProject(compilePath / "interface", "Compiler Interface") dependsOn(interfaceSub, ioSub % "test->test", logSub % "test->test", launchSub % "test->test") settings( compileInterfaceSettings : _*)
|
||||
lazy val precompiled28 = precompiled("2.8.1")
|
||||
lazy val precompiled290 = precompiled("2.9.0")
|
||||
lazy val precompiled281 = precompiled("2.8.1")
|
||||
lazy val precompiled280 = precompiled("2.8.0")
|
||||
// lazy val precompiled27 = precompiled("2.7.7")
|
||||
|
||||
// Implements the core functionality of detecting and propagating changes incrementally.
|
||||
|
|
@ -115,7 +117,7 @@ object Sbt extends Build
|
|||
// Strictly for bringing implicits and aliases from subsystems into the top-level sbt namespace through a single package object
|
||||
// technically, we need a dependency on all of mainSub's dependencies, but we don't do that since this is strictly an integration project
|
||||
// with the sole purpose of providing certain identifiers without qualification (with a package object)
|
||||
lazy val sbtSub = baseProject(sbtPath, "Simple Build Tool") dependsOn(mainSub, compileInterfaceSub, precompiled28, scriptedSbtSub % "test->test") settings(sbtSettings : _*)
|
||||
lazy val sbtSub = baseProject(sbtPath, "Simple Build Tool") dependsOn(mainSub, compileInterfaceSub, precompiled281, precompiled280, precompiled290, scriptedSbtSub % "test->test") settings(sbtSettings : _*)
|
||||
|
||||
/* Nested subproject paths */
|
||||
def sbtPath = file("sbt")
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
name :== "test"
|
||||
name := "test"
|
||||
|
||||
TaskKey[Unit]("check-same") <<= compile in Configurations.Compile map { analysis =>
|
||||
analysis.apis.internal foreach { case (_, api) =>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
> 'set scalacOptions += "-Xfatal-warnings"'
|
||||
|
||||
> compile
|
||||
|
||||
# have new class E extend A
|
||||
|
|
|
|||
Loading…
Reference in New Issue