Skip to content

Commit 98108fe

Browse files
Vlad Urechepaulp
authored andcommitted
Fixed "Definition Classes" in bug scala#5287
1 parent 2f5f7c1 commit 98108fe

File tree

8 files changed

+129
-128
lines changed

8 files changed

+129
-128
lines changed

src/compiler/scala/tools/nsc/ast/DocComments.scala

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ trait DocComments { self: Global =>
9999
*/
100100
def useCases(sym: Symbol, site: Symbol): List[(Symbol, String, Position)] = {
101101
def getUseCases(dc: DocComment) = {
102-
for (uc <- dc.useCases; defn <- uc.expandedDefs(site)) yield
102+
for (uc <- dc.useCases; defn <- uc.expandedDefs(sym, site)) yield
103103
(defn,
104104
expandVariables(merge(cookedDocComment(sym), uc.comment.raw, defn), sym, site),
105105
uc.pos)
@@ -346,7 +346,7 @@ trait DocComments { self: Global =>
346346
var defined: List[Symbol] = List() // initialized by Typer
347347
var aliases: List[Symbol] = List() // initialized by Typer
348348

349-
def expandedDefs(site: Symbol): List[Symbol] = {
349+
def expandedDefs(sym: Symbol, site: Symbol): List[Symbol] = {
350350

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

426426
for (defn <- defined) yield {
427-
defn.cloneSymbol.setFlag(Flags.SYNTHETIC).setInfo(
428-
substAliases(defn.info).asSeenFrom(site.thisType, defn.owner))
427+
val useCase = defn.cloneSymbol
428+
useCase.owner = sym.owner
429+
useCase.flags = sym.flags
430+
useCase.setFlag(Flags.SYNTHETIC).setInfo(substAliases(defn.info).asSeenFrom(site.thisType, sym.owner))
429431
}
430432
}
431433
}

src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,15 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
100100
if (inTpl == null) None else thisFactory.comment(sym, inTpl)
101101
override def inTemplate = inTpl
102102
override def toRoot: List[MemberImpl] = this :: inTpl.toRoot
103-
def inDefinitionTemplates =
104-
if (inTpl == null)
105-
makeRootPackage.toList
106-
else
107-
makeTemplate(sym.owner) :: (sym.allOverriddenSymbols map { inhSym => makeTemplate(inhSym.owner) })
103+
def inDefinitionTemplates = this match {
104+
case mb: NonTemplateMemberEntity if (mb.useCaseOf.isDefined) =>
105+
mb.useCaseOf.get.inDefinitionTemplates
106+
case _ =>
107+
if (inTpl == null)
108+
makeRootPackage.toList
109+
else
110+
makeTemplate(sym.owner) :: (sym.allOverriddenSymbols map { inhSym => makeTemplate(inhSym.owner) })
111+
}
108112
def visibility = {
109113
if (sym.isPrivateLocal) PrivateInInstance()
110114
else if (sym.isProtectedLocal) ProtectedInInstance()
@@ -119,18 +123,14 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
119123
else Public()
120124
}
121125
}
122-
def flags = this match {
123-
// workaround for uninitialized flags in use cases - see SI-5054
124-
case m: NonTemplateMemberEntity if (m.useCaseOf.isDefined) =>
125-
m.useCaseOf.get.flags
126-
case _ =>
127-
val fgs = mutable.ListBuffer.empty[Paragraph]
128-
if (sym.isImplicit) fgs += Paragraph(Text("implicit"))
129-
if (sym.isSealed) fgs += Paragraph(Text("sealed"))
130-
if (!sym.isTrait && (sym hasFlag Flags.ABSTRACT)) fgs += Paragraph(Text("abstract"))
131-
if (!sym.isTrait && (sym hasFlag Flags.DEFERRED)) fgs += Paragraph(Text("abstract"))
132-
if (!sym.isModule && (sym hasFlag Flags.FINAL)) fgs += Paragraph(Text("final"))
133-
fgs.toList
126+
def flags = {
127+
val fgs = mutable.ListBuffer.empty[Paragraph]
128+
if (sym.isImplicit) fgs += Paragraph(Text("implicit"))
129+
if (sym.isSealed) fgs += Paragraph(Text("sealed"))
130+
if (!sym.isTrait && (sym hasFlag Flags.ABSTRACT)) fgs += Paragraph(Text("abstract"))
131+
if (!sym.isTrait && (sym hasFlag Flags.DEFERRED)) fgs += Paragraph(Text("abstract"))
132+
if (!sym.isModule && (sym hasFlag Flags.FINAL)) fgs += Paragraph(Text("final"))
133+
fgs.toList
134134
}
135135
def deprecation =
136136
if (sym.isDeprecated)

src/partest/scala/tools/partest/nest/CompileManager.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ class DirectCompiler(val fileManager: FileManager) extends SimpleCompiler {
7575
val logWriter = new FileWriter(log)
7676

7777
// check whether there is a ".flags" file
78-
val flagsFileName = "%s.flags" format (basename(log.getName) dropRight 4) // 4 is "-run" or similar
78+
val logFile = basename(log.getName)
79+
val flagsFileName = "%s.flags" format (logFile.substring(0, logFile.lastIndexOf("-")))
7980
val argString = (io.File(log).parent / flagsFileName) ifFile (x => updatePluginPath(x.slurp())) getOrElse ""
8081
val allOpts = fileManager.SCALAC_OPTS.toList ::: argString.split(' ').toList.filter(_.length > 0)
8182
val args = allOpts.toList

test/scaladoc/resources/SI_5054_q7.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,17 @@ trait SI_5054_q7 {
66
*
77
* @param lost a lost parameter
88
* @return some integer
9-
* @usecase def test(): Int
9+
* @usecase def test1(): Int
1010
*
1111
* This takes the implicit value in scope.
1212
*
13-
* Example: `test()`
13+
* Example: `test1()`
1414
*
15-
* @usecase def test(explicit: Int): Int
15+
* @usecase def test2(explicit: Int): Int
1616
*
1717
* This takes the explicit value passed.
1818
*
19-
* Example: `test(3)`
19+
* Example: `test2(3)`
2020
*/
2121
def test(implicit lost: Int): Int
2222
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
trait SI_5287_A {
2+
def method(implicit a: Int): Int = a
3+
}
4+
5+
trait SI_5287_B extends SI_5287_A {
6+
override def method(implicit a: Int): Int = a + 1
7+
}
8+
9+
trait SI_5287 extends SI_5287_B{
10+
/**
11+
* Some explanation
12+
*
13+
* @usecase def method(): Int
14+
* The usecase explanation
15+
*/
16+
override def method(implicit a: Int): Int = a + 3
17+
}

test/scaladoc/scala/html.flags

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-encoding UTF-8
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-encoding UTF-8

test/scaladoc/scala/html/HtmlFactoryTest.scala

Lines changed: 81 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ object XMLUtil {
2121
}
2222

2323
object Test extends Properties("HtmlFactory") {
24+
25+
final val RESOURCES = "test/scaladoc/resources/"
26+
2427
import scala.tools.nsc.doc.{DocFactory, Settings}
2528
import scala.tools.nsc.doc.model.IndexModelFactory
2629
import scala.tools.nsc.doc.html.HtmlFactory
@@ -47,7 +50,7 @@ object Test extends Properties("HtmlFactory") {
4750
def createTemplates(basename: String) = {
4851
val result = scala.collection.mutable.Map[String, scala.xml.NodeSeq]()
4952

50-
createFactory.makeUniverse(List("test/scaladoc/resources/"+basename)) match {
53+
createFactory.makeUniverse(List(RESOURCES+basename)) match {
5154
case Some(universe) => {
5255
val index = IndexModelFactory.makeIndex(universe)
5356
(new HtmlFactory(universe, index)).writeTemplates((page) => {
@@ -61,7 +64,7 @@ object Test extends Properties("HtmlFactory") {
6164
}
6265

6366
def createReferenceIndex(basename: String) = {
64-
createFactory.makeUniverse(List("test/scaladoc/resources/"+basename)) match {
67+
createFactory.makeUniverse(List(RESOURCES+basename)) match {
6568
case Some(universe) => {
6669
val index = IndexModelFactory.makeIndex(universe)
6770
val pages = index.firstLetterIndex.map({
@@ -81,6 +84,52 @@ object Test extends Properties("HtmlFactory") {
8184
val html = scala.stripSuffix(".scala") + ".html"
8285
createTemplates(scala)(html)
8386
}
87+
88+
/**
89+
* See checkTextOnly(scalaFile: String, checks: List[String])
90+
*/
91+
def checkText1(scalaFile: String, check: String, debug: Boolean = true): Boolean = checkText(scalaFile, List(check), debug)
92+
93+
/**
94+
* This tests the text without the markup - ex:
95+
*
96+
* <h4 class="signature">
97+
* <span class="modifier_kind">
98+
* <span class="modifier">implicit</span>
99+
* <span class="kind">def</span>
100+
* </span>
101+
* <span class="symbol">
102+
* <span class="name">test</span><span class="params">()</span><span class="result">: <span name="scala.Int" class="extype">Int</span></span>
103+
* </span>
104+
* </h4>
105+
*
106+
* becomes:
107+
*
108+
* implicit def test(): Int
109+
*
110+
* and is required to contain the text in the given checks
111+
*
112+
* NOTE: Comparison is done ignoring all whitespace
113+
*/
114+
def checkText(scalaFile: String, checks: List[String], debug: Boolean = true): Boolean = {
115+
val htmlFile = scalaFile.stripSuffix(".scala") + ".html"
116+
val htmlText = createTemplates(scalaFile)(htmlFile).text.replace('→',' ').replaceAll("\\s+","")
117+
var result = true
118+
119+
for (check <- checks) {
120+
val checkText = check.replace('→',' ').replaceAll("\\s+","")
121+
val checkValue = htmlText.contains(checkText)
122+
if (debug && (!checkValue)) {
123+
Console.err.println("Check failed: ")
124+
Console.err.println("HTML: " + htmlText)
125+
Console.err.println("Check: " + checkText)
126+
}
127+
result &&= checkValue
128+
}
129+
130+
result
131+
}
132+
84133

85134
def shortComments(root: scala.xml.Node) =
86135
XMLUtil.stripGroup(root).descendant.flatMap {
@@ -377,113 +426,43 @@ object Test extends Properties("HtmlFactory") {
377426
createTemplate("SI_4898.scala")
378427
true
379428
}
380-
381-
// A piece of the signature - corresponding to the use case
382-
def signature(no: Int, modifier: String) = ("""
383-
<li visbl="pub" name="SI_5054_q""" + no + """#test" data-isabs="false">
384-
<a id="test():Int"></a>
385-
<h4 class="signature">
386-
<span class="modifier_kind">
387-
<span class="modifier">""" + modifier + """</span>
388-
<span class="kind">def</span>
389-
</span>
390-
<span class="symbol">
391-
<span class="name">test</span><span class="params">()</span><span class="result">: <span name="scala.Int" class="extype">Int</span></span>
392-
</span>
393-
</h4>
394-
<p class="shortcomment cmt">[use case]
395-
</p>
396-
</li>""").replaceAll("\\s+", "")
397429

398-
property("Use cases should override their original members") = {
399-
createTemplate("SI_5054_q1.scala") match {
400-
case node: scala.xml.Node =>
401-
node.toString.replaceAll("\\s+","").contains(signature(1, ""))
402-
case _ => false
403-
}
404-
}
405-
406-
property("Use cases should keep their flags - final should not be lost") = {
407-
createTemplate("SI_5054_q2.scala") match {
408-
case node: scala.xml.Node =>
409-
node.toString.replaceAll("\\s+","").contains(signature(2, "final"))
410-
case _ => false
411-
}
412-
}
430+
property("Use cases should override their original members") =
431+
checkText1("SI_5054_q1.scala", """def test(): Int""") &&
432+
!checkText1("SI_5054_q1.scala", """def test(implicit lost: Int): Int""")
413433

414-
property("Use cases should keep their flags - implicit should not be lost") = {
415-
createTemplate("SI_5054_q3.scala") match {
416-
case node: scala.xml.Node =>
417-
node.toString.replaceAll("\\s+","").contains(signature(3, "implicit"))
418-
case _ => false
419-
}
420-
}
421434

422-
property("Use cases should keep their flags - real abstract should not be lost") = {
423-
createTemplate("SI_5054_q4.scala") match {
424-
case node: scala.xml.Node =>
425-
node.toString.replaceAll("\\s+","").contains(signature(4, "abstract"))
426-
case _ => false
427-
}
428-
}
429-
430-
property("Use cases should keep their flags - traits should not be affected") = {
431-
createTemplate("SI_5054_q5.scala") match {
432-
case node: scala.xml.Node =>
433-
node.toString.replaceAll("\\s+","").contains(signature(5, ""))
434-
case _ => false
435-
}
436-
}
437-
438-
property("Use cases should keep their flags - traits should not be affected") = {
439-
createTemplate("SI_5054_q6.scala") match {
440-
case node: scala.xml.Node =>
441-
node.toString.replaceAll("\\s+","").contains(signature(6, "abstract"))
442-
case _ => false
443-
}
444-
}
435+
property("Use cases should keep their flags - final should not be lost") =
436+
checkText1("SI_5054_q2.scala", """final def test(): Int""")
445437

446-
val useCaseExplanation = """
447-
</li><li visbl="pub" name="SI_5054_q7#test" data-isabs="false">
448-
<a id="test():Int"></a>
449-
<h4 class="signature">
450-
<span class="modifier_kind">
451-
<span class="modifier">abstract </span>
452-
<span class="kind">def</span>
453-
</span>
454-
<span class="symbol">
455-
<span class="name">test</span><span class="params">()</span><span class="result">: <span name="scala.Int" class="extype">Int</span></span>
456-
</span>
457-
</h4>
458-
<p class="shortcomment cmt">[use case] This takes the implicit value in scope.</p><div class="fullcomment">[use case] <div class="comment cmt"><p>This takes the implicit value in scope.</p><p>Example: <code>test()</code></p></div><dl class="paramcmts block"><dt>returns</dt><dd class="cmt"><p>some integer
459-
</p></dd></dl></div>
460-
</li><li visbl="pub" name="SI_5054_q7#test" data-isabs="false">
461-
<a id="test(Int):Int"></a>
462-
<h4 class="signature">
463-
<span class="modifier_kind">
464-
<span class="modifier">abstract </span>
465-
<span class="kind">def</span>
466-
</span>
467-
<span class="symbol">
468-
<span class="name">test</span><span class="params">(<span name="explicit">explicit: <span name="scala.Int" class="extype">Int</span></span>)</span><span class="result">: <span name="scala.Int" class="extype">Int</span></span>
469-
</span>
470-
</h4>
471-
<p class="shortcomment cmt">[use case] This takes the explicit value passed.</p><div class="fullcomment">[use case] <div class="comment cmt"><p>This takes the explicit value passed.</p><p>Example: <code>test(3)</code></p></div><dl class="paramcmts block"><dt>returns</dt><dd class="cmt"><p>some integer
472-
</p></dd></dl></div>
473-
</li>
474-
""".replaceAll("\\s+","")
475-
476-
property("Use case individual signature test") = {
477-
createTemplate("SI_5054_q7.scala") match {
478-
case node: scala.xml.Node =>
479-
node.toString.replaceAll("\\s+","").contains(useCaseExplanation)
480-
case _ => false
481-
}
482-
}
438+
property("Use cases should keep their flags - implicit should not be lost") =
439+
checkText1("SI_5054_q3.scala", """implicit def test(): Int""")
440+
441+
property("Use cases should keep their flags - real abstract should not be lost") =
442+
checkText1("SI_5054_q4.scala", """abstract def test(): Int""")
443+
444+
property("Use cases should keep their flags - traits should not be affected") =
445+
checkText1("SI_5054_q5.scala", """def test(): Int""")
446+
447+
property("Use cases should keep their flags - traits should not be affected") =
448+
checkText1("SI_5054_q6.scala", """abstract def test(): Int""")
449+
450+
property("Use case individual signature test") =
451+
checkText("SI_5054_q7.scala", List(
452+
"""abstract def test2(explicit: Int): Int [use case] This takes the explicit value passed.""",
453+
"""abstract def test1(): Int [use case] This takes the implicit value in scope."""))
454+
455+
property("Display correct \"Definition classes\"") =
456+
checkText1("SI_5287.scala",
457+
"""def method(): Int
458+
[use case] The usecase explanation
459+
[use case] The usecase explanation
460+
Definition Classes SI_5287 SI_5287_B SI_5287_A""", debug=true)
461+
// explanation appears twice, as small comment and full comment
483462

484463
{
485464
val files = createTemplates("basic.scala")
486-
println(files)
465+
//println(files)
487466

488467
property("class") = files.get("com/example/p1/Clazz.html") match {
489468
case Some(node: scala.xml.Node) => {

0 commit comments

Comments
 (0)