Skip to content

WIP: delegate dotty compiler info to sbt #1528

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

Closed
Closed
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
563b8ab
Add symbols to Doc AST, needed for `@usecase`
felixmulder Aug 24, 2016
e8c9277
Add `Comments` object instead of `Scanners.Comment` case class
felixmulder Aug 24, 2016
1caf3c3
Typecheck usecases
felixmulder Aug 24, 2016
c99ff83
Add `UsecasePhase` to dottydoc
felixmulder Aug 24, 2016
d26b59d
Fix name clashes because of `@usecase`
felixmulder Aug 25, 2016
32c6bb7
Fix type parameters not getting properly typed
felixmulder Aug 25, 2016
f65e64b
Move typing of usecases to `typedClassDef`
felixmulder Aug 25, 2016
eef3de6
Fix cooking of docstrings
felixmulder Aug 26, 2016
a957770
Move docstring parser to dottydoc miniphase
felixmulder Aug 27, 2016
e1745ec
Move docstring cooking to dotty
felixmulder Aug 27, 2016
10a3970
Typecheck usecases in fresh local scope
felixmulder Sep 4, 2016
28edec9
Make Context#moreProperties strongly typed
odersky Sep 1, 2016
e4e19e0
Implement docbase as property
felixmulder Sep 8, 2016
ed3f56e
Update readme: mark Exhaustivity checks & multiv.eq. as implemented
DarkDimius Aug 29, 2016
8fa5627
Fix #1490: type test of union types via type alias
liufengyun Sep 1, 2016
930ad0c
Implement constraint merging
odersky Aug 26, 2016
c681930
Handle complex context merging cases
odersky Aug 26, 2016
dc2d178
Handle case where expected type of a SeqLiteral has an undetermined e…
odersky Aug 26, 2016
f024197
TyperState refactoring.
odersky Aug 26, 2016
d4de454
Bump dottydoc version for nightly builds
felixmulder Sep 6, 2016
a95ed55
Get property from environment instead of from sysprops
felixmulder Sep 6, 2016
d224d4a
Partially fix #1500: Implicit search breaks at a certain depth
OlivierBlanvillain Sep 9, 2016
0458e3e
Identation/spacing cleanup
OlivierBlanvillain Sep 7, 2016
ad2b6f8
Fix #1335: Generate null checks for extractors
OlivierBlanvillain Sep 7, 2016
1902f29
Add some run tests
odersky Aug 23, 2016
ffd9dbe
Fix test syntax to make it dotty compatible
odersky Aug 23, 2016
34e5563
Add missing check file.
odersky Aug 23, 2016
b1aaac8
Move t1335 test from /pos to /run
OlivierBlanvillain Sep 15, 2016
d298ea3
Allow try expression without catch or finally, issue warning
felixmulder Sep 14, 2016
8c79ce5
Improve error message on empty catch block
felixmulder Sep 14, 2016
4e08bb1
Fix #1468: Add type parameter support for scala.Dynamic
nicolasstucki Aug 24, 2016
0c407df
Fix #1470: Fix dynamic selection in presence of inaccessible members.
nicolasstucki Aug 24, 2016
7a59a78
fixup #1470
nicolasstucki Sep 5, 2016
39cbe09
Fix #1474: Fix applies to applyDynamic.
nicolasstucki Aug 25, 2016
e82e655
Enable scala.Dynamic pending/untried tests.
nicolasstucki Aug 26, 2016
1c9ef82
Reformat code after fixes on scala.Dynamic.
nicolasstucki Sep 4, 2016
43667b4
Fix #1510: Fix error message when abstract member not implemented.
nicolasstucki Sep 14, 2016
504b1f8
Fix #1513: misaligned by name type parameter type bounds
OlivierBlanvillain Sep 15, 2016
5525b0c
Fix corner case w types ALL passed by name & out of order
OlivierBlanvillain Sep 16, 2016
3a03e24
Fix #1457: Three incompatbilities with scalac
odersky Aug 23, 2016
1656850
Accommodate Scala2 name resolution scheme
odersky Aug 26, 2016
3175d4c
Add test file.
odersky Aug 26, 2016
56bd08f
Refactoring of findRef
odersky Sep 16, 2016
3c7053f
Fix #1503 - be careful where to insert an apply.
odersky Sep 17, 2016
73192b6
Address reviewer comments
odersky Sep 18, 2016
2359fb2
delegate dotty compiler info to sbt
MasseGuillaume Sep 20, 2016
2ff7e40
automatically clean sbt cache for the dotty sbt bridge
MasseGuillaume Sep 21, 2016
5ca5cf4
clean the sbt dotty-bridge before publishing
MasseGuillaume Sep 21, 2016
13b124d
cleanBridge is a workaround for sbt#2402
MasseGuillaume Sep 21, 2016
c5f0d06
failing scripted test
MasseGuillaume Sep 21, 2016
1083d69
green tests
MasseGuillaume Sep 21, 2016
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
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ See [github contributors page](https://github.com/lampepfl/dotty/graphs/contribu
| Colored Repl | Implemented |
| Sbt incremental build | Implemented |
| Non-blocking lazy vals | Implemented |
| Multiverse equality | Implemented |
| Option-less pattern matching(based on [name-based patmat](https://github.com/scala/scala/pull/2848)) | Implemented |
| Function arity adaptation | Implemented |
| Exhaustivity checks in pattern matching | Implemented |
| | |
| Non-boxed arrays of value classes | In progress |
| Working contravariant implicits | In progress |
Expand All @@ -44,8 +46,7 @@ See [github contributors page](https://github.com/lampepfl/dotty/graphs/contribu
| Effects | Under consideration |
| Auto-completion in repl | Under consideration |
| Spec Option-less pattern matching | Under consideration |
| Multiverse equality | Under consideration |
| Exhaustivity checks in pattern matching | Under consideration |

There are also plethora of small details such as [per-callsite @tailrec annotations](https://github.com/lampepfl/dotty/issues/1221)

####What are the complications that I can have If I start using Dotty?
Expand Down
14 changes: 8 additions & 6 deletions bridge/src/main/scala/xsbt/CompilerInterface.scala
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,17 @@ class CachedCompilerImpl(args: Array[String], output: Output, resident: Boolean)
def commandArguments(sources: Array[File]): Array[String] =
(outputArgs ++ args.toList ++ sources.map(_.getAbsolutePath).sortWith(_ < _)).toArray[String]

def run(sources: Array[File], changes: DependencyChanges, callback: AnalysisCallback, log: Logger, delegate: Reporter, progress: CompileProgress): Unit = synchronized {
run(sources.toList, changes, callback, log, progress)
def run(sources: Array[File], changes: DependencyChanges, callback: AnalysisCallback,
log: Logger, delegate: Reporter, progress: CompileProgress): Unit = synchronized {

run(sources.toList, changes, callback, log, delegate, progress)
}
private[this] def run(sources: List[File], changes: DependencyChanges, callback: AnalysisCallback, log: Logger, compileProgress: CompileProgress): Unit = {
private[this] def run(sources: List[File], changes: DependencyChanges, callback: AnalysisCallback,
log: Logger, delegate: Reporter, compileProgress: CompileProgress): Unit = {
debug(log, args.mkString("Calling Dotty compiler with arguments (CompilerInterface):\n\t", "\n\t", ""))
val ctx = (new ContextBase).initialCtx.fresh
.setSbtCallback(callback)
val freshContext = (new ContextBase).initialCtx.fresh
val ctx = freshContext.setSbtCallback(callback).setReporter(DelegatingReporter(delegate))
val cl = getClass.getClassLoader.asInstanceOf[URLClassLoader]

val reporter = DottyMain.process(commandArguments(sources.toArray), ctx)
if (reporter.hasErrors) {
throw new InterfaceCompileFailed(args, Array())
Expand Down
65 changes: 65 additions & 0 deletions bridge/src/main/scala/xsbt/DelegatingReporter.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/* sbt -- Simple Build Tool
* Copyright 2008, 2009 Mark Harrah
*/
package xsbt

import dotty.tools._
import dotc._
import reporting._
import core.Contexts._

import xsbti.Maybe

object DelegatingReporter {
def apply(delegate: xsbti.Reporter) = new DelegatingReporter(delegate)
}

final class DelegatingReporter(delegate: xsbti.Reporter) extends Reporter
with UniqueMessagePositions
with HideNonSensicalMessages {

def doReport(d: Diagnostic)(implicit ctx: Context): Unit = {
println("doReport " + d.toString)
val severity =
d match {
case _: Reporter.Error => xsbti.Severity.Error
case _: Reporter.Warning => xsbti.Severity.Warn
case _ => xsbti.Severity.Info
}
val pos =
if(d.pos.exists) Some(d.pos)
else None

val file =
if(d.pos.source.file.exists) {
val r = d.pos.source.file.file
if(r == null) None
else Some(r)
}
else None

val offset0 = pos.map(_.point)

val position = new xsbti.Position {
def line: Maybe[Integer] = maybe(pos.map(_.line))
def lineContent(): String = pos.map(_.lineContent).getOrElse("")
def offset(): xsbti.Maybe[Integer] = maybeInt(offset0)
def pointer(): xsbti.Maybe[Integer] = offset()
def pointerSpace(): xsbti.Maybe[String] = maybe(offset0.map(" " * _))
def sourceFile(): xsbti.Maybe[java.io.File] = maybe(file)
def sourcePath(): xsbti.Maybe[String] = maybe(file.map(_.getPath))
}

delegate.log(position, d.message, severity)
}

private[this] def maybe[T](opt: Option[T]): Maybe[T] = opt match {
case None => Maybe.nothing[T]
case Some(s) => Maybe.just[T](s)
}
import java.lang.{ Integer => I }
private[this] def maybeInt(opt: Option[Int]): Maybe[I] = opt match {
case None => Maybe.nothing[I]
case Some(s) => Maybe.just[I](s)
}
}
10 changes: 10 additions & 0 deletions bridge/src/sbt-test/compilerReporter/simple/B.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
trait A
trait B

trait Wr {
val z: A with B
}

object Er {
val a = er1
}
1 change: 1 addition & 0 deletions bridge/src/sbt-test/compilerReporter/simple/build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Reporter.checkSettings
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import sbt._
import Keys._

object DottyInjectedPlugin extends AutoPlugin {
override def requires = plugins.JvmPlugin
override def trigger = allRequirements

override val projectSettings = Seq(
scalaVersion := "0.1-SNAPSHOT",
scalaOrganization := "ch.epfl.lamp",
scalacOptions += "-language:Scala2",
scalaBinaryVersion := "2.11",
autoScalaLibrary := false,
libraryDependencies ++= Seq("org.scala-lang" % "scala-library" % "2.11.5"),
scalaCompilerBridgeSource := ("ch.epfl.lamp" % "dotty-bridge" % "0.1.1-SNAPSHOT" % "component").sources()
)
}
45 changes: 45 additions & 0 deletions bridge/src/sbt-test/compilerReporter/simple/project/Reporter.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import sbt._
import Keys._
import KeyRanks.DTask

object Reporter {
import xsbti.{Reporter, Problem, Position, Severity, Maybe}

lazy val check = TaskKey[Unit]("check", "make sure compilation info are forwared to sbt")

// compilerReporter is marked private in sbt
lazy val compilerReporter = TaskKey[Option[xsbti.Reporter]]("compilerReporter", "Experimental hook to listen (or send) compilation failure messages.", DTask)

lazy val reporter =
Some(new xsbti.Reporter {
private val buffer = collection.mutable.ArrayBuffer.empty[Problem]
def reset(): Unit = buffer.clear()
def hasErrors: Boolean = buffer.exists(_.severity == Severity.Error)
def hasWarnings: Boolean = buffer.exists(_.severity == Severity.Warn)
def printSummary(): Unit = println(problems.mkString(System.lineSeparator))
def problems: Array[Problem] = buffer.toArray
def log(pos: Position, msg: String, sev: Severity): Unit = {
object MyProblem extends Problem {
def category: String = null
def severity: Severity = sev
def message: String = msg
def position: Position = pos
override def toString = s"custom: $position:$severity: $message"
}
buffer.append(MyProblem)
}
def comment(pos: xsbti.Position, msg: String): Unit = ()
})

lazy val checkSettings = Seq(
compilerReporter in (Compile, compile) := reporter,
check <<= (compile in Compile).mapFailure( _ => {
val problems = reporter.get.problems
println(problems.toList)
assert(problems.size == 3)
assert(problems.count(_.severity == Severity.Error) == 1) // not found: er1,
assert(problems.count(_.severity == Severity.Warn) == 1) // `with' as a type operator has been deprecated; use `&' instead,
assert(problems.count(_.severity == Severity.Info) == 1) // one error found
})
)
}
1 change: 1 addition & 0 deletions bridge/src/sbt-test/compilerReporter/simple/test
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
> check
8 changes: 6 additions & 2 deletions dottydoc/src/dotty/tools/dottydoc/DottyDoc.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dotty.tools
package dottydoc

import dotty.tools.dottydoc.util.syntax._
import core._
import core.transform._
import dotc.config.CompilerCommand
Expand Down Expand Up @@ -31,7 +32,9 @@ class DocCompiler extends Compiler {
List(new DocFrontEnd),
List(new DocImplicitsPhase),
List(new DocASTPhase),
List(DocMiniTransformations(new LinkReturnTypes,
List(DocMiniTransformations(new UsecasePhase,
new DocstringPhase,
new LinkReturnTypes,
new LinkParamListTypes,
new LinkImplicitlyAddedTypes,
new LinkSuperTypes,
Expand All @@ -54,6 +57,7 @@ abstract class DocDriver extends Driver {

ctx.setSettings(summary.sstate)
ctx.setSetting(ctx.settings.YkeepComments, true)
ctx.setProperty(DocContext, new DocBase)

val fileNames = CompilerCommand.checkUsage(summary, sourcesRequired)(ctx)
(fileNames, ctx)
Expand All @@ -65,7 +69,7 @@ abstract class DocDriver extends Driver {
val (fileNames, ctx) = setup(args, initCtx.fresh)
doCompile(newCompiler(ctx), fileNames)(ctx)

ctx.docbase.packages[Package]
ctx.docbase.packages
}

def compiledDocsJava(args: Array[String]): JMap[String, Package] =
Expand Down
77 changes: 28 additions & 49 deletions dottydoc/src/dotty/tools/dottydoc/core/DocASTPhase.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,25 @@ package core
import dotc.ast.Trees._
import dotc.CompilationUnit
import dotc.config.Printers.dottydoc
import dotc.core.Contexts.Context
import dotc.core.Contexts.{ Context, DocBase }
import dotc.core.Phases.Phase
import dotc.core.Symbols.{ Symbol, NoSymbol }

class DocASTPhase extends Phase {
import model._
import model.factories._
import model.internal._
import model.parsers.WikiParser
import model.comment.Comment
import dotty.tools.dotc.core.Flags
import dotty.tools.dotc.ast.tpd._
import dotty.tools.dottydoc.util.syntax._
import util.traversing._
import util.internal.setters._

def phaseName = "docphase"

private[this] val commentParser = new WikiParser

/** Saves the commentParser function for later evaluation, for when the AST has been filled */
def track(symbol: Symbol, ctx: Context, parent: Symbol = NoSymbol)(op: => Entity) = {
val entity = op

if (entity != NonEntity)
commentParser += (entity, symbol, parent, ctx)

entity
}

/** Build documentation hierarchy from existing tree */
def collect(tree: Tree, prev: List[String] = Nil)(implicit ctx: Context): Entity = track(tree.symbol, ctx) {
def collect(tree: Tree, prev: List[String] = Nil)(implicit ctx: Context): Entity = {
val implicitConversions = ctx.docbase.defs(tree.symbol)

def collectList(xs: List[Tree], ps: List[String]): List[Entity] =
Expand All @@ -58,28 +46,26 @@ class DocASTPhase extends Phase {
val defs = sym.info.bounds.hi.membersBasedOnFlags(Flags.Method, Flags.Synthetic | Flags.Private)
.filterNot(_.symbol.owner.name.show == "Any")
.map { meth =>
track(meth.symbol, ctx, tree.symbol) {
DefImpl(
meth.symbol.name.show,
Nil,
path(meth.symbol),
returnType(meth.info),
typeParams(meth.symbol),
paramLists(meth.info),
implicitlyAddedFrom = Some(returnType(meth.symbol.owner.info))
)
}
DefImpl(
meth.symbol,
meth.symbol.name.show,
Nil,
path(meth.symbol),
returnType(meth.info),
typeParams(meth.symbol),
paramLists(meth.info),
implicitlyAddedFrom = Some(returnType(meth.symbol.owner.info))
)
}.toList

val vals = sym.info.fields.filterNot(_.symbol.is(Flags.Private | Flags.Synthetic)).map { value =>
track(value.symbol, ctx, tree.symbol) {
ValImpl(
value.symbol.name.show,
Nil, path(value.symbol),
returnType(value.info),
implicitlyAddedFrom = Some(returnType(value.symbol.owner.info))
)
}
ValImpl(
value.symbol,
value.symbol.name.show,
Nil, path(value.symbol),
returnType(value.info),
implicitlyAddedFrom = Some(returnType(value.symbol.owner.info))
)
}

defs ++ vals
Expand All @@ -90,38 +76,38 @@ class DocASTPhase extends Phase {
/** package */
case pd @ PackageDef(pid, st) =>
val newPath = prev :+ pid.name.toString
addEntity(PackageImpl(newPath.mkString("."), collectEntityMembers(st, newPath), newPath))
addEntity(PackageImpl(pd.symbol, newPath.mkString("."), collectEntityMembers(st, newPath), newPath))

/** trait */
case t @ TypeDef(n, rhs) if t.symbol.is(Flags.Trait) =>
val name = n.decode.toString
val newPath = prev :+ name
//TODO: should not `collectMember` from `rhs` - instead: get from symbol, will get inherited members as well
TraitImpl(name, collectMembers(rhs), flags(t), newPath, typeParams(t.symbol), traitParameters(t.symbol), superTypes(t))
TraitImpl(t.symbol, name, collectMembers(rhs), flags(t), newPath, typeParams(t.symbol), traitParameters(t.symbol), superTypes(t))

/** objects, on the format "Object$" so drop the last letter */
case o @ TypeDef(n, rhs) if o.symbol.is(Flags.Module) =>
val name = n.decode.toString.dropRight(1)
//TODO: should not `collectMember` from `rhs` - instead: get from symbol, will get inherited members as well
ObjectImpl(name, collectMembers(rhs, prev :+ name), flags(o), prev :+ (name + "$"), superTypes(o))
ObjectImpl(o.symbol, name, collectMembers(rhs, prev :+ name), flags(o), prev :+ (name + "$"), superTypes(o))

/** class / case class */
case c @ TypeDef(n, rhs) if c.symbol.isClass =>
val name = n.decode.toString
val newPath = prev :+ name
//TODO: should not `collectMember` from `rhs` - instead: get from symbol, will get inherited members as well
(name, collectMembers(rhs), flags(c), newPath, typeParams(c.symbol), constructors(c.symbol), superTypes(c), None) match {
(c.symbol, name, collectMembers(rhs), flags(c), newPath, typeParams(c.symbol), constructors(c.symbol), superTypes(c), None) match {
case x if c.symbol.is(Flags.CaseClass) => CaseClassImpl.tupled(x)
case x => ClassImpl.tupled(x)
}

/** def */
case d: DefDef =>
DefImpl(d.name.decode.toString, flags(d), path(d.symbol), returnType(d.tpt.tpe), typeParams(d.symbol), paramLists(d.symbol.info))
DefImpl(d.symbol, d.name.decode.toString, flags(d), path(d.symbol), returnType(d.tpt.tpe), typeParams(d.symbol), paramLists(d.symbol.info))

/** val */
case v: ValDef if !v.symbol.is(Flags.ModuleVal) =>
ValImpl(v.name.decode.toString, flags(v), path(v.symbol), returnType(v.tpt.tpe))
ValImpl(v.symbol, v.name.decode.toString, flags(v), path(v.symbol), returnType(v.tpt.tpe))

case x => {
//dottydoc.println(s"Found unwanted entity: $x (${x.pos},\n${x.show}")
Expand Down Expand Up @@ -175,15 +161,8 @@ class DocASTPhase extends Phase {
child <- parent.children
} setParent(child, to = parent)

// (3) Create documentation template from docstrings, with internal links
println("Generating documentation, this might take a while...")
commentParser.parse(packages)

// (4) Clear caches
commentParser.clear()

// (5) Update Doc AST in ctx.base
for (kv <- packages) ctx.docbase.packages += kv
// (3) Update Doc AST in ctx.base
for (kv <- packages) ctx.docbase.packagesMutable += kv

// Return super's result
compUnits
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package core
import dotty.tools.dotc.transform.TreeTransforms.{ MiniPhaseTransform, TransformerInfo }
import dotty.tools.dotc.core.Flags
import dotc.core.Contexts.Context
import util.syntax._

class DocImplicitsPhase extends MiniPhaseTransform { thisTransformer =>
import dotty.tools.dotc.ast.tpd._
Expand Down
Loading