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

Fixed "Definition Classes" in bug #5287 #63

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 6 additions & 4 deletions src/compiler/scala/tools/nsc/ast/DocComments.scala
Expand Up @@ -99,7 +99,7 @@ trait DocComments { self: Global =>
*/ */
def useCases(sym: Symbol, site: Symbol): List[(Symbol, String, Position)] = { def useCases(sym: Symbol, site: Symbol): List[(Symbol, String, Position)] = {
def getUseCases(dc: DocComment) = { def getUseCases(dc: DocComment) = {
for (uc <- dc.useCases; defn <- uc.expandedDefs(site)) yield for (uc <- dc.useCases; defn <- uc.expandedDefs(sym, site)) yield
(defn, (defn,
expandVariables(merge(cookedDocComment(sym), uc.comment.raw, defn), sym, site), expandVariables(merge(cookedDocComment(sym), uc.comment.raw, defn), sym, site),
uc.pos) uc.pos)
Expand Down Expand Up @@ -346,7 +346,7 @@ trait DocComments { self: Global =>
var defined: List[Symbol] = List() // initialized by Typer var defined: List[Symbol] = List() // initialized by Typer
var aliases: List[Symbol] = List() // initialized by Typer var aliases: List[Symbol] = List() // initialized by Typer


def expandedDefs(site: Symbol): List[Symbol] = { def expandedDefs(sym: Symbol, site: Symbol): List[Symbol] = {


def select(site: Type, name: Name, orElse: => Type): Type = { def select(site: Type, name: Name, orElse: => Type): Type = {
val member = site.nonPrivateMember(name) val member = site.nonPrivateMember(name)
Expand Down Expand Up @@ -424,8 +424,10 @@ trait DocComments { self: Global =>
} }


for (defn <- defined) yield { for (defn <- defined) yield {
defn.cloneSymbol.setFlag(Flags.SYNTHETIC).setInfo( val useCase = defn.cloneSymbol
substAliases(defn.info).asSeenFrom(site.thisType, defn.owner)) useCase.owner = sym.owner
useCase.flags = sym.flags
useCase.setFlag(Flags.SYNTHETIC).setInfo(substAliases(defn.info).asSeenFrom(site.thisType, sym.owner))
} }
} }
} }
Expand Down
34 changes: 17 additions & 17 deletions src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
Expand Up @@ -100,11 +100,15 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
if (inTpl == null) None else thisFactory.comment(sym, inTpl) if (inTpl == null) None else thisFactory.comment(sym, inTpl)
override def inTemplate = inTpl override def inTemplate = inTpl
override def toRoot: List[MemberImpl] = this :: inTpl.toRoot override def toRoot: List[MemberImpl] = this :: inTpl.toRoot
def inDefinitionTemplates = def inDefinitionTemplates = this match {
if (inTpl == null) case mb: NonTemplateMemberEntity if (mb.useCaseOf.isDefined) =>
makeRootPackage.toList mb.useCaseOf.get.inDefinitionTemplates
else case _ =>
makeTemplate(sym.owner) :: (sym.allOverriddenSymbols map { inhSym => makeTemplate(inhSym.owner) }) if (inTpl == null)
makeRootPackage.toList
else
makeTemplate(sym.owner) :: (sym.allOverriddenSymbols map { inhSym => makeTemplate(inhSym.owner) })
}
def visibility = { def visibility = {
if (sym.isPrivateLocal) PrivateInInstance() if (sym.isPrivateLocal) PrivateInInstance()
else if (sym.isProtectedLocal) ProtectedInInstance() else if (sym.isProtectedLocal) ProtectedInInstance()
Expand All @@ -119,18 +123,14 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
else Public() else Public()
} }
} }
def flags = this match { def flags = {
// workaround for uninitialized flags in use cases - see SI-5054 val fgs = mutable.ListBuffer.empty[Paragraph]
case m: NonTemplateMemberEntity if (m.useCaseOf.isDefined) => if (sym.isImplicit) fgs += Paragraph(Text("implicit"))
m.useCaseOf.get.flags if (sym.isSealed) fgs += Paragraph(Text("sealed"))
case _ => if (!sym.isTrait && (sym hasFlag Flags.ABSTRACT)) fgs += Paragraph(Text("abstract"))
val fgs = mutable.ListBuffer.empty[Paragraph] if (!sym.isTrait && (sym hasFlag Flags.DEFERRED)) fgs += Paragraph(Text("abstract"))
if (sym.isImplicit) fgs += Paragraph(Text("implicit")) if (!sym.isModule && (sym hasFlag Flags.FINAL)) fgs += Paragraph(Text("final"))
if (sym.isSealed) fgs += Paragraph(Text("sealed")) fgs.toList
if (!sym.isTrait && (sym hasFlag Flags.ABSTRACT)) fgs += Paragraph(Text("abstract"))
if (!sym.isTrait && (sym hasFlag Flags.DEFERRED)) fgs += Paragraph(Text("abstract"))
if (!sym.isModule && (sym hasFlag Flags.FINAL)) fgs += Paragraph(Text("final"))
fgs.toList
} }
def deprecation = def deprecation =
if (sym.isDeprecated) if (sym.isDeprecated)
Expand Down
26 changes: 24 additions & 2 deletions src/compiler/scala/tools/nsc/util/DocStrings.scala
Expand Up @@ -71,13 +71,35 @@ object DocStrings {
* Every section starts with a `@` and extends to the next `@`, or * Every section starts with a `@` and extends to the next `@`, or
* to the end of the comment string, but excluding the final two * to the end of the comment string, but excluding the final two
* characters which terminate the comment. * characters which terminate the comment.
*
* Also take usecases into account - they need to expand until the next
* @usecase or the end of the string, as they might include other sections
* of their own
*/ */
def tagIndex(str: String, p: Int => Boolean = (idx => true)): List[(Int, Int)] = def tagIndex(str: String, p: Int => Boolean = (idx => true)): List[(Int, Int)] =
findAll(str, 0) (idx => str(idx) == '@' && p(idx)) match { findAll(str, 0) (idx => str(idx) == '@' && p(idx)) match {
case List() => List() case List() => List()
case idxs => idxs zip (idxs.tail ::: List(str.length - 2)) case idxs => {
val idxs2 = mergeUsecaseSections(str, idxs)
idxs2 zip (idxs2.tail ::: List(str.length - 2))
}
} }


/**
* Merge sections following an @usecase into the usecase comment, so they
* can override the parent symbol's sections
*/
def mergeUsecaseSections(str: String, idxs: List[Int]): List[Int] = {
idxs.find(str.substring(_).startsWith("@usecase")) match {
case Some(firstUC) =>
val commentSections = idxs.take(idxs.indexOf(firstUC))
val usecaseSections = idxs.drop(idxs.indexOf(firstUC)).filter(str.substring(_).startsWith("@usecase"))
commentSections ::: usecaseSections
case None =>
idxs
}
}

/** Does interval `iv` start with given `tag`? /** Does interval `iv` start with given `tag`?
*/ */
def startsWithTag(str: String, section: (Int, Int), tag: String): Boolean = def startsWithTag(str: String, section: (Int, Int), tag: String): Boolean =
Expand Down
3 changes: 2 additions & 1 deletion src/partest/scala/tools/partest/nest/CompileManager.scala
Expand Up @@ -75,7 +75,8 @@ class DirectCompiler(val fileManager: FileManager) extends SimpleCompiler {
val logWriter = new FileWriter(log) val logWriter = new FileWriter(log)


// check whether there is a ".flags" file // check whether there is a ".flags" file
val flagsFileName = "%s.flags" format (basename(log.getName) dropRight 4) // 4 is "-run" or similar val logFile = basename(log.getName)
val flagsFileName = "%s.flags" format (logFile.substring(0, logFile.lastIndexOf("-")))
val argString = (io.File(log).parent / flagsFileName) ifFile (x => updatePluginPath(x.slurp())) getOrElse "" val argString = (io.File(log).parent / flagsFileName) ifFile (x => updatePluginPath(x.slurp())) getOrElse ""
val allOpts = fileManager.SCALAC_OPTS.toList ::: argString.split(' ').toList.filter(_.length > 0) val allOpts = fileManager.SCALAC_OPTS.toList ::: argString.split(' ').toList.filter(_.length > 0)
val args = allOpts.toList val args = allOpts.toList
Expand Down
8 changes: 4 additions & 4 deletions test/scaladoc/resources/SI_5054_q7.scala
Expand Up @@ -6,17 +6,17 @@ trait SI_5054_q7 {
* *
* @param lost a lost parameter * @param lost a lost parameter
* @return some integer * @return some integer
* @usecase def test(): Int * @usecase def test1(): Int
* *
* This takes the implicit value in scope. * This takes the implicit value in scope.
* *
* Example: `test()` * Example: `test1()`
* *
* @usecase def test(explicit: Int): Int * @usecase def test2(explicit: Int): Int
* *
* This takes the explicit value passed. * This takes the explicit value passed.
* *
* Example: `test(3)` * Example: `test2(3)`
*/ */
def test(implicit lost: Int): Int def test(implicit lost: Int): Int
} }
17 changes: 17 additions & 0 deletions test/scaladoc/resources/SI_5287.scala
@@ -0,0 +1,17 @@
trait SI_5287_A {
def method(implicit a: Int): Int = a
}

trait SI_5287_B extends SI_5287_A {
override def method(implicit a: Int): Int = a + 1
}

trait SI_5287 extends SI_5287_B{
/**
* Some explanation
*
* @usecase def method(): Int
* The usecase explanation
*/
override def method(implicit a: Int): Int = a + 3
}
1 change: 1 addition & 0 deletions test/scaladoc/scala/html.flags
@@ -0,0 +1 @@
-encoding UTF-8
1 change: 1 addition & 0 deletions test/scaladoc/scala/html/HtmlFactoryTest.flags
@@ -0,0 +1 @@
-encoding UTF-8