From d551ee9d751201491a1d64e4da76ab03e3815df6 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Thu, 20 Sep 2018 14:15:50 +0800 Subject: Include scaladoc as part of mill inspect (#435) --- .../src/mill/moduledefs/AutoOverridePlugin.scala | 114 +++++++++++++++++++++ main/moduledefs/src/mill/moduledefs/Scaladoc.java | 11 ++ 2 files changed, 125 insertions(+) create mode 100644 main/moduledefs/src/mill/moduledefs/Scaladoc.java (limited to 'main/moduledefs') diff --git a/main/moduledefs/src/mill/moduledefs/AutoOverridePlugin.scala b/main/moduledefs/src/mill/moduledefs/AutoOverridePlugin.scala index 5b33abbe..a870e7ec 100644 --- a/main/moduledefs/src/mill/moduledefs/AutoOverridePlugin.scala +++ b/main/moduledefs/src/mill/moduledefs/AutoOverridePlugin.scala @@ -1,10 +1,14 @@ package mill.moduledefs + +import scala.collection.mutable.ListBuffer import scala.reflect.internal.Flags +import scala.tools.nsc.doc.ScaladocSyntaxAnalyzer import scala.tools.nsc.io.VirtualFile import scala.tools.nsc.util.BatchSourceFile import scala.tools.nsc.{Global, Phase} import scala.tools.nsc.plugins.{Plugin, PluginComponent} +import scala.tools.nsc.transform.Transform class AutoOverridePlugin(val global: Global) extends Plugin { import global._ @@ -12,7 +16,117 @@ class AutoOverridePlugin(val global: Global) extends Plugin { val name = "auto-override-plugin" val description = "automatically inserts `override` keywords for you" + val components = List[PluginComponent]( + new PluginComponent with Transform { + type GT = AutoOverridePlugin.this.global.type + override val global: GT = AutoOverridePlugin.this.global + override val phaseName: String = "EmbedScaladocAnnotation" + override val runsAfter: List[String] = List("parser") + override def newTransformer(unit: global.CompilationUnit): global.Transformer = { + new ScaladocTransformer + } + import global._ + + + class ScaladocTransformer extends global.Transformer { + + val comments = new Comments() + + override def transformUnit(unit: CompilationUnit)= { + if (unit.source.file.name.endsWith(".scala") || + unit.source.file.name.endsWith(".sc")){ + comments.parseComments(unit) + super.transformUnit(unit) + } + } + + override def transform(tree: global.Tree): global.Tree = { + super.transform(tree match { + case x: global.ClassDef => + comments.getComment(x.pos) match { + case Some(comment) => + global.treeCopy.ClassDef(tree, newMods(x.mods, comment), x.name, x.tparams, x.impl) + case None => x + } + + case x: global.ModuleDef => + comments.getComment(x.pos) match { + case Some(comment) => + global.treeCopy.ModuleDef(tree, newMods(x.mods, comment), x.name, x.impl) + case None => x + } + + case x: global.DefDef => + comments.getComment(x.pos) match { + case Some(comment) => + global.treeCopy.DefDef(tree, newMods(x.mods, comment), x.name, x.tparams, x.vparamss, x.tpt, x.rhs) + case None => x + } + + case x: global.ValDef => + comments.getComment(x.pos) match { + case Some(comment) => + global.treeCopy.ValDef(tree, newMods(x.mods, comment), x.name, x.tpt, x.rhs) + case None => x + } + + case x => x + }) + } + + def newMods(old: global.Modifiers, comment: String) = { + old.copy( + annotations = createAnnotation(comment) :: old.annotations + ) + } + + private def createAnnotation(comment: String): global.Tree = + global.Apply( + global.Select( + global.New( + global.Select( + global.Select( + global.Ident( + global.newTermName("mill") + ), + global.newTermName("moduledefs") + ), + global.newTypeName("Scaladoc") + ) + ), + global.nme.CONSTRUCTOR + ), + List(Literal(Constant(comment))) + ) + + } + + class Comments extends ScaladocSyntaxAnalyzer[global.type](global){ + val comments = ListBuffer[(Position, String)]() + + def getComment(pos: Position): Option[String] = { + val tookComments = comments.takeWhile { case (x, _) => x.end < pos.start } + comments --= (tookComments) + tookComments.lastOption.map(_._2) + } + + def parseComments(unit: CompilationUnit): Unit = { + comments.clear() + + new ScaladocUnitParser(unit, Nil) { + override def newScanner = new ScaladocUnitScanner(unit, Nil) { + override def registerDocComment(str: String, pos: Position) = { + comments += ((pos, str)) + } + } + }.parse() + } + + override val runsAfter: List[String] = Nil + override val runsRightAfter: Option[String] = None + } + }, new PluginComponent { val global = AutoOverridePlugin.this.global diff --git a/main/moduledefs/src/mill/moduledefs/Scaladoc.java b/main/moduledefs/src/mill/moduledefs/Scaladoc.java new file mode 100644 index 00000000..7a7d700b --- /dev/null +++ b/main/moduledefs/src/mill/moduledefs/Scaladoc.java @@ -0,0 +1,11 @@ +package mill.moduledefs; + + +import java.lang.annotation.*; + +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Scaladoc { + String value(); +} -- cgit v1.2.3