From f914350f8f5fecce7350a4c7e1a6c2fe447c7324 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Sun, 5 Feb 2012 14:26:42 +0100 Subject: Fixes https://issues.scala-lang.org/browse/SI-5272 --- src/compiler/scala/tools/nsc/ast/Reifiers.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/compiler/scala/tools/nsc/ast/Reifiers.scala b/src/compiler/scala/tools/nsc/ast/Reifiers.scala index 952110ade2..ef87925959 100644 --- a/src/compiler/scala/tools/nsc/ast/Reifiers.scala +++ b/src/compiler/scala/tools/nsc/ast/Reifiers.scala @@ -281,9 +281,9 @@ trait Reifiers { self: Global => private def reifyTree(tree: Tree): Tree = tree match { case EmptyTree => reifyMirrorObject(EmptyTree) - case This(_) if !(boundSyms contains tree.symbol) => + case This(_) if tree.symbol != NoSymbol && !(boundSyms contains tree.symbol) => reifyFree(tree) - case Ident(_) if !(boundSyms contains tree.symbol) => + case Ident(_) if tree.symbol != NoSymbol && !(boundSyms contains tree.symbol) => if (tree.symbol.isVariable && tree.symbol.owner.isTerm) { captureVariable(tree.symbol) // Note order dependency: captureVariable needs to come before reifyTree here. mirrorCall("Select", reifyFree(tree), reifyName(nme.elem)) -- cgit v1.2.3 From e34098b7f6e37420198fa5c7c2820d0443b46cc4 Mon Sep 17 00:00:00 2001 From: Vlad Ureche Date: Sun, 5 Feb 2012 19:32:52 +0100 Subject: Added a rootdoc page for the compiler API scaladoc --- build.xml | 5 ++-- src/compiler/rootdoc.txt | 6 +++++ .../scala/tools/nsc/doc/html/HtmlFactory.scala | 4 +--- .../tools/nsc/doc/html/resource/lib/rootdoc.txt | 27 ---------------------- src/library/rootdoc.txt | 27 ++++++++++++++++++++++ 5 files changed, 37 insertions(+), 32 deletions(-) create mode 100644 src/compiler/rootdoc.txt delete mode 100644 src/compiler/scala/tools/nsc/doc/html/resource/lib/rootdoc.txt create mode 100644 src/library/rootdoc.txt (limited to 'src') diff --git a/build.xml b/build.xml index 57d2eed1c0..e65b66219b 100644 --- a/build.xml +++ b/build.xml @@ -1530,7 +1530,7 @@ DOCUMENTATION docUncompilable="${src.dir}/library-aux" sourcepath="${src.dir}" classpathref="pack.classpath" - docRootContent="${build-docs.dir}/library/lib/rootdoc.txt"> + docRootContent="${src.dir}/library/rootdoc.txt"> @@ -1613,7 +1613,8 @@ DOCUMENTATION docsourceurl="https://lampsvn.epfl.ch/trac/scala/browser/scala/trunk/src/€{FILE_PATH}.scala#L1" sourcepath="${src.dir}" classpathref="pack.classpath" - srcdir="${src.dir}/compiler"> + srcdir="${src.dir}/compiler" + docRootContent="${src.dir}/compiler/rootdoc.txt"> diff --git a/src/compiler/rootdoc.txt b/src/compiler/rootdoc.txt new file mode 100644 index 0000000000..173f604098 --- /dev/null +++ b/src/compiler/rootdoc.txt @@ -0,0 +1,6 @@ +The Scala compiler API. + +The following resources are useful for Scala plugin/compiler development: + - [[http://www.scala-lang.org/node/215 Scala development tutorials]] on [[http://www.scala-lang.org www.scala-lang.org]] + - [[https://wiki.scala-lang.org/display/SIW/ Scala Internals wiki]] + - [[http://lampwww.epfl.ch/~magarcia/ScalaCompilerCornerReloaded/ Scala compiler corner]], maintained by Miguel diff --git a/src/compiler/scala/tools/nsc/doc/html/HtmlFactory.scala b/src/compiler/scala/tools/nsc/doc/html/HtmlFactory.scala index c21507ef45..4f05678d85 100644 --- a/src/compiler/scala/tools/nsc/doc/html/HtmlFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/html/HtmlFactory.scala @@ -80,9 +80,7 @@ class HtmlFactory(val universe: doc.Universe, index: doc.Index) { "selected.png", "selected2-right.png", "selected2.png", - "unselected.png", - - "rootdoc.txt" + "unselected.png" ) /** Generates the Scaladoc site for a model into the site root. diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/lib/rootdoc.txt b/src/compiler/scala/tools/nsc/doc/html/resource/lib/rootdoc.txt deleted file mode 100644 index 6145429f1e..0000000000 --- a/src/compiler/scala/tools/nsc/doc/html/resource/lib/rootdoc.txt +++ /dev/null @@ -1,27 +0,0 @@ -This is the documentation for the Scala standard library. - -== Package structure == - -The [[scala]] package contains core types. - -scala.[[scala.collection]] and its subpackages contain a collections framework with higher-order functions for manipulation. Both [[scala.collection.immutable]] and [[scala.collection.mutable]] data structures are available, with immutable as the default. The [[scala.collection.parallel]] collections provide automatic parallel operation. - -Other important packages include: - - - scala.[[scala.actors]] - Concurrency framework inspired by Erlang. - - scala.[[scala.io]] - Input and output. - - scala.[[scala.math]] - Basic math functions and additional numeric types. - - scala.[[scala.sys]] - Interaction with other processes and the operating system. - - scala.util.[[scala.util.matching]] - Pattern matching in text using regular expressions. - - scala.util.parsing.[[scala.util.parsing.combinator]] - Composable combinators for parsing. - - scala.[[scala.xml]] - XML parsing, manipulation, and serialization. - -Many other packages exist. See the complete list on the left. - -== Automatic imports == - -Identifiers in the scala package and the [[scala.Predef]] object are always in scope by default. - -Some of these identifiers are type aliases provided as shortcuts to commonly used classes. For example, List is an alias for scala.collection.immutable.[[scala.collection.immutable.List]]. - -Other aliases refer to classes providing by the underlying platform. For example, on the JVM, String is an alias for java.lang.String. diff --git a/src/library/rootdoc.txt b/src/library/rootdoc.txt new file mode 100644 index 0000000000..6145429f1e --- /dev/null +++ b/src/library/rootdoc.txt @@ -0,0 +1,27 @@ +This is the documentation for the Scala standard library. + +== Package structure == + +The [[scala]] package contains core types. + +scala.[[scala.collection]] and its subpackages contain a collections framework with higher-order functions for manipulation. Both [[scala.collection.immutable]] and [[scala.collection.mutable]] data structures are available, with immutable as the default. The [[scala.collection.parallel]] collections provide automatic parallel operation. + +Other important packages include: + + - scala.[[scala.actors]] - Concurrency framework inspired by Erlang. + - scala.[[scala.io]] - Input and output. + - scala.[[scala.math]] - Basic math functions and additional numeric types. + - scala.[[scala.sys]] - Interaction with other processes and the operating system. + - scala.util.[[scala.util.matching]] - Pattern matching in text using regular expressions. + - scala.util.parsing.[[scala.util.parsing.combinator]] - Composable combinators for parsing. + - scala.[[scala.xml]] - XML parsing, manipulation, and serialization. + +Many other packages exist. See the complete list on the left. + +== Automatic imports == + +Identifiers in the scala package and the [[scala.Predef]] object are always in scope by default. + +Some of these identifiers are type aliases provided as shortcuts to commonly used classes. For example, List is an alias for scala.collection.immutable.[[scala.collection.immutable.List]]. + +Other aliases refer to classes providing by the underlying platform. For example, on the JVM, String is an alias for java.lang.String. -- cgit v1.2.3 From 7946ac410ad74894cd0eb6dfd29447f173911b99 Mon Sep 17 00:00:00 2001 From: Vlad Ureche Date: Sun, 5 Feb 2012 22:00:49 +0100 Subject: Scaladoc @usecase annotation overriding / SI-5287 From now on, the usecases inherit the comments from their parents, such as the explanation and the annotations: @param, @tparam, @return, etc. An example of usecase comment inheritance is: /** * The test function tests the parameter param for ... * * @param theParam the implicit parameter to be tested for ... * @return the result of the test * * * * @usecase def test(): Bool * * The test function tests the parameter taken implicitly from scope. * Example: `test()` * * @return the result of the test for the current scope * * * * @usecase def test(theParam: SomeType): Bool * * This takes the explicit value passed. * Example: `test(3)` * * @param theParam the explicit parameter to be tested for ... */ def test(implicit theParam: SomeType): Bool Notice both usecases override the explanation with their own examples. The first usecase also overrides the "@return" annotation while the 2nd usecase overrides the "@param theParam" annotation. If they didn't override the explanations and annotations, they would inherit the values from the actual implementation, def test(implicit ...) This will be followed by @inheritdoc, which enables more fine-grained control over comment inheritance. The full explanation of using comment inheritance and @inheritdoc and their interaction with variables is given at https://wiki.scala-lang.org/display/SW/Tags+and+Annotations in the "Comment inheritance" and "Inheritance Example" sections. --- src/compiler/scala/tools/nsc/util/DocStrings.scala | 26 ++- .../resources/implicit-inheritance-override.scala | 41 +++++ .../resources/implicit-inheritance-usecase.scala | 57 +++++++ test/scaladoc/scala/html/HtmlFactoryTest.scala | 189 +++++++++++++++++---- 4 files changed, 277 insertions(+), 36 deletions(-) create mode 100644 test/scaladoc/resources/implicit-inheritance-override.scala create mode 100644 test/scaladoc/resources/implicit-inheritance-usecase.scala (limited to 'src') diff --git a/src/compiler/scala/tools/nsc/util/DocStrings.scala b/src/compiler/scala/tools/nsc/util/DocStrings.scala index 1db6c38b4d..2c8b77be71 100755 --- a/src/compiler/scala/tools/nsc/util/DocStrings.scala +++ b/src/compiler/scala/tools/nsc/util/DocStrings.scala @@ -71,13 +71,35 @@ object DocStrings { * Every section starts with a `@` and extends to the next `@`, or * to the end of the comment string, but excluding the final two * 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)] = findAll(str, 0) (idx => str(idx) == '@' && p(idx)) match { 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`? */ def startsWithTag(str: String, section: (Int, Int), tag: String): Boolean = diff --git a/test/scaladoc/resources/implicit-inheritance-override.scala b/test/scaladoc/resources/implicit-inheritance-override.scala new file mode 100644 index 0000000000..85b8e8d543 --- /dev/null +++ b/test/scaladoc/resources/implicit-inheritance-override.scala @@ -0,0 +1,41 @@ +// This tests the implicit comment inheritance capabilities of scaladoc for class inheritance (no $super, no @inheritdoc) +class Base { + /** + * The base comment. And another sentence... + * + * @param arg1 The T term comment + * @param arg2 The string comment + * @tparam T the type of the first argument + * @return The return comment + */ + def function[T](arg1: T, arg2: String): Double = 0.0d +} + +class DerivedA extends Base { + /** + * Overriding the comment, the params and returns comments should stay the same. + */ + override def function[T](arg1: T, arg2: String): Double = 1.0d +} + +class DerivedB extends Base { + /** + * @param arg1 The overridden T term comment + * @param arg2 The overridden string comment + */ + override def function[T](arg1: T, arg2: String): Double = 2.0d +} + +class DerivedC extends Base { + /** + * @return The overridden return comment + */ + override def function[T](arg1: T, arg2: String): Double = 3.0d +} + +class DerivedD extends Base { + /** + * @tparam T The overriden type parameter comment + */ + override def function[T](arg1: T, arg2: String): Double = 3.0d +} \ No newline at end of file diff --git a/test/scaladoc/resources/implicit-inheritance-usecase.scala b/test/scaladoc/resources/implicit-inheritance-usecase.scala new file mode 100644 index 0000000000..8dd1262e4b --- /dev/null +++ b/test/scaladoc/resources/implicit-inheritance-usecase.scala @@ -0,0 +1,57 @@ +// This tests the implicit comment inheritance capabilities of scaladoc for usecases (no $super, no @inheritdoc) +/** Testing use case inheritance */ +class UseCaseInheritance { + /** + * The base comment. And another sentence... + * + * @param arg1 The T term comment + * @param arg2 The string comment + * @tparam T The type parameter + * @return The return comment + * + * @usecase def missing_arg[T](arg1: T): Double + * + * @usecase def missing_targ(arg1: Int, arg2: String): Double + * + * @usecase def overridden_arg1[T](implicit arg1: T, arg2: String): Double + * @param arg1 The overridden T term comment + * + * @usecase def overridden_targ[T](implicit arg1: T, arg2: String): Double + * @tparam T The overridden type parameter comment + * + * @usecase def overridden_return[T](implicit arg1: T, arg2: String): Double + * @return The overridden return comment + * + * @usecase def added_arg[T](implicit arg1: T, arg2: String, arg3: Float): Double + * @param arg3 The added float comment + * + * @usecase def overridden_comment[T](implicit arg1: T, arg2: String): Double + * The overridden comment. + */ + def function[T](implicit arg1: T, arg2: String): Double = 0.0d +} + +/** Testing the override-use case interaction */ +class UseCaseOverrideInheritance extends UseCaseInheritance { + /** + * @usecase def missing_arg[T](arg1: T): Double + * + * @usecase def missing_targ(arg1: Int, arg2: String): Double + * + * @usecase def overridden_arg1[T](implicit arg1: T, arg2: String): Double + * @param arg1 The overridden T term comment + * + * @usecase def overridden_targ[T](implicit arg1: T, arg2: String): Double + * @tparam T The overridden type parameter comment + * + * @usecase def overridden_return[T](implicit arg1: T, arg2: String): Double + * @return The overridden return comment + * + * @usecase def added_arg[T](implicit arg1: T, arg2: String, arg3: Float): Double + * @param arg3 The added float comment + * + * @usecase def overridden_comment[T](implicit arg1: T, arg2: String): Double + * The overridden comment. + */ + override def function[T](implicit arg1: T, arg2: String): Double = 0.0d +} diff --git a/test/scaladoc/scala/html/HtmlFactoryTest.scala b/test/scaladoc/scala/html/HtmlFactoryTest.scala index e2687dd510..37aa302ac7 100644 --- a/test/scaladoc/scala/html/HtmlFactoryTest.scala +++ b/test/scaladoc/scala/html/HtmlFactoryTest.scala @@ -84,12 +84,7 @@ object Test extends Properties("HtmlFactory") { val html = scala.stripSuffix(".scala") + ".html" createTemplates(scala)(html) } - - /** - * See checkTextOnly(scalaFile: String, checks: List[String]) - */ - def checkText1(scalaFile: String, check: String, debug: Boolean = true): Boolean = checkText(scalaFile, List(check), debug) - + /** * This tests the text without the markup - ex: * @@ -111,20 +106,31 @@ object Test extends Properties("HtmlFactory") { * * NOTE: Comparison is done ignoring all whitespace */ - def checkText(scalaFile: String, checks: List[String], debug: Boolean = true): Boolean = { + def checkText(scalaFile: String, debug: Boolean = true)(checks: (Option[String], String, Boolean)*): Boolean = { val htmlFile = scalaFile.stripSuffix(".scala") + ".html" - val htmlText = createTemplates(scalaFile)(htmlFile).text.replace('→',' ').replaceAll("\\s+","") + val htmlAllFiles = createTemplates(scalaFile) var result = true - for (check <- checks) { - val checkText = check.replace('→',' ').replaceAll("\\s+","") - val checkValue = htmlText.contains(checkText) - if (debug && (!checkValue)) { - Console.err.println("Check failed: ") - Console.err.println("HTML: " + htmlText) - Console.err.println("Check: " + checkText) - } - result &&= checkValue + for ((fileHint, check, expected) <- checks) { + // resolve the file to be checked + val fileName = fileHint match { + case Some(file) => + if (file endsWith ".html") + file + else + file + ".html" + case None => + htmlFile + } + val fileText = htmlAllFiles(fileName).text.replace('→',' ').replaceAll("\\s+","") + val checkText = check.replace('→',' ').replaceAll("\\s+","") + val checkValue = fileText.contains(checkText) == expected + if (debug && (!checkValue)) { + Console.err.println("Check failed: ") + Console.err.println("HTML: " + fileText) + Console.err.println("Check: " + checkText) + } + result &&= checkValue } result @@ -426,40 +432,155 @@ object Test extends Properties("HtmlFactory") { createTemplate("SI_4898.scala") true } - + property("Use cases should override their original members") = - checkText1("SI_5054_q1.scala", """def test(): Int""") && - !checkText1("SI_5054_q1.scala", """def test(implicit lost: Int): Int""") - + checkText("SI_5054_q1.scala")( + (None,"""def test(): Int""", true), + (None,"""def test(implicit lost: Int): Int""", false) + ) property("Use cases should keep their flags - final should not be lost") = - checkText1("SI_5054_q2.scala", """final def test(): Int""") + checkText("SI_5054_q2.scala")((None, """final def test(): Int""", true)) property("Use cases should keep their flags - implicit should not be lost") = - checkText1("SI_5054_q3.scala", """implicit def test(): Int""") - + checkText("SI_5054_q3.scala")((None, """implicit def test(): Int""", true)) + property("Use cases should keep their flags - real abstract should not be lost") = - checkText1("SI_5054_q4.scala", """abstract def test(): Int""") + checkText("SI_5054_q4.scala")((None, """abstract def test(): Int""", true)) property("Use cases should keep their flags - traits should not be affected") = - checkText1("SI_5054_q5.scala", """def test(): Int""") + checkText("SI_5054_q5.scala")((None, """def test(): Int""", true)) property("Use cases should keep their flags - traits should not be affected") = - checkText1("SI_5054_q6.scala", """abstract def test(): Int""") + checkText("SI_5054_q6.scala")((None, """abstract def test(): Int""", true)) property("Use case individual signature test") = - checkText("SI_5054_q7.scala", List( - """abstract def test2(explicit: Int): Int [use case] This takes the explicit value passed.""", - """abstract def test1(): Int [use case] This takes the implicit value in scope.""")) + checkText("SI_5054_q7.scala")( + (None, """abstract def test2(explicit: Int): Int [use case] This takes the explicit value passed.""", true), + (None, """abstract def test1(): Int [use case] This takes the implicit value in scope.""", true) + ) property("Display correct \"Definition classes\"") = - checkText1("SI_5287.scala", - """def method(): Int + checkText("SI_5287.scala")( + (None, + """def method(): Int [use case] The usecase explanation [use case] The usecase explanation - Definition Classes SI_5287 SI_5287_B SI_5287_A""", debug=true) - // explanation appears twice, as small comment and full comment + Definition Classes SI_5287 SI_5287_B SI_5287_A""", true) + ) // the explanation appears twice, as small comment and full comment + + property("Correct comment inheritance for overriding") = + checkText("implicit-inheritance-override.scala")( + (Some("Base"), + """def function[T](arg1: T, arg2: String): Double + The base comment. + The base comment. And another sentence... + T the type of the first argument + arg1 The T term comment + arg2 The string comment + returns The return comment + """, true), + (Some("DerivedA"), + """def function[T](arg1: T, arg2: String): Double + Overriding the comment, the params and returns comments should stay the same. + Overriding the comment, the params and returns comments should stay the same. + T the type of the first argument + arg1 The T term comment + arg2 The string comment + returns The return comment + """, true), + (Some("DerivedB"), + """def function[T](arg1: T, arg2: String): Double + T the type of the first argument + arg1 The overridden T term comment + arg2 The overridden string comment + returns The return comment + """, true), + (Some("DerivedC"), + """def function[T](arg1: T, arg2: String): Double + T the type of the first argument + arg1 The T term comment + arg2 The string comment + returns The overridden return comment + """, true), + (Some("DerivedD"), + """def function[T](arg1: T, arg2: String): Double + T The overriden type parameter comment + arg1 The T term comment + arg2 The string comment + returns The return comment + """, true) + ) + + for (useCaseFile <- List("UseCaseInheritance", "UseCaseOverrideInheritance")) { + property("Correct comment inheritance for usecases") = + checkText("implicit-inheritance-usecase.scala")( + (Some(useCaseFile), + """def missing_arg[T](arg1: T): Double + [use case] + [use case] + T The type parameter + arg1 The T term comment + returns The return comment + """, true), + (Some(useCaseFile), + """def missing_targ(arg1: Int, arg2: String): Double + [use case] + [use case] + arg1 The T term comment + arg2 The string comment + returns The return comment + """, true), + (Some(useCaseFile), + """def overridden_arg1[T](implicit arg1: T, arg2: String): Double + [use case] + [use case] + T The type parameter + arg1 The overridden T term comment + arg2 The string comment + returns The return comment + """, true), + (Some(useCaseFile), + """def overridden_targ[T](implicit arg1: T, arg2: String): Double + [use case] + [use case] + T The overridden type parameter comment + arg1 The T term comment + arg2 The string comment + returns The return comment + """, true), + (Some(useCaseFile), + """def overridden_return[T](implicit arg1: T, arg2: String): Double + [use case] + [use case] + T The type parameter + arg1 The T term comment + arg2 The string comment + returns The overridden return comment + """, true), + (Some(useCaseFile), + """def added_arg[T](implicit arg1: T, arg2: String, arg3: Float): Double + [use case] + [use case] + T The type parameter + arg1 The T term comment + arg2 The string comment + arg3 The added float comment + returns The return comment + """, true), + (Some(useCaseFile), + """def overridden_comment[T](implicit arg1: T, arg2: String): Double + [use case] The overridden comment. + [use case] The overridden comment. + T The type parameter + arg1 The T term comment + arg2 The string comment + returns The return comment + """, true) + ) + } + { val files = createTemplates("basic.scala") //println(files) -- cgit v1.2.3