summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@epfl.ch>2012-07-22 15:44:17 +0200
committerAdriaan Moors <adriaan.moors@epfl.ch>2012-07-22 15:47:58 +0200
commit078a1c5fae09970d22b886831e36745b7f7e25db (patch)
treef9df2087dbf1984b83d122ce1a3e41a96e6f4920
parente52fa7e652c175f561a1a0804e04b6d00b89aaa6 (diff)
parentfa4c1de6e7dc5e5703ccf822c5815da9e8ae47ed (diff)
downloadscala-078a1c5fae09970d22b886831e36745b7f7e25db.tar.gz
scala-078a1c5fae09970d22b886831e36745b7f7e25db.tar.bz2
scala-078a1c5fae09970d22b886831e36745b7f7e25db.zip
Merge branch '2.10.x`
Conflicts: test/files/run/existentials-in-compiler.scala
-rw-r--r--README.rst4
-rw-r--r--build.xml75
-rw-r--r--lib/scala-compiler-src.jar.desired.sha12
-rw-r--r--lib/scala-compiler.jar.desired.sha12
-rw-r--r--lib/scala-library-src.jar.desired.sha12
-rw-r--r--lib/scala-library.jar.desired.sha12
-rw-r--r--lib/scala-reflect-src.jar.desired.sha12
-rw-r--r--lib/scala-reflect.jar.desired.sha12
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Context.scala3
-rw-r--r--src/compiler/scala/reflect/makro/runtime/ContextReifiers.scala26
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Enclosures.scala1
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Mirrors.scala43
-rw-r--r--src/compiler/scala/reflect/reify/Taggers.scala32
-rw-r--r--src/compiler/scala/reflect/reify/codegen/GenSymbols.scala36
-rw-r--r--src/compiler/scala/reflect/reify/codegen/GenTypes.scala3
-rw-r--r--src/compiler/scala/reflect/reify/utils/Extractors.scala4
-rw-r--r--src/compiler/scala/tools/ant/FastScalac.scala2
-rw-r--r--src/compiler/scala/tools/ant/Scalac.scala2
-rw-r--r--src/compiler/scala/tools/ant/Scaladoc.scala28
-rw-r--r--src/compiler/scala/tools/cmd/FromString.scala2
-rw-r--r--src/compiler/scala/tools/nsc/CompileServer.scala2
-rw-r--r--src/compiler/scala/tools/nsc/Driver.scala6
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala2
-rw-r--r--src/compiler/scala/tools/nsc/Main.scala6
-rw-r--r--src/compiler/scala/tools/nsc/MainBench.scala48
-rw-r--r--src/compiler/scala/tools/nsc/ObjectRunner.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ScriptRunner.scala2
-rwxr-xr-xsrc/compiler/scala/tools/nsc/ast/DocComments.scala87
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala7
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Scanners.scala6
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala83
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala9
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala12
-rw-r--r--src/compiler/scala/tools/nsc/doc/DocFactory.scala9
-rw-r--r--src/compiler/scala/tools/nsc/doc/Settings.scala61
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/HtmlFactory.scala9
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala43
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/Page.scala22
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/page/Index.scala8
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/page/IndexScript.scala6
-rwxr-xr-xsrc/compiler/scala/tools/nsc/doc/html/page/ReferenceIndex.scala2
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/page/Template.scala162
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/page/diagram/DotDiagramGenerator.scala34
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/page/diagram/DotRunner.scala19
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/resource/lib/diagrams.css8
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js48
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/resource/lib/object_to_type_big.pngbin0 -> 9158 bytes
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/resource/lib/template.css25
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/resource/lib/template.js135
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/resource/lib/type.pngbin0 -> 3338 bytes
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/resource/lib/type_big.pngbin0 -> 7691 bytes
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/resource/lib/type_diagram.pngbin0 -> 3895 bytes
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/resource/lib/type_to_object_big.pngbin0 -> 9054 bytes
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/Entity.scala119
-rwxr-xr-xsrc/compiler/scala/tools/nsc/doc/model/IndexModelFactory.scala7
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/Links.scala24
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala187
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala687
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala44
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/ModelFactoryTypeSupport.scala323
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/TypeEntity.scala4
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/comment/Body.scala7
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/comment/Comment.scala12
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala101
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/diagram/Diagram.scala28
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala58
-rw-r--r--src/compiler/scala/tools/nsc/interactive/Global.scala2
-rw-r--r--src/compiler/scala/tools/nsc/interactive/PresentationCompilerThread.scala2
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ILoop.scala2
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/IMain.scala2
-rw-r--r--src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala4
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala21
-rw-r--r--src/compiler/scala/tools/nsc/transform/CleanUp.scala149
-rw-r--r--src/compiler/scala/tools/nsc/transform/Constructors.scala7
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala7
-rw-r--r--src/compiler/scala/tools/nsc/transform/TailCalls.scala19
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala64
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Macros.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala171
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala85
-rwxr-xr-xsrc/compiler/scala/tools/nsc/util/DocStrings.scala6
-rw-r--r--src/compiler/scala/tools/nsc/util/InterruptReq.scala5
-rw-r--r--src/compiler/scala/tools/reflect/FastTrack.scala3
-rw-r--r--src/compiler/scala/tools/reflect/MacroImplementations.scala9
-rw-r--r--src/compiler/scala/tools/reflect/StdTags.scala61
-rw-r--r--src/compiler/scala/tools/util/VerifyClass.scala3
-rw-r--r--src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala2
-rw-r--r--src/library-aux/scala/AnyRef.scala1
-rw-r--r--src/library/scala/Double.scala3
-rw-r--r--src/library/scala/Float.scala3
-rw-r--r--src/library/scala/annotation/static.scala20
-rw-r--r--src/library/scala/collection/immutable/List.scala3
-rw-r--r--src/library/scala/collection/immutable/StringOps.scala2
-rw-r--r--src/library/scala/collection/immutable/Vector.scala26
-rw-r--r--src/library/scala/collection/mutable/ArrayOps.scala2
-rw-r--r--src/library/scala/concurrent/BlockContext.scala35
-rw-r--r--src/library/scala/concurrent/Future.scala6
-rw-r--r--src/library/scala/concurrent/default/SchedulerImpl.scala.disabled44
-rw-r--r--src/library/scala/concurrent/default/TaskImpl.scala.disabled313
-rw-r--r--src/library/scala/concurrent/impl/ExecutionContextImpl.scala10
-rw-r--r--src/library/scala/concurrent/impl/Future.scala24
-rw-r--r--src/library/scala/concurrent/impl/Promise.scala2
-rw-r--r--src/library/scala/concurrent/package.scala66
-rw-r--r--src/library/scala/reflect/base/Base.scala3
-rw-r--r--src/library/scala/reflect/base/MirrorOf.scala65
-rw-r--r--src/library/scala/reflect/package.scala3
-rw-r--r--src/partest/scala/tools/partest/CompilerTest.scala2
-rw-r--r--src/partest/scala/tools/partest/DirectTest.scala5
-rw-r--r--src/partest/scala/tools/partest/ScaladocModelTest.scala67
-rw-r--r--src/partest/scala/tools/partest/nest/DirectRunner.scala6
-rw-r--r--src/reflect/scala/reflect/api/Mirrors.scala144
-rw-r--r--src/reflect/scala/reflect/api/StandardNames.scala1
-rw-r--r--src/reflect/scala/reflect/internal/AnnotationInfos.scala7
-rw-r--r--src/reflect/scala/reflect/internal/Definitions.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Mirrors.scala166
-rw-r--r--src/reflect/scala/reflect/internal/Names.scala3
-rw-r--r--src/reflect/scala/reflect/internal/Scopes.scala20
-rw-r--r--src/reflect/scala/reflect/internal/StdNames.scala4
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala6
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala202
-rw-r--r--src/reflect/scala/reflect/internal/util/SourceFile.scala24
-rw-r--r--src/reflect/scala/reflect/makro/Context.scala4
-rw-r--r--src/reflect/scala/reflect/makro/Enclosures.scala4
-rw-r--r--src/reflect/scala/reflect/runtime/JavaMirrors.scala70
-rw-r--r--src/reflect/scala/reflect/runtime/SymbolLoaders.scala4
-rw-r--r--src/reflect/scala/tools/nsc/io/VirtualFile.scala2
-rw-r--r--test/files/jvm/future-spec/FutureTests.scala6
-rw-r--r--test/files/jvm/future-spec/PromiseTests.scala9
-rw-r--r--test/files/jvm/scala-concurrent-tck.scala31
-rw-r--r--test/files/neg/macro-cyclic.check8
-rw-r--r--test/files/neg/macro-cyclic/Impls_Macros_1.scala2
-rw-r--r--test/files/neg/static-annot.check19
-rw-r--r--test/files/neg/static-annot.scala47
-rw-r--r--test/files/neg/t4069.check2
-rw-r--r--test/files/neg/t4425.check5
-rw-r--r--test/files/neg/t4584.check7
-rw-r--r--test/files/neg/t5856.check31
-rw-r--r--test/files/neg/t5856.scala11
-rw-r--r--test/files/neg/t5892.check17
-rw-r--r--test/files/neg/t5892.scala25
-rw-r--r--test/files/neg/unicode-unterminated-quote.check5
-rw-r--r--test/files/pos/t1832.scala8
-rw-r--r--test/files/pos/t5892.scala5
-rw-r--r--test/files/pos/t5957/T_1.scala6
-rw-r--r--test/files/pos/t6047.flags1
-rw-r--r--test/files/pos/t6047.scala20
-rw-r--r--test/files/run/existentials-in-compiler.scala2
-rw-r--r--test/files/run/inline-ex-handlers.check80
-rw-r--r--test/files/run/macro-openmacros/Impls_Macros_1.scala2
-rw-r--r--test/files/run/macro-reify-basic/Macros_1.scala2
-rw-r--r--test/files/run/macro-reify-freevars/Macros_1.scala2
-rw-r--r--test/files/run/macro-reify-nested-a/Impls_Macros_1.scala2
-rw-r--r--test/files/run/macro-reify-nested-b/Impls_Macros_1.scala2
-rw-r--r--test/files/run/macro-reify-ref-to-packageless/Impls_1.scala2
-rw-r--r--test/files/run/macro-reify-splice-splice/Macros_1.scala4
-rw-r--r--test/files/run/macro-reify-staticXXX.check12
-rw-r--r--test/files/run/macro-reify-staticXXX.flags1
-rw-r--r--test/files/run/macro-reify-staticXXX/Macros_1.scala48
-rw-r--r--test/files/run/macro-reify-staticXXX/Test_2.scala4
-rw-r--r--test/files/run/macro-reify-tagful-a/Macros_1.scala2
-rw-r--r--test/files/run/macro-reify-tagless-a/Impls_Macros_1.scala2
-rw-r--r--test/files/run/macro-reify-unreify/Macros_1.scala2
-rw-r--r--test/files/run/macro-settings/Impls_Macros_1.scala2
-rw-r--r--test/files/run/macro-sip19-revised/Impls_Macros_1.scala2
-rw-r--r--test/files/run/macro-sip19/Impls_Macros_1.scala2
-rw-r--r--test/files/run/macro-typecheck-macrosdisabled2.check4
-rw-r--r--test/files/run/macro-undetparams-consfromsls/Impls_Macros_1.scala4
-rw-r--r--test/files/run/macro-undetparams-macroitself/Impls_Macros_1.scala2
-rw-r--r--test/files/run/nullable-lazyvals.check3
-rw-r--r--test/files/run/nullable-lazyvals.scala36
-rw-r--r--test/files/run/outertest.scala26
-rw-r--r--test/files/run/reflection-constructormirror-inner-badpath.check2
-rw-r--r--test/files/run/reflection-constructormirror-nested-badpath.check2
-rw-r--r--test/files/run/reflection-constructormirror-toplevel-badpath.check2
-rw-r--r--test/files/run/reflection-fieldmirror-accessorsareokay.check6
-rw-r--r--test/files/run/reflection-fieldmirror-accessorsareokay.scala29
-rw-r--r--test/files/run/reflection-fieldmirror-ctorparam.check4
-rw-r--r--test/files/run/reflection-fieldmirror-getsetval.check2
-rw-r--r--test/files/run/reflection-fieldmirror-sanitycheck.check6
-rw-r--r--test/files/run/reflection-fieldmirror-sanitycheck.scala22
-rw-r--r--test/files/run/reflection-magicsymbols-repl.check39
-rw-r--r--test/files/run/reflection-magicsymbols-repl.scala23
-rw-r--r--test/files/run/reflection-magicsymbols-vanilla.check8
-rw-r--r--test/files/run/reflection-magicsymbols-vanilla.scala20
-rw-r--r--test/files/run/reflection-magicsymbols.check22
-rw-r--r--test/files/run/reflection-magicsymbols.scala11
-rw-r--r--test/files/run/reflection-modulemirror-inner-badpath.check4
-rw-r--r--test/files/run/reflection-modulemirror-nested-badpath.check4
-rw-r--r--test/files/run/reflection-modulemirror-toplevel-badpath.check4
-rw-r--r--test/files/run/reflection-sanitychecks.check8
-rw-r--r--test/files/run/reflection-sanitychecks.scala30
-rw-r--r--test/files/run/reify-staticXXX.check24
-rw-r--r--test/files/run/reify-staticXXX.scala56
-rw-r--r--test/files/run/static-annot/field.scala243
-rw-r--r--test/files/run/t4897.check1
-rw-r--r--test/files/run/t4897.scala10
-rw-r--r--test/files/run/t5158.check1
-rw-r--r--test/files/run/t5158.scala17
-rw-r--r--test/files/run/t5385.check8
-rw-r--r--test/files/run/t5385.scala16
-rw-r--r--test/files/run/t5713/Impls_Macros_1.scala6
-rw-r--r--test/files/run/t5856.scala10
-rw-r--r--test/files/run/t5937.scala12
-rw-r--r--test/files/run/t6070.check1
-rw-r--r--test/files/run/t6070.scala36
-rw-r--r--test/files/run/t6086-repl.check12
-rw-r--r--test/files/run/t6086-repl.scala8
-rw-r--r--test/files/run/t6086-vanilla.check1
-rw-r--r--test/files/run/t6086-vanilla.scala6
-rw-r--r--test/files/run/t6089.check1
-rw-r--r--test/files/run/t6089.scala13
-rw-r--r--test/files/run/t6104.check1
-rw-r--r--test/files/run/t6104.scala8
-rw-r--r--test/files/run/toolbox_typecheck_macrosdisabled2.check4
-rw-r--r--test/pending/run/macro-expand-implicit-macro-defeats-type-inference/Impls_1.scala2
-rw-r--r--test/pending/run/macro-reify-array/Macros_1.scala2
-rw-r--r--test/pending/run/macro-reify-tagful-b/Macros_1.scala2
-rw-r--r--test/pending/run/macro-reify-tagless-b/Impls_Macros_1.scala2
-rw-r--r--test/pending/run/t5692/Impls_Macros_1.scala2
-rw-r--r--test/pending/run/t5695.check2
-rw-r--r--test/pending/run/t5695/part_1.scala12
-rw-r--r--test/pending/run/t5695/part_2.scala8
-rw-r--r--test/scaladoc/resources/SI-3314-diagrams.scala78
-rw-r--r--test/scaladoc/resources/SI-3314.scala85
-rw-r--r--test/scaladoc/resources/SI-4360.scala42
-rw-r--r--test/scaladoc/resources/SI-5558.scala6
-rw-r--r--test/scaladoc/resources/SI-5784.scala28
-rw-r--r--test/scaladoc/resources/SI_4676.scala4
-rw-r--r--test/scaladoc/resources/Trac3484.scala27
-rw-r--r--test/scaladoc/resources/doc-root/AnyRef.scala1
-rw-r--r--test/scaladoc/resources/implicits-known-type-classes-res.scala38
-rw-r--r--test/scaladoc/resources/implicits-scopes-res.scala2
-rw-r--r--test/scaladoc/resources/links.scala57
-rw-r--r--test/scaladoc/resources/package-object-res.scala2
-rw-r--r--test/scaladoc/run/SI-3314-diagrams.check1
-rw-r--r--test/scaladoc/run/SI-3314-diagrams.scala28
-rw-r--r--test/scaladoc/run/SI-3314.check1
-rw-r--r--test/scaladoc/run/SI-3314.scala91
-rw-r--r--test/scaladoc/run/SI-3448.check1
-rw-r--r--test/scaladoc/run/SI-3448.scala38
-rw-r--r--test/scaladoc/run/SI-3484.check1
-rw-r--r--test/scaladoc/run/SI-3484.scala52
-rw-r--r--test/scaladoc/run/SI-4324.check1
-rw-r--r--test/scaladoc/run/SI-4324.scala24
-rw-r--r--test/scaladoc/run/SI-4360.check1
-rw-r--r--test/scaladoc/run/SI-4360.scala48
-rw-r--r--test/scaladoc/run/SI-4676.check1
-rw-r--r--test/scaladoc/run/SI-4676.scala26
-rw-r--r--test/scaladoc/run/SI-4887.check1
-rw-r--r--test/scaladoc/run/SI-4887.scala46
-rw-r--r--test/scaladoc/run/SI-5235.check4
-rw-r--r--test/scaladoc/run/SI-5235.scala87
-rw-r--r--test/scaladoc/run/SI-5533.check1
-rw-r--r--test/scaladoc/run/SI-5533.scala39
-rw-r--r--test/scaladoc/run/SI-5784.check1
-rw-r--r--test/scaladoc/run/SI-5784.scala44
-rw-r--r--test/scaladoc/run/SI-5965.check1
-rw-r--r--test/scaladoc/run/SI-5965.scala24
-rw-r--r--test/scaladoc/run/diagrams-base.scala6
-rw-r--r--test/scaladoc/run/diagrams-determinism.scala20
-rw-r--r--test/scaladoc/run/diagrams-filtering.scala2
-rw-r--r--test/scaladoc/run/groups.check1
-rw-r--r--test/scaladoc/run/groups.scala119
-rw-r--r--test/scaladoc/run/implicits-ambiguating.scala2
-rw-r--r--test/scaladoc/run/implicits-known-type-classes.check1
-rw-r--r--test/scaladoc/run/implicits-known-type-classes.scala33
-rw-r--r--test/scaladoc/run/implicits-scopes.scala6
-rw-r--r--test/scaladoc/run/implicits-shadowing.scala2
-rw-r--r--test/scaladoc/run/implicits-var-exp.scala35
-rw-r--r--test/scaladoc/run/links.check1
-rw-r--r--test/scaladoc/run/links.scala28
-rw-r--r--test/scaladoc/scalacheck/CommentFactoryTest.scala16
-rw-r--r--test/scaladoc/scalacheck/HtmlFactoryTest.scala73
-rw-r--r--test/scaladoc/scalacheck/IndexTest.scala13
279 files changed, 5308 insertions, 2025 deletions
diff --git a/README.rst b/README.rst
index 383db1c175..72c4b6028b 100644
--- a/README.rst
+++ b/README.rst
@@ -200,6 +200,8 @@ all code submitted to the project is unencumbered by copyrights or patents.
The form is available at:
http://www.scala-lang.org/sites/default/files/contributor_agreement.pdf
+Before submitting a pull-request, please make sure you have followed the guidelines
+outlined in our `Pull Request Policy <https://github.com/scala/scala/wiki/Pull-Request-Policy>`_.
------------------
@@ -208,5 +210,3 @@ http://www.scala-lang.org/sites/default/files/contributor_agreement.pdf
Thank you!
The Scala Team
-
-
diff --git a/build.xml b/build.xml
index 8fa1b9cd76..a4feada3c7 100644
--- a/build.xml
+++ b/build.xml
@@ -397,7 +397,7 @@ INITIALISATION
</target>
<target name="init" depends="init.jars, init.maven.jars, init.version.done, init.fail.bad.jdk, init.warn.jdk7">
- <property name="scalac.args.always" value="" />
+ <property name="scalac.args.always" value="-Yreify-copypaste" />
<!-- scalac.args.optimise is selectively overridden in certain antcall tasks. -->
<property name="scalac.args.optimise" value=""/>
<!-- scalac.args.quickonly are added to quick.* targets but not others (particularly, locker.)
@@ -499,7 +499,7 @@ LOCAL DEPENDENCY (Adapted ASM)
destdir="${build-asm.dir}/classes"
classpath="${build-asm.dir}/classes"
includes="**/*.java"
- target="1.5" source="1.5">
+ target="1.6" source="1.5">
<compilerarg line="${javac.args} -XDignore.symbol.file"/>
</javac>
<touch file="${build-asm.dir}/asm.complete" verbose="no"/>
@@ -540,7 +540,7 @@ LOCAL DEPENDENCY (FORKJOIN)
classpath="${build-libs.dir}/classes/forkjoin"
includes="**/*.java"
debug="true"
- target="1.5" source="1.5">
+ target="1.6" source="1.5">
<compilerarg line="${javac.args} -XDignore.symbol.file"/>
</javac>
<touch file="${build-libs.dir}/forkjoin.complete" verbose="no"/>
@@ -587,7 +587,7 @@ LOCAL DEPENDENCY (FJBG)
classpath="${build-libs.dir}/classes/fjbg"
includes="**/*.java"
debug="true"
- target="1.5" source="1.4">
+ target="1.6" source="1.4">
<compilerarg line="${javac.args} -XDignore.symbol.file"/>
</javac>
<touch file="${build-libs.dir}/fjbg.complete" verbose="no"/>
@@ -635,7 +635,7 @@ LOCAL REFERENCE BUILD (LOCKER)
srcdir="${src.dir}/library"
destdir="${build-locker.dir}/classes/library"
includes="**/*.java"
- target="1.5" source="1.5">
+ target="1.6" source="1.5">
<compilerarg line="${javac.args} -XDignore.symbol.file"/>
<classpath>
<path refid="forkjoin.classpath"/>
@@ -749,7 +749,7 @@ LOCAL REFERENCE BUILD (LOCKER)
includes="**/*.java"
excludes="**/tests/**"
debug="true"
- target="1.5" source="1.4">
+ target="1.6" source="1.4">
<compilerarg line="${javac.args}"/>
</javac>
<scalacfork
@@ -1009,7 +1009,7 @@ QUICK BUILD (QUICK)
srcdir="${src.dir}/library"
destdir="${build-quick.dir}/classes/library"
includes="**/*.java"
- target="1.5" source="1.5">
+ target="1.6" source="1.5">
<compilerarg line="${javac.args} -XDignore.symbol.file"/>
<classpath>
<path refid="forkjoin.classpath"/>
@@ -1020,7 +1020,7 @@ QUICK BUILD (QUICK)
srcdir="${src.dir}/actors"
destdir="${build-quick.dir}/classes/library"
includes="**/*.java"
- target="1.5" source="1.5">
+ target="1.6" source="1.5">
<compilerarg line="${javac.args}"/>
<classpath>
<path refid="forkjoin.classpath"/>
@@ -1145,7 +1145,7 @@ QUICK BUILD (QUICK)
includes="**/*.java"
excludes="**/tests/**"
debug="true"
- target="1.5" source="1.4">
+ target="1.6" source="1.4">
<compilerarg line="${javac.args}"/>
</javac>
<scalacfork
@@ -1349,7 +1349,7 @@ QUICK BUILD (QUICK)
<javac
srcdir="${src.dir}/partest"
destdir="${build-quick.dir}/classes/partest"
- target="1.5" source="1.5">
+ target="1.6" source="1.5">
<classpath>
<pathelement location="${build-quick.dir}/classes/library"/>
<pathelement location="${build-quick.dir}/classes/reflect"/>
@@ -1691,7 +1691,7 @@ BOOTSTRAPPING BUILD (STRAP)
srcdir="${src.dir}/library"
destdir="${build-strap.dir}/classes/library"
includes="**/*.java"
- target="1.5" source="1.5">
+ target="1.6" source="1.5">
<compilerarg line="${javac.args} -XDignore.symbol.file"/>
<classpath>
<path refid="forkjoin.classpath"/>
@@ -1702,7 +1702,7 @@ BOOTSTRAPPING BUILD (STRAP)
srcdir="${src.dir}/actors"
destdir="${build-strap.dir}/classes/library"
includes="**/*.java"
- target="1.5" source="1.5">
+ target="1.6" source="1.5">
<compilerarg line="${javac.args}"/>
<classpath>
<path refid="forkjoin.classpath"/>
@@ -1826,7 +1826,7 @@ BOOTSTRAPPING BUILD (STRAP)
includes="**/*.java"
excludes="**/tests/**"
debug="true"
- target="1.5" source="1.4">
+ target="1.6" source="1.4">
<compilerarg line="${javac.args}"/>
</javac>
<scalacfork
@@ -1994,7 +1994,7 @@ BOOTSTRAPPING BUILD (STRAP)
<javac
srcdir="${src.dir}/partest"
destdir="${build-strap.dir}/classes/partest"
- target="1.5" source="1.5">
+ target="1.6" source="1.5">
<classpath>
<pathelement location="${build-strap.dir}/classes/library"/>
<pathelement location="${build-strap.dir}/classes/reflect"/>
@@ -2044,7 +2044,7 @@ BOOTSTRAPPING BUILD (STRAP)
LIBRARIES (Forkjoin, FJBG, ASM)
============================================================================ -->
-
+
<target name="libs.clean" depends="pack.clean, asm.clean">
<delete dir="${build-libs.dir}" includeemptydirs="yes" quiet="yes" failonerror="no"/>
</target>
@@ -2082,8 +2082,9 @@ DOCUMENTATION
<property name="scaladoc.url" value="https://github.com/scala/scala/tree/${scaladoc.git.commit}/src"/>
<echo message="Scaladoc will point to ${scaladoc.url} for source files."/>
- <!-- Unless set with -Dscaladoc.raw.output, it won't be activated -->
+ <!-- Unless set with -Dscaladoc.<...>, these won't be activated -->
<property name="scaladoc.raw.output" value="no"/>
+ <property name="scaladoc.no.prefixes" value="no"/>
</target>
<target name="docs.pre-lib" depends="docs.start">
@@ -2111,7 +2112,11 @@ DOCUMENTATION
classpathref="pack.classpath"
addparams="${scalac.args.all}"
docRootContent="${src.dir}/library/rootdoc.txt"
- implicits="on" diagrams="on" rawOutput="${scaladoc.raw.output}">
+ implicits="on"
+ diagrams="on"
+ groups="on"
+ rawOutput="${scaladoc.raw.output}"
+ noPrefixes="${scaladoc.no.prefixes}">
<src>
<files includes="${src.dir}/actors-migration"/>
<files includes="${src.dir}/actors"/>
@@ -2195,7 +2200,11 @@ DOCUMENTATION
srcdir="${src.dir}/compiler"
docRootContent="${src.dir}/compiler/rootdoc.txt"
addparams="${scalac.args.all}"
- implicits="on" diagrams="on" rawOutput="${scaladoc.raw.output}">
+ implicits="on"
+ diagrams="on"
+ groups="on"
+ rawOutput="${scaladoc.raw.output}"
+ noPrefixes="${scaladoc.no.prefixes}">
<include name="**/*.scala"/>
</scaladoc>
<touch file="${build-docs.dir}/compiler.complete" verbose="no"/>
@@ -2217,7 +2226,11 @@ DOCUMENTATION
classpathref="pack.classpath"
srcdir="${src.dir}/jline/src/main/java"
addparams="${scalac.args.all}"
- implicits="on" diagrams="on" rawOutput="${scaladoc.raw.output}">
+ implicits="on"
+ diagrams="on"
+ groups="on"
+ rawOutput="${scaladoc.raw.output}"
+ noPrefixes="${scaladoc.no.prefixes}">
<include name="**/*.scala"/>
<include name="**/*.java"/>
</scaladoc>
@@ -2241,7 +2254,11 @@ DOCUMENTATION
classpathref="pack.classpath"
srcdir="${src.dir}/scalap"
addparams="${scalac.args.all}"
- implicits="on" diagrams="on" rawOutput="${scaladoc.raw.output}">
+ implicits="on"
+ diagrams="on"
+ groups="on"
+ rawOutput="${scaladoc.raw.output}"
+ noPrefixes="${scaladoc.no.prefixes}">
<include name="**/*.scala"/>
</scaladoc>
<touch file="${build-docs.dir}/scalap.complete" verbose="no"/>
@@ -2263,7 +2280,11 @@ DOCUMENTATION
classpathref="pack.classpath"
srcdir="${src.dir}/partest"
addparams="${scalac.args.all}"
- implicits="on" diagrams="on" rawOutput="${scaladoc.raw.output}">
+ implicits="on"
+ diagrams="on"
+ groups="on"
+ rawOutput="${scaladoc.raw.output}"
+ noPrefixes="${scaladoc.no.prefixes}">
<include name="**/*.scala"/>
</scaladoc>
<touch file="${build-docs.dir}/partest.complete" verbose="no"/>
@@ -2285,7 +2306,11 @@ DOCUMENTATION
classpathref="pack.classpath"
srcdir="${src.dir}/continuations/plugin"
addparams="${scalac.args.all}"
- implicits="on" diagrams="on" rawOutput="${scaladoc.raw.output}">
+ implicits="on"
+ diagrams="on"
+ groups="on"
+ rawOutput="${scaladoc.raw.output}"
+ noPrefixes="${scaladoc.no.prefixes}">
<include name="**/*.scala"/>
</scaladoc>
<touch file="${build-docs.dir}/continuations-plugin.complete" verbose="no"/>
@@ -2307,7 +2332,11 @@ DOCUMENTATION
classpathref="pack.classpath"
srcdir="${src.dir}/actors-migration"
addparams="${scalac.args.all}"
- implicits="on" diagrams="on" rawOutput="${scaladoc.raw.output}">
+ implicits="on"
+ diagrams="on"
+ groups="on"
+ rawOutput="${scaladoc.raw.output}"
+ noPrefixes="${scaladoc.no.prefixes}">
<include name="**/*.scala"/>
</scaladoc>
<touch file="${build-docs.dir}/actors-migration.complete" verbose="no"/>
diff --git a/lib/scala-compiler-src.jar.desired.sha1 b/lib/scala-compiler-src.jar.desired.sha1
index 48b3d3284e..6840b60528 100644
--- a/lib/scala-compiler-src.jar.desired.sha1
+++ b/lib/scala-compiler-src.jar.desired.sha1
@@ -1 +1 @@
-259fd9f0a50ed6003248a01a366a97a5549aa386 ?scala-compiler-src.jar
+6a03de33fb670e1b1a9930234adb6d1d6435323d ?scala-compiler-src.jar
diff --git a/lib/scala-compiler.jar.desired.sha1 b/lib/scala-compiler.jar.desired.sha1
index a8dbdb0a38..393820f481 100644
--- a/lib/scala-compiler.jar.desired.sha1
+++ b/lib/scala-compiler.jar.desired.sha1
@@ -1 +1 @@
-42f7367cc6ac59022d098e6091e5425390b9c925 ?scala-compiler.jar
+cf6aab754bcf77ab433e2b05d1f452e13f24cedc ?scala-compiler.jar
diff --git a/lib/scala-library-src.jar.desired.sha1 b/lib/scala-library-src.jar.desired.sha1
index 3379287733..cefff7eec9 100644
--- a/lib/scala-library-src.jar.desired.sha1
+++ b/lib/scala-library-src.jar.desired.sha1
@@ -1 +1 @@
-e31e38414fd19c10add3e65bf77c2fd7c6c26f7d ?scala-library-src.jar
+02dcd8656f99eabbad8d9dce06a33d4f6f8d7c38 ?scala-library-src.jar
diff --git a/lib/scala-library.jar.desired.sha1 b/lib/scala-library.jar.desired.sha1
index bef528ce26..f7f2321177 100644
--- a/lib/scala-library.jar.desired.sha1
+++ b/lib/scala-library.jar.desired.sha1
@@ -1 +1 @@
-2418c95bf7db34f87ebda4a5eaa918fe85047afb ?scala-library.jar
+6a035e798a94c6ca051e6a7663293cfee3d7136f ?scala-library.jar
diff --git a/lib/scala-reflect-src.jar.desired.sha1 b/lib/scala-reflect-src.jar.desired.sha1
index b3a5f03efe..fb09e9d585 100644
--- a/lib/scala-reflect-src.jar.desired.sha1
+++ b/lib/scala-reflect-src.jar.desired.sha1
@@ -1 +1 @@
-51c64d77ad4c4233a06cea7ea80b0fb77e9867c4 ?scala-reflect-src.jar
+ecb9dd737935812a6399a3426e9126908ef870b2 ?scala-reflect-src.jar
diff --git a/lib/scala-reflect.jar.desired.sha1 b/lib/scala-reflect.jar.desired.sha1
index 4d913d73ab..dc5b7abd0e 100644
--- a/lib/scala-reflect.jar.desired.sha1
+++ b/lib/scala-reflect.jar.desired.sha1
@@ -1 +1 @@
-5656bf2f17bb9f22b3ba61a83393a9794eaa5429 ?scala-reflect.jar
+344f3feafa4bd155b13ba7a6ab3efd605f8f8388 ?scala-reflect.jar
diff --git a/src/compiler/scala/reflect/makro/runtime/Context.scala b/src/compiler/scala/reflect/makro/runtime/Context.scala
index c7563e7b67..68964b7abb 100644
--- a/src/compiler/scala/reflect/makro/runtime/Context.scala
+++ b/src/compiler/scala/reflect/makro/runtime/Context.scala
@@ -8,7 +8,6 @@ abstract class Context extends scala.reflect.makro.Context
with CapturedVariables
with Infrastructure
with Enclosures
- with Mirrors
with Names
with Reifiers
with FrontEnds
@@ -23,7 +22,7 @@ abstract class Context extends scala.reflect.makro.Context
val universe: Global
- val mirror: MirrorOf[universe.type] = new ContextMirror
+ val mirror: MirrorOf[universe.type] = universe.rootMirror
val callsiteTyper: universe.analyzer.Typer
diff --git a/src/compiler/scala/reflect/makro/runtime/ContextReifiers.scala b/src/compiler/scala/reflect/makro/runtime/ContextReifiers.scala
deleted file mode 100644
index 564148fe6c..0000000000
--- a/src/compiler/scala/reflect/makro/runtime/ContextReifiers.scala
+++ /dev/null
@@ -1,26 +0,0 @@
-package scala.reflect.makro
-package runtime
-
-abstract class ContextReifiers { self =>
- val c: Context
-
- import c.universe._
- import definitions._
- import treeBuild._
-
- import scala.reflect.reify.Taggers
- import language.implicitConversions
- private implicit def context2taggers(c0: Context) : Taggers { val c: c0.type } = new { val c: c0.type = c0 } with Taggers
-
- private def forMacroContext[T](prefix: Tree)(op: (Tree, Tree) => T): T = {
- val universe = gen.mkAttributedSelect(prefix.duplicate, MacroContextUniverse) setType SingleType(prefix.tpe, MacroContextUniverse)
- val mirror = TypeApply(Select(Select(prefix.duplicate, nme.mirror), nme.asInstanceOf_), List(Select(Ident(nme.UNIVERSE_SHORT), tpnme.Mirror)))
- op(universe, mirror)
- }
-
- def materializeExprForMacroContext(prefix: Tree, expr: Tree): Tree =
- forMacroContext(prefix)((universe, mirror) => c.materializeExpr(universe, mirror, expr))
-
- def materializeTypeTagForMacroContext(prefix: Tree, tpe: Type, concrete: Boolean): Tree =
- forMacroContext(prefix)((universe, mirror) => c.materializeTypeTag(universe, mirror, tpe, concrete))
-} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/makro/runtime/Enclosures.scala b/src/compiler/scala/reflect/makro/runtime/Enclosures.scala
index 80c35d22ff..360a4b8e8a 100644
--- a/src/compiler/scala/reflect/makro/runtime/Enclosures.scala
+++ b/src/compiler/scala/reflect/makro/runtime/Enclosures.scala
@@ -14,7 +14,6 @@ trait Enclosures {
// vals are eager to simplify debugging
// after all we wouldn't save that much time by making them lazy
val macroApplication: Tree = expandee
- val enclosingApplication: Tree = enclTrees collectFirst { case t: Apply => t } getOrElse EmptyTree
val enclosingClass: Tree = site.enclClass.tree
val enclosingImplicits: List[(Type, Tree)] = site.openImplicits
val enclosingMacros: List[Context] = this :: universe.analyzer.openMacros // include self
diff --git a/src/compiler/scala/reflect/makro/runtime/Mirrors.scala b/src/compiler/scala/reflect/makro/runtime/Mirrors.scala
deleted file mode 100644
index ec970ee696..0000000000
--- a/src/compiler/scala/reflect/makro/runtime/Mirrors.scala
+++ /dev/null
@@ -1,43 +0,0 @@
-package scala.reflect.makro
-package runtime
-
-import scala.tools.nsc.util.ScalaClassLoader
-
-trait Mirrors {
- self: Context =>
-
- import universe._
- import definitions._
-
- class ContextMirror extends RootsBase(NoSymbol) {
- val universe: self.universe.type = self.universe
- def rootLoader: LazyType = rootMirror.rootLoader
-
- val RootPackage = rootMirror.RootPackage
- val RootClass = rootMirror.RootClass
- val EmptyPackage = rootMirror.EmptyPackage
- val EmptyPackageClass = rootMirror.EmptyPackageClass
-
- // [Eugene++] this still doesn't solve the problem of invoking `c.typeCheck` on the code that refers to packageless symbols
- override protected def mirrorMissingHook(owner: Symbol, name: Name): Symbol = {
- if (owner.isRoot && isJavaClass(name.toString)) EmptyPackageClass.info decl name
- else NoSymbol
- }
-
- private lazy val libraryClasspathLoader: ClassLoader = {
- val classpath = platform.classPath.asURLs
- ScalaClassLoader.fromURLs(classpath)
- }
-
- private def isJavaClass(path: String): Boolean =
- try {
- Class.forName(path, true, libraryClasspathLoader)
- true
- } catch {
- case (_: ClassNotFoundException) | (_: NoClassDefFoundError) | (_: IncompatibleClassChangeError) =>
- false
- }
-
- override def toString = "macro context mirror"
- }
-} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/reify/Taggers.scala b/src/compiler/scala/reflect/reify/Taggers.scala
index e09f13a052..4e30d0acf8 100644
--- a/src/compiler/scala/reflect/reify/Taggers.scala
+++ b/src/compiler/scala/reflect/reify/Taggers.scala
@@ -37,23 +37,21 @@ abstract class Taggers {
}
def materializeTypeTag(universe: Tree, mirror: Tree, tpe: Type, concrete: Boolean): Tree = {
- if (universe.symbol == MacroContextUniverse && mirror == EmptyTree) {
- import scala.reflect.makro.runtime.ContextReifiers
- import language.implicitConversions
- implicit def context2contextreifiers(c0: Context) : ContextReifiers { val c: c0.type } = new { val c: c0.type = c0 } with ContextReifiers
- val Select(prefix, _) = universe
- c.materializeTypeTagForMacroContext(prefix, tpe, concrete)
- } else {
- val tagType = if (concrete) TypeTagClass else AbsTypeTagClass
- val unaffiliatedTagTpe = TypeRef(BaseUniverseClass.asTypeConstructor, tagType, List(tpe))
- val unaffiliatedTag = c.inferImplicitValue(unaffiliatedTagTpe, silent = true, withMacrosDisabled = true)
- unaffiliatedTag match {
- case success if !success.isEmpty =>
- Apply(Select(success, nme.in), List(mirror orElse mkDefaultMirrorRef(c.universe)(universe, c.callsiteTyper)))
- case _ =>
- val tagModule = if (concrete) TypeTagModule else AbsTypeTagModule
- materializeTag(universe, tpe, tagModule, c.reifyType(universe, mirror, tpe, concrete = concrete))
- }
+ val tagType = if (concrete) TypeTagClass else AbsTypeTagClass
+ // what we need here is to compose a type BaseUniverse # TypeTag[$tpe]
+ // to look for an implicit that conforms to this type
+ // that's why neither appliedType(tagType, List(tpe)) aka TypeRef(TypeTagsClass.thisType, tagType, List(tpe))
+ // nor TypeRef(BaseUniverseClass.thisType, tagType, List(tpe)) won't fit here
+ // scala> :type -v def foo: scala.reflect.base.Universe#TypeTag[Int] = ???
+ // NullaryMethodType(TypeRef(pre = TypeRef(TypeSymbol(Universe)), TypeSymbol(TypeTag), args = List($tpe))))
+ val unaffiliatedTagTpe = TypeRef(BaseUniverseClass.typeConstructor, tagType, List(tpe))
+ val unaffiliatedTag = c.inferImplicitValue(unaffiliatedTagTpe, silent = true, withMacrosDisabled = true)
+ unaffiliatedTag match {
+ case success if !success.isEmpty =>
+ Apply(Select(success, nme.in), List(mirror orElse mkDefaultMirrorRef(c.universe)(universe, c.callsiteTyper)))
+ case _ =>
+ val tagModule = if (concrete) TypeTagModule else AbsTypeTagModule
+ materializeTag(universe, tpe, tagModule, c.reifyType(universe, mirror, tpe, concrete = concrete))
}
}
diff --git a/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala b/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala
index 9b0777580b..38c8fedac5 100644
--- a/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala
+++ b/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala
@@ -37,10 +37,40 @@ trait GenSymbols {
mirrorMirrorSelect(nme.EmptyPackageClass)
else if (sym.isModuleClass)
Select(Select(reify(sym.sourceModule), nme.asModuleSymbol), nme.moduleClass)
+ else if (sym.isPackage)
+ mirrorMirrorCall(nme.staticPackage, reify(sym.fullName))
else if (sym.isLocatable) {
- // [Eugene] am I doing this right?
-// if (sym.isStaticOwner) { // no good for us, because it returns false for packages
- if (sym.isStatic && (sym.isClass || sym.isModule)) {
+ /** This is a fancy conundrum that stems from the fact that Scala allows
+ * packageless packages and packageless objects with the same names in the same program.
+ *
+ * For more details read the docs to staticModule and staticPackage.
+ * Here I'll just provide the examples of how reify works for different kinds of symbols.
+ *
+ * // 1) packageless
+ * // packageless classes are non-ambiguous, but modules vs packages might be
+ * // that's why we have separate methods to reify those
+ * // note that staticModule will never resolve to a package if an object is missing and an homonymous package is present and vice versa
+ * // otherwise reification would be unsound
+ * class C => staticClass("C")
+ * object B => staticModule("B")
+ * package B => staticPackage("B")
+ *
+ * // 2) classes and modules enclosed in a package
+ * // staticXXX methods always look into parent packages and ignores parent modules, so for fully qualified names they are non-ambiguous
+ * // namely even if there's an object B { class C } next to package B { class C }, then staticClass("B.C") will resolve to a packageful class
+ * // this closely mirrors Scala's behavior, read up the docs to staticModule/staticPackage for more information
+ * package B { class C } => staticClass("B.C")
+ * package B { object B } => staticModule("B.B")
+ * package B { package B } => staticPackage("B.B")
+ *
+ * // 3) classes and modules enclosed in a packageless module
+ * // staticClass/staticModule won't look into EmptyPackageClass, so we reify such symbols in a roundabout way
+ * object B { class C } => selectType(staticModule("B"), "C")
+ * object B { object B } => selectType(staticModule("B"), "B")
+ * object B { package B } => impossible
+ */
+ val hasPackagelessParent = sym.ownerChain.tail.tail exists (_.isEmptyPackageClass)
+ if (sym.isStatic && (sym.isClass || sym.isModule) && !hasPackagelessParent) {
val resolver = if (sym.isType) nme.staticClass else nme.staticModule
mirrorMirrorCall(resolver, reify(sym.fullName))
} else {
diff --git a/src/compiler/scala/reflect/reify/codegen/GenTypes.scala b/src/compiler/scala/reflect/reify/codegen/GenTypes.scala
index 82951a2434..c49e5b3342 100644
--- a/src/compiler/scala/reflect/reify/codegen/GenTypes.scala
+++ b/src/compiler/scala/reflect/reify/codegen/GenTypes.scala
@@ -41,8 +41,7 @@ trait GenTypes {
case tpe @ ThisType(empty) if empty.isEmptyPackageClass =>
mirrorBuildCall(nme.thisPrefix, mirrorMirrorSelect(nme.EmptyPackageClass))
case tpe @ ThisType(clazz) if clazz.isModuleClass && clazz.isStatic =>
- // [Eugene++ to Martin] makes sense?
- val module = mirrorMirrorCall(nme.staticModule, reify(clazz.fullName))
+ val module = reify(clazz.sourceModule)
val moduleClass = Select(Select(module, nme.asModuleSymbol), nme.moduleClass)
mirrorFactoryCall(nme.ThisType, moduleClass)
case tpe @ ThisType(_) =>
diff --git a/src/compiler/scala/reflect/reify/utils/Extractors.scala b/src/compiler/scala/reflect/reify/utils/Extractors.scala
index 52e4ff08c1..86265ec77a 100644
--- a/src/compiler/scala/reflect/reify/utils/Extractors.scala
+++ b/src/compiler/scala/reflect/reify/utils/Extractors.scala
@@ -27,7 +27,7 @@ trait Extractors {
// def applyImpl[U >: Nothing <: scala.reflect.api.Universe with Singleton]($m$untyped: scala.reflect.base.MirrorOf[U]): U#Tree = {
// val $u: U = $m$untyped.universe;
// val $m: $u.Mirror = $m$untyped.asInstanceOf[$u.Mirror];
- // $u.Apply($u.Select($u.Select($u.build.This($m.staticModule("scala.collection.immutable").moduleClass), $u.newTermName("List")), $u.newTermName("apply")), List($u.Literal($u.Constant(1)), $u.Literal($u.Constant(2))))
+ // $u.Apply($u.Select($u.Select($u.build.This($m.staticPackage("scala.collection.immutable").moduleClass), $u.newTermName("List")), $u.newTermName("apply")), List($u.Literal($u.Constant(1)), $u.Literal($u.Constant(2))))
// }
// };
// new $treecreator1()
@@ -40,7 +40,7 @@ trait Extractors {
// def apply[U >: Nothing <: scala.reflect.base.Universe with Singleton]($m$untyped: scala.reflect.base.MirrorOf[U]): U#Type = {
// val $u: U = $m$untyped.universe;
// val $m: $u.Mirror = $m$untyped.asInstanceOf[$u.Mirror];
- // $u.TypeRef($u.ThisType($m.staticModule("scala.collection.immutable").moduleClass), $m.staticClass("scala.collection.immutable.List"), List($m.staticClass("scala.Int").asTypeConstructor))
+ // $u.TypeRef($u.ThisType($m.staticPackage("scala.collection.immutable").moduleClass), $m.staticClass("scala.collection.immutable.List"), List($m.staticClass("scala.Int").asTypeConstructor))
// }
// };
// new $typecreator1()
diff --git a/src/compiler/scala/tools/ant/FastScalac.scala b/src/compiler/scala/tools/ant/FastScalac.scala
index c0d7441ad5..f146722087 100644
--- a/src/compiler/scala/tools/ant/FastScalac.scala
+++ b/src/compiler/scala/tools/ant/FastScalac.scala
@@ -159,7 +159,7 @@ class FastScalac extends Scalac {
val url = ScalaClassLoader.originOfClass(classOf[FastScalac]).get
File(url.getFile).jfile.getParentFile.getParentFile.getAbsolutePath
} catch {
- case _ =>
+ case _: Throwable =>
buildError("Compilation failed because of an internal compiler error;"+
" couldn't determine value for -Dscala.home=<value>")
}
diff --git a/src/compiler/scala/tools/ant/Scalac.scala b/src/compiler/scala/tools/ant/Scalac.scala
index e70716885e..c6809fb48e 100644
--- a/src/compiler/scala/tools/ant/Scalac.scala
+++ b/src/compiler/scala/tools/ant/Scalac.scala
@@ -99,7 +99,7 @@ class Scalac extends ScalaMatchingTask with ScalacShared {
/** Defines valid values for the `target` property. */
object Target extends PermissibleValue {
- val values = List("jvm-1.5", "jvm-1.6", "jvm-1.7", "msil")
+ val values = List("jvm-1.5", "jvm-1.5-fjbg", "jvm-1.5-asm", "jvm-1.6", "jvm-1.7", "msil")
}
/** Defines valid values for the `deprecation` and `unchecked` properties. */
diff --git a/src/compiler/scala/tools/ant/Scaladoc.scala b/src/compiler/scala/tools/ant/Scaladoc.scala
index 2cada92c1e..b96ac6f29b 100644
--- a/src/compiler/scala/tools/ant/Scaladoc.scala
+++ b/src/compiler/scala/tools/ant/Scaladoc.scala
@@ -153,6 +153,11 @@ class Scaladoc extends ScalaMatchingTask {
/** Instruct the scaladoc to produce textual ouput from html pages, for easy diff-ing */
private var docRawOutput: Boolean = false
+ /** Instruct the scaladoc not to generate prefixes */
+ private var docNoPrefixes: Boolean = false
+
+ /** Instruct the scaladoc tool to group similar functions together */
+ private var docGroups: Boolean = false
/*============================================================================*\
** Properties setters **
@@ -427,6 +432,16 @@ class Scaladoc extends ScalaMatchingTask {
def setRawOutput(input: String) =
docRawOutput = Flag.getBooleanValue(input, "rawOutput")
+ /** Set the `noPrefixes` bit to prevent Scaladoc from generating prefixes in
+ * front of types -- may lead to confusion, but significantly speeds up the generation.
+ * @param input One of the flags `yes/no` or `on/off`. Default if no/off. */
+ def setNoPrefixes(input: String) =
+ docNoPrefixes = Flag.getBooleanValue(input, "noPrefixes")
+
+ /** Instruct the scaladoc tool to group similar functions together */
+ def setGroups(input: String) =
+ docGroups = Flag.getBooleanValue(input, "groups")
+
/*============================================================================*\
** Properties getters **
\*============================================================================*/
@@ -625,6 +640,8 @@ class Scaladoc extends ScalaMatchingTask {
docSettings.docDiagrams.value = docDiagrams
docSettings.docDiagramsDebug.value = docDiagramsDebug
docSettings.docRawOutput.value = docRawOutput
+ docSettings.docNoPrefixes.value = docNoPrefixes
+ docSettings.docGroups.value = docGroups
if(!docDiagramsDotPath.isEmpty) docSettings.docDiagramsDotPath.value = docDiagramsDotPath.get
if (!docgenerator.isEmpty) docSettings.docgenerator.value = docgenerator.get
@@ -658,15 +675,10 @@ class Scaladoc extends ScalaMatchingTask {
"; see the documenter output for details.")
reporter.printSummary()
} catch {
- case exception: Throwable if exception.getMessage ne null =>
- exception.printStackTrace()
- safeBuildError("Document failed because of an internal documenter error (" +
- exception.getMessage + "); see the error output for details.")
- case exception =>
+ case exception: Throwable =>
exception.printStackTrace()
- safeBuildError("Document failed because of an internal documenter error " +
- "(no error message provided); see the error output for details.")
+ val msg = Option(exception.getMessage) getOrElse "no error message provided"
+ safeBuildError(s"Document failed because of an internal documenter error ($msg); see the error output for details.")
}
}
-
}
diff --git a/src/compiler/scala/tools/cmd/FromString.scala b/src/compiler/scala/tools/cmd/FromString.scala
index 29f1baaa0c..415940b3fd 100644
--- a/src/compiler/scala/tools/cmd/FromString.scala
+++ b/src/compiler/scala/tools/cmd/FromString.scala
@@ -8,7 +8,7 @@ package cmd
import nsc.io.{ Path, File, Directory }
import scala.reflect.runtime.{universe => ru}
-import scala.tools.reflect.StdTags._
+import scala.tools.reflect.StdRuntimeTags._
/** A general mechanism for defining how a command line argument
* (always a String) is transformed into an arbitrary type. A few
diff --git a/src/compiler/scala/tools/nsc/CompileServer.scala b/src/compiler/scala/tools/nsc/CompileServer.scala
index fd59319c14..fb278db2bf 100644
--- a/src/compiler/scala/tools/nsc/CompileServer.scala
+++ b/src/compiler/scala/tools/nsc/CompileServer.scala
@@ -154,7 +154,7 @@ class StandardCompileServer extends SocketServer {
case ex @ FatalError(msg) =>
reporter.error(null, "fatal error: " + msg)
clearCompiler()
- case ex =>
+ case ex: Throwable =>
warn("Compile server encountered fatal condition: " + ex)
shutdown = true
throw ex
diff --git a/src/compiler/scala/tools/nsc/Driver.scala b/src/compiler/scala/tools/nsc/Driver.scala
index 0051c3bdec..1775602122 100644
--- a/src/compiler/scala/tools/nsc/Driver.scala
+++ b/src/compiler/scala/tools/nsc/Driver.scala
@@ -1,10 +1,12 @@
package scala.tools.nsc
import scala.tools.nsc.reporters.{Reporter, ConsoleReporter}
-import Properties.{ versionString, copyrightString }
+import Properties.{ versionString, copyrightString, residentPromptString }
import scala.reflect.internal.util.{ BatchSourceFile, FakePos }
abstract class Driver {
+
+ val prompt = residentPromptString
val versionMsg = "Scala compiler " +
versionString + " -- " +
@@ -51,7 +53,7 @@ abstract class Driver {
else
doCompile(compiler)
} catch {
- case ex =>
+ case ex: Throwable =>
compiler.logThrowable(ex)
ex match {
case FatalError(msg) => reporter.error(null, "fatal error: " + msg)
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 6a61beb55d..e07702fc41 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -1401,6 +1401,8 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
settings.userSetSettings filter (_.isDeprecated) foreach { s =>
unit.deprecationWarning(NoPosition, s.name + " is deprecated: " + s.deprecationMessage.get)
}
+ if (settings.target.value.contains("jvm-1.5"))
+ unit.deprecationWarning(NoPosition, settings.target.name + ":" + settings.target.value + " is deprecated: use target for Java 1.6 or above.")
}
/* An iterator returning all the units being compiled in this run */
diff --git a/src/compiler/scala/tools/nsc/Main.scala b/src/compiler/scala/tools/nsc/Main.scala
index 19c872b6d3..8b7e76e994 100644
--- a/src/compiler/scala/tools/nsc/Main.scala
+++ b/src/compiler/scala/tools/nsc/Main.scala
@@ -12,15 +12,13 @@ import scala.tools.nsc.interactive.{ RefinedBuildManager, SimpleBuildManager }
import scala.tools.nsc.io.AbstractFile
import scala.tools.nsc.reporters.{Reporter, ConsoleReporter}
import scala.reflect.internal.util.{ BatchSourceFile, FakePos } //{Position}
-import Properties.{ versionString, copyrightString, residentPromptString, msilLibPath }
+import Properties.msilLibPath
/** The main class for NSC, a compiler for the programming
- * language Scala.
+ * language Scala.
*/
object Main extends Driver with EvalLoop {
- val prompt = residentPromptString
-
def resident(compiler: Global) {
loop { line =>
val args = line.split(' ').toList
diff --git a/src/compiler/scala/tools/nsc/MainBench.scala b/src/compiler/scala/tools/nsc/MainBench.scala
new file mode 100644
index 0000000000..0037de7b94
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/MainBench.scala
@@ -0,0 +1,48 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.tools.nsc
+
+import java.io.File
+import File.pathSeparator
+
+import scala.tools.nsc.interactive.{ RefinedBuildManager, SimpleBuildManager }
+import scala.tools.nsc.io.AbstractFile
+import scala.tools.nsc.reporters.{Reporter, ConsoleReporter}
+import scala.reflect.internal.util.{ BatchSourceFile, FakePos } //{Position}
+import Properties.{ versionString, copyrightString, residentPromptString, msilLibPath }
+import scala.reflect.internal.util.Statistics
+
+/** The main class for NSC, a compiler for the programming
+ * language Scala.
+ */
+object MainBench extends Driver with EvalLoop {
+
+ lazy val theCompiler = Global(settings, reporter)
+
+ override def newCompiler() = theCompiler
+
+ val NIter = 50
+ val NBest = 10
+
+ override def main(args: Array[String]) = {
+ val times = new Array[Long](NIter)
+ var start = System.nanoTime()
+ for (i <- 0 until NIter) {
+ if (i == NIter-1) {
+ theCompiler.settings.Ystatistics.value = true
+ Statistics.enabled = true
+ }
+ process(args)
+ val end = System.nanoTime()
+ val duration = (end-start)/1000000
+ println(s"${duration}ms")
+ times(i) = duration
+ start = end
+ }
+ val avg = times.sorted.take(NBest).sum / NBest
+ println(s"avg shortest $NBest times ${avg}ms")
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/ObjectRunner.scala b/src/compiler/scala/tools/nsc/ObjectRunner.scala
index 110de7aad5..24ae0089a2 100644
--- a/src/compiler/scala/tools/nsc/ObjectRunner.scala
+++ b/src/compiler/scala/tools/nsc/ObjectRunner.scala
@@ -33,7 +33,7 @@ trait CommonRunner {
*/
def runAndCatch(urls: List[URL], objectName: String, arguments: Seq[String]): Either[Throwable, Boolean] = {
try { run(urls, objectName, arguments) ; Right(true) }
- catch { case e => Left(unwrap(e)) }
+ catch { case e: Throwable => Left(unwrap(e)) }
}
}
diff --git a/src/compiler/scala/tools/nsc/ScriptRunner.scala b/src/compiler/scala/tools/nsc/ScriptRunner.scala
index dd9bca4b7b..14c508548a 100644
--- a/src/compiler/scala/tools/nsc/ScriptRunner.scala
+++ b/src/compiler/scala/tools/nsc/ScriptRunner.scala
@@ -199,7 +199,7 @@ class ScriptRunner extends HasCompileSocket {
scriptArgs: List[String]): Either[Throwable, Boolean] =
{
try Right(runScript(settings, scriptFile, scriptArgs))
- catch { case e => Left(unwrap(e)) }
+ catch { case e: Throwable => Left(unwrap(e)) }
}
/** Run a command
diff --git a/src/compiler/scala/tools/nsc/ast/DocComments.scala b/src/compiler/scala/tools/nsc/ast/DocComments.scala
index b545140c4a..d0d0b4b5f4 100755
--- a/src/compiler/scala/tools/nsc/ast/DocComments.scala
+++ b/src/compiler/scala/tools/nsc/ast/DocComments.scala
@@ -171,15 +171,15 @@ trait DocComments { self: Global =>
* 3. If there is no @return section in `dst` but there is one in `src`, copy it.
*/
def merge(src: String, dst: String, sym: Symbol, copyFirstPara: Boolean = false): String = {
- val srcSections = tagIndex(src)
- val dstSections = tagIndex(dst)
- val srcParams = paramDocs(src, "@param", srcSections)
- val dstParams = paramDocs(dst, "@param", dstSections)
- val srcTParams = paramDocs(src, "@tparam", srcSections)
- val dstTParams = paramDocs(dst, "@tparam", dstSections)
- val out = new StringBuilder
- var copied = 0
- var tocopy = startTag(dst, dstSections dropWhile (!isMovable(dst, _)))
+ val srcSections = tagIndex(src)
+ val dstSections = tagIndex(dst)
+ val srcParams = paramDocs(src, "@param", srcSections)
+ val dstParams = paramDocs(dst, "@param", dstSections)
+ val srcTParams = paramDocs(src, "@tparam", srcSections)
+ val dstTParams = paramDocs(dst, "@tparam", dstSections)
+ val out = new StringBuilder
+ var copied = 0
+ var tocopy = startTag(dst, dstSections dropWhile (!isMovable(dst, _)))
if (copyFirstPara) {
val eop = // end of comment body (first para), which is delimited by blank line, or tag, or end of comment
@@ -209,6 +209,7 @@ trait DocComments { self: Global =>
for (tparam <- sym.typeParams)
mergeSection(srcTParams get tparam.name.toString, dstTParams get tparam.name.toString)
mergeSection(returnDoc(src, srcSections), returnDoc(dst, dstSections))
+ mergeSection(groupDoc(src, srcSections), groupDoc(dst, dstSections))
if (out.length == 0) dst
else {
@@ -457,22 +458,16 @@ trait DocComments { self: Global =>
case List() => NoType
case site :: sites1 => select(site.thisType, name, findIn(sites1))
}
- val (classes, pkgs) = site.ownerChain.span(!_.isPackageClass)
- findIn(classes ::: List(pkgs.head, rootMirror.RootClass))
+ // Previously, searching was taking place *only* in the current package and in the root package
+ // now we're looking for it everywhere in the hierarchy, so we'll be able to link variable expansions like
+ // immutable.Seq in package immutable
+ //val (classes, pkgs) = site.ownerChain.span(!_.isPackageClass)
+ //val sites = (classes ::: List(pkgs.head, rootMirror.RootClass)))
+ //findIn(sites)
+ findIn(site.ownerChain ::: List(definitions.EmptyPackage))
}
- def getType(_str: String, variable: String): Type = {
- /*
- * work around the backticks issue suggested by Simon in
- * https://groups.google.com/forum/?hl=en&fromgroups#!topic/scala-internals/z7s1CCRCz74
- * ideally, we'd have a removeWikiSyntax method in the CommentFactory to completely eliminate the wiki markup
- */
- val str =
- if (_str.length >= 2 && _str.startsWith("`") && _str.endsWith("`"))
- _str.substring(1, _str.length - 2)
- else
- _str
-
+ def getType(str: String, variable: String): Type = {
def getParts(start: Int): List[String] = {
val end = skipIdent(str, start)
if (end == start) List()
@@ -484,7 +479,7 @@ trait DocComments { self: Global =>
val parts = getParts(0)
if (parts.isEmpty) {
reporter.error(comment.codePos, "Incorrect variable expansion for " + variable + " in use case. Does the " +
- "variable expand to wiki syntax when documenting " + site + "?")
+ "variable expand to wiki syntax when documenting " + site + "?")
return ErrorType
}
val partnames = (parts.init map newTermName) :+ newTypeName(parts.last)
@@ -498,25 +493,46 @@ trait DocComments { self: Global =>
case _ =>
(getSite(partnames.head), partnames.tail)
}
- (start /: rest)(select(_, _, NoType))
+ val result = (start /: rest)(select(_, _, NoType))
+ if (result == NoType)
+ reporter.warning(comment.codePos, "Could not find the type " + variable + " points to while expanding it " +
+ "for the usecase signature of " + sym + " in " + site + "." +
+ "In this context, " + variable + " = \"" + str + "\".")
+ result
+ }
+
+ /**
+ * work around the backticks issue suggested by Simon in
+ * https://groups.google.com/forum/?hl=en&fromgroups#!topic/scala-internals/z7s1CCRCz74
+ * ideally, we'd have a removeWikiSyntax method in the CommentFactory to completely eliminate the wiki markup
+ */
+ def cleanupVariable(str: String) = {
+ val tstr = str.trim
+ if (tstr.length >= 2 && tstr.startsWith("`") && tstr.endsWith("`"))
+ tstr.substring(1, tstr.length - 1)
+ else
+ tstr
}
- val aliasExpansions: List[Type] =
+ // the Boolean tells us whether we can normalize: if we found an actual type, then yes, we can normalize, else no,
+ // use the synthetic alias created for the variable
+ val aliasExpansions: List[(Type, Boolean)] =
for (alias <- aliases) yield
lookupVariable(alias.name.toString.substring(1), site) match {
case Some(repl) =>
- val tpe = getType(repl.trim, alias.name.toString)
- if (tpe != NoType) tpe
+ val repl2 = cleanupVariable(repl)
+ val tpe = getType(repl2, alias.name.toString)
+ if (tpe != NoType) (tpe, true)
else {
- val alias1 = alias.cloneSymbol(rootMirror.RootClass, alias.rawflags, newTypeName(repl))
- typeRef(NoPrefix, alias1, Nil)
+ val alias1 = alias.cloneSymbol(rootMirror.RootClass, alias.rawflags, newTypeName(repl2))
+ (typeRef(NoPrefix, alias1, Nil), false)
}
case None =>
- typeRef(NoPrefix, alias, Nil)
+ (typeRef(NoPrefix, alias, Nil), false)
}
- def subst(sym: Symbol, from: List[Symbol], to: List[Type]): Type =
- if (from.isEmpty) sym.tpe
+ def subst(sym: Symbol, from: List[Symbol], to: List[(Type, Boolean)]): (Type, Boolean) =
+ if (from.isEmpty) (sym.tpe, false)
else if (from.head == sym) to.head
else subst(sym, from.tail, to.tail)
@@ -524,8 +540,9 @@ trait DocComments { self: Global =>
def apply(tp: Type) = mapOver(tp) match {
case tp1 @ TypeRef(pre, sym, args) if (sym.name.length > 1 && sym.name.startChar == '$') =>
subst(sym, aliases, aliasExpansions) match {
- case TypeRef(pre1, sym1, _) =>
- typeRef(pre1, sym1, args)
+ case (TypeRef(pre1, sym1, _), canNormalize) =>
+ val tpe = typeRef(pre1, sym1, args)
+ if (canNormalize) tpe.normalize else tpe
case _ =>
tp1
}
diff --git a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
index f88e41375d..e02d605965 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
@@ -140,7 +140,7 @@ abstract class TreeBrowsers {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel")
}
catch {
- case _ => UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName())
+ case _: Throwable => UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName())
}
val frame = new JFrame("Scala AST after " + phaseName + " phase")
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index e0c9631246..cde971085d 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -1169,7 +1169,12 @@ self =>
if (inPattern) dropAnyBraces(pattern())
else {
if (in.token == IDENTIFIER) atPos(in.offset)(Ident(ident()))
- else expr()
+ else if(in.token == LBRACE) expr()
+ else if(in.token == THIS) { in.nextToken(); atPos(in.offset)(This(tpnme.EMPTY)) }
+ else {
+ syntaxErrorOrIncomplete("error in interpolated string: identifier or block expected", true)
+ EmptyTree
+ }
}
}
}
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
index f1baeca8d0..1de510747d 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
@@ -729,8 +729,12 @@ trait Scanners extends ScannersCommon {
next.token = IDENTIFIER
next.name = newTermName(cbuf.toString)
cbuf.clear()
+ val idx = next.name.start - kwOffset
+ if (idx >= 0 && idx < kwArray.length) {
+ next.token = kwArray(idx)
+ }
} else {
- syntaxError("invalid string interpolation")
+ syntaxError("invalid string interpolation: `$$', `$'ident or `$'BlockExpr expected")
}
} else {
val isUnclosedLiteral = !isUnicodeEscape && (ch == SU || (!multiLine && (ch == CR || ch == LF)))
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index b638745327..982267097b 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -113,26 +113,42 @@ abstract class GenICode extends SubComponent {
m.native = m.symbol.hasAnnotation(definitions.NativeAttr)
if (!m.isAbstractMethod && !m.native) {
- ctx1 = genLoad(rhs, ctx1, m.returnType);
-
- // reverse the order of the local variables, to match the source-order
- m.locals = m.locals.reverse
-
- rhs match {
- case Block(_, Return(_)) => ()
- case Return(_) => ()
- case EmptyTree =>
- globalError("Concrete method has no definition: " + tree + (
- if (settings.debug.value) "(found: " + m.symbol.owner.info.decls.toList.mkString(", ") + ")"
- else "")
- )
- case _ => if (ctx1.bb.isEmpty)
- ctx1.bb.closeWith(RETURN(m.returnType), rhs.pos)
- else
+ if (m.symbol.isAccessor && m.symbol.accessed.hasStaticAnnotation) {
+ // in companion object accessors to @static fields, we access the static field directly
+ val hostClass = m.symbol.owner.companionClass
+ val staticfield = hostClass.info.findMember(m.symbol.accessed.name, NoFlags, NoFlags, false)
+
+ if (m.symbol.isGetter) {
+ ctx1.bb.emit(LOAD_FIELD(staticfield, true) setHostClass hostClass, tree.pos)
ctx1.bb.closeWith(RETURN(m.returnType))
+ } else if (m.symbol.isSetter) {
+ ctx1.bb.emit(LOAD_LOCAL(m.locals.head), tree.pos)
+ ctx1.bb.emit(STORE_FIELD(staticfield, true), tree.pos)
+ ctx1.bb.closeWith(RETURN(m.returnType))
+ } else assert(false, "unreachable")
+ } else {
+ ctx1 = genLoad(rhs, ctx1, m.returnType);
+
+ // reverse the order of the local variables, to match the source-order
+ m.locals = m.locals.reverse
+
+ rhs match {
+ case Block(_, Return(_)) => ()
+ case Return(_) => ()
+ case EmptyTree =>
+ globalError("Concrete method has no definition: " + tree + (
+ if (settings.debug.value) "(found: " + m.symbol.owner.info.decls.toList.mkString(", ") + ")"
+ else "")
+ )
+ case _ =>
+ if (ctx1.bb.isEmpty)
+ ctx1.bb.closeWith(RETURN(m.returnType), rhs.pos)
+ else
+ ctx1.bb.closeWith(RETURN(m.returnType))
+ }
+ if (!ctx1.bb.closed) ctx1.bb.close
+ prune(ctx1.method)
}
- if (!ctx1.bb.closed) ctx1.bb.close
- prune(ctx1.method)
} else
ctx1.method.setCode(NoCode)
ctx1
@@ -854,9 +870,32 @@ abstract class GenICode extends SubComponent {
generatedType = toTypeKind(fun.symbol.tpe.resultType)
ctx1
+ case app @ Apply(fun @ Select(qual, _), args)
+ if !ctx.method.symbol.isStaticConstructor
+ && fun.symbol.isAccessor && fun.symbol.accessed.hasStaticAnnotation =>
+ // bypass the accessor to the companion object and load the static field directly
+ // the only place were this bypass is not done, is the static intializer for the static field itself
+ val sym = fun.symbol
+ generatedType = toTypeKind(sym.accessed.info)
+ val hostClass = qual.tpe.typeSymbol.orElse(sym.owner).companionClass
+ val staticfield = hostClass.info.findMember(sym.accessed.name, NoFlags, NoFlags, false)
+
+ if (sym.isGetter) {
+ ctx.bb.emit(LOAD_FIELD(staticfield, true) setHostClass hostClass, tree.pos)
+ ctx
+ } else if (sym.isSetter) {
+ val ctx1 = genLoadArguments(args, sym.info.paramTypes, ctx)
+ ctx1.bb.emit(STORE_FIELD(staticfield, true), tree.pos)
+ ctx1.bb.emit(CONSTANT(Constant(false)), tree.pos)
+ ctx1
+ } else {
+ assert(false, "supposedly unreachable")
+ ctx
+ }
+
case app @ Apply(fun, args) =>
val sym = fun.symbol
-
+
if (sym.isLabel) { // jump to a label
val label = ctx.labels.getOrElse(sym, {
// it is a forward jump, scan for labels
@@ -1623,8 +1662,12 @@ abstract class GenICode extends SubComponent {
* backend emits them as static).
* No code is needed for this module symbol.
*/
- for (f <- cls.info.decls ; if !f.isMethod && f.isTerm && !f.isModule)
+ for (
+ f <- cls.info.decls;
+ if !f.isMethod && f.isTerm && !f.isModule && !(f.owner.isModuleClass && f.hasStaticAnnotation)
+ ) {
ctx.clazz addField new IField(f)
+ }
}
/**
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
index eb9b4b7dd3..1b4b4334bb 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
@@ -598,7 +598,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
reverseJavaName.put(internalName, trackedSym)
case Some(oldsym) =>
assert((oldsym == trackedSym) || (oldsym == RuntimeNothingClass) || (oldsym == RuntimeNullClass), // In contrast, neither NothingClass nor NullClass show up bytecode-level.
- "how can getCommonSuperclass() do its job if different class symbols get the same bytecode-level internal name.")
+ "how can getCommonSuperclass() do its job if different class symbols get the same bytecode-level internal name: " + internalName)
}
}
@@ -877,7 +877,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
def wrap(op: => Unit) = {
try { op; true }
- catch { case _ => false }
+ catch { case _: Throwable => false }
}
if (settings.Xverify.value) {
@@ -1170,7 +1170,9 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
log("No forwarder for " + m + " due to conflict with " + linkedClass.info.member(m.name))
else {
log("Adding static forwarder for '%s' from %s to '%s'".format(m, jclassName, moduleClass))
- addForwarder(isRemoteClass, jclass, moduleClass, m)
+ if (m.isAccessor && m.accessed.hasStaticAnnotation) {
+ log("@static: accessor " + m + ", accessed: " + m.accessed)
+ } else addForwarder(isRemoteClass, jclass, moduleClass, m)
}
}
}
@@ -1675,6 +1677,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
jmethod = clinitMethod
jMethodName = CLASS_CONSTRUCTOR_NAME
jmethod.visitCode()
+ computeLocalVarsIndex(m)
genCode(m, false, true)
jmethod.visitMaxs(0, 0) // just to follow protocol, dummy arguments
jmethod.visitEnd()
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index 280afb441f..62b5d69cff 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -1021,6 +1021,8 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
method = m
jmethod = clinitMethod
+
+ computeLocalVarsIndex(m)
genCode(m)
case None =>
legacyStaticInitializer(cls, clinit)
@@ -1114,7 +1116,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
linkedClass.info.members collect { case sym if sym.name.isTermName => sym.name } toSet
}
debuglog("Potentially conflicting names for forwarders: " + conflictingNames)
-
+
for (m <- moduleClass.info.membersBasedOnFlags(ExcludedForwarderFlags, Flags.METHOD)) {
if (m.isType || m.isDeferred || (m.owner eq ObjectClass) || m.isConstructor)
debuglog("No forwarder for '%s' from %s to '%s'".format(m, className, moduleClass))
@@ -1122,7 +1124,9 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
log("No forwarder for " + m + " due to conflict with " + linkedClass.info.member(m.name))
else {
log("Adding static forwarder for '%s' from %s to '%s'".format(m, className, moduleClass))
- addForwarder(jclass, moduleClass, m)
+ if (m.isAccessor && m.accessed.hasStaticAnnotation) {
+ log("@static: accessor " + m + ", accessed: " + m.accessed)
+ } else addForwarder(jclass, moduleClass, m)
}
}
}
@@ -1304,7 +1308,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
jclass.getType())
}
}
-
+
style match {
case Static(true) => dbg("invokespecial"); jcode.emitINVOKESPECIAL(jowner, jname, jtype)
case Static(false) => dbg("invokestatic"); jcode.emitINVOKESTATIC(jowner, jname, jtype)
@@ -1885,7 +1889,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
*/
def computeLocalVarsIndex(m: IMethod) {
var idx = if (m.symbol.isStaticMember) 0 else 1;
-
+
for (l <- m.params) {
debuglog("Index value for " + l + "{" + l.## + "}: " + idx)
l.index = idx
diff --git a/src/compiler/scala/tools/nsc/doc/DocFactory.scala b/src/compiler/scala/tools/nsc/doc/DocFactory.scala
index 3c92c3b4b6..27a03d5381 100644
--- a/src/compiler/scala/tools/nsc/doc/DocFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/DocFactory.scala
@@ -48,8 +48,8 @@ class DocFactory(val reporter: Reporter, val settings: doc.Settings) { processor
/** Creates a scaladoc site for all symbols defined in this call's `source`,
* as well as those defined in `sources` of previous calls to the same processor.
- * @param files The list of paths (relative to the compiler's source path,
- * or absolute) of files to document. */
+ * @param source The list of paths (relative to the compiler's source path,
+ * or absolute) of files to document or the source code. */
def makeUniverse(source: Either[List[String], String]): Option[Universe] = {
assert(settings.docformat.value == "html")
source match {
@@ -81,9 +81,11 @@ class DocFactory(val reporter: Reporter, val settings: doc.Settings) { processor
new { override val global: compiler.type = compiler }
with model.ModelFactory(compiler, settings)
with model.ModelFactoryImplicitSupport
+ with model.ModelFactoryTypeSupport
with model.diagram.DiagramFactory
with model.comment.CommentFactory
- with model.TreeFactory {
+ with model.TreeFactory
+ with model.MemberLookup {
override def templateShouldDocument(sym: compiler.Symbol, inTpl: TemplateImpl) =
extraTemplatesToDocument(sym) || super.templateShouldDocument(sym, inTpl)
}
@@ -99,7 +101,6 @@ class DocFactory(val reporter: Reporter, val settings: doc.Settings) { processor
println("no documentable class found in compilation units")
None
}
-
}
object NoCompilerRunException extends ControlThrowable { }
diff --git a/src/compiler/scala/tools/nsc/doc/Settings.scala b/src/compiler/scala/tools/nsc/doc/Settings.scala
index 31e49131f6..ad178b8158 100644
--- a/src/compiler/scala/tools/nsc/doc/Settings.scala
+++ b/src/compiler/scala/tools/nsc/doc/Settings.scala
@@ -147,7 +147,7 @@ class Settings(error: String => Unit, val printMsg: String => Unit = println(_))
val docDiagramsDotTimeout = IntSetting(
"-diagrams-dot-timeout",
- "The timeout before the graphviz dot util is forecefully closed, in seconds (default: 10)",
+ "The timeout before the graphviz dot util is forcefully closed, in seconds (default: 10)",
10,
None,
_ => None
@@ -166,6 +166,33 @@ class Settings(error: String => Unit, val printMsg: String => Unit = println(_))
"For each html file, create another .html.raw file containing only the text. (can be used for quickly diffing two scaladoc outputs)"
)
+ val docNoPrefixes = BooleanSetting (
+ "-no-prefixes",
+ "Prevents generating prefixes in types, possibly creating ambiguous references, but significantly speeding up scaladoc."
+ )
+
+ val docNoLinkWarnings = BooleanSetting (
+ "-no-link-warnings",
+ "Avoid warnings for ambiguous and incorrect links."
+ )
+
+ val docSkipPackages = StringSetting (
+ "-skip-packages",
+ "<package1>:...:<packageN>",
+ "A colon-delimited list of fully qualified package names that will be skipped from scaladoc.",
+ ""
+ )
+
+ val docExpandAllTypes = BooleanSetting (
+ "-expand-all-types",
+ "Expand all type aliases and abstract types into full template pages. (locally this can be done with the @template annotation)"
+ )
+
+ val docGroups = BooleanSetting (
+ "-groups",
+ "Group similar functions together (based on the @group annotation)"
+ )
+
// Somewhere slightly before r18708 scaladoc stopped building unless the
// self-type check was suppressed. I hijacked the slotted-for-removal-anyway
// suppress-vt-warnings option and renamed it for this purpose.
@@ -177,7 +204,9 @@ class Settings(error: String => Unit, val printMsg: String => Unit = println(_))
docDiagrams, docDiagramsDebug, docDiagramsDotPath,
docDiagramsDotTimeout, docDiagramsDotRestart,
docImplicits, docImplicitsDebug, docImplicitsShowAll,
- docDiagramsMaxNormalClasses, docDiagramsMaxImplicitClasses
+ docDiagramsMaxNormalClasses, docDiagramsMaxImplicitClasses,
+ docNoPrefixes, docNoLinkWarnings, docRawOutput, docSkipPackages,
+ docExpandAllTypes, docGroups
)
val isScaladocSpecific: String => Boolean = scaladocSpecific map (_.name)
@@ -186,6 +215,15 @@ class Settings(error: String => Unit, val printMsg: String => Unit = println(_))
// set by the testsuite, when checking test output
var scaladocQuietRun = false
+ lazy val skipPackageNames =
+ if (docSkipPackages.value == "")
+ Set[String]()
+ else
+ docSkipPackages.value.toLowerCase.split(':').toSet
+
+ def skipPackage(qname: String) =
+ skipPackageNames(qname.toLowerCase)
+
/**
* This is the hardcoded area of Scaladoc. This is where "undesirable" stuff gets eliminated. I know it's not pretty,
* but ultimately scaladoc has to be useful. :)
@@ -198,16 +236,15 @@ class Settings(error: String => Unit, val printMsg: String => Unit = println(_))
* the function result should be a humanly-understandable description of the type class
*/
val knownTypeClasses: Map[String, String => String] = Map() +
- // TODO: Bring up to date and test these
- ("scala.package.Numeric" -> ((tparam: String) => tparam + " is a numeric class, such as Int, Long, Float or Double")) +
- ("scala.package.Integral" -> ((tparam: String) => tparam + " is an integral numeric class, such as Int or Long")) +
- ("scala.package.Fractional" -> ((tparam: String) => tparam + " is a fractional numeric class, such as Float or Double")) +
- ("scala.reflect.Manifest" -> ((tparam: String) => tparam + " is accompanied by a Manifest, which is a runtime representation of its type that survives erasure")) +
- ("scala.reflect.ClassManifest" -> ((tparam: String) => tparam + " is accompanied by a ClassManifest, which is a runtime representation of its type that survives erasure")) +
- ("scala.reflect.OptManifest" -> ((tparam: String) => tparam + " is accompanied by an OptManifest, which can be either a runtime representation of its type or the NoManifest, which means the runtime type is not available")) +
- ("scala.reflect.ClassTag" -> ((tparam: String) => tparam + " is accompanied by a ClassTag, which is a runtime representation of its type that survives erasure")) +
- ("scala.reflect.AbsTypeTag" -> ((tparam: String) => tparam + " is accompanied by an AbsTypeTag, which is a runtime representation of its type that survives erasure")) +
- ("scala.reflect.TypeTag" -> ((tparam: String) => tparam + " is accompanied by a TypeTag, which is a runtime representation of its type that survives erasure"))
+ ("scala.math.Numeric" -> ((tparam: String) => tparam + " is a numeric class, such as Int, Long, Float or Double")) +
+ ("scala.math.Integral" -> ((tparam: String) => tparam + " is an integral numeric class, such as Int or Long")) +
+ ("scala.math.Fractional" -> ((tparam: String) => tparam + " is a fractional numeric class, such as Float or Double")) +
+ ("scala.reflect.Manifest" -> ((tparam: String) => tparam + " is accompanied by a Manifest, which is a runtime representation of its type that survives erasure")) +
+ ("scala.reflect.ClassManifest" -> ((tparam: String) => tparam + " is accompanied by a ClassManifest, which is a runtime representation of its type that survives erasure")) +
+ ("scala.reflect.OptManifest" -> ((tparam: String) => tparam + " is accompanied by an OptManifest, which can be either a runtime representation of its type or the NoManifest, which means the runtime type is not available")) +
+ ("scala.reflect.ClassTag" -> ((tparam: String) => tparam + " is accompanied by a ClassTag, which is a runtime representation of its type that survives erasure")) +
+ ("scala.reflect.AbsTypeTag" -> ((tparam: String) => tparam + " is accompanied by an AbsTypeTag, which is a runtime representation of its type that survives erasure")) +
+ ("scala.reflect.base.TypeTags.TypeTag" -> ((tparam: String) => tparam + " is accompanied by a TypeTag, which is a runtime representation of its type that survives erasure"))
/**
* Set of classes to exclude from index and diagrams
diff --git a/src/compiler/scala/tools/nsc/doc/html/HtmlFactory.scala b/src/compiler/scala/tools/nsc/doc/html/HtmlFactory.scala
index 51c5793d46..436425df83 100644
--- a/src/compiler/scala/tools/nsc/doc/html/HtmlFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/HtmlFactory.scala
@@ -53,11 +53,16 @@ class HtmlFactory(val universe: doc.Universe, index: doc.Index) {
"trait.png",
"trait_big.png",
"trait_diagram.png",
+ "type.png",
+ "type_big.png",
+ "type_diagram.png",
"class_to_object_big.png",
"object_to_class_big.png",
- "object_to_trait_big.png",
"trait_to_object_big.png",
+ "object_to_trait_big.png",
+ "type_to_object_big.png",
+ "object_to_type_big.png",
"arrow-down.png",
"arrow-right.png",
@@ -138,7 +143,7 @@ class HtmlFactory(val universe: doc.Universe, index: doc.Index) {
if (!(written contains tpl)) {
writeForThis(new page.Template(universe, diagramGenerator, tpl))
written += tpl
- tpl.templates map writeTemplate
+ tpl.templates collect { case d: DocTemplateEntity => d } map writeTemplate
}
}
diff --git a/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala b/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala
index 4a1a8cf898..aa2df57967 100644
--- a/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala
@@ -122,17 +122,30 @@ abstract class HtmlPage extends Page { thisPage =>
case Text(text) => xml.Text(text)
case Summary(in) => inlineToHtml(in)
case HtmlTag(tag) => xml.Unparsed(tag)
- case EntityLink(target, template) => template() match {
- case Some(tpl) =>
- templateToHtml(tpl)
- case None =>
- xml.Text(target)
- }
+ case EntityLink(target, link) => linkToHtml(target, link, true)
+ }
+
+ def linkToHtml(text: Inline, link: LinkTo, hasLinks: Boolean) = link match {
+ case LinkToTpl(dtpl) =>
+ if (hasLinks)
+ <a href={ relativeLinkTo(dtpl) } class="extype" name={ dtpl.qualifiedName }>{ inlineToHtml(text) }</a>
+ else
+ <span class="extype" name={ dtpl.qualifiedName }>{ inlineToHtml(text) }</span>
+ case LinkToMember(mbr, inTpl) =>
+ if (hasLinks)
+ <a href={ relativeLinkTo(inTpl) + "#" + mbr.signature } class="extmbr" name={ mbr.qualifiedName }>{ inlineToHtml(text) }</a>
+ else
+ <span class="extmbr" name={ mbr.qualifiedName }>{ inlineToHtml(text) }</span>
+ case Tooltip(tooltip) =>
+ <span class="extype" name={ tooltip }>{ inlineToHtml(text) }</span>
+ // TODO: add case LinkToExternal here
+ case NoLink =>
+ inlineToHtml(text)
}
def typeToHtml(tpes: List[model.TypeEntity], hasLinks: Boolean): NodeSeq = tpes match {
case Nil =>
- sys.error("Internal Scaladoc error")
+ NodeSeq.Empty
case List(tpe) =>
typeToHtml(tpe, hasLinks)
case tpe :: rest =>
@@ -153,15 +166,9 @@ abstract class HtmlPage extends Page { thisPage =>
}
}
def toLinksIn(inPos: Int, starts: List[Int]): NodeSeq = {
- val (tpl, width) = tpe.refEntity(inPos)
- (tpl match {
- case dtpl:DocTemplateEntity if hasLinks =>
- <a href={ relativeLinkTo(dtpl) } class="extype" name={ dtpl.qualifiedName }>{
- string.slice(inPos, inPos + width)
- }</a>
- case tpl =>
- <span class="extype" name={ tpl.qualifiedName }>{ string.slice(inPos, inPos + width) }</span>
- }) ++ toLinksOut(inPos + width, starts.tail)
+ val (link, width) = tpe.refEntity(inPos)
+ val text = comment.Text(string.slice(inPos, inPos + width))
+ linkToHtml(text, link, hasLinks) ++ toLinksOut(inPos + width, starts.tail)
}
if (hasLinks)
toLinksOut(0, tpe.refEntity.keySet.toList)
@@ -204,10 +211,12 @@ abstract class HtmlPage extends Page { thisPage =>
else if (ety.isTrait) "trait_big.png"
else if (ety.isClass && !ety.companion.isEmpty && ety.companion.get.visibility.isPublic && ety.companion.get.inSource != None) "class_to_object_big.png"
else if (ety.isClass) "class_big.png"
+ else if ((ety.isAbstractType || ety.isAliasType) && !ety.companion.isEmpty && ety.companion.get.visibility.isPublic && ety.companion.get.inSource != None) "type_to_object_big.png"
+ else if ((ety.isAbstractType || ety.isAliasType)) "type_big.png"
else if (ety.isObject && !ety.companion.isEmpty && ety.companion.get.visibility.isPublic && ety.companion.get.inSource != None && ety.companion.get.isClass) "object_to_class_big.png"
else if (ety.isObject && !ety.companion.isEmpty && ety.companion.get.visibility.isPublic && ety.companion.get.inSource != None && ety.companion.get.isTrait) "object_to_trait_big.png"
+ else if (ety.isObject && !ety.companion.isEmpty && ety.companion.get.visibility.isPublic && ety.companion.get.inSource != None && (ety.companion.get.isAbstractType || ety.companion.get.isAliasType)) "object_to_trait_big.png"
else if (ety.isObject) "object_big.png"
else if (ety.isPackage) "package_big.png"
else "class_big.png" // FIXME: an entity *should* fall into one of the above categories, but AnyRef is somehow not
-
}
diff --git a/src/compiler/scala/tools/nsc/doc/html/Page.scala b/src/compiler/scala/tools/nsc/doc/html/Page.scala
index 5e3ab87ccd..d30ca5dc08 100644
--- a/src/compiler/scala/tools/nsc/doc/html/Page.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/Page.scala
@@ -48,13 +48,21 @@ abstract class Page {
* @param generator The generator that is writing this page. */
def writeFor(site: HtmlFactory): Unit
- def docEntityKindToString(ety: DocTemplateEntity) =
- if (ety.isTrait) "trait"
- else if (ety.isCaseClass) "case class"
- else if (ety.isClass) "class"
- else if (ety.isObject) "object"
- else if (ety.isPackage) "package"
- else "class" // FIXME: an entity *should* fall into one of the above categories, but AnyRef is somehow not
+ def kindToString(mbr: MemberEntity) =
+ mbr match {
+ case c: Class => if (c.isCaseClass) "case class" else "class"
+ case _: Trait => "trait"
+ case _: Package => "package"
+ case _: Object => "object"
+ case _: AbstractType => "type"
+ case _: AliasType => "type"
+ case _: Constructor => "new"
+ case v: Def => "def"
+ case v: Val if (v.isLazyVal) => "lazy val"
+ case v: Val if (v.isVal) => "val"
+ case v: Val if (v.isVar) => "var"
+ case _ => sys.error("Cannot create kind for: " + mbr + " of class " + mbr.getClass)
+ }
def templateToPath(tpl: TemplateEntity): List[String] = {
def doName(tpl: TemplateEntity): String =
diff --git a/src/compiler/scala/tools/nsc/doc/html/page/Index.scala b/src/compiler/scala/tools/nsc/doc/html/page/Index.scala
index 0e894a03bf..b15d602b57 100644
--- a/src/compiler/scala/tools/nsc/doc/html/page/Index.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/page/Index.scala
@@ -14,7 +14,7 @@ import scala.collection._
import scala.xml._
import scala.util.parsing.json.{JSONObject, JSONArray}
-class Index(universe: doc.Universe, index: doc.Index) extends HtmlPage {
+class Index(universe: doc.Universe, val index: doc.Index) extends HtmlPage {
def path = List("index.html")
@@ -61,12 +61,14 @@ class Index(universe: doc.Universe, index: doc.Index) extends HtmlPage {
}
<ol class="templates">{
val tpls: Map[String, Seq[DocTemplateEntity]] =
- (pack.templates filter (t => !t.isPackage && !universe.settings.hardcoded.isExcluded(t.qualifiedName) )) groupBy (_.name)
+ (pack.templates collect {
+ case t: DocTemplateEntity if !t.isPackage && !universe.settings.hardcoded.isExcluded(t.qualifiedName) => t
+ }) groupBy (_.name)
val placeholderSeq: NodeSeq = <div class="placeholder"></div>
def createLink(entity: DocTemplateEntity, includePlaceholder: Boolean, includeText: Boolean) = {
- val entityType = docEntityKindToString(entity)
+ val entityType = kindToString(entity)
val linkContent = (
{ if (includePlaceholder) placeholderSeq else NodeSeq.Empty }
++
diff --git a/src/compiler/scala/tools/nsc/doc/html/page/IndexScript.scala b/src/compiler/scala/tools/nsc/doc/html/page/IndexScript.scala
index 2b68ac2937..a37dd3fb8b 100644
--- a/src/compiler/scala/tools/nsc/doc/html/page/IndexScript.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/page/IndexScript.scala
@@ -27,7 +27,7 @@ class IndexScript(universe: doc.Universe, index: doc.Index) extends Page {
val ary = merged.keys.toList.sortBy(_.toLowerCase).map(key => {
val pairs = merged(key).map(
- t => docEntityKindToString(t) -> relativeLinkTo(t)
+ t => kindToString(t) -> relativeLinkTo(t)
) :+ ("name" -> key)
JSONObject(scala.collection.immutable.Map(pairs : _*))
@@ -62,7 +62,9 @@ class IndexScript(universe: doc.Universe, index: doc.Index) extends Page {
def allPackagesWithTemplates = {
Map(allPackages.map((key) => {
- key -> key.templates.filter(t => !t.isPackage && !universe.settings.hardcoded.isExcluded(t.qualifiedName))
+ key -> key.templates.collect {
+ case t: DocTemplateEntity if !t.isPackage && !universe.settings.hardcoded.isExcluded(t.qualifiedName) => t
+ }
}) : _*)
}
}
diff --git a/src/compiler/scala/tools/nsc/doc/html/page/ReferenceIndex.scala b/src/compiler/scala/tools/nsc/doc/html/page/ReferenceIndex.scala
index a76cc231b4..effaee711d 100755
--- a/src/compiler/scala/tools/nsc/doc/html/page/ReferenceIndex.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/page/ReferenceIndex.scala
@@ -34,7 +34,7 @@ class ReferenceIndex(letter: Char, index: doc.Index, universe: Universe) extends
} else {
html
}
- })
+ }).toList.distinct
<div class="entry">
<div class="name">{
diff --git a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
index 0d0410c7e2..422ea5ef1c 100644
--- a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
@@ -64,10 +64,10 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp
nonAbsValueMembers partition (_.deprecation.isDefined)
val (concValueMembers, shadowedImplicitMembers) =
- nonDeprValueMembers partition (!Template.isShadowedOrAmbiguousImplicit(_))
+ nonDeprValueMembers partition (!_.isShadowedOrAmbiguousImplicit)
val typeMembers =
- tpl.abstractTypes ++ tpl.aliasTypes ++ tpl.templates.filter(x => x.isTrait || x.isClass) sorted
+ tpl.abstractTypes ++ tpl.aliasTypes ++ tpl.templates.filter(x => x.isTrait || x.isClass) sorted (implicitly[Ordering[MemberEntity]])
val constructors = (tpl match {
case cls: Class => (cls.constructors: List[MemberEntity]).sorted
@@ -92,7 +92,7 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp
<p id="owner">{ templatesToHtml(tpl.inTemplate.toRoot.reverse.tail, xml.Text(".")) }</p>
}
- <body class={ if (tpl.isTrait || tpl.isClass || tpl.qualifiedName == "scala.AnyRef") "type" else "value" }>
+ <body class={ if (tpl.isType) "type" else "value" }>
<div id="definition">
{
tpl.companion match {
@@ -110,10 +110,26 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp
<div id="mbrsel">
<div id='textfilter'><span class='pre'/><span class='input'><input id='mbrsel-input' type='text' accesskey='/'/></span><span class='post'/></div>
- { if (tpl.linearizationTemplates.isEmpty && tpl.conversions.isEmpty) NodeSeq.Empty else
+ { if (tpl.linearizationTemplates.isEmpty && tpl.conversions.isEmpty && (!universe.settings.docGroups.value || (tpl.members.map(_.group).distinct.length == 1)))
+ NodeSeq.Empty
+ else
<div id="order">
<span class="filtertype">Ordering</span>
- <ol><li class="alpha in"><span>Alphabetic</span></li><li class="inherit out"><span>By inheritance</span></li></ol>
+ <ol>
+ {
+ if (!universe.settings.docGroups.value || (tpl.members.map(_.group).distinct.length == 1))
+ NodeSeq.Empty
+ else
+ <li class="group out"><span>Grouped</span></li>
+ }
+ <li class="alpha in"><span>Alphabetic</span></li>
+ {
+ if (tpl.linearizationTemplates.isEmpty && tpl.conversions.isEmpty)
+ NodeSeq.Empty
+ else
+ <li class="inherit out"><span>By inheritance</span></li>
+ }
+ </ol>
</div>
}
{ if (tpl.linearizationTemplates.isEmpty && tpl.conversions.isEmpty) NodeSeq.Empty else
@@ -223,6 +239,25 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp
}
</div>
+ <div id="groupedMembers">
+ {
+ val allGroups = tpl.members.map(_.group).distinct
+ val orderedGroups = allGroups.map(group => (tpl.groupPriority(group), group)).sorted.map(_._2)
+ // linearization
+ NodeSeq fromSeq (for (group <- orderedGroups) yield
+ <div class="group" name={ group }>
+ <h3>{ tpl.groupName(group) }</h3>
+ {
+ tpl.groupDescription(group) match {
+ case Some(body) => <div class="comment cmt">{ bodyToHtml(body) }</div>
+ case _ => NodeSeq.Empty
+ }
+ }
+ </div>
+ )
+ }
+ </div>
+
</div>
<div id="tooltip" ></div>
@@ -238,44 +273,13 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp
</body>
}
- def boundsToString(hi: Option[TypeEntity], lo: Option[TypeEntity]): String = {
- def bound0(bnd: Option[TypeEntity], pre: String): String = bnd match {
- case None => ""
- case Some(tpe) => pre ++ tpe.toString
- }
- bound0(hi, "<:") ++ bound0(lo, ">:")
- }
-
- def tparamsToString(tpss: List[TypeParam]): String = {
- if (tpss.isEmpty) "" else {
- def tparam0(tp: TypeParam): String =
- tp.variance + tp.name + boundsToString(tp.hi, tp.lo)
- def tparams0(tpss: List[TypeParam]): String = (tpss: @unchecked) match {
- case tp :: Nil => tparam0(tp)
- case tp :: tps => tparam0(tp) ++ ", " ++ tparams0(tps)
- }
- "[" + tparams0(tpss) + "]"
- }
- }
-
- def defParamsToString(d: MemberEntity with Def): String = {
- val paramLists: List[String] =
- if (d.valueParams.isEmpty) Nil
- else d.valueParams map (ps => ps map (_.resultType.name) mkString ("(",",",")"))
-
- tparamsToString(d.typeParams) + paramLists.mkString
- }
-
def memberToHtml(mbr: MemberEntity, inTpl: DocTemplateEntity): NodeSeq = {
- val defParamsString = mbr match {
- case d:MemberEntity with Def => defParamsToString(d)
- case _ => ""
- }
val memberComment = memberToCommentHtml(mbr, inTpl, false)
<li name={ mbr.definitionName } visbl={ if (mbr.visibility.isProtected) "prt" else "pub" }
data-isabs={ mbr.isAbstract.toString }
- fullComment={ if(memberComment.filter(_.label=="div").isEmpty) "no" else "yes" }>
- <a id={ mbr.name +defParamsString +":"+ mbr.resultType.name}/>
+ fullComment={ if(memberComment.filter(_.label=="div").isEmpty) "no" else "yes" }
+ group={ mbr.group }>
+ <a id={ mbr.signature }/>
{ signature(mbr, false) }
{ memberComment }
</li>
@@ -419,7 +423,7 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp
{ constraintText }
</dd>
} ++ {
- if (Template.isShadowedOrAmbiguousImplicit(mbr)) {
+ if (mbr.isShadowedOrAmbiguousImplicit) {
// These are the members that are shadowing or ambiguating the current implicit
// see ImplicitMemberShadowing trait for more information
val shadowingSuggestion = {
@@ -434,10 +438,10 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp
}
val shadowingWarning: NodeSeq =
- if (Template.isShadowedImplicit(mbr))
+ if (mbr.isShadowedImplicit)
xml.Text("This implicitly inherited member is shadowed by one or more members in this " +
"class.") ++ shadowingSuggestion
- else if (Template.isAmbiguousImplicit(mbr))
+ else if (mbr.isAmbiguousImplicit)
xml.Text("This implicitly inherited member is ambiguous. One or more implicitly " +
"inherited members have similar signatures, so calling this member may produce an ambiguous " +
"implicit conversion compiler error.") ++ shadowingSuggestion
@@ -633,13 +637,13 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp
}
val typeHierarchy = if (s.docDiagrams.isSetByUser) mbr match {
- case dtpl: DocTemplateEntity if isSelf && !isReduced && dtpl.inheritanceDiagram.isDefined =>
+ case dtpl: DocTemplateEntity if isSelf && !isReduced =>
makeDiagramHtml(dtpl, dtpl.inheritanceDiagram, "Type Hierarchy", "inheritance-diagram")
case _ => NodeSeq.Empty
} else NodeSeq.Empty // diagrams not generated
val contentHierarchy = if (s.docDiagrams.isSetByUser) mbr match {
- case dtpl: DocTemplateEntity if isSelf && !isReduced && dtpl.contentDiagram.isDefined =>
+ case dtpl: DocTemplateEntity if isSelf && !isReduced =>
makeDiagramHtml(dtpl, dtpl.contentDiagram, "Content Hierarchy", "content-diagram")
case _ => NodeSeq.Empty
} else NodeSeq.Empty // diagrams not generated
@@ -647,19 +651,6 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp
memberComment ++ paramComments ++ attributesBlock ++ linearization ++ subclasses ++ typeHierarchy ++ contentHierarchy
}
- def kindToString(mbr: MemberEntity): String = {
- mbr match {
- case tpl: DocTemplateEntity => docEntityKindToString(tpl)
- case ctor: Constructor => "new"
- case tme: MemberEntity =>
- ( if (tme.isDef) "def"
- else if (tme.isVal) "val"
- else if (tme.isLazyVal) "lazy val"
- else if (tme.isVar) "var"
- else "type")
- }
- }
-
def boundsToHtml(hi: Option[TypeEntity], lo: Option[TypeEntity], hasLinks: Boolean): NodeSeq = {
def bound0(bnd: Option[TypeEntity], pre: String): NodeSeq = bnd match {
case None => NodeSeq.Empty
@@ -677,13 +668,13 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp
case PrivateInTemplate(owner) if (owner == mbr.inTemplate) =>
Some(Paragraph(CText("private")))
case PrivateInTemplate(owner) =>
- Some(Paragraph(Chain(List(CText("private["), EntityLink(owner.qualifiedName, () => Some(owner)), CText("]")))))
+ Some(Paragraph(Chain(List(CText("private["), EntityLink(comment.Text(owner.qualifiedName), LinkToTpl(owner)), CText("]")))))
case ProtectedInInstance() =>
Some(Paragraph(CText("protected[this]")))
case ProtectedInTemplate(owner) if (owner == mbr.inTemplate) =>
Some(Paragraph(CText("protected")))
case ProtectedInTemplate(owner) =>
- Some(Paragraph(Chain(List(CText("protected["), EntityLink(owner.qualifiedName, () => Some(owner)), CText("]")))))
+ Some(Paragraph(Chain(List(CText("protected["), EntityLink(comment.Text(owner.qualifiedName), LinkToTpl(owner)), CText("]")))))
case Public() =>
None
}
@@ -700,8 +691,8 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp
<span class="symbol">
{
val nameClass =
- if (Template.isImplicit(mbr))
- if (Template.isShadowedOrAmbiguousImplicit(mbr))
+ if (mbr.isImplicitlyInherited)
+ if (mbr.isShadowedOrAmbiguousImplicit)
"implicit shadowed"
else
"implicit"
@@ -779,20 +770,21 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp
}
}{ if (isReduced) NodeSeq.Empty else {
mbr match {
- case tpl: DocTemplateEntity if !tpl.parentTypes.isEmpty =>
- <span class="result"> extends { typeToHtml(tpl.parentTypes.map(_._2), hasLinks) }</span>
-
case tme: MemberEntity if (tme.isDef || tme.isVal || tme.isLazyVal || tme.isVar) =>
<span class="result">: { typeToHtml(tme.resultType, hasLinks) }</span>
- case abt: AbstractType =>
+ case abt: MemberEntity with AbstractType =>
val b2s = boundsToHtml(abt.hi, abt.lo, hasLinks)
if (b2s != NodeSeq.Empty)
<span class="result">{ b2s }</span>
else NodeSeq.Empty
- case alt: AliasType =>
+ case alt: MemberEntity with AliasType =>
<span class="result"> = { typeToHtml(alt.alias, hasLinks) }</span>
+
+ case tpl: MemberTemplateEntity if !tpl.parentTypes.isEmpty =>
+ <span class="result"> extends { typeToHtml(tpl.parentTypes.map(_._2), hasLinks) }</span>
+
case _ => NodeSeq.Empty
}
}}
@@ -800,7 +792,7 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp
</xml:group>
mbr match {
case dte: DocTemplateEntity if !isSelf =>
- <h4 class="signature">{ inside(hasLinks = false, nameLink = relativeLinkTo(dte)) }</h4>
+ <h4 class="signature">{ inside(hasLinks = true, nameLink = relativeLinkTo(dte)) }</h4>
case _ if isSelf =>
<h4 id="signature" class="signature">{ inside(hasLinks = true) }</h4>
case _ =>
@@ -850,18 +842,13 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp
val link = relativeLinkTo(mbr)
myXml ++= <span class="name"><a href={link}>{str.substring(from, to)}</a></span>
case mbr: MemberEntity =>
- val anchor = "#" + mbr.name + defParamsString(mbr) + ":" + mbr.resultType.name
+ val anchor = "#" + mbr.signature
val link = relativeLinkTo(mbr.inTemplate)
myXml ++= <span class="name"><a href={link ++ anchor}>{str.substring(from, to)}</a></span>
}
index = to
}
}
- // function used in the MemberEntity case above
- def defParamsString(mbr: Entity):String = mbr match {
- case d:MemberEntity with Def => defParamsToString(d)
- case _ => ""
- }
if (index <= length-1)
myXml ++= codeStringToXml(str.substring(index, length ))
@@ -952,16 +939,18 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp
}
def makeDiagramHtml(tpl: DocTemplateEntity, diagram: Option[Diagram], description: String, id: String) = {
- val s = universe.settings
- val diagramSvg = generator.generate(diagram.get, tpl, this)
- if (diagramSvg != NodeSeq.Empty) {
- <div class="toggleContainer block diagram-container" id={ id + "-container"}>
- <span class="toggle diagram-link">{ description }</span>
- <a href="http://docs.scala-lang.org/overviews/scaladoc/usage.html#diagrams" target="_blank" class="diagram-help">Learn more about scaladoc diagrams</a>
- <div class="diagram" id={ id }>{
- diagramSvg
- }</div>
- </div>
+ if (diagram.isDefined) {
+ val s = universe.settings
+ val diagramSvg = generator.generate(diagram.get, tpl, this)
+ if (diagramSvg != NodeSeq.Empty) {
+ <div class="toggleContainer block diagram-container" id={ id + "-container"}>
+ <span class="toggle diagram-link">{ description }</span>
+ <a href="http://docs.scala-lang.org/overviews/scaladoc/usage.html#diagrams" target="_blank" class="diagram-help">Learn more about scaladoc diagrams</a>
+ <div class="diagram" id={ id }>{
+ diagramSvg
+ }</div>
+ </div>
+ } else NodeSeq.Empty
} else NodeSeq.Empty
}
}
@@ -970,12 +959,5 @@ object Template {
/* Vlad: Lesson learned the hard way: don't put any stateful code that references the model here,
* it won't be garbage collected and you'll end up filling the heap with garbage */
- def isImplicit(mbr: MemberEntity) = mbr.byConversion.isDefined
- def isShadowedImplicit(mbr: MemberEntity): Boolean =
- mbr.byConversion.map(_.source.implicitsShadowing.get(mbr).map(_.isShadowed).getOrElse(false)).getOrElse(false)
- def isAmbiguousImplicit(mbr: MemberEntity): Boolean =
- mbr.byConversion.map(_.source.implicitsShadowing.get(mbr).map(_.isAmbiguous).getOrElse(false)).getOrElse(false)
- def isShadowedOrAmbiguousImplicit(mbr: MemberEntity) = isShadowedImplicit(mbr) || isAmbiguousImplicit(mbr)
-
def lowerFirstLetter(s: String) = if (s.length >= 1) s.substring(0,1).toLowerCase() + s.substring(1) else s
}
diff --git a/src/compiler/scala/tools/nsc/doc/html/page/diagram/DotDiagramGenerator.scala b/src/compiler/scala/tools/nsc/doc/html/page/diagram/DotDiagramGenerator.scala
index dc6f941c30..bae61f1a3b 100644
--- a/src/compiler/scala/tools/nsc/doc/html/page/diagram/DotDiagramGenerator.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/page/diagram/DotDiagramGenerator.scala
@@ -25,7 +25,7 @@ class DotDiagramGenerator(settings: doc.Settings) extends DiagramGenerator {
// maps an index to its corresponding node
private var index2Node: Map[Int, Node] = null
// true if the current diagram is a class diagram
- private var isClassDiagram = false
+ private var isInheritanceDiagram = false
// incoming implicit nodes (needed for determining the CSS class of a node)
private var incomingImplicitNodes: List[Node] = List()
// the suffix used when there are two many classes to show
@@ -66,15 +66,15 @@ class DotDiagramGenerator(settings: doc.Settings) extends DiagramGenerator {
var superClasses = List[Node]()
var incomingImplicits = List[Node]()
var outgoingImplicits = List[Node]()
- isClassDiagram = false
+ isInheritanceDiagram = false
d match {
- case ClassDiagram(_thisNode, _superClasses, _subClasses, _incomingImplicits, _outgoingImplicits) =>
+ case InheritanceDiagram(_thisNode, _superClasses, _subClasses, _incomingImplicits, _outgoingImplicits) =>
def textTypeEntity(text: String) =
new TypeEntity {
val name = text
- def refEntity: SortedMap[Int, (TemplateEntity, Int)] = SortedMap()
+ def refEntity: SortedMap[Int, (LinkTo, Int)] = SortedMap()
}
// it seems dot chokes on node names over 8000 chars, so let's limit the size of the string
@@ -86,29 +86,29 @@ class DotDiagramGenerator(settings: doc.Settings) extends DiagramGenerator {
// them by on node with a corresponding tooltip
superClasses = if (_superClasses.length > settings.docDiagramsMaxNormalClasses.value) {
val superClassesTooltip = Some(limitSize(_superClasses.map(_.tpe.name).mkString(", ")))
- List(NormalNode(textTypeEntity(_superClasses.length + MultiSuffix), None, superClassesTooltip))
+ List(NormalNode(textTypeEntity(_superClasses.length + MultiSuffix), None)(superClassesTooltip))
} else _superClasses
subClasses = if (_subClasses.length > settings.docDiagramsMaxNormalClasses.value) {
val subClassesTooltip = Some(limitSize(_subClasses.map(_.tpe.name).mkString(", ")))
- List(NormalNode(textTypeEntity(_subClasses.length + MultiSuffix), None, subClassesTooltip))
+ List(NormalNode(textTypeEntity(_subClasses.length + MultiSuffix), None)(subClassesTooltip))
} else _subClasses
incomingImplicits = if (_incomingImplicits.length > settings.docDiagramsMaxImplicitClasses.value) {
val incomingImplicitsTooltip = Some(limitSize(_incomingImplicits.map(_.tpe.name).mkString(", ")))
- List(ImplicitNode(textTypeEntity(_incomingImplicits.length + MultiSuffix), None, incomingImplicitsTooltip))
+ List(ImplicitNode(textTypeEntity(_incomingImplicits.length + MultiSuffix), None)(incomingImplicitsTooltip))
} else _incomingImplicits
outgoingImplicits = if (_outgoingImplicits.length > settings.docDiagramsMaxImplicitClasses.value) {
val outgoingImplicitsTooltip = Some(limitSize(_outgoingImplicits.map(_.tpe.name).mkString(", ")))
- List(ImplicitNode(textTypeEntity(_outgoingImplicits.length + MultiSuffix), None, outgoingImplicitsTooltip))
+ List(ImplicitNode(textTypeEntity(_outgoingImplicits.length + MultiSuffix), None)(outgoingImplicitsTooltip))
} else _outgoingImplicits
thisNode = _thisNode
nodes = List()
edges = (thisNode -> superClasses) :: subClasses.map(_ -> List(thisNode))
node2Index = (thisNode::subClasses:::superClasses:::incomingImplicits:::outgoingImplicits).zipWithIndex.toMap
- isClassDiagram = true
+ isInheritanceDiagram = true
incomingImplicitNodes = incomingImplicits
case _ =>
nodes = d.nodes
@@ -119,7 +119,7 @@ class DotDiagramGenerator(settings: doc.Settings) extends DiagramGenerator {
index2Node = node2Index map {_.swap}
val implicitsDot = {
- if (!isClassDiagram) ""
+ if (!isInheritanceDiagram) ""
else {
// dot cluster containing thisNode
val thisCluster = "subgraph clusterThis {\n" +
@@ -242,6 +242,8 @@ class DotDiagramGenerator(settings: doc.Settings) extends DiagramGenerator {
attr ++= classStyle
else if(node.isObjectNode)
attr ++= objectStyle
+ else if(node.isTypeNode)
+ attr ++= typeStyle
else
attr ++= defaultStyle
@@ -254,6 +256,8 @@ class DotDiagramGenerator(settings: doc.Settings) extends DiagramGenerator {
img = "class_diagram.png"
else if(node.isObjectNode)
img = "object_diagram.png"
+ else if(node.isTypeNode)
+ img = "type_diagram.png"
if(!img.equals("")) {
img = "<TD><IMG SCALE=\"TRUE\" SRC=\"" + settings.outdir.value + "/lib/" + img + "\" /></TD>"
@@ -307,6 +311,8 @@ class DotDiagramGenerator(settings: doc.Settings) extends DiagramGenerator {
space + "trait"
else if (node.isObjectNode)
space + "object"
+ else if (node.isTypeNode)
+ space + "type"
else
default
@@ -360,7 +366,7 @@ class DotDiagramGenerator(settings: doc.Settings) extends DiagramGenerator {
private def transform(e:scala.xml.Node): scala.xml.Node = e match {
// add an id and class attribute to the SVG element
case Elem(prefix, "svg", attribs, scope, child @ _*) => {
- val klass = if (isClassDiagram) "class-diagram" else "package-diagram"
+ val klass = if (isInheritanceDiagram) "class-diagram" else "package-diagram"
Elem(prefix, "svg", attribs, scope, child map(x => transform(x)) : _*) %
new UnprefixedAttribute("id", "graph" + counter, Null) %
new UnprefixedAttribute("class", klass, Null)
@@ -491,6 +497,12 @@ class DotDiagramGenerator(settings: doc.Settings) extends DiagramGenerator {
"fontcolor" -> "#ffffff"
)
+ private val typeStyle = Map(
+ "color" -> "#115F3B",
+ "fillcolor" -> "#0A955B",
+ "fontcolor" -> "#ffffff"
+ )
+
private def flatten(attributes: Map[String, String]) = attributes.map{ case (key, value) => key + "=\"" + value + "\"" }.mkString(", ")
private val graphAttributesStr = graphAttributes.map{ case (key, value) => key + "=\"" + value + "\";\n" }.mkString
diff --git a/src/compiler/scala/tools/nsc/doc/html/page/diagram/DotRunner.scala b/src/compiler/scala/tools/nsc/doc/html/page/diagram/DotRunner.scala
index 37600fa908..5cdd5c74a4 100644
--- a/src/compiler/scala/tools/nsc/doc/html/page/diagram/DotRunner.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/page/diagram/DotRunner.scala
@@ -28,7 +28,7 @@ class DotRunner(settings: doc.Settings) {
if (dotProcess == null) {
if (dotRestarts < settings.docDiagramsDotRestart.value) {
if (dotRestarts != 0)
- settings.printMsg("A new graphviz dot process will be created...\n")
+ settings.printMsg("Graphviz will be restarted...\n")
dotRestarts += 1
dotProcess = new DotProcess(settings)
} else
@@ -46,7 +46,7 @@ class DotRunner(settings: doc.Settings) {
if (dotRestarts == settings.docDiagramsDotRestart.value) {
settings.printMsg("\n")
settings.printMsg("**********************************************************************")
- settings.printMsg("Diagrams will be disabled for this run beucause the graphviz dot tool")
+ settings.printMsg("Diagrams will be disabled for this run because the graphviz dot tool")
settings.printMsg("has malfunctioned too many times. These scaladoc flags may help:")
settings.printMsg("")
val baseList = List(settings.docDiagramsDebug,
@@ -106,7 +106,7 @@ class DotProcess(settings: doc.Settings) {
result
} catch {
- case exc =>
+ case exc: Throwable =>
errorBuffer.append(" Main thread in " + templateName + ": " +
(if (exc.isInstanceOf[NoSuchElementException]) "Timeout" else "Exception: " + exc))
error = true
@@ -145,9 +145,10 @@ class DotProcess(settings: doc.Settings) {
settings.printMsg("**********************************************************************")
} else {
// we shouldn't just sit there for 50s not reporting anything, no?
- settings.printMsg("Graphviz dot encountered an error when generating the diagram for")
- settings.printMsg(templateName + ". Use the " + settings.docDiagramsDebug.name + " flag")
- settings.printMsg("for more information.")
+ settings.printMsg("Graphviz dot encountered an error when generating the diagram for:")
+ settings.printMsg(templateName)
+ settings.printMsg("These are usually spurious errors, but if you notice a persistant error on")
+ settings.printMsg("a diagram, please use the " + settings.docDiagramsDebug.name + " flag and report a bug with the output.")
}
}
}
@@ -173,7 +174,7 @@ class DotProcess(settings: doc.Settings) {
}
stdin.close()
} catch {
- case exc =>
+ case exc: Throwable =>
error = true
stdin.close()
errorBuffer.append(" Input thread in " + templateName + ": Exception: " + exc + "\n")
@@ -199,7 +200,7 @@ class DotProcess(settings: doc.Settings) {
outputString.put(buffer.toString)
stdOut.close()
} catch {
- case exc =>
+ case exc: Throwable =>
error = true
stdOut.close()
errorBuffer.append(" Output thread in " + templateName + ": Exception: " + exc + "\n")
@@ -218,7 +219,7 @@ class DotProcess(settings: doc.Settings) {
}
stdErr.close()
} catch {
- case exc =>
+ case exc: Throwable =>
error = true
stdErr.close()
errorBuffer.append(" Error thread in " + templateName + ": Exception: " + exc + "\n")
diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/lib/diagrams.css b/src/compiler/scala/tools/nsc/doc/html/resource/lib/diagrams.css
index 04d29580b7..5fe33f72f5 100644
--- a/src/compiler/scala/tools/nsc/doc/html/resource/lib/diagrams.css
+++ b/src/compiler/scala/tools/nsc/doc/html/resource/lib/diagrams.css
@@ -119,6 +119,14 @@ svg.class-diagram .node.this.trait.over polygon
fill: #235d7b;
}
+svg.package-diagram .node.type.over polygon,
+svg.class-diagram .node.this.type.over polygon
+{
+ fill: #098552;
+ fill: #04663e;
+}
+
+
svg.package-diagram .node.object.over polygon
{
fill: #183377;
diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js b/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js
index eb7f752440..f29438edfb 100644
--- a/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js
+++ b/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js
@@ -15,15 +15,15 @@ var lastHash = "";
$(document).ready(function() {
$('body').layout({ west__size: '20%' });
- $('#browser').layout({
+ $('#browser').layout({
center__paneSelector: ".ui-west-center"
//,center__initClosed:true
,north__paneSelector: ".ui-west-north"
- });
+ });
$('iframe').bind("load", function(){
var subtitle = $(this).contents().find('title').text();
$(document).attr('title', (title ? title + " - " : "") + subtitle);
-
+
setUrlFragmentFromFrameSrc();
});
@@ -81,16 +81,16 @@ function setUrlFragmentFromFrameSrc() {
var commonLength = location.pathname.lastIndexOf("/");
var frameLocation = frames["template"].location;
var relativePath = frameLocation.pathname.slice(commonLength + 1);
-
+
if(!relativePath || frameLocation.pathname.indexOf("/") < 0)
return;
-
+
// Add #, remove ".html" and replace "/" with "."
fragment = "#" + relativePath.replace(/\.html$/, "").replace(/\//g, ".");
-
+
// Add the frame's hash after an @
if(frameLocation.hash) fragment += ("@" + frameLocation.hash.slice(1));
-
+
// Use replace to not add history items
lastFragment = fragment;
location.replace(fragment);
@@ -109,7 +109,7 @@ var Index = {};
if (type == 'object') {
href = t['object'];
} else {
- href = t['class'] || t['trait'] || t['case class'];
+ href = t['class'] || t['trait'] || t['case class'] || t['type'];
}
return [
'<a class="tplshow" target="template" href="',
@@ -142,10 +142,10 @@ var Index = {};
inner += openLink(template, 'object');
}
- if (template['class'] || template['trait'] || template['case class']) {
+ if (template['class'] || template['trait'] || template['case class'] || template['type']) {
inner += (inner == '') ?
'<div class="placeholder" />' : '</a>';
- inner += openLink(template, template['trait'] ? 'trait' : 'class');
+ inner += openLink(template, template['trait'] ? 'trait' : template['type'] ? 'type' : 'class');
} else {
inner += '<div class="placeholder"/>';
}
@@ -245,6 +245,7 @@ function configureEntityList() {
function prepareEntityList() {
var classIcon = $("#library > img.class");
var traitIcon = $("#library > img.trait");
+ var typeIcon = $("#library > img.type");
var objectIcon = $("#library > img.object");
var packageIcon = $("#library > img.package");
@@ -252,6 +253,7 @@ function prepareEntityList() {
$('#tpl li.pack').each(function () {
$("span.class", this).each(function() { $(this).replaceWith(classIcon.clone()); });
$("span.trait", this).each(function() { $(this).replaceWith(traitIcon.clone()); });
+ $("span.type", this).each(function() { $(this).replaceWith(typeIcon.clone()); });
$("span.object", this).each(function() { $(this).replaceWith(objectIcon.clone()); });
$("span.package", this).each(function() { $(this).replaceWith(packageIcon.clone()); });
});
@@ -265,11 +267,11 @@ function keyboardScrolldownLeftPane() {
scheduler.add("init", function() {
$("#textfilter input").blur();
var $items = $("#tpl li");
- $items.first().addClass('selected');
+ $items.first().addClass('selected');
$(window).bind("keydown", function(e) {
var $old = $items.filter('.selected'),
- $new;
+ $new;
switch ( e.keyCode ) {
@@ -286,7 +288,7 @@ function keyboardScrolldownLeftPane() {
case 27: // escape
$old.removeClass('selected');
$(window).unbind(e);
- $("#textfilter input").focus();
+ $("#textfilter input").focus();
break;
@@ -296,7 +298,7 @@ function keyboardScrolldownLeftPane() {
if (!$new.length) {
$new = $old.parent().prev();
}
-
+
if ($new.is('ol') && $new.children(':last').is('ol')) {
$new = $new.children().children(':last');
} else if ($new.is('ol')) {
@@ -313,17 +315,17 @@ function keyboardScrolldownLeftPane() {
if ($new.is('ol')) {
$new = $new.children(':first');
}
- break;
- }
-
+ break;
+ }
+
if ($new.is('li')) {
$old.removeClass('selected');
- $new.addClass('selected');
+ $new.addClass('selected');
} else if (e.keyCode == 38) {
$(window).unbind(e);
$("#textfilter input").focus();
}
- });
+ });
});
}
@@ -342,13 +344,13 @@ function configureTextFilter() {
$("#template").contents().find("#mbrsel-input").focus();
input.attr("value", "");
return false;
- }
+ }
if (event.keyCode == 40) { // down arrow
$(window).unbind("keydown");
keyboardScrolldownLeftPane();
return false;
- }
- textFilter();
+ }
+ textFilter();
});
input.focus(function(event) { input.select(); });
});
@@ -419,7 +421,7 @@ function textFilter() {
});
configureHideFilter();
};
-
+
scheduler.add('filter', searchLoop);
}
diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/lib/object_to_type_big.png b/src/compiler/scala/tools/nsc/doc/html/resource/lib/object_to_type_big.png
new file mode 100644
index 0000000000..7502942eb6
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/doc/html/resource/lib/object_to_type_big.png
Binary files differ
diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.css b/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.css
index 1bee55313b..6fb7953724 100644
--- a/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.css
+++ b/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.css
@@ -253,6 +253,17 @@ dl.attributes > dd {
color: white;
}
+#groupedMembers > div.group > h3 {
+ background: #dadada url("typebg.gif") repeat-x bottom left; /* green */
+ height: 17px;
+ font-size: 12pt;
+}
+
+#groupedMembers > div.group > h3 * {
+ color: white;
+}
+
+
/* Member cells */
div.members > ol {
@@ -516,6 +527,20 @@ div.members > ol > li:last-child {
/* Comments structured layout */
+.group > div.comment {
+ padding-top: 5px;
+ padding-bottom: 5px;
+ padding-right: 5px;
+ padding-left: 5px;
+ border: 1px solid #ddd;
+ background-color: #eeeee;
+ margin-top:5px;
+ margin-bottom:5px;
+ margin-right:5px;
+ margin-left:5px;
+ display: block;
+}
+
p.comment {
display: block;
margin-left: 14.7em;
diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.js b/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.js
index c418c3280b..afd0293fe1 100644
--- a/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.js
+++ b/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.js
@@ -43,20 +43,20 @@ $(document).ready(function(){
case 33: //page up
input.val("");
- filter(false);
+ filter(false);
break;
case 34: //page down
input.val("");
- filter(false);
- break;
+ filter(false);
+ break;
- default:
+ default:
window.scrollTo(0, $("#mbrsel").offset().top);
- filter(true);
+ filter(true);
break;
- }
+ }
});
input.focus(function(event) {
input.select();
@@ -70,7 +70,7 @@ $(document).ready(function(){
if (event.keyCode == 9) { // tab
$("#index-input", window.parent.document).focus();
input.attr("value", "");
- return false;
+ return false;
}
});
@@ -135,18 +135,21 @@ $(document).ready(function(){
});
$("#order > ol > li.alpha").click(function() {
if ($(this).hasClass("out")) {
- $(this).removeClass("out").addClass("in");
- $("#order > ol > li.inherit").removeClass("in").addClass("out");
orderAlpha();
};
})
$("#order > ol > li.inherit").click(function() {
if ($(this).hasClass("out")) {
- $(this).removeClass("out").addClass("in");
- $("#order > ol > li.alpha").removeClass("in").addClass("out");
orderInherit();
};
});
+ $("#order > ol > li.group").click(function() {
+ if ($(this).hasClass("out")) {
+ orderGroup();
+ };
+ });
+ $("#groupedMembers").hide();
+
initInherit();
// Create tooltips
@@ -202,9 +205,14 @@ $(document).ready(function(){
// Set parent window title
windowTitle();
+
+ if ($("#order > ol > li.group").length == 1) { orderGroup(); };
});
function orderAlpha() {
+ $("#order > ol > li.alpha").removeClass("out").addClass("in");
+ $("#order > ol > li.inherit").removeClass("in").addClass("out");
+ $("#order > ol > li.group").removeClass("in").addClass("out");
$("#template > div.parent").hide();
$("#template > div.conversion").hide();
$("#mbrsel > div[id=ancestors]").show();
@@ -212,12 +220,25 @@ function orderAlpha() {
};
function orderInherit() {
+ $("#order > ol > li.inherit").removeClass("out").addClass("in");
+ $("#order > ol > li.alpha").removeClass("in").addClass("out");
+ $("#order > ol > li.group").removeClass("in").addClass("out");
$("#template > div.parent").show();
$("#template > div.conversion").show();
$("#mbrsel > div[id=ancestors]").hide();
filter();
};
+function orderGroup() {
+ $("#order > ol > li.group").removeClass("out").addClass("in");
+ $("#order > ol > li.alpha").removeClass("in").addClass("out");
+ $("#order > ol > li.inherit").removeClass("in").addClass("out");
+ $("#template > div.parent").hide();
+ $("#template > div.conversion").hide();
+ $("#mbrsel > div[id=ancestors]").show();
+ filter();
+};
+
/** Prepares the DOM for inheritance-based display. To do so it will:
* - hide all statically-generated parents headings;
* - copy all members from the value and type members lists (flat members) to corresponding lists nested below the
@@ -225,44 +246,74 @@ function orderInherit() {
* - initialises a control variable used by the filter method to control whether filtering happens on flat members
* or on inheritance-grouped members. */
function initInherit() {
- // parents is a map from fully-qualified names to the DOM node of parent headings.
- var parents = new Object();
+ // inheritParents is a map from fully-qualified names to the DOM node of parent headings.
+ var inheritParents = new Object();
+ var groupParents = new Object();
$("#inheritedMembers > div.parent").each(function(){
- parents[$(this).attr("name")] = $(this);
+ inheritParents[$(this).attr("name")] = $(this);
});
$("#inheritedMembers > div.conversion").each(function(){
- parents[$(this).attr("name")] = $(this);
+ inheritParents[$(this).attr("name")] = $(this);
+ });
+ $("#groupedMembers > div.group").each(function(){
+ groupParents[$(this).attr("name")] = $(this);
});
+
$("#types > ol > li").each(function(){
var mbr = $(this);
this.mbrText = mbr.find("> .fullcomment .cmt").text();
var qualName = mbr.attr("name");
var owner = qualName.slice(0, qualName.indexOf("#"));
var name = qualName.slice(qualName.indexOf("#") + 1);
- var parent = parents[owner];
- if (parent != undefined) {
- var types = $("> .types > ol", parent);
+ var inheritParent = inheritParents[owner];
+ if (inheritParent != undefined) {
+ var types = $("> .types > ol", inheritParent);
+ if (types.length == 0) {
+ inheritParent.append("<div class='types members'><h3>Type Members</h3><ol></ol></div>");
+ types = $("> .types > ol", inheritParent);
+ }
+ var clone = mbr.clone();
+ clone[0].mbrText = this.mbrText;
+ types.append(clone);
+ }
+ var group = mbr.attr("group")
+ var groupParent = groupParents[group];
+ if (groupParent != undefined) {
+ var types = $("> .types > ol", groupParent);
if (types.length == 0) {
- parent.append("<div class='types members'><h3>Type Members</h3><ol></ol></div>");
- types = $("> .types > ol", parent);
+ groupParent.append("<div class='types members'><ol></ol></div>");
+ types = $("> .types > ol", groupParent);
}
var clone = mbr.clone();
clone[0].mbrText = this.mbrText;
types.append(clone);
}
});
+
$("#values > ol > li").each(function(){
var mbr = $(this);
this.mbrText = mbr.find("> .fullcomment .cmt").text();
var qualName = mbr.attr("name");
var owner = qualName.slice(0, qualName.indexOf("#"));
var name = qualName.slice(qualName.indexOf("#") + 1);
- var parent = parents[owner];
- if (parent != undefined) {
- var values = $("> .values > ol", parent);
+ var inheritParent = inheritParents[owner];
+ if (inheritParent != undefined) {
+ var values = $("> .values > ol", inheritParent);
if (values.length == 0) {
- parent.append("<div class='values members'><h3>Value Members</h3><ol></ol></div>");
- values = $("> .values > ol", parent);
+ inheritParent.append("<div class='values members'><h3>Value Members</h3><ol></ol></div>");
+ values = $("> .values > ol", inheritParent);
+ }
+ var clone = mbr.clone();
+ clone[0].mbrText = this.mbrText;
+ values.append(clone);
+ }
+ var group = mbr.attr("group")
+ var groupParent = groupParents[group];
+ if (groupParent != undefined) {
+ var values = $("> .values > ol", groupParent);
+ if (values.length == 0) {
+ groupParent.append("<div class='values members'><ol></ol></div>");
+ values = $("> .values > ol", groupParent);
}
var clone = mbr.clone();
clone[0].mbrText = this.mbrText;
@@ -275,6 +326,9 @@ function initInherit() {
$("#inheritedMembers > div.conversion").each(function() {
if ($("> div.members", this).length == 0) { $(this).remove(); };
});
+ $("#groupedMembers > div.group").each(function() {
+ if ($("> div.members", this).length == 0) { $(this).remove(); };
+ });
};
/* filter used to take boolean scrollToMember */
@@ -284,26 +338,43 @@ function filter() {
var queryRegExp = new RegExp(query, "i");
var privateMembersHidden = $("#visbl > ol > li.public").hasClass("in");
var orderingAlphabetic = $("#order > ol > li.alpha").hasClass("in");
- var hiddenSuperclassElementsLinearization = orderingAlphabetic ? $("#linearization > li.out") : $("#linearization > li:gt(0)");
+ var orderingInheritance = $("#order > ol > li.inherit").hasClass("in");
+ var orderingGroups = $("#order > ol > li.group").hasClass("in");
+ var hiddenSuperclassElementsLinearization = orderingInheritance ? $("#linearization > li:gt(0)") : $("#linearization > li.out");
var hiddenSuperclassesLinearization = hiddenSuperclassElementsLinearization.map(function() {
return $(this).attr("name");
}).get();
- var hiddenSuperclassElementsImplicits = orderingAlphabetic ? $("#implicits > li.out") : $("#implicits > li");
+ var hiddenSuperclassElementsImplicits = orderingInheritance ? $("#implicits > li") : $("#implicits > li.out");
var hiddenSuperclassesImplicits = hiddenSuperclassElementsImplicits.map(function() {
return $(this).attr("name");
}).get();
var hideInheritedMembers;
- if(orderingAlphabetic) {
+ if (orderingAlphabetic) {
+ $("#allMembers").show();
$("#inheritedMembers").hide();
+ $("#groupedMembers").hide();
hideInheritedMembers = true;
$("#allMembers > .members").each(filterFunc);
- }
- else {
- $("#inheritedMembers").show();
+ } else if (orderingGroups) {
+ $("#groupedMembers").show();
+ $("#inheritedMembers").hide();
+ $("#allMembers").hide();
hideInheritedMembers = true;
- $("#allMembers > .members").each(filterFunc);
+ $("#groupedMembers > .group > .members").each(filterFunc);
+ $("#groupedMembers > div.group").each(function() {
+ $(this).show();
+ if ($("> div.members", this).not(":hidden").length == 0) {
+ $(this).hide();
+ } else {
+ $(this).show();
+ }
+ });
+ } else if (orderingInheritance) {
+ $("#inheritedMembers").show();
+ $("#groupedMembers").hide();
+ $("#allMembers").hide();
hideInheritedMembers = false;
$("#inheritedMembers > .parent > .members").each(filterFunc);
$("#inheritedMembers > .conversion > .members").each(filterFunc);
diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/lib/type.png b/src/compiler/scala/tools/nsc/doc/html/resource/lib/type.png
new file mode 100644
index 0000000000..366ec4e992
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/doc/html/resource/lib/type.png
Binary files differ
diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/lib/type_big.png b/src/compiler/scala/tools/nsc/doc/html/resource/lib/type_big.png
new file mode 100644
index 0000000000..df0dc118bf
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/doc/html/resource/lib/type_big.png
Binary files differ
diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/lib/type_diagram.png b/src/compiler/scala/tools/nsc/doc/html/resource/lib/type_diagram.png
new file mode 100644
index 0000000000..d6fbb84ff2
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/doc/html/resource/lib/type_diagram.png
Binary files differ
diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/lib/type_to_object_big.png b/src/compiler/scala/tools/nsc/doc/html/resource/lib/type_to_object_big.png
new file mode 100644
index 0000000000..1bd2833a63
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/doc/html/resource/lib/type_to_object_big.png
Binary files differ
diff --git a/src/compiler/scala/tools/nsc/doc/model/Entity.scala b/src/compiler/scala/tools/nsc/doc/model/Entity.scala
index 2901daafd6..16ade0787e 100644
--- a/src/compiler/scala/tools/nsc/doc/model/Entity.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/Entity.scala
@@ -53,6 +53,15 @@ trait Entity {
/** The kind of the entity */
def kind: String
+
+ /** Whether or not the template was defined in a package object */
+ def inPackageObject: Boolean
+
+ /** Indicates whether this entity lives in the types namespace (classes, traits, abstract/alias types) */
+ def isType: Boolean
+
+ /** Indicates whether this entity lives in the terms namespace (objects, packages, methods, values) */
+ def isTerm: Boolean
}
object Entity {
@@ -88,17 +97,14 @@ trait TemplateEntity extends Entity {
/** Whether documentation is available for this template. */
def isDocTemplate: Boolean
+ /** Whether documentation is available for this template. */
+ def isNoDocMemberTemplate: Boolean
+
/** Whether this template is a case class. */
def isCaseClass: Boolean
- /** Whether or not the template was defined in a package object */
- def inPackageObject: Boolean
-
/** The self-type of this template, if it differs from the template type. */
def selfType : Option[TypeEntity]
-
- /** The type of this entity, with type members */
- def ownType: TypeEntity
}
@@ -110,6 +116,9 @@ trait MemberEntity extends Entity {
/** The comment attached to this member, if any. */
def comment: Option[Comment]
+ /** The group this member is from */
+ def group: String
+
/** The template of which this entity is a member. */
def inTemplate: DocTemplateEntity
@@ -179,11 +188,28 @@ trait MemberEntity extends Entity {
/** If this symbol is a use case, the useCaseOf will contain the member it was derived from, containing the full
* signature and the complete parameter descriptions. */
- def useCaseOf: Option[MemberEntity] = None
+ def useCaseOf: Option[MemberEntity]
/** If this member originates from an implicit conversion, we set the implicit information to the correct origin */
def byConversion: Option[ImplicitConversion]
+
+ /** The identity of this member, used for linking */
+ def signature: String
+
+ /** Indicates whether the member is inherited by implicit conversion */
+ def isImplicitlyInherited: Boolean
+
+ /** Indicates whether there is another member with the same name in the template that will take precendence */
+ def isShadowedImplicit: Boolean
+
+ /** Indicates whether there are other implicitly inherited members that have similar signatures (and thus they all
+ * become ambiguous) */
+ def isAmbiguousImplicit: Boolean
+
+ /** Indicates whether the implicitly inherited member is shadowed or ambiguous in its template */
+ def isShadowedOrAmbiguousImplicit: Boolean
}
+
object MemberEntity {
// Oh contravariance, contravariance, wherefore art thou contravariance?
// Note: the above works for both the commonly misunderstood meaning of the line and the real one.
@@ -195,24 +221,38 @@ trait HigherKinded {
/** The type parameters of this entity. */
def typeParams: List[TypeParam]
-
}
/** A template (class, trait, object or package) which is referenced in the universe, but for which no further
* documentation is available. Only templates for which a source file is given are documented by Scaladoc. */
trait NoDocTemplate extends TemplateEntity {
- def kind = "<no doc>"
+ def kind =
+ if (isClass) "class"
+ else if (isTrait) "trait"
+ else if (isObject) "object"
+ else ""
}
-/** TODO: Document */
-trait NoDocTemplateMemberEntity extends TemplateEntity with MemberEntity {
- def kind = "<no doc, mbr>"
+/** An inherited template that was not documented in its original owner - example:
+ * in classpath: trait T { class C } -- T (and implicitly C) are not documented
+ * in the source: trait U extends T -- C appears in U as a MemberTemplateImpl
+ * -- that is, U has a member for it but C doesn't get its own page */
+trait MemberTemplateEntity extends TemplateEntity with MemberEntity with HigherKinded {
+
+ /** The value parameters of this case class, or an empty list if this class is not a case class. As case class value
+ * parameters cannot be curried, the outer list has exactly one element. */
+ def valueParams: List[List[ValueParam]]
+
+ /** The direct super-type of this template
+ e.g: {{{class A extends B[C[Int]] with D[E]}}} will have two direct parents: class B and D
+ NOTE: we are dropping the refinement here! */
+ def parentTypes: List[(TemplateEntity, TypeEntity)]
}
/** A template (class, trait, object or package) for which documentation is available. Only templates for which
* a source file is given are documented by Scaladoc. */
-trait DocTemplateEntity extends TemplateEntity with MemberEntity {
+trait DocTemplateEntity extends MemberTemplateEntity {
/** The list of templates such that each is a member of the template that follows it; the first template is always
* this template, the last the root package entity. */
@@ -226,11 +266,6 @@ trait DocTemplateEntity extends TemplateEntity with MemberEntity {
* only if the `docsourceurl` setting has been set. */
def sourceUrl: Option[java.net.URL]
- /** The direct super-type of this template
- e.g: {{{class A extends B[C[Int]] with D[E]}}} will have two direct parents: class B and D
- NOTE: we are dropping the refinement here! */
- def parentTypes: List[(TemplateEntity, TypeEntity)]
-
/** All class, trait and object templates which are part of this template's linearization, in lineratization order.
* This template's linearization contains all of its direct and indirect super-classes and super-traits. */
def linearizationTemplates: List[TemplateEntity]
@@ -253,7 +288,7 @@ trait DocTemplateEntity extends TemplateEntity with MemberEntity {
/** All templates that are members of this template. If this template is a package, only templates for which
* documentation is available in the universe (`DocTemplateEntity`) are listed. */
- def templates: List[DocTemplateEntity]
+ def templates: List[TemplateEntity with MemberEntity]
/** All methods that are members of this template. */
def methods: List[Def]
@@ -267,6 +302,12 @@ trait DocTemplateEntity extends TemplateEntity with MemberEntity {
/** All type aliases that are members of this template. */
def aliasTypes: List[AliasType]
+ /** The primary constructor of this class, if it has been defined. */
+ def primaryConstructor: Option[Constructor]
+
+ /** All constructors of this class, including the primary constructor. */
+ def constructors: List[Constructor]
+
/** The companion of this template, or none. If a class and an object are defined as a pair of the same name, the
* other entity of the pair is the companion. */
def companion: Option[DocTemplateEntity]
@@ -289,41 +330,35 @@ trait DocTemplateEntity extends TemplateEntity with MemberEntity {
/** If this template contains other templates, such as classes and traits, they will be shown in this diagram */
def contentDiagram: Option[Diagram]
-}
+ /** Returns the group description taken either from this template or its linearizationTypes */
+ def groupDescription(group: String): Option[Body]
+
+ /** Returns the group description taken either from this template or its linearizationTypes */
+ def groupPriority(group: String): Int
+
+ /** Returns the group description taken either from this template or its linearizationTypes */
+ def groupName(group: String): String
+}
/** A trait template. */
-trait Trait extends DocTemplateEntity with HigherKinded {
+trait Trait extends MemberTemplateEntity {
def kind = "trait"
}
-
/** A class template. */
-trait Class extends Trait with HigherKinded {
-
- /** The primary constructor of this class, if it has been defined. */
- def primaryConstructor: Option[Constructor]
-
- /** All constructors of this class, including the primary constructor. */
- def constructors: List[Constructor]
-
- /** The value parameters of this case class, or an empty list if this class is not a case class. As case class value
- * parameters cannot be curried, the outer list has exactly one element. */
- def valueParams: List[List[ValueParam]]
-
+trait Class extends MemberTemplateEntity {
override def kind = "class"
}
-
/** An object template. */
-trait Object extends DocTemplateEntity {
+trait Object extends MemberTemplateEntity {
def kind = "object"
}
-
/** A package template. A package is in the universe if it is declared as a package object, or if it
* contains at least one template. */
-trait Package extends Object {
+trait Package extends DocTemplateEntity {
/** The package of which this package is a member. */
def inTemplate: Package
@@ -354,7 +389,6 @@ trait NonTemplateMemberEntity extends MemberEntity {
/** Whether this member is a bridge member. A bridge member does only exist for binary compatibility reasons
* and should not appear in ScalaDoc. */
def isBridge: Boolean
-
}
@@ -391,7 +425,7 @@ trait Val extends NonTemplateMemberEntity {
/** An abstract type member of a template. */
-trait AbstractType extends NonTemplateMemberEntity with HigherKinded {
+trait AbstractType extends MemberTemplateEntity with HigherKinded {
/** The lower bound for this abstract type, if it has been defined. */
def lo: Option[TypeEntity]
@@ -404,7 +438,7 @@ trait AbstractType extends NonTemplateMemberEntity with HigherKinded {
/** An type alias of a template. */
-trait AliasType extends NonTemplateMemberEntity with HigherKinded {
+trait AliasType extends MemberTemplateEntity with HigherKinded {
/** The type aliased by this type alias. */
def alias: TypeEntity
@@ -495,6 +529,9 @@ trait ImplicitConversion {
/** The members inherited by this implicit conversion */
def members: List[MemberEntity]
+
+ /** Is this a common implicit conversion (aka conversion that affects all classes, in Predef?) */
+ def isCommonConversion: Boolean
}
/** Shadowing captures the information that the member is shadowed by some other members
diff --git a/src/compiler/scala/tools/nsc/doc/model/IndexModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/IndexModelFactory.scala
index 6392de22ff..f4c96505a7 100755
--- a/src/compiler/scala/tools/nsc/doc/model/IndexModelFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/IndexModelFactory.scala
@@ -36,7 +36,6 @@ object IndexModelFactory {
} + d
this(firstLetter) = letter + (d.name -> members)
}
-
}
//@scala.annotation.tailrec // TODO
@@ -46,11 +45,7 @@ object IndexModelFactory {
case tpl: DocTemplateEntity =>
result.addMember(tpl)
gather(tpl)
- case alias: AliasType =>
- result.addMember(alias)
- case absType: AbstractType =>
- result.addMember(absType)
- case non: NonTemplateMemberEntity if !non.isConstructor =>
+ case non: MemberEntity if !non.isConstructor =>
result.addMember(non)
case x @ _ =>
}
diff --git a/src/compiler/scala/tools/nsc/doc/model/Links.scala b/src/compiler/scala/tools/nsc/doc/model/Links.scala
new file mode 100644
index 0000000000..b76dee0f14
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/doc/model/Links.scala
@@ -0,0 +1,24 @@
+/* NSC -- new Scala compiler
+ * Copyright 2007-2011 LAMP/EPFL
+ */
+
+package scala.tools.nsc
+package doc
+package model
+
+import scala.collection._
+
+abstract sealed class LinkTo
+case class LinkToTpl(tpl: DocTemplateEntity) extends LinkTo
+case class LinkToMember(mbr: MemberEntity, inTpl: DocTemplateEntity) extends LinkTo
+case class Tooltip(name: String) extends LinkTo { def this(tpl: TemplateEntity) = this(tpl.qualifiedName) }
+// case class LinkToExternal(name: String, url: String) extends LinkTo // for SI-191, whenever Manohar will have time
+case object NoLink extends LinkTo // you should use Tooltip if you have a name from the user, this is only in case all fails
+
+object LinkToTpl {
+ // this makes it easier to create links
+ def apply(tpl: TemplateEntity) = tpl match {
+ case dtpl: DocTemplateEntity => new LinkToTpl(dtpl)
+ case ntpl: TemplateEntity => new Tooltip(ntpl.qualifiedName)
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala b/src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala
new file mode 100644
index 0000000000..ab14498a7c
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala
@@ -0,0 +1,187 @@
+package scala.tools.nsc
+package doc
+package model
+
+import comment._
+
+import scala.reflect.internal.util.FakePos //Position
+
+/** This trait extracts all required information for documentation from compilation units */
+trait MemberLookup {
+ thisFactory: ModelFactory =>
+
+ import global._
+
+ def makeEntityLink(title: Inline, pos: Position, query: String, inTplOpt: Option[DocTemplateImpl]) =
+ new EntityLink(title) { lazy val link = memberLookup(pos, query, inTplOpt) }
+
+ def memberLookup(pos: Position, query: String, inTplOpt: Option[DocTemplateImpl]): LinkTo = {
+ assert(modelFinished)
+
+ var members = breakMembers(query)
+ //println(query + " => " + members)
+
+ // (1) Lookup in the root package, as most of the links are qualified
+ var linkTo: List[LinkTo] = lookupInRootPackage(pos, members)
+
+ // (2) Recursively go into each
+ if (inTplOpt.isDefined) {
+ var currentTpl = inTplOpt.get
+ while (currentTpl != null && !currentTpl.isRootPackage && (linkTo.isEmpty)) {
+ linkTo = lookupInTemplate(pos, members, currentTpl)
+ currentTpl = currentTpl.inTemplate
+ }
+ }
+
+ // (3) Look at external links
+ if (linkTo.isEmpty) {
+ // TODO: IF THIS IS THE ROOT PACKAGE, LOOK AT EXTERNAL LINKS
+ }
+
+ // (4) if we still haven't found anything, create a tooltip, if we found too many, report
+ if (linkTo.isEmpty){
+ if (!settings.docNoLinkWarnings.value)
+ reporter.warning(pos, "Could not find any member to link for \"" + query + "\".")
+ Tooltip(query)
+ } else {
+ if (linkTo.length > 1) {
+
+ val chosen =
+ if (linkTo.exists(_.isInstanceOf[LinkToMember]))
+ linkTo.collect({case lm: LinkToMember => lm}).min(Ordering[MemberEntity].on[LinkToMember](_.mbr))
+ else
+ linkTo.head
+
+ def linkToString(link: LinkTo) = {
+ val description =
+ link match {
+ case lm@LinkToMember(mbr, inTpl) => " * " + mbr.kind + " \"" + mbr.signature + "\" in " + inTpl.kind + " " + inTpl.qualifiedName
+ case lt@LinkToTpl(tpl) => " * " + tpl.kind + " \"" + tpl.qualifiedName + "\""
+ case other => " * " + other.toString
+ }
+ val chosenInfo =
+ if (link == chosen)
+ " [chosen]"
+ else
+ ""
+ description + chosenInfo + "\n"
+ }
+ if (!settings.docNoLinkWarnings.value)
+ reporter.warning(pos,
+ "The link target \"" + query + "\" is ambiguous. Several (possibly overloaded) members fit the target:\n" +
+ linkTo.map(link => linkToString(link)).mkString +
+ (if (MemberLookup.showExplanation)
+ "\n\n" +
+ "Quick crash course on using Scaladoc links\n" +
+ "==========================================\n" +
+ "Disambiguating terms and types: Prefix terms with '$' and types with '!' in case both names are in use:\n" +
+ " - [[scala.collection.immutable.List!.apply class List's apply method]] and\n" +
+ " - [[scala.collection.immutable.List$.apply object List's apply method]]\n" +
+ "Disambiguating overloaded members: If a term is overloaded, you can indicate the first part of its signature followed by *:\n" +
+ " - [[[scala.collection.immutable.List$.fill[A](Int)(⇒A):List[A]* Fill with a single parameter]]]\n" +
+ " - [[[scala.collection.immutable.List$.fill[A](Int,Int)(⇒A):List[List[A]]* Fill with a two parameters]]]\n" +
+ "Notes: \n" +
+ " - you can use any number of matching square brackets to avoid interference with the signature\n" +
+ " - you can use \\. to escape dots in prefixes (don't forget to use * at the end to match the signature!)\n" +
+ " - you can use \\# to escape hashes, otherwise they will be considered as delimiters, like dots.\n"
+ else "")
+ )
+ chosen
+ } else
+ linkTo.head
+ }
+ }
+
+ private abstract class SearchStrategy
+ private object BothTypeAndTerm extends SearchStrategy
+ private object OnlyType extends SearchStrategy
+ private object OnlyTerm extends SearchStrategy
+
+ private def lookupInRootPackage(pos: Position, members: List[String]) = lookupInTemplate(pos, members, makeRootPackage)
+
+ private def lookupInTemplate(pos: Position, members: List[String], inTpl: DocTemplateImpl): List[LinkTo] = {
+ // Maintaining compatibility with previous links is a bit tricky here:
+ // we have a preference for term names for all terms except for the last, where we prefer a class:
+ // How to do this:
+ // - at each step we do a DFS search with the prefered strategy
+ // - if the search doesn't return any members, we backtrack on the last decision
+ // * we look for terms with the last member's name
+ // * we look for types with the same name, all the way up
+ val result = members match {
+ case Nil =>
+ Nil
+ case mbrName::Nil =>
+ var members = lookupInTemplate(pos, mbrName, inTpl, OnlyType)
+ if (members.isEmpty)
+ members = lookupInTemplate(pos, mbrName, inTpl, OnlyTerm)
+
+ members.map(_ match {
+ case tpl: DocTemplateEntity => LinkToTpl(tpl)
+ case mbr => LinkToMember(mbr, inTpl)
+ })
+
+ case tplName::rest =>
+
+ def completeSearch(mbrs: List[MemberImpl]) =
+ mbrs.collect({case d:DocTemplateImpl => d}).flatMap(tpl => lookupInTemplate(pos, rest, tpl))
+
+ var members = completeSearch(lookupInTemplate(pos, tplName, inTpl, OnlyTerm))
+ if (members.isEmpty)
+ members = completeSearch(lookupInTemplate(pos, tplName, inTpl, OnlyType))
+
+ members
+ }
+ //println("lookupInTemplate(" + members + ", " + inTpl + ") => " + result)
+ result
+ }
+
+ private def lookupInTemplate(pos: Position, member: String, inTpl: DocTemplateImpl, strategy: SearchStrategy): List[MemberImpl] = {
+ val name = member.stripSuffix("$").stripSuffix("!").stripSuffix("*")
+ val result = if (member.endsWith("$"))
+ inTpl.members.filter(mbr => (mbr.name == name) && (mbr.isTerm))
+ else if (member.endsWith("!"))
+ inTpl.members.filter(mbr => (mbr.name == name) && (mbr.isType))
+ else if (member.endsWith("*"))
+ inTpl.members.filter(mbr => (mbr.signature.startsWith(name)))
+ else {
+ if (strategy == BothTypeAndTerm)
+ inTpl.members.filter(_.name == name)
+ else if (strategy == OnlyType)
+ inTpl.members.filter(mbr => (mbr.name == name) && (mbr.isType))
+ else if (strategy == OnlyTerm)
+ inTpl.members.filter(mbr => (mbr.name == name) && (mbr.isTerm))
+ else
+ Nil
+ }
+
+ //println("lookupInTemplate(" + member + ", " + inTpl + ") => " + result)
+ result
+ }
+
+ private def breakMembers(query: String): List[String] = {
+ // Okay, how does this work? Well: you split on . but you don't want to split on \. => thus the ugly regex
+ // query.split((?<=[^\\\\])\\.).map(_.replaceAll("\\."))
+ // The same code, just faster:
+ var members = List[String]()
+ var index = 0
+ var last_index = 0
+ val length = query.length
+ while (index < length) {
+ if ((query.charAt(index) == '.' || query.charAt(index) == '#') &&
+ ((index == 0) || (query.charAt(index-1) != '\\'))) {
+
+ members ::= query.substring(last_index, index).replaceAll("\\\\([#\\.])", "$1")
+ last_index = index + 1
+ }
+ index += 1
+ }
+ if (last_index < length)
+ members ::= query.substring(last_index, length).replaceAll("\\\\\\.", ".")
+ members.reverse
+ }
+}
+
+object MemberLookup {
+ private[this] var _showExplanation = true
+ def showExplanation: Boolean = if (_showExplanation) { _showExplanation = false; true } else false
+} \ No newline at end of file
diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
index 9fa6619e9f..00e6f3769e 100644
--- a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
@@ -19,7 +19,13 @@ import model.{ RootPackage => RootPackageEntity }
/** This trait extracts all required information for documentation from compilation units */
class ModelFactory(val global: Global, val settings: doc.Settings) {
- thisFactory: ModelFactory with ModelFactoryImplicitSupport with DiagramFactory with CommentFactory with TreeFactory =>
+ thisFactory: ModelFactory
+ with ModelFactoryImplicitSupport
+ with ModelFactoryTypeSupport
+ with DiagramFactory
+ with CommentFactory
+ with TreeFactory
+ with MemberLookup =>
import global._
import definitions.{ ObjectClass, NothingClass, AnyClass, AnyValClass, AnyRefClass }
@@ -32,7 +38,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
private var universe: Universe = null
private def dbg(msg: String) = if (sys.props contains "scala.scaladoc.debug") println(msg)
- private def closestPackage(sym: Symbol) = {
+ protected def closestPackage(sym: Symbol) = {
if (sym.isPackage || sym.isPackageClass) sym
else sym.enclosingPackage
}
@@ -63,7 +69,10 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
private val droppedPackages = mutable.Set[PackageImpl]()
protected val docTemplatesCache = new mutable.LinkedHashMap[Symbol, DocTemplateImpl]
protected val noDocTemplatesCache = new mutable.LinkedHashMap[Symbol, NoDocTemplateImpl]
- protected var typeCache = new mutable.LinkedHashMap[Type, TypeEntity]
+ def packageDropped(tpl: DocTemplateImpl) = tpl match {
+ case p: PackageImpl => droppedPackages(p)
+ case _ => false
+ }
def optimize(str: String): String =
if (str.length < 16) str.intern else str
@@ -83,6 +92,9 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
def toRoot: List[EntityImpl] = this :: inTpl.toRoot
def qualifiedName = name
def annotations = sym.annotations.map(makeAnnotation)
+ def inPackageObject: Boolean = sym.owner.isModuleClass && sym.owner.sourceModule.isPackageObject
+ def isType = sym.name.isTypeName
+ def isTerm = sym.name.isTermName
}
trait TemplateImpl extends EntityImpl with TemplateEntity {
@@ -94,13 +106,22 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
def isObject = sym.isModule && !sym.isPackage
def isCaseClass = sym.isCaseClass
def isRootPackage = false
- def ownType = makeType(sym.tpe, this)
+ def isNoDocMemberTemplate = false
def selfType = if (sym.thisSym eq sym) None else Some(makeType(sym.thisSym.typeOfThis, this))
- def inPackageObject: Boolean = sym.owner.isModuleClass && sym.owner.sourceModule.isPackageObject
}
- abstract class MemberImpl(sym: Symbol, implConv: ImplicitConversionImpl, inTpl: DocTemplateImpl) extends EntityImpl(sym, inTpl) with MemberEntity {
- lazy val comment = if (inTpl != null) thisFactory.comment(sym, inTpl) else None
+ abstract class MemberImpl(sym: Symbol, inTpl: DocTemplateImpl) extends EntityImpl(sym, inTpl) with MemberEntity {
+ lazy val comment = {
+ // If the current tpl is a DocTemplate, we consider itself as the root for resolving link targets (instead of the
+ // package the class is in) -- so people can refer to methods directly [[foo]], instead of using [[MyClass.foo]]
+ // in the doc comment of MyClass
+ val thisTpl = this match {
+ case d: DocTemplateImpl => Some(d)
+ case _ => None
+ }
+ if (inTpl != null) thisFactory.comment(sym, thisTpl, inTpl) else None
+ }
+ def group = if (comment.isDefined) comment.get.group.getOrElse("No Group") else "No Group"
override def inTemplate = inTpl
override def toRoot: List[MemberImpl] = this :: inTpl.toRoot
def inDefinitionTemplates = this match {
@@ -138,16 +159,16 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
* }}}
* the type the method returns is TraversableOps, which has all-abstract symbols. But in reality, it couldn't have
* any abstract terms, otherwise it would fail compilation. So we reset the DEFERRED flag. */
- if (!sym.isTrait && (sym hasFlag Flags.DEFERRED) && (implConv eq null)) fgs += Paragraph(Text("abstract"))
+ if (!sym.isTrait && (sym hasFlag Flags.DEFERRED) && (!isImplicitlyInherited)) fgs += Paragraph(Text("abstract"))
if (!sym.isModule && (sym hasFlag Flags.FINAL)) fgs += Paragraph(Text("final"))
fgs.toList
}
def deprecation =
if (sym.isDeprecated)
Some((sym.deprecationMessage, sym.deprecationVersion) match {
- case (Some(msg), Some(ver)) => parseWiki("''(Since version " + ver + ")'' " + msg, NoPosition)
- case (Some(msg), None) => parseWiki(msg, NoPosition)
- case (None, Some(ver)) => parseWiki("''(Since version " + ver + ")''", NoPosition)
+ case (Some(msg), Some(ver)) => parseWiki("''(Since version " + ver + ")'' " + msg, NoPosition, Some(inTpl))
+ case (Some(msg), None) => parseWiki(msg, NoPosition, Some(inTpl))
+ case (None, Some(ver)) => parseWiki("''(Since version " + ver + ")''", NoPosition, Some(inTpl))
case (None, None) => Body(Nil)
})
else
@@ -155,9 +176,9 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
def migration =
if(sym.hasMigrationAnnotation)
Some((sym.migrationMessage, sym.migrationVersion) match {
- case (Some(msg), Some(ver)) => parseWiki("''(Changed in version " + ver + ")'' " + msg, NoPosition)
- case (Some(msg), None) => parseWiki(msg, NoPosition)
- case (None, Some(ver)) => parseWiki("''(Changed in version " + ver + ")''", NoPosition)
+ case (Some(msg), Some(ver)) => parseWiki("''(Changed in version " + ver + ")'' " + msg, NoPosition, Some(inTpl))
+ case (Some(msg), None) => parseWiki(msg, NoPosition, Some(inTpl))
+ case (None, Some(ver)) => parseWiki("''(Changed in version " + ver + ")''", NoPosition, Some(inTpl))
case (None, None) => Body(Nil)
})
else
@@ -172,7 +193,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
case NullaryMethodType(res) => resultTpe(res)
case _ => tpe
}
- val tpe = if (implConv eq null) sym.tpe else implConv.toType memberInfo sym
+ val tpe = if (!isImplicitlyInherited) sym.tpe else byConversion.get.toType memberInfo sym
makeTypeInTemplateContext(resultTpe(tpe), inTemplate, sym)
}
def isDef = false
@@ -184,11 +205,43 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
def isAliasType = false
def isAbstractType = false
def isAbstract =
- // for the explanation of implConv == null see comment on flags
- ((!sym.isTrait && ((sym hasFlag Flags.ABSTRACT) || (sym hasFlag Flags.DEFERRED)) && (implConv == null)) ||
+ // for the explanation of conversion == null see comment on flags
+ ((!sym.isTrait && ((sym hasFlag Flags.ABSTRACT) || (sym hasFlag Flags.DEFERRED)) && (!isImplicitlyInherited)) ||
sym.isAbstractClass || sym.isAbstractType) && !sym.isSynthetic
def isTemplate = false
- def byConversion = if (implConv ne null) Some(implConv) else None
+ lazy val signature = {
+
+ def defParams(mbr: Any): String = mbr match {
+ case d: MemberEntity with Def =>
+ val paramLists: List[String] =
+ if (d.valueParams.isEmpty) Nil
+ else d.valueParams map (ps => ps map (_.resultType.name) mkString ("(",",",")"))
+ paramLists.mkString
+ case _ => ""
+ }
+
+ def tParams(mbr: Any): String = mbr match {
+ case hk: HigherKinded if !hk.typeParams.isEmpty =>
+ def boundsToString(hi: Option[TypeEntity], lo: Option[TypeEntity]): String = {
+ def bound0(bnd: Option[TypeEntity], pre: String): String = bnd match {
+ case None => ""
+ case Some(tpe) => pre ++ tpe.toString
+ }
+ bound0(hi, "<:") ++ bound0(lo, ">:")
+ }
+ "[" + hk.typeParams.map(tp => tp.variance + tp.name + tParams(tp) + boundsToString(tp.hi, tp.lo)).mkString(", ") + "]"
+ case _ => ""
+ }
+
+ (name + tParams(this) + defParams(this) +":"+ resultType.name).replaceAll("\\s","") // no spaces allowed, they break links
+ }
+ // these only apply for NonTemplateMemberEntities
+ def useCaseOf: Option[MemberEntity] = None
+ def byConversion: Option[ImplicitConversionImpl] = None
+ def isImplicitlyInherited = false
+ def isShadowedImplicit = false
+ def isAmbiguousImplicit = false
+ def isShadowedOrAmbiguousImplicit = false
}
/** A template that is not documented at all. The class is instantiated during lookups, to indicate that the class
@@ -198,26 +251,53 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
assert(modelFinished)
assert(!(noDocTemplatesCache isDefinedAt sym))
noDocTemplatesCache += (sym -> this)
-
def isDocTemplate = false
}
/** An inherited template that was not documented in its original owner - example:
* in classpath: trait T { class C } -- T (and implicitly C) are not documented
- * in the source: trait U extends T -- C appears in U as a NoDocTemplateMemberImpl -- that is, U has a member for it
+ * in the source: trait U extends T -- C appears in U as a MemberTemplateImpl -- that is, U has a member for it
* but C doesn't get its own page
*/
- class NoDocTemplateMemberImpl(sym: Symbol, inTpl: DocTemplateImpl) extends MemberImpl(sym, null, inTpl) with TemplateImpl with HigherKindedImpl with NoDocTemplateMemberEntity {
- assert(modelFinished)
-
+ abstract class MemberTemplateImpl(sym: Symbol, inTpl: DocTemplateImpl) extends MemberImpl(sym, inTpl) with TemplateImpl with HigherKindedImpl with MemberTemplateEntity {
+ // no templates cache for this class, each owner gets its own instance
+ override def isTemplate = true
def isDocTemplate = false
+ override def isNoDocMemberTemplate = true
lazy val definitionName = optimize(inDefinitionTemplates.head.qualifiedName + "." + name)
+ def valueParams: List[List[ValueParam]] = Nil /** TODO, these are now only computed for DocTemplates */
+
+ // Seems unused
+ // def parentTemplates =
+ // if (sym.isPackage || sym == AnyClass)
+ // List()
+ // else
+ // sym.tpe.parents.flatMap { tpe: Type =>
+ // val tSym = tpe.typeSymbol
+ // if (tSym != NoSymbol)
+ // List(makeTemplate(tSym))
+ // else
+ // List()
+ // } filter (_.isInstanceOf[DocTemplateEntity])
+
+ def parentTypes =
+ if (sym.isPackage || sym == AnyClass) List() else {
+ val tps = (this match {
+ case a: AliasType => sym.tpe.dealias.parents
+ case a: AbstractType => sym.info.bounds match {
+ case TypeBounds(lo, hi) => List(hi)
+ case _ => Nil
+ }
+ case _ => sym.tpe.parents
+ }) map { _.asSeenFrom(sym.thisType, sym) }
+ makeParentTypes(RefinedType(tps, EmptyScope), Some(this), inTpl)
+ }
}
/** The instantiation of `TemplateImpl` triggers the creation of the following entities:
* All ancestors of the template and all non-package members.
*/
- abstract class DocTemplateImpl(sym: Symbol, inTpl: DocTemplateImpl) extends MemberImpl(sym, null, inTpl) with TemplateImpl with HigherKindedImpl with DocTemplateEntity {
+ abstract class DocTemplateImpl(sym: Symbol, inTpl: DocTemplateImpl) extends MemberTemplateImpl(sym, inTpl) with DocTemplateEntity {
assert(!modelFinished)
assert(!(docTemplatesCache isDefinedAt sym), sym)
docTemplatesCache += (sym -> this)
@@ -253,24 +333,6 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
else None
}
- def parentTemplates =
- if (sym.isPackage || sym == AnyClass)
- List()
- else
- sym.tpe.parents.flatMap { tpe: Type =>
- val tSym = tpe.typeSymbol
- if (tSym != NoSymbol)
- List(makeTemplate(tSym))
- else
- List()
- } filter (_.isInstanceOf[DocTemplateEntity])
-
- def parentTypes =
- if (sym.isPackage || sym == AnyClass) List() else {
- val tps = sym.tpe.parents map { _.asSeenFrom(sym.thisType, sym) }
- makeParentTypes(RefinedType(tps, EmptyScope), Some(this), inTpl)
- }
-
protected def linearizationFromSymbol(symbol: Symbol): List[(TemplateEntity, TypeEntity)] = {
symbol.ancestors map { ancestor =>
val typeEntity = makeType(symbol.info.baseType(ancestor), this)
@@ -299,14 +361,14 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
def directSubClasses = allSubClasses.filter(_.parentTypes.map(_._1).contains(this))
/* Implcitly convertible class cache */
- private var implicitlyConvertibleClassesCache: mutable.ListBuffer[(DocTemplateEntity, ImplicitConversionImpl)] = null
- def registerImplicitlyConvertibleClass(dtpl: DocTemplateEntity, conv: ImplicitConversionImpl): Unit = {
+ private var implicitlyConvertibleClassesCache: mutable.ListBuffer[(DocTemplateImpl, ImplicitConversionImpl)] = null
+ def registerImplicitlyConvertibleClass(dtpl: DocTemplateImpl, conv: ImplicitConversionImpl): Unit = {
if (implicitlyConvertibleClassesCache == null)
- implicitlyConvertibleClassesCache = mutable.ListBuffer[(DocTemplateEntity, ImplicitConversionImpl)]()
+ implicitlyConvertibleClassesCache = mutable.ListBuffer[(DocTemplateImpl, ImplicitConversionImpl)]()
implicitlyConvertibleClassesCache += ((dtpl, conv))
}
- def incomingImplicitlyConvertedClasses: List[(DocTemplateEntity, ImplicitConversionImpl)] =
+ def incomingImplicitlyConvertedClasses: List[(DocTemplateImpl, ImplicitConversionImpl)] =
if (implicitlyConvertibleClassesCache == null)
List()
else
@@ -321,16 +383,16 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
lazy val memberSyms = sym.info.members.filter(s => membersShouldDocument(s, this))
// the inherited templates (classes, traits or objects)
- var memberSymsLazy = memberSyms.filter(t => templateShouldDocument(t, this) && !inOriginalOnwer(t, this))
+ var memberSymsLazy = memberSyms.filter(t => templateShouldDocument(t, this) && !inOriginalOwner(t, this))
// the direct members (methods, values, vars, types and directly contained templates)
var memberSymsEager = memberSyms.filter(!memberSymsLazy.contains(_))
// the members generated by the symbols in memberSymsEager
- val ownMembers = (memberSyms.flatMap(makeMember(_, null, this)))
+ val ownMembers = (memberSymsEager.flatMap(makeMember(_, None, this)))
// all the members that are documentented PLUS the members inherited by implicit conversions
var members: List[MemberImpl] = ownMembers
- def templates = members collect { case c: DocTemplateEntity => c }
+ def templates = members collect { case c: TemplateEntity with MemberEntity => c }
def methods = members collect { case d: Def => d }
def values = members collect { case v: Val => v }
def abstractTypes = members collect { case t: AbstractType => t }
@@ -342,13 +404,15 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
*/
def completeModel: Unit = {
// DFS completion
- for (member <- members)
- member match {
- case d: DocTemplateImpl => d.completeModel
- case _ =>
- }
+ // since alias types and abstract types have no own members, there's no reason for them to call completeModel
+ if (!sym.isAliasType && !sym.isAbstractType)
+ for (member <- members)
+ member match {
+ case d: DocTemplateImpl => d.completeModel
+ case _ =>
+ }
- members :::= memberSymsLazy.map(modelCreation.createLazyTemplateMember(_, inTpl))
+ members :::= memberSymsLazy.map(modelCreation.createLazyTemplateMember(_, this))
// compute linearization to register subclasses
linearization
@@ -369,7 +433,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
conv.targetTypeComponents map {
case pair@(template, tpe) =>
template match {
- case d: DocTemplateImpl => d.registerImplicitlyConvertibleClass(this, conv)
+ case d: DocTemplateImpl if (d != this) => d.registerImplicitlyConvertibleClass(this, conv)
case _ => // nothing
}
(pair._1, pair._2, conv)
@@ -378,21 +442,66 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
)
override def isTemplate = true
- lazy val definitionName = optimize(inDefinitionTemplates.head.qualifiedName + "." + name)
- def isDocTemplate = true
- def companion = sym.companionSymbol match {
- case NoSymbol => None
- case comSym if !isEmptyJavaObject(comSym) && (comSym.isClass || comSym.isModule) =>
- makeTemplate(comSym) match {
- case d: DocTemplateImpl => Some(d)
- case _ => None
+ override def isDocTemplate = true
+ private[this] lazy val companionSymbol =
+ if (sym.isAliasType || sym.isAbstractType) {
+ inTpl.sym.info.member(sym.name.toTermName) match {
+ case NoSymbol => NoSymbol
+ case s =>
+ s.info match {
+ case ot: OverloadedType =>
+ NoSymbol
+ case _ =>
+ // that's to navigate from val Foo: FooExtractor to FooExtractor :)
+ s.info.resultType.typeSymbol
+ }
}
- case _ => None
+ }
+ else
+ sym.companionSymbol
+
+ def companion =
+ companionSymbol match {
+ case NoSymbol => None
+ case comSym if !isEmptyJavaObject(comSym) && (comSym.isClass || comSym.isModule) =>
+ makeTemplate(comSym) match {
+ case d: DocTemplateImpl => Some(d)
+ case _ => None
+ }
+ case _ => None
+ }
+
+ def constructors: List[MemberImpl with Constructor] = if (isClass) members collect { case d: Constructor => d } else Nil
+ def primaryConstructor: Option[MemberImpl with Constructor] = if (isClass) constructors find { _.isPrimary } else None
+ override def valueParams =
+ // we don't want params on a class (non case class) signature
+ if (isCaseClass) primaryConstructor match {
+ case Some(const) => const.sym.paramss map (_ map (makeValueParam(_, this)))
+ case None => List()
+ }
+ else List.empty
+
+ // These are generated on-demand, make sure you don't call them more than once
+ def inheritanceDiagram = makeInheritanceDiagram(this)
+ def contentDiagram = makeContentDiagram(this)
+
+ def groupSearch[T](extractor: Comment => T, default: T): T = {
+ // query this template
+ if (comment.isDefined) {
+ val entity = extractor(comment.get)
+ if (entity != default) return entity
+ }
+ // query linearization
+ for (tpl <- linearizationTemplates.collect{ case dtpl: DocTemplateImpl if dtpl!=this => dtpl}) {
+ val entity = tpl.groupSearch(extractor, default)
+ if (entity != default) return entity
+ }
+ default
}
- // We make the diagram a lazy val, since we're not sure we'll include the diagrams in the page
- lazy val inheritanceDiagram = makeInheritanceDiagram(this)
- lazy val contentDiagram = makeContentDiagram(this)
+ def groupDescription(group: String): Option[Body] = groupSearch(_.groupDesc.get(group), None)
+ def groupPriority(group: String): Int = groupSearch(_.groupPrio.get(group) match { case Some(prio) => prio; case _ => 0 }, 0)
+ def groupName(group: String): String = groupSearch(_.groupNames.get(group) match { case Some(name) => name; case _ => group }, group)
}
abstract class PackageImpl(sym: Symbol, inTpl: PackageImpl) extends DocTemplateImpl(sym, inTpl) with Package {
@@ -409,18 +518,49 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
abstract class RootPackageImpl(sym: Symbol) extends PackageImpl(sym, null) with RootPackageEntity
- abstract class NonTemplateMemberImpl(sym: Symbol, implConv: ImplicitConversionImpl, inTpl: DocTemplateImpl) extends MemberImpl(sym, implConv, inTpl) with NonTemplateMemberEntity {
+ abstract class NonTemplateMemberImpl(sym: Symbol, conversion: Option[ImplicitConversionImpl],
+ override val useCaseOf: Option[MemberEntity], inTpl: DocTemplateImpl)
+ extends MemberImpl(sym, inTpl) with NonTemplateMemberEntity {
+ override lazy val comment = {
+ val inRealTpl =
+ /* Variable precendence order for implicitly added members: Take the variable defifinitions from ...
+ * 1. the target of the implicit conversion
+ * 2. the definition template (owner)
+ * 3. the current template
+ */
+ if (conversion.isDefined) findTemplateMaybe(conversion.get.toType.typeSymbol) match {
+ case Some(d) if d != makeRootPackage => d //in case of NoSymbol, it will give us the root package
+ case _ => findTemplateMaybe(sym.owner) match {
+ case Some(d) if d != makeRootPackage => d //in case of NoSymbol, it will give us the root package
+ case _ => inTpl
+ }
+ } else inTpl
+ if (inRealTpl != null) thisFactory.comment(sym, None, inRealTpl) else None
+ }
+
override def qualifiedName = optimize(inTemplate.qualifiedName + "#" + name)
- lazy val definitionName =
- if (implConv == null) optimize(inDefinitionTemplates.head.qualifiedName + "#" + name)
- else optimize(implConv.conversionQualifiedName + "#" + name)
- def isUseCase = sym.isSynthetic
+ lazy val definitionName = {
+ // this contrived name is here just to satisfy some older tests -- if you decide to remove it, be my guest, and
+ // also remove property("package object") from test/scaladoc/scalacheck/HtmlFactoryTest.scala so you don't break
+ // the test suite...
+ val packageObject = if (inPackageObject) ".package" else ""
+ if (!conversion.isDefined) optimize(inDefinitionTemplates.head.qualifiedName + packageObject + "#" + name)
+ else optimize(conversion.get.conversionQualifiedName + packageObject + "#" + name)
+ }
def isBridge = sym.isBridge
+ def isUseCase = useCaseOf.isDefined
+ override def byConversion: Option[ImplicitConversionImpl] = conversion
+ override def isImplicitlyInherited = { assert(modelFinished); conversion.isDefined }
+ override def isShadowedImplicit = isImplicitlyInherited && inTpl.implicitsShadowing.get(this).map(_.isShadowed).getOrElse(false)
+ override def isAmbiguousImplicit = isImplicitlyInherited && inTpl.implicitsShadowing.get(this).map(_.isAmbiguous).getOrElse(false)
+ override def isShadowedOrAmbiguousImplicit = isShadowedImplicit || isAmbiguousImplicit
}
- abstract class NonTemplateParamMemberImpl(sym: Symbol, implConv: ImplicitConversionImpl, inTpl: DocTemplateImpl) extends NonTemplateMemberImpl(sym, implConv, inTpl) {
+ abstract class NonTemplateParamMemberImpl(sym: Symbol, conversion: Option[ImplicitConversionImpl],
+ useCaseOf: Option[MemberEntity], inTpl: DocTemplateImpl)
+ extends NonTemplateMemberImpl(sym, conversion, useCaseOf, inTpl) {
def valueParams = {
- val info = if (implConv eq null) sym.info else implConv.toType memberInfo sym
+ val info = if (!isImplicitlyInherited) sym.info else conversion.get.toType memberInfo sym
info.paramss map { ps => (ps.zipWithIndex) map { case (p, i) =>
if (p.nameString contains "$") makeValueParam(p, inTpl, optimize("arg" + i)) else makeValueParam(p, inTpl)
}}
@@ -431,6 +571,12 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
val name = optimize(sym.nameString)
}
+ private trait AliasImpl {
+ def sym: Symbol
+ def inTpl: TemplateImpl
+ def alias = makeTypeInTemplateContext(sym.tpe.dealias, inTpl, sym)
+ }
+
private trait TypeBoundsImpl {
def sym: Symbol
def inTpl: TemplateImpl
@@ -454,14 +600,42 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
}
/* ============== MAKER METHODS ============== */
- /** */
+ /** This method makes it easier to work with the different kinds of symbols created by scalac by stripping down the
+ * package object abstraction and placing members directly in the package.
+ *
+ * Here's the explanation of what we do. The code:
+ *
+ * package foo {
+ * object `package` {
+ * class Bar
+ * }
+ * }
+ *
+ * will yield this Symbol structure:
+ * +---------+ (2)
+ * | |
+ * +---------------+ +---------- v ------- | ---+ +--------+ (2)
+ * | package foo#1 <---(1)---- module class foo#2 | | | |
+ * +---------------+ | +------------------ | -+ | +------------------- v ---+ |
+ * | | package object foo#3 <-----(1)---- module class package#4 | |
+ * | +----------------------+ | | +---------------------+ | |
+ * +--------------------------+ | | class package$Bar#5 | | |
+ * | +----------------- | -+ | |
+ * +------------------- | ---+ |
+ * | |
+ * +--------+
+ * (1) sourceModule
+ * (2) you get out of owners with .owner
+ *
+ * and normalizeTemplate(Bar.owner) will get us the package, instead of the module class of the package object.
+ */
def normalizeTemplate(aSym: Symbol): Symbol = aSym match {
case null | rootMirror.EmptyPackage | NoSymbol =>
normalizeTemplate(RootPackage)
case ObjectClass =>
normalizeTemplate(AnyRefClass)
case _ if aSym.isPackageObject =>
- aSym
+ normalizeTemplate(aSym.owner)
case _ if aSym.isModuleClass =>
normalizeTemplate(aSym.sourceModule)
case _ =>
@@ -477,13 +651,16 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
def createRootPackage: PackageImpl = docTemplatesCache.get(RootPackage) match {
case Some(root: PackageImpl) => root
- case _ => modelCreation.createTemplate(RootPackage, null).asInstanceOf[PackageImpl]
+ case _ => modelCreation.createTemplate(RootPackage, null) match {
+ case Some(root: PackageImpl) => root
+ case _ => sys.error("Scaladoc: Unable to create root package!")
+ }
}
/**
* Create a template, either a package, class, trait or object
*/
- def createTemplate(aSym: Symbol, inTpl: DocTemplateImpl): DocTemplateImpl = {
+ def createTemplate(aSym: Symbol, inTpl: DocTemplateImpl): Option[MemberImpl] = {
// don't call this after the model finished!
assert(!modelFinished)
@@ -493,7 +670,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
import Streamable._
Path(settings.docRootContent.value) match {
case f : File => {
- val rootComment = closing(f.inputStream)(is => parse(slurp(is), "", NoPosition))
+ val rootComment = closing(f.inputStream)(is => parse(slurp(is), "", NoPosition, Option(inTpl)))
Some(rootComment)
}
case _ => None
@@ -501,27 +678,24 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
}
def createDocTemplate(bSym: Symbol, inTpl: DocTemplateImpl): DocTemplateImpl = {
- if (bSym.isModule || (bSym.isAliasType && bSym.tpe.typeSymbol.isModule))
- new DocTemplateImpl(bSym, inTpl) with Object
- else if (bSym.isTrait || (bSym.isAliasType && bSym.tpe.typeSymbol.isTrait))
- new DocTemplateImpl(bSym, inTpl) with Trait
- else if (bSym.isClass || (bSym.isAliasType && bSym.tpe.typeSymbol.isClass))
- new DocTemplateImpl(bSym, inTpl) with Class {
- def valueParams =
- // we don't want params on a class (non case class) signature
- if (isCaseClass) List(sym.constrParamAccessors map (makeValueParam(_, this)))
- else List.empty
- val constructors =
- members collect { case d: Constructor => d }
- def primaryConstructor = constructors find { _.isPrimary }
- }
+ assert(!modelFinished) // only created BEFORE the model is finished
+ if (bSym.isAliasType && bSym != AnyRefClass)
+ new DocTemplateImpl(bSym, inTpl) with AliasImpl with AliasType { override def isAliasType = true }
+ else if (bSym.isAbstractType)
+ new DocTemplateImpl(bSym, inTpl) with TypeBoundsImpl with AbstractType { override def isAbstractType = true }
+ else if (bSym.isModule)
+ new DocTemplateImpl(bSym, inTpl) with Object {}
+ else if (bSym.isTrait)
+ new DocTemplateImpl(bSym, inTpl) with Trait {}
+ else if (bSym.isClass || bSym == AnyRefClass)
+ new DocTemplateImpl(bSym, inTpl) with Class {}
else
- sys.error("'" + bSym + "' isn't a class, trait or object thus cannot be built as a documentable template")
+ sys.error("'" + bSym + "' isn't a class, trait or object thus cannot be built as a documentable template.")
}
val bSym = normalizeTemplate(aSym)
if (docTemplatesCache isDefinedAt bSym)
- return docTemplatesCache(bSym)
+ return Some(docTemplatesCache(bSym))
/* Three cases of templates:
* (1) root package -- special cased for bootstrapping
@@ -529,7 +703,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
* (3) class/object/trait
*/
if (bSym == RootPackage) // (1)
- new RootPackageImpl(bSym) {
+ Some(new RootPackageImpl(bSym) {
override lazy val comment = createRootPackageComment
override val name = "root"
override def inTemplate = this
@@ -541,31 +715,52 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
(bSym.info.members ++ EmptyPackage.info.members) filter { s =>
s != EmptyPackage && s != RootPackage
}
- }
+ })
else if (bSym.isPackage) // (2)
- inTpl match {
- case inPkg: PackageImpl =>
- val pack = new PackageImpl(bSym, inPkg) {}
- if (pack.templates.isEmpty && pack.memberSymsLazy.isEmpty)
- droppedPackages += pack
- pack
- case _ =>
- sys.error("'" + bSym + "' must be in a package")
- }
+ if (settings.skipPackage(makeQualifiedName(bSym)))
+ None
+ else
+ inTpl match {
+ case inPkg: PackageImpl =>
+ val pack = new PackageImpl(bSym, inPkg) {}
+ // Used to check package pruning works:
+ //println(pack.qualifiedName)
+ if (pack.templates.filter(_.isDocTemplate).isEmpty && pack.memberSymsLazy.isEmpty) {
+ droppedPackages += pack
+ None
+ } else
+ Some(pack)
+ case _ =>
+ sys.error("'" + bSym + "' must be in a package")
+ }
else {
// no class inheritance at this point
- assert(inOriginalOnwer(bSym, inTpl))
- createDocTemplate(bSym, inTpl)
+ assert(inOriginalOwner(bSym, inTpl) || bSym.isAbstractType || bSym.isAliasType, bSym + " in " + inTpl)
+ Some(createDocTemplate(bSym, inTpl))
}
}
/**
* After the model is completed, no more DocTemplateEntities are created.
* Therefore any symbol that still appears is:
- * - NoDocTemplateMemberEntity (created here)
+ * - MemberTemplateEntity (created here)
* - NoDocTemplateEntity (created in makeTemplate)
*/
def createLazyTemplateMember(aSym: Symbol, inTpl: DocTemplateImpl): MemberImpl = {
+
+ // Code is duplicate because the anonymous classes are created statically
+ def createNoDocMemberTemplate(bSym: Symbol, inTpl: DocTemplateImpl): MemberTemplateImpl = {
+ assert(modelFinished) // only created AFTER the model is finished
+ if (bSym.isModule || (bSym.isAliasType && bSym.tpe.typeSymbol.isModule))
+ new MemberTemplateImpl(bSym, inTpl) with Object {}
+ else if (bSym.isTrait || (bSym.isAliasType && bSym.tpe.typeSymbol.isTrait))
+ new MemberTemplateImpl(bSym, inTpl) with Trait {}
+ else if (bSym.isClass || (bSym.isAliasType && bSym.tpe.typeSymbol.isClass))
+ new MemberTemplateImpl(bSym, inTpl) with Class {}
+ else
+ sys.error("'" + bSym + "' isn't a class, trait or object thus cannot be built as a member template.")
+ }
+
assert(modelFinished)
val bSym = normalizeTemplate(aSym)
@@ -579,7 +774,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
mbrs.head
case _ =>
// move the class completely to the new location
- new NoDocTemplateMemberImpl(aSym, inTpl)
+ createNoDocMemberTemplate(bSym, inTpl)
}
}
}
@@ -588,20 +783,18 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
def makeRootPackage: PackageImpl = docTemplatesCache(RootPackage).asInstanceOf[PackageImpl]
// TODO: Should be able to override the type
- def makeMember(aSym: Symbol, implConv: ImplicitConversionImpl, inTpl: DocTemplateImpl): List[MemberImpl] = {
+ def makeMember(aSym: Symbol, conversion: Option[ImplicitConversionImpl], inTpl: DocTemplateImpl): List[MemberImpl] = {
- def makeMember0(bSym: Symbol, _useCaseOf: Option[MemberImpl]): Option[MemberImpl] = {
+ def makeMember0(bSym: Symbol, useCaseOf: Option[MemberImpl]): Option[MemberImpl] = {
if (bSym.isGetter && bSym.isLazy)
- Some(new NonTemplateMemberImpl(bSym, implConv, inTpl) with Val {
+ Some(new NonTemplateMemberImpl(bSym, conversion, useCaseOf, inTpl) with Val {
override lazy val comment = // The analyser does not duplicate the lazy val's DocDef when it introduces its accessor.
- thisFactory.comment(bSym.accessed, inTpl.asInstanceOf[DocTemplateImpl]) // This hack should be removed after analyser is fixed.
+ thisFactory.comment(bSym.accessed, None, inTpl.asInstanceOf[DocTemplateImpl]) // This hack should be removed after analyser is fixed.
override def isLazyVal = true
- override def useCaseOf = _useCaseOf
})
else if (bSym.isGetter && bSym.accessed.isMutable)
- Some(new NonTemplateMemberImpl(bSym, implConv, inTpl) with Val {
+ Some(new NonTemplateMemberImpl(bSym, conversion, useCaseOf, inTpl) with Val {
override def isVar = true
- override def useCaseOf = _useCaseOf
})
else if (bSym.isMethod && !bSym.hasAccessorFlag && !bSym.isConstructor && !bSym.isModule) {
val cSym = { // This unsightly hack closes issue #4086.
@@ -615,45 +808,32 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
}
else bSym
}
- Some(new NonTemplateParamMemberImpl(cSym, implConv, inTpl) with HigherKindedImpl with Def {
+ Some(new NonTemplateParamMemberImpl(cSym, conversion, useCaseOf, inTpl) with HigherKindedImpl with Def {
override def isDef = true
- override def useCaseOf = _useCaseOf
})
}
- else if (bSym.isConstructor && (implConv == null))
- Some(new NonTemplateParamMemberImpl(bSym, implConv, inTpl) with Constructor {
- override def isConstructor = true
- def isPrimary = sym.isPrimaryConstructor
- override def useCaseOf = _useCaseOf
- })
+ else if (bSym.isConstructor)
+ if (conversion.isDefined)
+ None // don't list constructors inherted by implicit conversion
+ else
+ Some(new NonTemplateParamMemberImpl(bSym, conversion, useCaseOf, inTpl) with Constructor {
+ override def isConstructor = true
+ def isPrimary = sym.isPrimaryConstructor
+ })
else if (bSym.isGetter) // Scala field accessor or Java field
- Some(new NonTemplateMemberImpl(bSym, implConv, inTpl) with Val {
+ Some(new NonTemplateMemberImpl(bSym, conversion, useCaseOf, inTpl) with Val {
override def isVal = true
- override def useCaseOf = _useCaseOf
})
- else if (bSym.isAbstractType)
- Some(new NonTemplateMemberImpl(bSym, implConv, inTpl) with TypeBoundsImpl with HigherKindedImpl with AbstractType {
+ else if (bSym.isAbstractType && !typeShouldDocument(bSym, inTpl))
+ Some(new MemberTemplateImpl(bSym, inTpl) with TypeBoundsImpl with AbstractType {
override def isAbstractType = true
- override def useCaseOf = _useCaseOf
})
- else if (bSym.isAliasType && bSym != AnyRefClass)
- Some(new NonTemplateMemberImpl(bSym, implConv, inTpl) with HigherKindedImpl with AliasType {
+ else if (bSym.isAliasType && !typeShouldDocument(bSym, inTpl))
+ Some(new MemberTemplateImpl(bSym, inTpl) with AliasImpl with AliasType {
override def isAliasType = true
- def alias = makeTypeInTemplateContext(sym.tpe.dealias, inTpl, sym)
- override def useCaseOf = _useCaseOf
})
- else if (bSym.isPackage && !modelFinished)
- inTpl match {
- case inPkg: PackageImpl => modelCreation.createTemplate(bSym, inTpl) match {
- case p: PackageImpl if droppedPackages contains p => None
- case p: PackageImpl => Some(p)
- case _ => sys.error("'" + bSym + "' must be a package")
- }
- case _ =>
- sys.error("'" + bSym + "' must be in a package")
- }
- else if (!modelFinished && templateShouldDocument(bSym, inTpl) && inOriginalOnwer(bSym, inTpl))
- Some(modelCreation.createTemplate(bSym, inTpl))
+ else if (!modelFinished && (bSym.isPackage || bSym.isAliasType || bSym.isAbstractType || templateShouldDocument(bSym, inTpl)))
+ modelCreation.createTemplate(bSym, inTpl)
else
None
}
@@ -680,17 +860,20 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
inTpl.members.find(_.sym == aSym)
}
+ @deprecated("2.10", "Use findLinkTarget instead!")
def findTemplate(query: String): Option[DocTemplateImpl] = {
assert(modelFinished)
- docTemplatesCache.values find { (tpl: TemplateImpl) => tpl.qualifiedName == query && !tpl.isObject }
+ docTemplatesCache.values find { (tpl: DocTemplateImpl) => tpl.qualifiedName == query && !packageDropped(tpl) && !tpl.isObject }
}
def findTemplateMaybe(aSym: Symbol): Option[DocTemplateImpl] = {
assert(modelFinished)
- docTemplatesCache.get(normalizeTemplate(aSym))
+ docTemplatesCache.get(normalizeTemplate(aSym)).filterNot(packageDropped(_))
}
- def makeTemplate(aSym: Symbol): TemplateImpl = {
+ def makeTemplate(aSym: Symbol): TemplateImpl = makeTemplate(aSym, None)
+
+ def makeTemplate(aSym: Symbol, inTpl: Option[TemplateImpl]): TemplateImpl = {
assert(modelFinished)
def makeNoDocTemplate(aSym: Symbol, inTpl: TemplateImpl): NoDocTemplateImpl = {
@@ -706,11 +889,10 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
dtpl
case None =>
val bSym = normalizeTemplate(aSym)
- makeNoDocTemplate(bSym, makeTemplate(bSym.owner))
+ makeNoDocTemplate(bSym, if (inTpl.isDefined) inTpl.get else makeTemplate(bSym.owner))
}
}
-
/** */
def makeAnnotation(annot: AnnotationInfo): Annotation = {
val aSym = annot.symbol
@@ -720,7 +902,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
val arguments = { // lazy
def noParams = annot.args map { _ => None }
val params: List[Option[ValueParam]] = annotationClass match {
- case aClass: Class =>
+ case aClass: DocTemplateEntity with Class =>
(aClass.primaryConstructor map { _.valueParams.head }) match {
case Some(vps) => vps map { Some(_) }
case None => noParams
@@ -795,17 +977,37 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
}
/** Get the types of the parents of the current class, ignoring the refinements */
- def makeParentTypes(aType: Type, tpl: Option[DocTemplateImpl], inTpl: TemplateImpl): List[(TemplateEntity, TypeEntity)] = aType match {
+ def makeParentTypes(aType: Type, tpl: Option[MemberTemplateImpl], inTpl: TemplateImpl): List[(TemplateEntity, TypeEntity)] = aType match {
case RefinedType(parents, defs) =>
- val ignoreParents = Set[Symbol](AnyRefClass, ObjectClass)
+ val ignoreParents = Set[Symbol](AnyClass, AnyRefClass, ObjectClass)
val filtParents =
// we don't want to expose too many links to AnyRef, that will just be redundant information
- if (tpl.isDefined && (!tpl.get.isObject && parents.length < 2))
+ if (tpl.isDefined && { val sym = tpl.get.sym; (!sym.isModule && parents.length < 2) || (sym == AnyValClass) || (sym == AnyRefClass) || (sym == AnyClass) })
parents
else
parents.filterNot((p: Type) => ignoreParents(p.typeSymbol))
+
+ /** Returns:
+ * - a DocTemplate if the type's symbol is documented
+ * - a NoDocTemplateMember if the type's symbol is not documented in its parent but in another template
+ * - a NoDocTemplate if the type's symbol is not documented at all */
+ def makeTemplateOrMemberTemplate(parent: Type): TemplateImpl = {
+ def noDocTemplate = makeTemplate(parent.typeSymbol)
+ findTemplateMaybe(parent.typeSymbol) match {
+ case Some(tpl) => tpl
+ case None => parent match {
+ case TypeRef(pre, sym, args) =>
+ findTemplateMaybe(pre.typeSymbol) match {
+ case Some(tpl) => findMember(parent.typeSymbol, tpl).collect({case t: TemplateImpl => t}).getOrElse(noDocTemplate)
+ case None => noDocTemplate
+ }
+ case _ => noDocTemplate
+ }
+ }
+ }
+
filtParents.map(parent => {
- val templateEntity = makeTemplate(parent.typeSymbol)
+ val templateEntity = makeTemplateOrMemberTemplate(parent)
val typeEntity = makeType(parent, inTpl)
(templateEntity, typeEntity)
})
@@ -813,160 +1015,38 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
List((makeTemplate(aType.typeSymbol), makeType(aType, inTpl)))
}
- /** */
- def makeType(aType: Type, inTpl: TemplateImpl): TypeEntity = {
- def templatePackage = closestPackage(inTpl.sym)
-
- def createTypeEntity = new TypeEntity {
- private val nameBuffer = new StringBuilder
- private var refBuffer = new immutable.TreeMap[Int, (TemplateEntity, Int)]
- private def appendTypes0(types: List[Type], sep: String): Unit = types match {
- case Nil =>
- case tp :: Nil =>
- appendType0(tp)
- case tp :: tps =>
- appendType0(tp)
- nameBuffer append sep
- appendTypes0(tps, sep)
- }
-
- private def appendType0(tpe: Type): Unit = tpe match {
- /* Type refs */
- case tp: TypeRef if definitions.isFunctionType(tp) =>
- val args = tp.normalize.typeArgs
- nameBuffer append '('
- appendTypes0(args.init, ", ")
- nameBuffer append ") ⇒ "
- appendType0(args.last)
- case tp: TypeRef if definitions.isScalaRepeatedParamType(tp) =>
- appendType0(tp.args.head)
- nameBuffer append '*'
- case tp: TypeRef if definitions.isByNameParamType(tp) =>
- nameBuffer append "⇒ "
- appendType0(tp.args.head)
- case tp: TypeRef if definitions.isTupleType(tp) =>
- val args = tp.normalize.typeArgs
- nameBuffer append '('
- appendTypes0(args, ", ")
- nameBuffer append ')'
- case TypeRef(pre, aSym, targs) =>
- val preSym = pre.widen.typeSymbol
- // There's a work in progress here trying to deal with the
- // places where undesirable prefixes are printed.
- // ...
- // If the prefix is something worthy of printing, see if the prefix type
- // is in the same package as the enclosing template. If so, print it
- // unqualified and they'll figure it out.
- //
- // val stripPrefixes = List(templatePackage.fullName + ".", "package.", "java.lang.")
- // if (!preSym.printWithoutPrefix) {
- // nameBuffer append stripPrefixes.foldLeft(pre.prefixString)(_ stripPrefix _)
- // }
- val bSym = normalizeTemplate(aSym)
- if (bSym.isNonClassType && bSym != AnyRefClass) {
- nameBuffer append bSym.decodedName
- } else {
- val tpl = makeTemplate(bSym)
- val pos0 = nameBuffer.length
- refBuffer += pos0 -> (tpl, tpl.name.length)
- nameBuffer append tpl.name
- }
- if (!targs.isEmpty) {
- nameBuffer append '['
- appendTypes0(targs, ", ")
- nameBuffer append ']'
- }
- /* Refined types */
- case RefinedType(parents, defs) =>
- val ignoreParents = Set[Symbol](AnyClass, ObjectClass)
- val filtParents = parents filterNot (x => ignoreParents(x.typeSymbol)) match {
- case Nil => parents
- case ps => ps
- }
- appendTypes0(filtParents, " with ")
- // XXX Still todo: properly printing refinements.
- // Since I didn't know how to go about displaying a multi-line type, I went with
- // printing single method refinements (which should be the most common) and printing
- // the number of members if there are more.
- defs.toList match {
- case Nil => ()
- case x :: Nil => nameBuffer append (" { " + x.defString + " }")
- case xs => nameBuffer append (" { ... /* %d definitions in type refinement */ }" format xs.size)
- }
- /* Eval-by-name types */
- case NullaryMethodType(result) =>
- nameBuffer append '⇒'
- appendType0(result)
- /* Polymorphic types */
- case PolyType(tparams, result) => assert(tparams.nonEmpty)
-// throw new Error("Polymorphic type '" + tpe + "' cannot be printed as a type")
- def typeParamsToString(tps: List[Symbol]): String = if (tps.isEmpty) "" else
- tps.map{tparam =>
- tparam.varianceString + tparam.name + typeParamsToString(tparam.typeParams)
- }.mkString("[", ", ", "]")
- nameBuffer append typeParamsToString(tparams)
- appendType0(result)
- case tpen =>
- nameBuffer append tpen.toString
+ def makeQualifiedName(sym: Symbol, relativeTo: Option[Symbol] = None): String = {
+ val stop = if (relativeTo.isDefined) relativeTo.get.ownerChain.toSet else Set[Symbol]()
+ var sym1 = sym
+ var path = new StringBuilder()
+ // var path = List[Symbol]()
+
+ while ((sym1 != NoSymbol) && (path.isEmpty || !stop(sym1))) {
+ val sym1Norm = normalizeTemplate(sym1)
+ if (!sym1.sourceModule.isPackageObject && sym1Norm != RootPackage) {
+ if (path.length != 0)
+ path.insert(0, ".")
+ path.insert(0, sym1Norm.nameString)
+ // path::= sym1Norm
}
- appendType0(aType)
- val refEntity = refBuffer
- val name = optimize(nameBuffer.toString)
+ sym1 = sym1.owner
}
- if (aType.isTrivial)
- typeCache.get(aType) match {
- case Some(typeEntity) => typeEntity
- case None =>
- val typeEntity = createTypeEntity
- typeCache += aType -> typeEntity
- typeEntity
- }
- else
- createTypeEntity
+ optimize(path.toString)
+ //path.mkString(".")
}
- def normalizeOwner(aSym: Symbol): Symbol =
- /*
- * Okay, here's the explanation of what happens. The code:
- *
- * package foo {
- * object `package` {
- * class Bar
- * }
- * }
- *
- * will yield this Symbol structure:
- *
- * +---------------+ +--------------------------+
- * | package foo#1 ----(1)---> module class foo#2 |
- * +---------------+ | +----------------------+ | +-------------------------+
- * | | package object foo#3 ------(1)---> module class package#4 |
- * | +----------------------+ | | +---------------------+ |
- * +--------------------------+ | | class package$Bar#5 | |
- * | +---------------------+ |
- * +-------------------------+
- * (1) sourceModule
- * (2) you get out of owners with .owner
- */
- normalizeTemplate(aSym) match {
- case bSym if bSym.isPackageObject =>
- normalizeOwner(bSym.owner)
- case bSym =>
- bSym
- }
-
- def inOriginalOnwer(aSym: Symbol, inTpl: TemplateImpl): Boolean =
- normalizeOwner(aSym.owner) == normalizeOwner(inTpl.sym)
+ def inOriginalOwner(aSym: Symbol, inTpl: TemplateImpl): Boolean =
+ normalizeTemplate(aSym.owner) == normalizeTemplate(inTpl.sym)
def templateShouldDocument(aSym: Symbol, inTpl: TemplateImpl): Boolean =
- (aSym.isClass || aSym.isModule || aSym == AnyRefClass) &&
+ (aSym.isTrait || aSym.isClass || aSym.isModule) &&
localShouldDocument(aSym) &&
!isEmptyJavaObject(aSym) &&
// either it's inside the original owner or we can document it later:
- (!inOriginalOnwer(aSym, inTpl) || (aSym.isPackageClass || (aSym.sourceFile != null)))
+ (!inOriginalOwner(aSym, inTpl) || (aSym.isPackageClass || (aSym.sourceFile != null)))
- def membersShouldDocument(sym: Symbol, inTpl: TemplateImpl) =
+ def membersShouldDocument(sym: Symbol, inTpl: TemplateImpl) = {
// pruning modules that shouldn't be documented
// Why Symbol.isInitialized? Well, because we need to avoid exploring all the space available to scaladoc
// from the classpath -- scaladoc is a hog, it will explore everything starting from the root package unless we
@@ -979,6 +1059,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
(!sym.isConstructor || sym.owner == inTpl.sym) &&
// If the @bridge annotation overrides a normal member, show it
!isPureBridge(sym)
+ }
def isEmptyJavaObject(aSym: Symbol): Boolean =
aSym.isModule && aSym.isJavaDefined &&
@@ -995,5 +1076,11 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
// the implicit conversions that are excluded from the pages should not appear in the diagram
def implicitExcluded(convertorMethod: String): Boolean = settings.hardcoded.commonConversionTargets.contains(convertorMethod)
+
+ // whether or not to create a page for an {abstract,alias} type
+ def typeShouldDocument(bSym: Symbol, inTpl: DocTemplateImpl) =
+ (settings.docExpandAllTypes.value && (bSym.sourceFile != null)) ||
+ { val rawComment = global.expandedDocComment(bSym, inTpl.sym)
+ rawComment.contains("@template") || rawComment.contains("@documentable") }
}
diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala
index 8cbf2ac1b6..a12b67c9ed 100644
--- a/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala
@@ -53,7 +53,7 @@ import model.{ RootPackage => RootPackageEntity }
* TODO: Give an overview here
*/
trait ModelFactoryImplicitSupport {
- thisFactory: ModelFactory with CommentFactory with TreeFactory =>
+ thisFactory: ModelFactory with ModelFactoryTypeSupport with CommentFactory with TreeFactory =>
import global._
import global.analyzer._
@@ -115,7 +115,7 @@ trait ModelFactoryImplicitSupport {
// Put the class-specific conversions in front
val (ownConversions, commonConversions) =
- conversions.partition(conv => !hardcoded.commonConversionTargets.contains(conv.conversionQualifiedName))
+ conversions.partition(!_.isCommonConversion)
ownConversions ::: commonConversions
}
@@ -242,7 +242,7 @@ trait ModelFactoryImplicitSupport {
available = Some(search.tree != EmptyTree)
} catch {
- case _ =>
+ case _: TypeError =>
}
}
@@ -329,11 +329,6 @@ trait ModelFactoryImplicitSupport {
}
}
- def makeQualifiedName(sym: Symbol): String = {
- val remove = Set[Symbol](RootPackage, RootClass, EmptyPackage, EmptyPackageClass)
- sym.ownerChain.filterNot(remove.contains(_)).reverse.map(_.nameString).mkString(".")
- }
-
/* ============== IMPLEMENTATION PROVIDING ENTITY TYPES ============== */
class ImplicitConversionImpl(
@@ -352,7 +347,7 @@ trait ModelFactoryImplicitSupport {
if (convSym != NoSymbol)
makeTemplate(convSym.owner)
else {
- error("Scaladoc implicits: Implicit conversion from " + sym.tpe + " to " + toType + " done by " + convSym + " = NoSymbol!")
+ error("Scaladoc implicits: " + toString + " = NoSymbol!")
makeRootPackage
}
@@ -408,29 +403,22 @@ trait ModelFactoryImplicitSupport {
debug("")
memberSyms.flatMap({ aSym =>
- makeTemplate(aSym.owner) match {
- case d: DocTemplateImpl =>
- // we can't just pick up nodes from the previous template, although that would be very convenient:
- // they need the byConversion field to be attached to themselves -- this is design decision I should
- // revisit soon
- //
- // d.ownMembers.collect({
- // // it's either a member or has a couple of usecases it's hidden behind
- // case m: MemberImpl if m.sym == aSym =>
- // m // the member itself
- // case m: MemberImpl if m.useCaseOf.isDefined && m.useCaseOf.get.asInstanceOf[MemberImpl].sym == aSym =>
- // m.useCaseOf.get.asInstanceOf[MemberImpl] // the usecase
- // })
- makeMember(aSym, this, d)
- case _ =>
- // should only happen if the code for this template is not part of the scaladoc run =>
- // members won't have any comments
- makeMember(aSym, this, inTpl)
- }
+ // we can't just pick up nodes from the original template, although that would be very convenient:
+ // they need the byConversion field to be attached to themselves and the types to be transformed by
+ // asSeenFrom
+
+ // at the same time, the member itself is in the inTpl, not in the new template -- but should pick up
+ // variables from the old template. Ugly huh? We'll always create the member inTpl, but it will change
+ // the template when expanding variables in the comment :)
+ makeMember(aSym, Some(this), inTpl)
})
}
lazy val members: List[MemberEntity] = memberImpls
+
+ def isCommonConversion = hardcoded.commonConversionTargets.contains(conversionQualifiedName)
+
+ override def toString = "Implcit conversion from " + sym.tpe + " to " + toType + " done by " + convSym
}
/* ========================= HELPER METHODS ========================== */
diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactoryTypeSupport.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryTypeSupport.scala
new file mode 100644
index 0000000000..d2a26d1309
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryTypeSupport.scala
@@ -0,0 +1,323 @@
+/* NSC -- new Scala compiler -- Copyright 2007-2011 LAMP/EPFL */
+
+package scala.tools.nsc
+package doc
+package model
+
+import comment._
+
+import diagram._
+
+import scala.collection._
+import scala.util.matching.Regex
+
+import symtab.Flags
+
+import io._
+
+import model.{ RootPackage => RootPackageEntity }
+
+/** This trait extracts all required information for documentation from compilation units */
+trait ModelFactoryTypeSupport {
+ thisFactory: ModelFactory
+ with ModelFactoryImplicitSupport
+ with ModelFactoryTypeSupport
+ with DiagramFactory
+ with CommentFactory
+ with TreeFactory =>
+
+ import global._
+ import definitions.{ ObjectClass, NothingClass, AnyClass, AnyValClass, AnyRefClass }
+ import rootMirror.{ RootPackage, RootClass, EmptyPackage }
+
+ protected var typeCache = new mutable.LinkedHashMap[Type, TypeEntity]
+
+ /** */
+ def makeType(aType: Type, inTpl: TemplateImpl): TypeEntity = {
+ def templatePackage = closestPackage(inTpl.sym)
+
+ def createTypeEntity = new TypeEntity {
+ private var nameBuffer = new StringBuilder
+ private var refBuffer = new immutable.TreeMap[Int, (LinkTo, Int)]
+ private def appendTypes0(types: List[Type], sep: String): Unit = types match {
+ case Nil =>
+ case tp :: Nil =>
+ appendType0(tp)
+ case tp :: tps =>
+ appendType0(tp)
+ nameBuffer append sep
+ appendTypes0(tps, sep)
+ }
+
+ private def appendType0(tpe: Type): Unit = tpe match {
+ /* Type refs */
+ case tp: TypeRef if definitions.isFunctionType(tp) =>
+ val args = tp.normalize.typeArgs
+ nameBuffer append '('
+ appendTypes0(args.init, ", ")
+ nameBuffer append ") ⇒ "
+ appendType0(args.last)
+ case tp: TypeRef if definitions.isScalaRepeatedParamType(tp) =>
+ appendType0(tp.args.head)
+ nameBuffer append '*'
+ case tp: TypeRef if definitions.isByNameParamType(tp) =>
+ nameBuffer append "⇒ "
+ appendType0(tp.args.head)
+ case tp: TypeRef if definitions.isTupleType(tp) =>
+ val args = tp.normalize.typeArgs
+ nameBuffer append '('
+ appendTypes0(args, ", ")
+ nameBuffer append ')'
+ case TypeRef(pre, aSym, targs) =>
+ val preSym = pre.widen.typeSymbol
+
+ // SI-3314/SI-4888: Classes, Traits and Types can be inherited from a template to another:
+ // class Enum { abstract class Value }
+ // class Day extends Enum { object Mon extends Value /*...*/ }
+ // ===> in such cases we have two options:
+ // (0) if there's no inheritance taking place (Enum#Value) we can link to the template directly
+ // (1) if we generate the doc template for Day, we can link to the correct member
+ // (2) if we don't generate the doc template, we should at least indicate the correct prefix in the tooltip
+ val bSym = normalizeTemplate(aSym)
+ val owner =
+ if ((preSym != NoSymbol) && /* it needs a prefix */
+ (preSym != bSym.owner) && /* prefix is different from owner */
+ (aSym == bSym)) /* normalization doesn't play tricks on us */
+ preSym
+ else
+ bSym.owner
+
+ val bTpl = findTemplateMaybe(bSym)
+ val link =
+ if (owner == bSym.owner && bTpl.isDefined)
+ // (0) the owner's class is linked AND has a template - lovely
+ LinkToTpl(bTpl.get)
+ else {
+ val oTpl = findTemplateMaybe(owner)
+ val bMbr = oTpl.map(findMember(bSym, _))
+ if (oTpl.isDefined && bMbr.isDefined && bMbr.get.isDefined)
+ // (1) the owner's class
+ LinkToMember(bMbr.get.get, oTpl.get) //ugh
+ else
+ // (2) if we still couldn't find the owner, show a tooltip with the qualified name
+ Tooltip(makeQualifiedName(bSym))
+ }
+
+ // SI-4360 Showing prefixes when necessary
+ // We check whether there's any directly accessible type with the same name in the current template OR if the
+ // type is inherited from one template to another. There may be multiple symbols with the same name in scope,
+ // but we won't show the prefix if our symbol is among them, only if *it's not* -- that's equal to showing
+ // the prefix only for ambiguous references, not for overloaded ones.
+ def needsPrefix: Boolean = {
+ if ((owner != bSym.owner || preSym.isRefinementClass) && (normalizeTemplate(owner) != inTpl.sym))
+ return true
+ // don't get tricked into prefixng method type params and existentials:
+ // I tried several tricks BUT adding the method for which I'm creating the type => that simply won't scale,
+ // as ValueParams are independent of their parent member, and I really don't want to add this information to
+ // all terms, as we're already over the allowed memory footprint
+ if (aSym.isTypeParameterOrSkolem || aSym.isExistentiallyBound /* existential or existential skolem */)
+ return false
+
+ for (tpl <- inTpl.sym.ownerChain) {
+ tpl.info.member(bSym.name) match {
+ case NoSymbol =>
+ // No syms with that name, look further inside the owner chain
+ case sym =>
+ // Symbol found -- either the correct symbol, another one OR an overloaded alternative
+ if (sym == bSym)
+ return false
+ else sym.info match {
+ case OverloadedType(owner, alternatives) =>
+ return alternatives.contains(bSym)
+ case _ =>
+ return true
+ }
+ }
+ }
+ // if it's not found in the owner chain, we can safely leave out the prefix
+ false
+ }
+
+ val prefix =
+ if (!settings.docNoPrefixes.value && needsPrefix && (bSym != AnyRefClass /* which we normalize */)) {
+ if (!owner.isRefinementClass) {
+ val qName = makeQualifiedName(owner, Some(inTpl.sym))
+ if (qName != "") qName + "." else ""
+ }
+ else {
+ nameBuffer append "("
+ appendType0(pre)
+ nameBuffer append ")#"
+ "" // we already appended the prefix
+ }
+ } else ""
+
+ //DEBUGGING:
+ //if (makeQualifiedName(bSym) == "pack1.A") println("needsPrefix(" + bSym + ", " + owner + ", " + inTpl.qualifiedName + ") => " + needsPrefix + " and prefix=" + prefix)
+
+ val name = prefix + bSym.nameString
+ val pos0 = nameBuffer.length
+ refBuffer += pos0 -> ((link, name.length))
+ nameBuffer append name
+
+ if (!targs.isEmpty) {
+ nameBuffer append '['
+ appendTypes0(targs, ", ")
+ nameBuffer append ']'
+ }
+ /* Refined types */
+ case RefinedType(parents, defs) =>
+ val ignoreParents = Set[Symbol](AnyClass, ObjectClass)
+ val filtParents = parents filterNot (x => ignoreParents(x.typeSymbol)) match {
+ case Nil => parents
+ case ps => ps
+ }
+ appendTypes0(filtParents, " with ")
+ // XXX Still todo: properly printing refinements.
+ // Since I didn't know how to go about displaying a multi-line type, I went with
+ // printing single method refinements (which should be the most common) and printing
+ // the number of members if there are more.
+ defs.toList match {
+ case Nil => ()
+ case x :: Nil => nameBuffer append (" { " + x.defString + " }")
+ case xs => nameBuffer append (" { ... /* %d definitions in type refinement */ }" format xs.size)
+ }
+ /* Eval-by-name types */
+ case NullaryMethodType(result) =>
+ nameBuffer append '⇒'
+ appendType0(result)
+
+ /* Polymorphic types */
+ case PolyType(tparams, result) => assert(tparams.nonEmpty)
+ def typeParamsToString(tps: List[Symbol]): String = if (tps.isEmpty) "" else
+ tps.map{tparam =>
+ tparam.varianceString + tparam.name + typeParamsToString(tparam.typeParams)
+ }.mkString("[", ", ", "]")
+ nameBuffer append typeParamsToString(tparams)
+ appendType0(result)
+
+ case et@ExistentialType(quantified, underlying) =>
+
+ def appendInfoStringReduced(sym: Symbol, tp: Type): Unit = {
+ if (sym.isType && !sym.isAliasType && !sym.isClass) {
+ tp match {
+ case PolyType(tparams, _) =>
+ nameBuffer append "["
+ appendTypes0(tparams.map(_.tpe), ", ")
+ nameBuffer append "]"
+ case _ =>
+ }
+ tp.resultType match {
+ case rt @ TypeBounds(_, _) =>
+ appendType0(rt)
+ case rt =>
+ nameBuffer append " <: "
+ appendType0(rt)
+ }
+ } else {
+ // fallback to the Symbol infoString
+ nameBuffer append sym.infoString(tp)
+ }
+ }
+
+ def appendClauses = {
+ nameBuffer append " forSome {"
+ var first = true
+ val qset = quantified.toSet
+ for (sym <- quantified) {
+ if (!first) { nameBuffer append ", " } else first = false
+ if (sym.isSingletonExistential) {
+ nameBuffer append "val "
+ nameBuffer append tpnme.dropSingletonName(sym.name)
+ nameBuffer append ": "
+ appendType0(dropSingletonType(sym.info.bounds.hi))
+ } else {
+ if (sym.flagString != "") nameBuffer append (sym.flagString + " ")
+ if (sym.keyString != "") nameBuffer append (sym.keyString + " ")
+ nameBuffer append sym.varianceString
+ nameBuffer append sym.nameString
+ appendInfoStringReduced(sym, sym.info)
+ }
+ }
+ nameBuffer append "}"
+ }
+
+ underlying match {
+ case TypeRef(pre, sym, args) if et.isRepresentableWithWildcards =>
+ appendType0(typeRef(pre, sym, Nil))
+ nameBuffer append "["
+ var first = true
+ val qset = quantified.toSet
+ for (arg <- args) {
+ if (!first) { nameBuffer append ", " } else first = false
+ arg match {
+ case TypeRef(_, sym, _) if (qset contains sym) =>
+ nameBuffer append "_"
+ appendInfoStringReduced(sym, sym.info)
+ case arg =>
+ appendType0(arg)
+ }
+ }
+ nameBuffer append "]"
+ case MethodType(_, _) | NullaryMethodType(_) | PolyType(_, _) =>
+ nameBuffer append "("
+ appendType0(underlying)
+ nameBuffer append ")"
+ appendClauses
+ case _ =>
+ appendType0(underlying)
+ appendClauses
+ }
+
+ case tb@TypeBounds(lo, hi) =>
+ if (tb.lo != TypeBounds.empty.lo) {
+ nameBuffer append " >: "
+ appendType0(lo)
+ }
+ if (tb.hi != TypeBounds.empty.hi) {
+ nameBuffer append " <: "
+ appendType0(hi)
+ }
+ // case tpen: ThisType | SingleType | SuperType =>
+ // if (tpen.isInstanceOf[ThisType] && tpen.asInstanceOf[ThisType].sym.isEffectiveRoot) {
+ // appendType0 typeRef(NoPrefix, sym, Nil)
+ // } else {
+ // val underlying =
+ // val pre = underlying.typeSymbol.skipPackageObject
+ // if (pre.isOmittablePrefix) pre.fullName + ".type"
+ // else prefixString + "type"
+ case tpen@ThisType(sym) =>
+ appendType0(typeRef(NoPrefix, sym, Nil))
+ nameBuffer append ".this"
+ if (!tpen.underlying.typeSymbol.skipPackageObject.isOmittablePrefix) nameBuffer append ".type"
+ case tpen@SuperType(thistpe, supertpe) =>
+ nameBuffer append "super["
+ appendType0(supertpe)
+ nameBuffer append "]"
+ case tpen@SingleType(pre, sym) =>
+ appendType0(typeRef(pre, sym, Nil))
+ if (!tpen.underlying.typeSymbol.skipPackageObject.isOmittablePrefix) nameBuffer append ".type"
+ case tpen =>
+ nameBuffer append tpen.toString
+ }
+ appendType0(aType)
+ val refEntity = refBuffer
+ val name = optimize(nameBuffer.toString)
+ nameBuffer = null
+ }
+
+ // SI-4360: Entity caching depends on both the type AND the template it's in, as the prefixes might change for the
+ // same type based on the template the type is shown in.
+ if (settings.docNoPrefixes.value) {
+ val cached = typeCache.get(aType)
+ cached match {
+ case Some(typeEntity) =>
+ typeEntity
+ case None =>
+ val typeEntity = createTypeEntity
+ typeCache += aType -> typeEntity
+ typeEntity
+ }
+ } else createTypeEntity
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/tools/nsc/doc/model/TypeEntity.scala b/src/compiler/scala/tools/nsc/doc/model/TypeEntity.scala
index 67e955f613..643067cca5 100644
--- a/src/compiler/scala/tools/nsc/doc/model/TypeEntity.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/TypeEntity.scala
@@ -9,7 +9,6 @@ package model
import scala.collection._
-
/** A type. Note that types and templates contain the same information only for the simplest types. For example, a type
* defines how a template's type parameters are instantiated (as in `List[Cow]`), what the template's prefix is
* (as in `johnsFarm.Cow`), and supports compound or structural types. */
@@ -21,9 +20,8 @@ abstract class TypeEntity {
/** Maps which parts of this type's name reference entities. The map is indexed by the position of the first
* character that reference some entity, and contains the entity and the position of the last referenced
* character. The referenced character ranges do not to overlap or nest. The map is sorted by position. */
- def refEntity: SortedMap[Int, (TemplateEntity, Int)]
+ def refEntity: SortedMap[Int, (LinkTo, Int)]
/** The human-readable representation of this type. */
override def toString = name
-
}
diff --git a/src/compiler/scala/tools/nsc/doc/model/comment/Body.scala b/src/compiler/scala/tools/nsc/doc/model/comment/Body.scala
index ecc3273903..3f0024cb68 100644
--- a/src/compiler/scala/tools/nsc/doc/model/comment/Body.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/comment/Body.scala
@@ -44,7 +44,6 @@ final case class Body(blocks: Seq[Block]) {
case inlines => Some(Chain(inlines))
}
}
-
}
/** A block-level element of text, such as a paragraph or code block. */
@@ -67,10 +66,14 @@ final case class Bold(text: Inline) extends Inline
final case class Underline(text: Inline) extends Inline
final case class Superscript(text: Inline) extends Inline
final case class Subscript(text: Inline) extends Inline
-final case class EntityLink(target: String, template: () => Option[TemplateEntity]) extends Inline
final case class Link(target: String, title: Inline) extends Inline
final case class Monospace(text: Inline) extends Inline
final case class Text(text: String) extends Inline
+abstract class EntityLink(val title: Inline) extends Inline { def link: LinkTo }
+object EntityLink {
+ def apply(title: Inline, linkTo: LinkTo) = new EntityLink(title) { def link: LinkTo = linkTo }
+ def unapply(el: EntityLink): Option[(Inline, LinkTo)] = Some((el.title, el.link))
+}
final case class HtmlTag(data: String) extends Inline {
def canClose(open: HtmlTag) = {
open.data.stripPrefix("<") == data.stripPrefix("</")
diff --git a/src/compiler/scala/tools/nsc/doc/model/comment/Comment.scala b/src/compiler/scala/tools/nsc/doc/model/comment/Comment.scala
index 7b70683db5..c8f4c2f285 100644
--- a/src/compiler/scala/tools/nsc/doc/model/comment/Comment.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/comment/Comment.scala
@@ -114,6 +114,18 @@ abstract class Comment {
/** A set of diagram directives for the content diagram */
def contentDiagram: List[String]
+ /** The group this member is part of */
+ def group: Option[String]
+
+ /** Member group descriptions */
+ def groupDesc: Map[String,Body]
+
+ /** Member group names (overriding the short tag) */
+ def groupNames: Map[String,String]
+
+ /** Member group priorities */
+ def groupPrio: Map[String,Int]
+
override def toString =
body.toString + "\n" +
(authors map ("@author " + _.toString)).mkString("\n") +
diff --git a/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala b/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala
index 2099315cc6..1a11964e37 100644
--- a/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala
@@ -23,7 +23,7 @@ import language.postfixOps
*
* @author Manohar Jonnalagedda
* @author Gilles Dubochet */
-trait CommentFactory { thisFactory: ModelFactory with CommentFactory =>
+trait CommentFactory { thisFactory: ModelFactory with CommentFactory with MemberLookup=>
val global: Global
import global.{ reporter, definitions }
@@ -31,16 +31,16 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory =>
protected val commentCache = mutable.HashMap.empty[(global.Symbol, TemplateImpl), Comment]
def addCommentBody(sym: global.Symbol, inTpl: TemplateImpl, docStr: String, docPos: global.Position): global.Symbol = {
- commentCache += (sym, inTpl) -> parse(docStr, docStr, docPos)
+ commentCache += (sym, inTpl) -> parse(docStr, docStr, docPos, None)
sym
}
- def comment(sym: global.Symbol, inTpl: DocTemplateImpl): Option[Comment] = {
+ def comment(sym: global.Symbol, currentTpl: Option[DocTemplateImpl], inTpl: DocTemplateImpl): Option[Comment] = {
val key = (sym, inTpl)
if (commentCache isDefinedAt key)
Some(commentCache(key))
else {
- val c = defineComment(sym, inTpl)
+ val c = defineComment(sym, currentTpl, inTpl)
if (c isDefined) commentCache += (sym, inTpl) -> c.get
c
}
@@ -50,7 +50,7 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory =>
* cases we have to give some `inTpl` comments (parent class for example)
* to the comment of the symbol.
* This function manages some of those cases : Param accessor and Primary constructor */
- def defineComment(sym: global.Symbol, inTpl: DocTemplateImpl):Option[Comment] = {
+ def defineComment(sym: global.Symbol, currentTpl: Option[DocTemplateImpl], inTpl: DocTemplateImpl):Option[Comment] = {
//param accessor case
// We just need the @param argument, we put it into the body
@@ -87,7 +87,8 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory =>
else {
val rawComment = global.expandedDocComment(sym, inTpl.sym).trim
if (rawComment != "") {
- val c = parse(rawComment, global.rawDocComment(sym), global.docCommentPos(sym))
+ val tplOpt = if (currentTpl.isDefined) currentTpl else Some(inTpl)
+ val c = parse(rawComment, global.rawDocComment(sym), global.docCommentPos(sym), tplOpt)
Some(c)
}
else None
@@ -113,7 +114,11 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory =>
constructor0: Option[Body] = None,
source0: Option[String] = None,
inheritDiagram0: List[String] = List.empty,
- contentDiagram0: List[String] = List.empty
+ contentDiagram0: List[String] = List.empty,
+ group0: Option[Body] = None,
+ groupDesc0: Map[String,Body] = Map.empty,
+ groupNames0: Map[String,Body] = Map.empty,
+ groupPrio0: Map[String,Body] = Map.empty
) : Comment = new Comment{
val body = if(body0 isDefined) body0.get else Body(Seq.empty)
val authors = authors0
@@ -132,6 +137,35 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory =>
val source = source0
val inheritDiagram = inheritDiagram0
val contentDiagram = contentDiagram0
+ val groupDesc = groupDesc0
+ val group =
+ group0 match {
+ case Some(Body(List(Paragraph(Chain(List(Summary(Text(groupId)))))))) => Some(groupId.toString.trim)
+ case _ => None
+ }
+ val groupPrio = groupPrio0 flatMap {
+ case (group, body) =>
+ try {
+ body match {
+ case Body(List(Paragraph(Chain(List(Summary(Text(prio))))))) => List(group -> prio.toInt)
+ case _ => List()
+ }
+ } catch {
+ case _: java.lang.NumberFormatException => List()
+ }
+ }
+ val groupNames = groupNames0 flatMap {
+ case (group, body) =>
+ try {
+ body match {
+ case Body(List(Paragraph(Chain(List(Summary(Text(name))))))) if (!name.trim.contains("\n")) => List(group -> (name.trim))
+ case _ => List()
+ }
+ } catch {
+ case _: java.lang.NumberFormatException => List()
+ }
+ }
+
}
protected val endOfText = '\u0003'
@@ -201,7 +235,7 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory =>
/** A Scaladoc tag linked to a symbol. Returns the name of the tag, the name
* of the symbol, and the rest of the line. */
protected val SymbolTag =
- new Regex("""\s*@(param|tparam|throws)\s+(\S*)\s*(.*)""")
+ new Regex("""\s*@(param|tparam|throws|groupdesc|groupname|groupprio)\s+(\S*)\s*(.*)""")
/** The start of a scaladoc code block */
protected val CodeBlockStart =
@@ -225,7 +259,8 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory =>
* @param comment The expanded comment string (including start and end markers) to be parsed.
* @param src The raw comment source string.
* @param pos The position of the comment in source. */
- protected def parse(comment: String, src: String, pos: Position): Comment = {
+ protected def parse(comment: String, src: String, pos: Position, inTplOpt: Option[DocTemplateImpl] = None): Comment = {
+ assert(!inTplOpt.isDefined || inTplOpt.get != null)
/** The cleaned raw comment as a list of lines. Cleaning removes comment
* start and end markers, line start markers and unnecessary whitespace. */
@@ -348,10 +383,11 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory =>
case None => List.empty
}
- val tagsWithoutDiagram = tags.filterNot(pair => pair._1 == inheritDiagramTag || pair._1 == contentDiagramTag)
+ val stripTags=List(inheritDiagramTag, contentDiagramTag, SimpleTagKey("template"), SimpleTagKey("documentable"))
+ val tagsWithoutDiagram = tags.filterNot(pair => stripTags.contains(pair._1))
val bodyTags: mutable.Map[TagKey, List[Body]] =
- mutable.Map(tagsWithoutDiagram mapValues {tag => tag map (parseWiki(_, pos))} toSeq: _*)
+ mutable.Map(tagsWithoutDiagram mapValues {tag => tag map (parseWiki(_, pos, inTplOpt))} toSeq: _*)
def oneTag(key: SimpleTagKey): Option[Body] =
((bodyTags remove key): @unchecked) match {
@@ -384,7 +420,7 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory =>
}
val com = createComment (
- body0 = Some(parseWiki(docBody.toString, pos)),
+ body0 = Some(parseWiki(docBody.toString, pos, inTplOpt)),
authors0 = allTags(SimpleTagKey("author")),
see0 = allTags(SimpleTagKey("see")),
result0 = oneTag(SimpleTagKey("return")),
@@ -400,7 +436,11 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory =>
constructor0 = oneTag(SimpleTagKey("constructor")),
source0 = Some(clean(src).mkString("\n")),
inheritDiagram0 = inheritDiagramText,
- contentDiagram0 = contentDiagramText
+ contentDiagram0 = contentDiagramText,
+ group0 = oneTag(SimpleTagKey("group")),
+ groupDesc0 = allSymsOneTag(SimpleTagKey("groupdesc")),
+ groupNames0 = allSymsOneTag(SimpleTagKey("groupname")),
+ groupPrio0 = allSymsOneTag(SimpleTagKey("groupprio"))
)
for ((key, _) <- bodyTags)
@@ -420,8 +460,10 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory =>
* - Removed start-of-line star and one whitespace afterwards (if present).
* - Removed all end-of-line whitespace.
* - Only `endOfLine` is used to mark line endings. */
- def parseWiki(string: String, pos: Position): Body = {
- new WikiParser(string, pos).document()
+ def parseWiki(string: String, pos: Position, inTplOpt: Option[DocTemplateImpl]): Body = {
+ assert(!inTplOpt.isDefined || inTplOpt.get != null)
+
+ new WikiParser(string, pos, inTplOpt).document()
}
/** TODO
@@ -429,7 +471,8 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory =>
* @author Ingo Maier
* @author Manohar Jonnalagedda
* @author Gilles Dubochet */
- protected final class WikiParser(val buffer: String, pos: Position) extends CharReader(buffer) { wiki =>
+ protected final class WikiParser(val buffer: String, pos: Position, inTplOpt: Option[DocTemplateImpl]) extends CharReader(buffer) { wiki =>
+ assert(!inTplOpt.isDefined || inTplOpt.get != null)
var summaryParsed = false
@@ -617,7 +660,7 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory =>
else if (check(",,")) subscript()
else if (check("[[")) link()
else {
- readUntil { char == safeTagMarker || check("''") || char == '`' || check("__") || char == '^' || check(",,") || check("[[") || isInlineEnd || checkParaEnded || char == endOfLine }
+ readUntil { char == safeTagMarker || check("''") || char == '`' || check("__") || char == '^' || check(",,") || check("[[") || check("{{") || isInlineEnd || checkParaEnded || char == endOfLine }
Text(getRead())
}
}
@@ -719,29 +762,27 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory =>
def link(): Inline = {
val SchemeUri = """([^:]+:.*)""".r
jump("[[")
- readUntil { check("]]") || check(" ") }
+ var parens = 1
+ readUntil { parens += 1; !check("[") }
+ getRead // clear the buffer
+ val start = "[" * parens
+ val stop = "]" * parens
+ //println("link with " + parens + " matching parens")
+ readUntil { check(stop) || check(" ") }
val target = getRead()
val title =
- if (!check("]]")) Some({
+ if (!check(stop)) Some({
jump(" ")
- inline(check("]]"))
+ inline(check(stop))
})
else None
- jump("]]")
+ jump(stop)
(target, title) match {
case (SchemeUri(uri), optTitle) =>
Link(uri, optTitle getOrElse Text(uri))
case (qualName, optTitle) =>
- optTitle foreach (text => reportError(pos, "entity link to " + qualName + " cannot have a custom title'" + text + "'"))
- // XXX rather than warning here we should allow unqualified names
- // to refer to members of the same package. The "package exists"
- // exclusion is because [[scala]] is used in some scaladoc.
- if (!qualName.contains(".") && !definitions.packageExists(qualName))
- reportError(pos, "entity link to " + qualName + " should be a fully qualified name")
-
- // move the template resolution as late as possible
- EntityLink(qualName, () => findTemplate(qualName))
+ makeEntityLink(optTitle getOrElse Text(target), pos, target, inTplOpt)
}
}
diff --git a/src/compiler/scala/tools/nsc/doc/model/diagram/Diagram.scala b/src/compiler/scala/tools/nsc/doc/model/diagram/Diagram.scala
index 8527ca4039..c2aa1f17f3 100644
--- a/src/compiler/scala/tools/nsc/doc/model/diagram/Diagram.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/diagram/Diagram.scala
@@ -13,18 +13,18 @@ import model._
abstract class Diagram {
def nodes: List[Node]
def edges: List[(Node, List[Node])]
- def isPackageDiagram = false
- def isClassDiagram = false
+ def isContentDiagram = false // Implemented by ContentDiagram
+ def isInheritanceDiagram = false // Implemented by InheritanceDiagram
def depthInfo: DepthInfo
}
-case class PackageDiagram(nodes:List[/*Class*/Node], edges:List[(Node, List[Node])]) extends Diagram {
- override def isPackageDiagram = true
- lazy val depthInfo = new PackageDiagramDepth(this)
+case class ContentDiagram(nodes:List[/*Class*/Node], edges:List[(Node, List[Node])]) extends Diagram {
+ override def isContentDiagram = true
+ lazy val depthInfo = new ContentDiagramDepth(this)
}
/** A class diagram */
-case class ClassDiagram(thisNode: ThisNode,
+case class InheritanceDiagram(thisNode: ThisNode,
superClasses: List[/*Class*/Node],
subClasses: List[/*Class*/Node],
incomingImplicits: List[ImplicitNode],
@@ -33,7 +33,7 @@ case class ClassDiagram(thisNode: ThisNode,
def edges = (thisNode -> (superClasses ::: outgoingImplicits)) ::
(subClasses ::: incomingImplicits).map(_ -> List(thisNode))
- override def isClassDiagram = true
+ override def isInheritanceDiagram = true
lazy val depthInfo = new DepthInfo {
def maxDepth = 3
def nodeDepth(node: Node) =
@@ -70,7 +70,8 @@ abstract class Node {
def isClassNode = if (tpl.isDefined) (tpl.get.isClass || tpl.get.qualifiedName == "scala.AnyRef") else false
def isTraitNode = if (tpl.isDefined) tpl.get.isTrait else false
def isObjectNode= if (tpl.isDefined) tpl.get.isObject else false
- def isOtherNode = !(isClassNode || isTraitNode || isObjectNode)
+ def isTypeNode = if (doctpl.isDefined) doctpl.get.isAbstractType || doctpl.get.isAliasType else false
+ def isOtherNode = !(isClassNode || isTraitNode || isObjectNode || isTypeNode)
def isImplicitNode = false
def isOutsideNode = false
def tooltip: Option[String]
@@ -91,6 +92,7 @@ abstract class Node {
object Node { def unapply(n: Node): Option[(TypeEntity, Option[TemplateEntity])] = Some((n.tpe, n.tpl)) }
object ClassNode { def unapply(n: Node): Option[(TypeEntity, Option[TemplateEntity])] = if (n.isClassNode) Some((n.tpe, n.tpl)) else None }
object TraitNode { def unapply(n: Node): Option[(TypeEntity, Option[TemplateEntity])] = if (n.isTraitNode) Some((n.tpe, n.tpl)) else None }
+object TypeNode { def unapply(n: Node): Option[(TypeEntity, Option[TemplateEntity])] = if (n.isTypeNode) Some((n.tpe, n.tpl)) else None }
object ObjectNode { def unapply(n: Node): Option[(TypeEntity, Option[TemplateEntity])] = if (n.isObjectNode) Some((n.tpe, n.tpl)) else None }
object OutsideNode { def unapply(n: Node): Option[(TypeEntity, Option[TemplateEntity])] = if (n.isOutsideNode) Some((n.tpe, n.tpl)) else None }
object OtherNode { def unapply(n: Node): Option[(TypeEntity, Option[TemplateEntity])] = if (n.isOtherNode) Some((n.tpe, n.tpl)) else None }
@@ -98,24 +100,24 @@ object OtherNode { def unapply(n: Node): Option[(TypeEntity, Option[TemplateEn
/** The node for the current class */
-case class ThisNode(tpe: TypeEntity, tpl: Option[TemplateEntity], tooltip: Option[String] = None) extends Node { override def isThisNode = true }
+case class ThisNode(tpe: TypeEntity, tpl: Option[TemplateEntity])(val tooltip: Option[String] = None) extends Node { override def isThisNode = true }
/** The usual node */
-case class NormalNode(tpe: TypeEntity, tpl: Option[TemplateEntity], tooltip: Option[String] = None) extends Node { override def isNormalNode = true }
+case class NormalNode(tpe: TypeEntity, tpl: Option[TemplateEntity])(val tooltip: Option[String] = None) extends Node { override def isNormalNode = true }
/** A class or trait the thisnode can be converted to by an implicit conversion
* TODO: I think it makes more sense to use the tpe links to templates instead of the TemplateEntity for implicit nodes
* since some implicit conversions convert the class to complex types that cannot be represented as a single tmeplate
*/
-case class ImplicitNode(tpe: TypeEntity, tpl: Option[TemplateEntity], tooltip: Option[String] = None) extends Node { override def isImplicitNode = true }
+case class ImplicitNode(tpe: TypeEntity, tpl: Option[TemplateEntity])(val tooltip: Option[String] = None) extends Node { override def isImplicitNode = true }
/** An outside node is shown in packages when a class from a different package makes it to the package diagram due to
* its relation to a class in the template (see @contentDiagram hideInheritedNodes annotation) */
-case class OutsideNode(tpe: TypeEntity, tpl: Option[TemplateEntity], tooltip: Option[String] = None) extends Node { override def isOutsideNode = true }
+case class OutsideNode(tpe: TypeEntity, tpl: Option[TemplateEntity])(val tooltip: Option[String] = None) extends Node { override def isOutsideNode = true }
// Computing and offering node depth information
-class PackageDiagramDepth(pack: PackageDiagram) extends DepthInfo {
+class ContentDiagramDepth(pack: ContentDiagram) extends DepthInfo {
private[this] var _maxDepth = 0
private[this] var _nodeDepth = Map[Node, Int]()
private[this] var seedNodes = Set[Node]()
diff --git a/src/compiler/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala b/src/compiler/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala
index 1a8ad193aa..2645d8fd14 100644
--- a/src/compiler/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala
@@ -18,21 +18,14 @@ import scala.collection.immutable.SortedMap
* @author Vlad Ureche
*/
trait DiagramFactory extends DiagramDirectiveParser {
- this: ModelFactory with DiagramFactory with CommentFactory with TreeFactory =>
+ this: ModelFactory with ModelFactoryTypeSupport with DiagramFactory with CommentFactory with TreeFactory =>
import this.global.definitions._
import this.global._
// the following can used for hardcoding different relations into the diagram, for bootstrapping purposes
- lazy val AnyNode = normalNode(AnyClass)
- lazy val AnyRefNode = normalNode(AnyRefClass)
- lazy val AnyValNode = normalNode(AnyValClass)
- lazy val NullNode = normalNode(NullClass)
- lazy val NothingNode = normalNode(NothingClass)
- def normalNode(sym: Symbol) =
- NormalNode(makeTemplate(sym).ownType, Some(makeTemplate(sym)))
def aggregationNode(text: String) =
- NormalNode(new TypeEntity { val name = text; val refEntity = SortedMap[Int, (TemplateEntity, Int)]() }, None)
+ NormalNode(new TypeEntity { val name = text; val refEntity = SortedMap[Int, (LinkTo, Int)]() }, None)()
/** Create the inheritance diagram for this template */
def makeInheritanceDiagram(tpl: DocTemplateImpl): Option[Diagram] = {
@@ -52,31 +45,30 @@ trait DiagramFactory extends DiagramDirectiveParser {
None
else {
// the main node
- val thisNode = ThisNode(tpl.ownType, Some(tpl), Some(tpl.qualifiedName + " (this " + tpl.kind + ")"))
+ val thisNode = ThisNode(tpl.resultType, Some(tpl))(Some(tpl.qualifiedName + " (this " + tpl.kind + ")"))
// superclasses
var superclasses: List[Node] =
tpl.parentTypes.collect {
- case p: (TemplateEntity, TypeEntity) if !classExcluded(p._1) => NormalNode(p._2, Some(p._1))
+ case p: (TemplateEntity, TypeEntity) if !classExcluded(p._1) => NormalNode(p._2, Some(p._1))()
}.reverse
// incoming implcit conversions
lazy val incomingImplicitNodes = tpl.incomingImplicitlyConvertedClasses.map {
case (incomingTpl, conv) =>
- ImplicitNode(incomingTpl.ownType, Some(incomingTpl), implicitTooltip(from=incomingTpl, to=tpl, conv=conv))
+ ImplicitNode(makeType(incomingTpl.sym.tpe, tpl), Some(incomingTpl))(implicitTooltip(from=incomingTpl, to=tpl, conv=conv))
}
// subclasses
var subclasses: List[Node] =
- tpl.directSubClasses.flatMap {
- case d: TemplateEntity if !classExcluded(d) => List(NormalNode(d.ownType, Some(d)))
- case _ => Nil
+ tpl.directSubClasses.collect {
+ case d: TemplateImpl if !classExcluded(d) => NormalNode(makeType(d.sym.tpe, tpl), Some(d))()
}.sortBy(_.tpl.get.name)(implicitly[Ordering[String]].reverse)
// outgoing implicit coversions
lazy val outgoingImplicitNodes = tpl.outgoingImplicitlyConvertedClasses.map {
case (outgoingTpl, outgoingType, conv) =>
- ImplicitNode(outgoingType, Some(outgoingTpl), implicitTooltip(from=tpl, to=tpl, conv=conv))
+ ImplicitNode(outgoingType, Some(outgoingTpl))(implicitTooltip(from=tpl, to=tpl, conv=conv))
}
// TODO: Everyone should be able to use the @{inherit,content}Diagram annotation to change the diagrams.
@@ -93,7 +85,7 @@ trait DiagramFactory extends DiagramDirectiveParser {
val filteredImplicitOutgoingNodes = if (diagramFilter.hideOutgoingImplicits) Nil else outgoingImplicitNodes
// final diagram filter
- filterDiagram(ClassDiagram(thisNode, filteredSuperclasses.reverse, filteredSubclasses.reverse, filteredIncomingImplicits, filteredImplicitOutgoingNodes), diagramFilter)
+ filterDiagram(InheritanceDiagram(thisNode, filteredSuperclasses.reverse, filteredSubclasses.reverse, filteredIncomingImplicits, filteredImplicitOutgoingNodes), diagramFilter)
}
tModel += System.currentTimeMillis
@@ -129,12 +121,10 @@ trait DiagramFactory extends DiagramDirectiveParser {
// for each node, add its subclasses
for (node <- nodesAll if !classExcluded(node)) {
node match {
- case dnode: DocTemplateImpl =>
- var superClasses = dnode.parentTypes.map(_._1)
+ case dnode: MemberTemplateImpl =>
+ var superClasses = dnode.parentTypes.map(_._1).filter(nodesAll.contains(_))
- superClasses = superClasses.filter(nodesAll.contains(_))
-
- // TODO: Everyone should be able to use the @{inherit,content}Diagram annotation to change the diagrams.
+ // TODO: Everyone should be able to use the @{inherit,content}Diagram annotation to add nodes to diagrams.
if (pack.sym == ScalaPackage)
if (dnode.sym == NullClass)
superClasses = List(makeTemplate(AnyRefClass))
@@ -149,7 +139,12 @@ trait DiagramFactory extends DiagramDirectiveParser {
case _ =>
}
- mapNodes += node -> (if (node.inTemplate == pack) NormalNode(node.ownType, Some(node)) else OutsideNode(node.ownType, Some(node)))
+ mapNodes += node -> (
+ if (node.inTemplate == pack && (node.isDocTemplate || node.isAbstractType || node.isAliasType))
+ NormalNode(node.resultType, Some(node))()
+ else
+ OutsideNode(node.resultType, Some(node))()
+ )
}
if (nodesShown.isEmpty)
@@ -173,9 +168,12 @@ trait DiagramFactory extends DiagramDirectiveParser {
val anyRefSubtypes = Nil
val allAnyRefTypes = aggregationNode("All AnyRef subtypes")
val nullTemplate = makeTemplate(NullClass)
- PackageDiagram(allAnyRefTypes::nodes, (mapNodes(nullTemplate), allAnyRefTypes::anyRefSubtypes)::edges.filterNot(_._1.tpl == Some(nullTemplate)))
+ if (nullTemplate.isDocTemplate)
+ ContentDiagram(allAnyRefTypes::nodes, (mapNodes(nullTemplate), allAnyRefTypes::anyRefSubtypes)::edges.filterNot(_._1.tpl == Some(nullTemplate)))
+ else
+ ContentDiagram(nodes, edges)
} else
- PackageDiagram(nodes, edges)
+ ContentDiagram(nodes, edges)
filterDiagram(diagram, diagramFilter)
}
@@ -200,10 +198,10 @@ trait DiagramFactory extends DiagramDirectiveParser {
else {
// Final diagram, with the filtered nodes and edges
diagram match {
- case ClassDiagram(thisNode, _, _, _, _) if diagramFilter.hideNode(thisNode) =>
+ case InheritanceDiagram(thisNode, _, _, _, _) if diagramFilter.hideNode(thisNode) =>
None
- case ClassDiagram(thisNode, superClasses, subClasses, incomingImplicits, outgoingImplicits) =>
+ case InheritanceDiagram(thisNode, superClasses, subClasses, incomingImplicits, outgoingImplicits) =>
def hideIncoming(node: Node): Boolean =
diagramFilter.hideNode(node) || diagramFilter.hideEdge(node, thisNode)
@@ -214,13 +212,13 @@ trait DiagramFactory extends DiagramDirectiveParser {
// println(thisNode)
// println(superClasses.map(cl => "super: " + cl + " " + hideOutgoing(cl)).mkString("\n"))
// println(subClasses.map(cl => "sub: " + cl + " " + hideIncoming(cl)).mkString("\n"))
- Some(ClassDiagram(thisNode,
+ Some(InheritanceDiagram(thisNode,
superClasses.filterNot(hideOutgoing(_)),
subClasses.filterNot(hideIncoming(_)),
incomingImplicits.filterNot(hideIncoming(_)),
outgoingImplicits.filterNot(hideOutgoing(_))))
- case PackageDiagram(nodes0, edges0) =>
+ case ContentDiagram(nodes0, edges0) =>
// Filter out all edges that:
// (1) are sources of hidden classes
// (2) are manually hidden by the user
@@ -242,7 +240,7 @@ trait DiagramFactory extends DiagramDirectiveParser {
val sourceNodes = edges.map(_._1)
val sinkNodes = edges.map(_._2).flatten
val nodes = (sourceNodes ::: sinkNodes).distinct
- Some(PackageDiagram(nodes, edges))
+ Some(ContentDiagram(nodes, edges))
}
}
diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala
index 76f02ed141..68f5e0e394 100644
--- a/src/compiler/scala/tools/nsc/interactive/Global.scala
+++ b/src/compiler/scala/tools/nsc/interactive/Global.scala
@@ -627,7 +627,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
response raise ex
throw ex
- case ex =>
+ case ex: Throwable =>
if (debugIDE) {
println("exception thrown during response: "+ex)
ex.printStackTrace()
diff --git a/src/compiler/scala/tools/nsc/interactive/PresentationCompilerThread.scala b/src/compiler/scala/tools/nsc/interactive/PresentationCompilerThread.scala
index 098884dab1..70d8a826d0 100644
--- a/src/compiler/scala/tools/nsc/interactive/PresentationCompilerThread.scala
+++ b/src/compiler/scala/tools/nsc/interactive/PresentationCompilerThread.scala
@@ -36,7 +36,7 @@ final class PresentationCompilerThread(var compiler: Global, name: String = "")
// make sure we don't keep around stale instances
compiler = null
- case ex =>
+ case ex: Throwable =>
compiler.log.flush()
ex match {
diff --git a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
index 2e0cc1a7c3..d934e9e3a3 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
@@ -25,7 +25,7 @@ import ScalaClassLoader._
import scala.tools.util._
import language.{implicitConversions, existentials}
import scala.reflect.{ClassTag, classTag}
-import scala.tools.reflect.StdTags._
+import scala.tools.reflect.StdRuntimeTags._
/** The Scala interactive shell. It provides a read-eval-print loop
* around the Interpreter class.
diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala
index 5a8bbfff15..05a77ee979 100644
--- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/IMain.scala
@@ -28,7 +28,7 @@ import typechecker.Analyzer
import language.implicitConversions
import scala.reflect.runtime.{ universe => ru }
import scala.reflect.{ ClassTag, classTag }
-import scala.tools.reflect.StdTags._
+import scala.tools.reflect.StdRuntimeTags._
/** directory to save .class files to */
private class ReplVirtualDirectory(out: JPrintWriter) extends VirtualDirectory("(memory)", None) {
diff --git a/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala
index f0ee8b11f3..0991577829 100644
--- a/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala
@@ -40,9 +40,9 @@ trait StandardScalaSettings {
val nowarn = BooleanSetting ("-nowarn", "Generate no warnings.")
val optimise: BooleanSetting // depends on post hook which mutates other settings
val print = BooleanSetting ("-print", "Print program with Scala-specific features removed.")
- val target = ChoiceSetting ("-target", "target", "Target platform for object files.",
+ val target = ChoiceSetting ("-target", "target", "Target platform for object files. All JVM 1.5 targets are deprecated.",
List("jvm-1.5", "jvm-1.5-fjbg", "jvm-1.5-asm", "jvm-1.6", "jvm-1.7", "msil"),
- "jvm-1.5-asm")
+ "jvm-1.6")
val unchecked = BooleanSetting ("-unchecked", "Enable detailed unchecked (erasure) warnings.")
val uniqid = BooleanSetting ("-uniqid", "Uniquely tag all identifiers in debugging output.")
val usejavacp = BooleanSetting ("-usejavacp", "Utilize the java.class.path in classpath resolution.")
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
index 0c988ceae4..9b4e793241 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
@@ -34,8 +34,7 @@ abstract class SymbolLoaders {
/** Enter class with given `name` into scope of `root`
* and give them `completer` as type.
*/
- def enterClass(root: Symbol, name: String, completer: SymbolLoader): Symbol = {
- val owner = root.ownerOfNewSymbols
+ def enterClass(owner: Symbol, name: String, completer: SymbolLoader): Symbol = {
val clazz = owner.newClass(newTypeName(name))
clazz setInfo completer
enterIfNew(owner, clazz, completer)
@@ -44,8 +43,7 @@ abstract class SymbolLoaders {
/** Enter module with given `name` into scope of `root`
* and give them `completer` as type.
*/
- def enterModule(root: Symbol, name: String, completer: SymbolLoader): Symbol = {
- val owner = root.ownerOfNewSymbols
+ def enterModule(owner: Symbol, name: String, completer: SymbolLoader): Symbol = {
val module = owner.newModule(newTermName(name))
module setInfo completer
module.moduleClass setInfo moduleClassLoader
@@ -217,15 +215,18 @@ abstract class SymbolLoaders {
root.setInfo(new PackageClassInfoType(newScope, root))
val sourcepaths = classpath.sourcepaths
- for (classRep <- classpath.classes if platform.doLoad(classRep)) {
- initializeFromClassPath(root, classRep)
+ if (!root.isRoot) {
+ for (classRep <- classpath.classes if platform.doLoad(classRep)) {
+ initializeFromClassPath(root, classRep)
+ }
}
+ if (!root.isEmptyPackageClass) {
+ for (pkg <- classpath.packages) {
+ enterPackage(root, pkg.name, new PackageLoader(pkg))
+ }
- for (pkg <- classpath.packages) {
- enterPackage(root, pkg.name, new PackageLoader(pkg))
+ openPackageModule(root)
}
-
- openPackageModule(root)
}
}
diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala
index bbdf10a021..e672f1914a 100644
--- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala
+++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala
@@ -23,9 +23,12 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
new CleanUpTransformer(unit)
class CleanUpTransformer(unit: CompilationUnit) extends Transformer {
- private val newStaticMembers = mutable.Buffer.empty[Tree]
- private val newStaticInits = mutable.Buffer.empty[Tree]
- private val symbolsStoredAsStatic = mutable.Map.empty[String, Symbol]
+ private val newStaticMembers = mutable.Buffer.empty[Tree]
+ private val newStaticInits = mutable.Buffer.empty[Tree]
+ private val symbolsStoredAsStatic = mutable.Map.empty[String, Symbol]
+ private val staticBodies = mutable.Map.empty[(Symbol, Symbol), Tree]
+ private val syntheticClasses = mutable.Map.empty[Symbol, mutable.Set[Tree]] // package and trees
+ private val classNames = mutable.Map.empty[Symbol, Set[Name]]
private def clearStatics() {
newStaticMembers.clear()
newStaticInits.clear()
@@ -45,15 +48,16 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
result
}
private def transformTemplate(tree: Tree) = {
- val Template(parents, self, body) = tree
+ val t @ Template(parents, self, body) = tree
clearStatics()
+
val newBody = transformTrees(body)
val templ = deriveTemplate(tree)(_ => transformTrees(newStaticMembers.toList) ::: newBody)
try addStaticInits(templ) // postprocess to include static ctors
finally clearStatics()
}
private def mkTerm(prefix: String): TermName = unit.freshTermName(prefix)
-
+
/** Kludge to provide a safe fix for #4560:
* If we generate a reference in an implementation class, we
* watch out for embedded This(..) nodes that point to the interface.
@@ -555,7 +559,73 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
else tree
}
-
+
+ case ValDef(mods, name, tpt, rhs) if tree.symbol.hasStaticAnnotation =>
+ log("moving @static valdef field: " + name + ", in: " + tree.symbol.owner)
+ val sym = tree.symbol
+ val owner = sym.owner
+
+ val staticBeforeLifting = atPhase(currentRun.erasurePhase) { owner.isStatic }
+ val isPrivate = atPhase(currentRun.typerPhase) { sym.getter(owner).hasFlag(PRIVATE) }
+ val isProtected = atPhase(currentRun.typerPhase) { sym.getter(owner).hasFlag(PROTECTED) }
+ val isLazy = atPhase(currentRun.typerPhase) { sym.getter(owner).hasFlag(LAZY) }
+ if (!owner.isModuleClass || !staticBeforeLifting) {
+ if (!sym.isSynthetic) {
+ reporter.error(tree.pos, "Only members of top-level objects and their nested objects can be annotated with @static.")
+ tree.symbol.removeAnnotation(StaticClass)
+ }
+ super.transform(tree)
+ } else if (isPrivate || isProtected) {
+ reporter.error(tree.pos, "The @static annotation is only allowed on public members.")
+ tree.symbol.removeAnnotation(StaticClass)
+ super.transform(tree)
+ } else if (isLazy) {
+ reporter.error(tree.pos, "The @static annotation is not allowed on lazy members.")
+ tree.symbol.removeAnnotation(StaticClass)
+ super.transform(tree)
+ } else if (owner.isModuleClass) {
+ val linkedClass = owner.companionClass match {
+ case NoSymbol =>
+ // create the companion class if it does not exist
+ val enclosing = owner.owner
+ val compclass = enclosing.newClass(newTypeName(owner.name.toString))
+ compclass setInfo ClassInfoType(List(ObjectClass.tpe), newScope, compclass)
+ enclosing.info.decls enter compclass
+
+ val compclstree = ClassDef(compclass, NoMods, List(List()), List(List()), List(), tree.pos)
+
+ syntheticClasses.getOrElseUpdate(enclosing, mutable.Set()) += compclstree
+
+ compclass
+ case comp => comp
+ }
+
+ // create a static field in the companion class for this @static field
+ val stfieldSym = linkedClass.newVariable(newTermName(name), tree.pos, STATIC | SYNTHETIC | FINAL) setInfo sym.tpe
+ stfieldSym.addAnnotation(StaticClass)
+
+ val names = classNames.getOrElseUpdate(linkedClass, linkedClass.info.decls.collect {
+ case sym if sym.name.isTermName => sym.name
+ } toSet)
+ if (names(stfieldSym.name)) {
+ reporter.error(
+ tree.pos,
+ "@static annotated field " + tree.symbol.name + " has the same name as a member of class " + linkedClass.name
+ )
+ } else {
+ linkedClass.info.decls enter stfieldSym
+
+ val initializerBody = rhs
+
+ // static field was previously initialized in the companion object itself, like this:
+ // staticBodies((linkedClass, stfieldSym)) = Select(This(owner), sym.getter(owner))
+ // instead, we move the initializer to the static ctor of the companion class
+ // we save the entire ValDef/DefDef to extract the rhs later
+ staticBodies((linkedClass, stfieldSym)) = tree
+ }
+ }
+ super.transform(tree)
+
/* MSIL requires that the stack is empty at the end of a try-block.
* Hence, we here rewrite all try blocks with a result != {Unit, All} such that they
* store their result in a local variable. The catch blocks are adjusted as well.
@@ -665,6 +735,11 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
if (newStaticInits.isEmpty)
template
else {
+ val ctorBody = newStaticInits.toList flatMap {
+ case Block(stats, expr) => stats :+ expr
+ case t => List(t)
+ }
+
val newCtor = findStaticCtor(template) match {
// in case there already were static ctors - augment existing ones
// currently, however, static ctors aren't being generated anywhere else
@@ -673,22 +748,76 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
deriveDefDef(ctor) {
case block @ Block(stats, expr) =>
// need to add inits to existing block
- treeCopy.Block(block, newStaticInits.toList ::: stats, expr)
+ treeCopy.Block(block, ctorBody ::: stats, expr)
case term: TermTree =>
// need to create a new block with inits and the old term
- treeCopy.Block(term, newStaticInits.toList, term)
+ treeCopy.Block(term, ctorBody, term)
}
case _ =>
// create new static ctor
val staticCtorSym = currentClass.newStaticConstructor(template.pos)
- val rhs = Block(newStaticInits.toList, Literal(Constant(())))
+ val rhs = Block(ctorBody, Literal(Constant(())))
localTyper.typedPos(template.pos)(DefDef(staticCtorSym, rhs))
}
deriveTemplate(template)(newCtor :: _)
}
}
-
+
+ private def addStaticDeclarations(tree: Template, clazz: Symbol) {
+ // add static field initializer statements for each static field in clazz
+ if (!clazz.isModuleClass) for {
+ staticSym <- clazz.info.decls
+ if staticSym.hasStaticAnnotation
+ } staticSym match {
+ case stfieldSym if stfieldSym.isVariable =>
+ val valdef = staticBodies((clazz, stfieldSym))
+ val ValDef(_, _, _, rhs) = valdef
+ val fixedrhs = rhs.changeOwner((valdef.symbol, clazz.info.decl(nme.CONSTRUCTOR)))
+
+ val stfieldDef = localTyper.typedPos(tree.pos)(VAL(stfieldSym) === EmptyTree)
+ val flattenedInit = fixedrhs match {
+ case Block(stats, expr) => Block(stats, safeREF(stfieldSym) === expr)
+ case rhs => safeREF(stfieldSym) === rhs
+ }
+ val stfieldInit = localTyper.typedPos(tree.pos)(flattenedInit)
+
+ // add field definition to new defs
+ newStaticMembers append stfieldDef
+ newStaticInits append stfieldInit
+ }
+ }
+
+
+
+ override def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = {
+ super.transformStats(stats, exprOwner) ++ {
+ // flush pending synthetic classes created in this owner
+ val synthclassdefs = syntheticClasses.get(exprOwner).toList.flatten
+ syntheticClasses -= exprOwner
+ synthclassdefs map {
+ cdef => localTyper.typedPos(cdef.pos)(cdef)
+ }
+ } map {
+ case clsdef @ ClassDef(mods, name, tparams, t @ Template(parent, self, body)) =>
+ // process all classes in the package again to add static initializers
+ clearStatics()
+
+ addStaticDeclarations(t, clsdef.symbol)
+
+ val templ = deriveTemplate(t)(_ => transformTrees(newStaticMembers.toList) ::: body)
+ val ntempl =
+ try addStaticInits(templ)
+ finally clearStatics()
+
+ val derived = deriveClassDef(clsdef)(_ => ntempl)
+ classNames.remove(clsdef.symbol)
+ derived
+
+ case stat => stat
+ }
+ }
+
} // CleanUpTransformer
}
diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala
index e5119eac71..70bd0bd21b 100644
--- a/src/compiler/scala/tools/nsc/transform/Constructors.scala
+++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala
@@ -186,12 +186,15 @@ abstract class Constructors extends Transform with ast.TreeDSL {
// before the superclass constructor call, otherwise it goes after.
// Lazy vals don't get the assignment in the constructor.
if (!stat.symbol.tpe.isInstanceOf[ConstantType]) {
- if (rhs != EmptyTree && !stat.symbol.isLazy) {
+ if (stat.symbol.hasStaticAnnotation) {
+ debuglog("@static annotated field initialization skipped.")
+ defBuf += deriveValDef(stat)(tree => tree)
+ } else if (rhs != EmptyTree && !stat.symbol.isLazy) {
val rhs1 = intoConstructor(stat.symbol, rhs);
(if (canBeMoved(stat)) constrPrefixBuf else constrStatBuf) += mkAssign(
stat.symbol, rhs1)
+ defBuf += deriveValDef(stat)(_ => EmptyTree)
}
- defBuf += deriveValDef(stat)(_ => EmptyTree)
}
case ClassDef(_, _, _, _) =>
// classes are treated recursively, and left in the template
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
index b692482972..8ffbdcf066 100644
--- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -46,10 +46,13 @@ abstract class ExplicitOuter extends InfoTransform
private def haveSameOuter(parent: Type, clazz: Symbol) = parent match {
case TypeRef(pre, sym, _) =>
val owner = clazz.owner
+
+ //println(s"have same outer $parent $clazz $sym ${sym.owner} $owner $pre")
sym.isClass && owner.isClass &&
- owner == sym.owner &&
+ (owner isSubClass sym.owner) &&
owner.thisType =:= pre
+
case _ => false
}
@@ -480,7 +483,7 @@ abstract class ExplicitOuter extends InfoTransform
val vparamss1 =
if (isInner(clazz)) { // (4)
val outerParam =
- sym.newValueParameter(nme.OUTER, sym.pos) setInfo outerField(clazz).info
+ sym.newValueParameter(nme.OUTER, sym.pos) setInfo clazz.outerClass.thisType
((ValDef(outerParam) setType NoType) :: vparamss.head) :: vparamss.tail
} else vparamss
super.transform(copyDefDef(tree)(vparamss = vparamss1))
diff --git a/src/compiler/scala/tools/nsc/transform/TailCalls.scala b/src/compiler/scala/tools/nsc/transform/TailCalls.scala
index 4c9d855413..492273dfdc 100644
--- a/src/compiler/scala/tools/nsc/transform/TailCalls.scala
+++ b/src/compiler/scala/tools/nsc/transform/TailCalls.scala
@@ -373,7 +373,7 @@ abstract class TailCalls extends Transform {
// the labels all look like: matchEnd(x) {x}
// then, in a forward jump `matchEnd(expr)`, `expr` is considered in tail position (and the matchEnd jump is replaced by the jump generated by expr)
class TailPosLabelsTraverser extends Traverser {
- val tailLabels = new collection.mutable.ListBuffer[Symbol]()
+ val tailLabels = new collection.mutable.HashSet[Symbol]()
private var maybeTail: Boolean = true // since we start in the rhs of a DefDef
@@ -388,9 +388,18 @@ abstract class TailCalls extends Transform {
def traverseTreesNoTail(trees: List[Tree]) = trees foreach traverseNoTail
override def traverse(tree: Tree) = tree match {
- case LabelDef(_, List(arg), body@Ident(_)) if arg.symbol == body.symbol => // we're looking for label(x){x} in tail position, since that means `a` is in tail position in a call `label(a)`
+ // we're looking for label(x){x} in tail position, since that means `a` is in tail position in a call `label(a)`
+ case LabelDef(_, List(arg), body@Ident(_)) if arg.symbol == body.symbol =>
if (maybeTail) tailLabels += tree.symbol
+ // jumps to matchEnd are transparent; need this case for nested matches
+ // (and the translated match case below does things in reverse for this case's sake)
+ case Apply(fun, arg :: Nil) if hasSynthCaseSymbol(fun) && tailLabels(fun.symbol) =>
+ traverse(arg)
+
+ case Apply(fun, args) if (fun.symbol == Boolean_or || fun.symbol == Boolean_and) =>
+ traverseTrees(args)
+
// a translated casedef
case LabelDef(_, _, body) if hasSynthCaseSymbol(tree) =>
traverse(body)
@@ -400,9 +409,9 @@ abstract class TailCalls extends Transform {
// the assumption is once we encounter a case, the remainder of the block will consist of cases
// the prologue may be empty, usually it is the valdef that stores the scrut
val (prologue, cases) = stats span (s => !s.isInstanceOf[LabelDef])
- traverseTreesNoTail(prologue) // selector (may be absent)
- traverseTrees(cases)
traverse(expr)
+ traverseTrees(cases.reverse) // reverse so that we enter the matchEnd LabelDef before we see jumps to it
+ traverseTreesNoTail(prologue) // selector (may be absent)
case CaseDef(pat, guard, body) =>
traverse(body)
@@ -426,7 +435,7 @@ abstract class TailCalls extends Transform {
traverseTreesNoTail(catches)
traverseNoTail(finalizer)
- case EmptyTree | Super(_, _) | This(_) | Select(_, _) | Ident(_) | Literal(_) | Function(_, _) | TypeTree() =>
+ case Apply(_, _) | EmptyTree | Super(_, _) | This(_) | Select(_, _) | Ident(_) | Literal(_) | Function(_, _) | TypeTree() =>
case _ => super.traverse(tree)
}
}
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index a5bfac0e03..ebf0ecd634 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -33,6 +33,14 @@ import language.postfixOps
* - convert implicit method types to method types
* - convert non-trivial catches in try statements to matches
* - convert non-local returns to throws with enclosing try statements.
+ * - convert try-catch expressions in contexts where there might be values on the stack to
+ * a local method and a call to it (since an exception empties the evaluation stack):
+ *
+ * meth(x_1,..., try { x_i } catch { ..}, .. x_b0) ==>
+ * {
+ * def liftedTry$1 = try { x_i } catch { .. }
+ * meth(x_1, .., liftedTry$1(), .. )
+ * }
*/
/*</export> */
abstract class UnCurry extends InfoTransform
@@ -217,38 +225,15 @@ abstract class UnCurry extends InfoTransform
}
- /* Transform a function node (x_1,...,x_n) => body of type FunctionN[T_1, .., T_N, R] to
+ /** Transform a function node (x_1,...,x_n) => body of type FunctionN[T_1, .., T_N, R] to
*
* class $anon() extends AbstractFunctionN[T_1, .., T_N, R] with Serializable {
* def apply(x_1: T_1, ..., x_N: T_n): R = body
* }
* new $anon()
*
- * transform a function node (x => body) of type PartialFunction[T, R] where
- * body = expr match { case P_i if G_i => E_i }_i=1..n
- * to:
+ * If `settings.XoldPatmat.value`, also synthesized AbstractPartialFunction subclasses (see synthPartialFunction).
*
- //TODO: correct code template below
- * class $anon() extends AbstractPartialFunction[T, R] with Serializable {
- * def applyOrElse[A1 <: A, B1 >: B](x: A1, default: A1 => B1): B1 = (expr: @unchecked) match {
- * case P_1 if G_1 => E_1
- * ...
- * case P_n if G_n => E_n
- * case _ => default(expr)
- * }
- * def isDefinedAt(x: T): boolean = (x: @unchecked) match {
- * case P_1 if G_1 => true
- * ...
- * case P_n if G_n => true
- * case _ => false
- * }
- * }
- * new $anon()
- *
- * However, if one of the patterns P_i if G_i is a default pattern,
- * drop the last default clause in the definition of `apply` and generate for `_isDefinedAt` instead
- *
- * def isDefinedAtCurrent(x: T): boolean = true
*/
def transformFunction(fun: Function): Tree =
deEta(fun) match {
@@ -292,6 +277,28 @@ abstract class UnCurry extends InfoTransform
}
+ /** Transform a function node (x => body) of type PartialFunction[T, R] where
+ * body = expr match { case P_i if G_i => E_i }_i=1..n
+ * to (assuming none of the cases is a default case):
+ *
+ * class $anon() extends AbstractPartialFunction[T, R] with Serializable {
+ * def applyOrElse[A1 <: A, B1 >: B](x: A1, default: A1 => B1): B1 = (expr: @unchecked) match {
+ * case P_1 if G_1 => E_1
+ * ...
+ * case P_n if G_n => E_n
+ * case _ => default(expr)
+ * }
+ * def isDefinedAt(x: T): boolean = (x: @unchecked) match {
+ * case P_1 if G_1 => true
+ * ...
+ * case P_n if G_n => true
+ * case _ => false
+ * }
+ * }
+ * new $anon()
+ *
+ * If there's a default case, the original match is used for applyOrElse, and isDefinedAt returns `true`
+ */
def synthPartialFunction(fun: Function) = {
if (!settings.XoldPatmat.value) debugwarn("Under the new pattern matching scheme, PartialFunction should have been synthesized during typers.")
@@ -634,6 +641,13 @@ abstract class UnCurry extends InfoTransform
case ret @ Return(_) if (isNonLocalReturn(ret)) =>
withNeedLift(true) { super.transform(ret) }
+ case Try(_, Nil, _) =>
+ // try-finally does not need lifting: lifting is needed only for try-catch
+ // expressions that are evaluated in a context where the stack might not be empty.
+ // `finally` does not attempt to continue evaluation after an exception, so the fact
+ // that values on the stack are 'lost' does not matter
+ super.transform(tree)
+
case Try(block, catches, finalizer) =>
if (needTryLift || shouldBeLiftedAnyway(tree)) transform(liftTree(tree))
else super.transform(tree)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index bcf529ecd2..805f60ba87 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -636,6 +636,12 @@ trait Contexts { self: Analyzer =>
collect(imp.tree.selectors)
}
+ /* SI-5892 / SI-4270: `implicitss` can return results which are not accessible at the
+ * point where implicit search is triggered. Example: implicits in (annotations of)
+ * class type parameters (SI-5892). The `context.owner` is the class symbol, therefore
+ * `implicitss` will return implicit conversions defined inside the class. These are
+ * filtered out later by `eligibleInfos` (SI-4270 / 9129cfe9), as they don't type-check.
+ */
def implicitss: List[List[ImplicitInfo]] = {
if (implicitsRunId != currentRunId) {
implicitsRunId = currentRunId
diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
index b7043e58de..d33857371d 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
@@ -1140,7 +1140,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
}
try macroExpandInternal
- catch { case ex => handleMacroExpansionException(typer, expandee, ex) }
+ catch { case ex: Throwable => handleMacroExpansionException(typer, expandee, ex) }
}
private def macroExpandWithoutRuntime(typer: Typer, expandee: Tree): MacroExpansionResult = {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 48fd6ba928..0a0bf9d710 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -1214,8 +1214,8 @@ trait Namers extends MethodSynthesis {
if (!annotated.isInitialized) tree match {
case defn: MemberDef =>
val ainfos = defn.mods.annotations filterNot (_ eq null) map { ann =>
- // need to be lazy, #1782
- AnnotationInfo lazily (typer typedAnnotation ann)
+ // need to be lazy, #1782. enteringTyper to allow inferView in annotation args, SI-5892.
+ AnnotationInfo lazily enteringTyper(typer typedAnnotation ann)
}
if (ainfos.nonEmpty) {
annotated setAnnotations ainfos
diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
index 5c94ff63a6..99e978fb51 100644
--- a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
@@ -15,6 +15,7 @@ import scala.tools.nsc.transform.Transform
import scala.collection.mutable.HashSet
import scala.collection.mutable.HashMap
import reflect.internal.util.Statistics
+import scala.reflect.internal.Types
/** Translate pattern matching.
*
@@ -53,6 +54,25 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
}
import debugging.patmatDebug
+ // to govern how much time we spend analyzing matches for unreachability/exhaustivity
+ object AnalysisBudget {
+ import scala.tools.cmd.FromString.IntFromString
+ val max = sys.props.get("scalac.patmat.analysisBudget").collect(IntFromString.orElse{case "off" => Integer.MAX_VALUE}).getOrElse(256)
+
+ abstract class Exception extends RuntimeException("CNF budget exceeded") {
+ val advice: String
+ def warn(pos: Position, kind: String) = currentUnit.uncheckedWarning(pos, s"Cannot check match for $kind.\n$advice")
+ }
+
+ object exceeded extends Exception {
+ val advice = s"(The analysis required more space than allowed. Please try with scalac -Dscalac.patmat.analysisBudget=${AnalysisBudget.max*2} or -Dscalac.patmat.analysisBudget=off.)"
+ }
+
+ object stackOverflow extends Exception {
+ val advice = "(There was a stack overflow. Please try increasing the stack available to the compiler using e.g., -Xss2m.)"
+ }
+ }
+
def newTransformer(unit: CompilationUnit): Transformer =
if (!settings.XoldPatmat.value) new MatchTransformer(unit)
else noopTransformer
@@ -71,7 +91,15 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
case Match(sel, cases) =>
val origTp = tree.tpe
// setType origTp intended for CPS -- TODO: is it necessary?
- localTyper.typed(translator.translateMatch(treeCopy.Match(tree, transform(sel), transformTrees(cases).asInstanceOf[List[CaseDef]]))) setType origTp
+ val translated = translator.translateMatch(treeCopy.Match(tree, transform(sel), transformTrees(cases).asInstanceOf[List[CaseDef]]))
+ try {
+ localTyper.typed(translated) setType origTp
+ } catch {
+ case x: (Types#TypeError) =>
+ // TODO: this should never happen; error should've been reported during type checking
+ unit.error(tree.pos, "error during expansion of this match (this is a scalac bug).\nThe underlying error was: "+ x.msg)
+ translated
+ }
case Try(block, catches, finalizer) =>
treeCopy.Try(tree, transform(block), translator.translateTry(transformTrees(catches).asInstanceOf[List[CaseDef]], tree.tpe, tree.pos), transform(finalizer))
case _ => super.transform(tree)
@@ -413,7 +441,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
The pattern matches any value v such that r == v (§12.1).
The type of r must conform to the expected type of the pattern.
**/
- case Literal(Constant(_)) | Ident(_) | Select(_, _) =>
+ case Literal(Constant(_)) | Ident(_) | Select(_, _) | This(_) =>
noFurtherSubPats(EqualityTestTreeMaker(patBinder, patTree, pos))
case Alternative(alts) =>
@@ -430,7 +458,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
patmatDebug("WARNING: Bind tree with unbound symbol "+ patTree)
noFurtherSubPats() // there's no symbol -- something's wrong... don't fail here though (or should we?)
- // case Star(_) | ArrayValue | This => error("stone age pattern relics encountered!")
+ // case Star(_) | ArrayValue => error("stone age pattern relics encountered!")
case _ =>
error("unsupported pattern: "+ patTree +"(a "+ patTree.getClass +")")
@@ -547,7 +575,10 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
if(isSeq) {
val TypeRef(pre, SeqClass, args) = seqTp
// do repeated-parameter expansion to match up with the expected number of arguments (in casu, subpatterns)
- formalTypes(rawSubPatTypes.init :+ typeRef(pre, RepeatedParamClass, args), nbSubPats)
+ val formalsWithRepeated = rawSubPatTypes.init :+ typeRef(pre, RepeatedParamClass, args)
+
+ if (lastIsStar) formalTypes(formalsWithRepeated, nbSubPats - 1) :+ seqTp
+ else formalTypes(formalsWithRepeated, nbSubPats)
} else rawSubPatTypes
protected def rawSubPatTypes: List[Type]
@@ -637,7 +668,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// binder has type paramType
def treeMaker(binder: Symbol, pos: Position): TreeMaker = {
// checks binder ne null before chaining to the next extractor
- ProductExtractorTreeMaker(binder, lengthGuard(binder))(Substitution(subPatBinders, subPatRefs(binder)))
+ ProductExtractorTreeMaker(binder, lengthGuard(binder))(subPatBinders, subPatRefs(binder))
}
// reference the (i-1)th case accessor if it exists, otherwise the (i-1)th tuple component
@@ -681,7 +712,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// the extractor call (applied to the binder bound by the flatMap corresponding to the previous (i.e., enclosing/outer) pattern)
val extractorApply = atPos(pos)(spliceApply(patBinderOrCasted))
val binder = freshSym(pos, pureType(resultInMonad)) // can't simplify this when subPatBinders.isEmpty, since UnitClass.tpe is definitely wrong when isSeq, and resultInMonad should always be correct since it comes directly from the extractor's result type
- ExtractorTreeMaker(extractorApply, lengthGuard(binder), binder)(Substitution(subPatBinders, subPatRefs(binder)), resultType.typeSymbol == BooleanClass, checkedLength, patBinderOrCasted)
+ ExtractorTreeMaker(extractorApply, lengthGuard(binder), binder)(subPatBinders, subPatRefs(binder), resultType.typeSymbol == BooleanClass, checkedLength, patBinderOrCasted)
}
override protected def seqTree(binder: Symbol): Tree =
@@ -837,6 +868,20 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
}
private[this] var currSub: Substitution = null
+ /** The substitution that specifies the trees that compute the values of the subpattern binders.
+ *
+ * Should not be used to perform actual substitution!
+ * Only used to reason symbolically about the values the subpattern binders are bound to.
+ * See TreeMakerToCond#updateSubstitution.
+ *
+ * Overridden in PreserveSubPatBinders to pretend it replaces the subpattern binders by subpattern refs
+ * (Even though we don't do so anymore -- see SI-5158, SI-5739 and SI-6070.)
+ *
+ * TODO: clean this up, would be nicer to have some higher-level way to compute
+ * the binders bound by this tree maker and the symbolic values that correspond to them
+ */
+ def subPatternsAsSubstitution: Substitution = substitution
+
// build Tree that chains `next` after the current extractor
def chainBefore(next: Tree)(casegen: Casegen): Tree
}
@@ -885,32 +930,89 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
atPos(pos)(casegen.flatMapCond(cond, res, nextBinder, substitution(next)))
}
+ trait PreserveSubPatBinders extends NoNewBinders {
+ val subPatBinders: List[Symbol]
+ val subPatRefs: List[Tree]
+
+ /** The substitution that specifies the trees that compute the values of the subpattern binders.
+ *
+ * We pretend to replace the subpattern binders by subpattern refs
+ * (Even though we don't do so anymore -- see SI-5158, SI-5739 and SI-6070.)
+ */
+ override def subPatternsAsSubstitution =
+ Substitution(subPatBinders, subPatRefs) >> super.subPatternsAsSubstitution
+
+ import CODE._
+ def bindSubPats(in: Tree): Tree = Block(map2(subPatBinders, subPatRefs)(VAL(_) === _), in)
+ }
+
/**
* Make a TreeMaker that will result in an extractor call specified by `extractor`
* the next TreeMaker (here, we don't know which it'll be) is chained after this one by flatMap'ing
* a function with binder `nextBinder` over our extractor's result
* the function's body is determined by the next TreeMaker
- * in this function's body, and all the subsequent ones, references to the symbols in `from` will be replaced by the corresponding tree in `to`
+ * (furthermore, the interpretation of `flatMap` depends on the codegen instance we're using).
+ *
+ * The values for the subpatterns, as computed by the extractor call in `extractor`,
+ * are stored in local variables that re-use the symbols in `subPatBinders`.
+ * This makes extractor patterns more debuggable (SI-5739).
*/
- case class ExtractorTreeMaker(extractor: Tree, extraCond: Option[Tree], nextBinder: Symbol)(val localSubstitution: Substitution, extractorReturnsBoolean: Boolean, val checkedLength: Option[Int], val prevBinder: Symbol) extends FunTreeMaker {
+ case class ExtractorTreeMaker(extractor: Tree, extraCond: Option[Tree], nextBinder: Symbol)(
+ val subPatBinders: List[Symbol],
+ val subPatRefs: List[Tree],
+ extractorReturnsBoolean: Boolean,
+ val checkedLength: Option[Int],
+ val prevBinder: Symbol) extends FunTreeMaker with PreserveSubPatBinders {
+
def chainBefore(next: Tree)(casegen: Casegen): Tree = {
- val condAndNext = extraCond map (casegen.ifThenElseZero(_, next)) getOrElse next
+ val condAndNext = extraCond match {
+ case Some(cond) =>
+ casegen.ifThenElseZero(substitution(cond), bindSubPats(substitution(next)))
+ case _ =>
+ bindSubPats(substitution(next))
+ }
atPos(extractor.pos)(
- if (extractorReturnsBoolean) casegen.flatMapCond(extractor, CODE.UNIT, nextBinder, substitution(condAndNext))
- else casegen.flatMap(extractor, nextBinder, substitution(condAndNext))
+ if (extractorReturnsBoolean) casegen.flatMapCond(extractor, CODE.UNIT, nextBinder, condAndNext)
+ else casegen.flatMap(extractor, nextBinder, condAndNext)
)
}
override def toString = "X"+(extractor, nextBinder.name)
}
- // TODO: allow user-defined unapplyProduct
- case class ProductExtractorTreeMaker(prevBinder: Symbol, extraCond: Option[Tree])(val localSubstitution: Substitution) extends FunTreeMaker { import CODE._
+ /**
+ * An optimized version of ExtractorTreeMaker for Products.
+ * For now, this is hard-coded to case classes, and we simply extract the case class fields.
+ *
+ * The values for the subpatterns, as specified by the case class fields at the time of extraction,
+ * are stored in local variables that re-use the symbols in `subPatBinders`.
+ * This makes extractor patterns more debuggable (SI-5739) as well as
+ * avoiding mutation after the pattern has been matched (SI-5158, SI-6070)
+ *
+ * TODO: make this user-definable as follows
+ * When a companion object defines a method `def unapply_1(x: T): U_1`, but no `def unapply` or `def unapplySeq`,
+ * the extractor is considered to match any non-null value of type T
+ * the pattern is expected to have as many sub-patterns as there are `def unapply_I(x: T): U_I` methods,
+ * and the type of the I'th sub-pattern is `U_I`.
+ * The same exception for Seq patterns applies: if the last extractor is of type `Seq[U_N]`,
+ * the pattern must have at least N arguments (exactly N if the last argument is annotated with `: _*`).
+ * The arguments starting at N (and beyond) are taken from the sequence returned by apply_N,
+ * and it is checked that that sequence has enough elements to provide values for all expected sub-patterns.
+ *
+ * For a case class C, the implementation is assumed to be `def unapply_I(x: C) = x._I`,
+ * and the extractor call is inlined under that assumption.
+ */
+ case class ProductExtractorTreeMaker(prevBinder: Symbol, extraCond: Option[Tree])(
+ val subPatBinders: List[Symbol],
+ val subPatRefs: List[Tree]) extends FunTreeMaker with PreserveSubPatBinders {
+
+ import CODE._
val nextBinder = prevBinder // just passing through
+
def chainBefore(next: Tree)(casegen: Casegen): Tree = {
val nullCheck = REF(prevBinder) OBJ_NE NULL
val cond = extraCond map (nullCheck AND _) getOrElse nullCheck
- casegen.ifThenElseZero(cond, substitution(next))
+ casegen.ifThenElseZero(cond, bindSubPats(substitution(next)))
}
override def toString = "P"+(prevBinder.name, extraCond getOrElse "", localSubstitution)
@@ -1024,7 +1126,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
else expectedTp match {
// TODO: [SPEC] the spec requires `eq` instead of `==` for singleton types
// this implies sym.isStable
- case SingleType(_, sym) => and(equalsTest(CODE.REF(sym), testedBinder), typeTest(testedBinder, expectedTp.widen))
+ case SingleType(_, sym) => and(equalsTest(gen.mkAttributedQualifier(expectedTp), testedBinder), typeTest(testedBinder, expectedTp.widen))
// must use == to support e.g. List() == Nil
case ThisType(sym) if sym.isModule => and(equalsTest(CODE.REF(sym), testedBinder), typeTest(testedBinder, expectedTp.widen))
case ConstantType(Constant(null)) if testedBinder.info.widen <:< AnyRefClass.tpe
@@ -1541,7 +1643,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
* TODO: don't ignore outer-checks
*/
def apply(tm: TreeMaker): Cond = {
- if (!substitutionComputed) updateSubstitution(tm.substitution)
+ if (!substitutionComputed) updateSubstitution(tm.subPatternsAsSubstitution)
tm match {
case ttm@TypeTestTreeMaker(prevBinder, testedBinder, pt, _) =>
@@ -1863,14 +1965,14 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
type Formula
def andFormula(a: Formula, b: Formula): Formula
- class CNFBudgetExceeded extends RuntimeException("CNF budget exceeded")
- // may throw an CNFBudgetExceeded
- def propToSolvable(p: Prop) = {
+ // may throw an AnalysisBudget.Exception
+ def propToSolvable(p: Prop): Formula = {
val (eqAxioms, pure :: Nil) = removeVarEq(List(p), modelNull = false)
eqFreePropToSolvable(And(eqAxioms, pure))
}
+ // may throw an AnalysisBudget.Exception
def eqFreePropToSolvable(p: Prop): Formula
def cnfString(f: Formula): String
@@ -1896,7 +1998,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
type Lit
def Lit(sym: Sym, pos: Boolean = true): Lit
- // throws an CNFBudgetExceeded when the prop results in a CNF that's too big
+ // throws an AnalysisBudget.Exception when the prop results in a CNF that's too big
def eqFreePropToSolvable(p: Prop): Formula = {
// TODO: for now, reusing the normalization from DPLL
def negationNormalForm(p: Prop): Prop = p match {
@@ -1918,9 +2020,9 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
def lit(s: Sym) = formula(clause(Lit(s)))
def negLit(s: Sym) = formula(clause(Lit(s, false)))
- def conjunctiveNormalForm(p: Prop, budget: Int = 256): Formula = {
+ def conjunctiveNormalForm(p: Prop, budget: Int = AnalysisBudget.max): Formula = {
def distribute(a: Formula, b: Formula, budget: Int): Formula =
- if (budget <= 0) throw new CNFBudgetExceeded
+ if (budget <= 0) throw AnalysisBudget.exceeded
else
(a, b) match {
// true \/ _ = true
@@ -1935,7 +2037,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
big flatMap (c => distribute(formula(c), small, budget - (big.size*small.size)))
}
- if (budget <= 0) throw new CNFBudgetExceeded
+ if (budget <= 0) throw AnalysisBudget.exceeded
p match {
case True => TrueF
@@ -1954,9 +2056,17 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
}
val start = Statistics.startTimer(patmatCNF)
- val res = conjunctiveNormalForm(negationNormalForm(p))
+ val res =
+ try {
+ conjunctiveNormalForm(negationNormalForm(p))
+ } catch { case ex : StackOverflowError =>
+ throw AnalysisBudget.stackOverflow
+ }
+
Statistics.stopTimer(patmatCNF, start)
- patmatCNFSizes(res.size).value += 1
+
+ //
+ if (Statistics.enabled) patmatCNFSizes(res.size).value += 1
// patmatDebug("cnf for\n"+ p +"\nis:\n"+cnfString(res))
res
@@ -2357,6 +2467,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// right now hackily implement this by pruning counter-examples
// unreachability would also benefit from a more faithful representation
+
// reachability (dead code)
// computes the first 0-based case index that is unreachable (if any)
@@ -2425,9 +2536,8 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
if (reachable) None else Some(caseIndex)
} catch {
- case e : CNFBudgetExceeded =>
-// debugWarn(util.Position.formatMessage(prevBinder.pos, "Cannot check match for reachability", false))
-// e.printStackTrace()
+ case ex: AnalysisBudget.Exception =>
+ ex.warn(prevBinder.pos, "unreachability")
None // CNF budget exceeded
}
}
@@ -2568,9 +2678,8 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
Statistics.stopTimer(patmatAnaExhaust, start)
pruned
} catch {
- case e : CNFBudgetExceeded =>
- patmatDebug(util.Position.formatMessage(prevBinder.pos, "Cannot check match for exhaustivity", false))
- // e.printStackTrace()
+ case ex : AnalysisBudget.Exception =>
+ ex.warn(prevBinder.pos, "exhaustivity")
Nil // CNF budget exceeded
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 063ebe5614..c448547ea1 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -119,7 +119,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
// those with the DEFAULTPARAM flag, and infer the methods. Looking for the methods
// directly requires inspecting the parameter list of every one. That modification
// shaved 95% off the time spent in this method.
- val defaultGetters = clazz.info.findMember(nme.ANYNAME, 0L, DEFAULTPARAM, false).alternatives
+ val defaultGetters = clazz.info.findMembers(0L, DEFAULTPARAM)
val defaultMethodNames = defaultGetters map (sym => nme.defaultGetterToMethod(sym.name))
defaultMethodNames.distinct foreach { name =>
diff --git a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
index b0956446a7..a378a95786 100644
--- a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
@@ -129,7 +129,7 @@ abstract class TreeCheckers extends Analyzer {
private def wrap[T](msg: => Any)(body: => Unit) {
try body
- catch { case x =>
+ catch { case x: Throwable =>
Console.println("Caught " + x)
Console.println(msg)
x.printStackTrace
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 53f9429572..568a3a9c14 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1972,7 +1972,8 @@ trait Typers extends Modes with Adaptations with Tags {
case SilentResultValue(tpt) =>
val alias = enclClass.newAliasType(name.toTypeName, useCase.pos)
val tparams = cloneSymbolsAtOwner(tpt.tpe.typeSymbol.typeParams, alias)
- alias setInfo typeFun(tparams, appliedType(tpt.tpe, tparams map (_.tpe)))
+ val newInfo = genPolyType(tparams, appliedType(tpt.tpe, tparams map (_.tpe)))
+ alias setInfo newInfo
context.scope.enter(alias)
case _ =>
}
@@ -3883,40 +3884,51 @@ trait Typers extends Modes with Adaptations with Tags {
}
}
- def typedBind(name: Name, body: Tree) = {
- var vble = tree.symbol
- def typedBindType(name: TypeName) = {
- assert(body == EmptyTree, context.unit + " typedBind: " + name.debugString + " " + body + " " + body.getClass)
- if (vble == NoSymbol)
- vble =
- if (isFullyDefined(pt))
- context.owner.newAliasType(name, tree.pos) setInfo pt
- else
- context.owner.newAbstractType(name, tree.pos) setInfo TypeBounds.empty
- val rawInfo = vble.rawInfo
- vble = if (vble.name == tpnme.WILDCARD) context.scope.enter(vble)
- else namer.enterInScope(vble)
- tree setSymbol vble setType vble.tpe
- }
- def typedBindTerm(name: TermName) = {
- if (vble == NoSymbol)
- vble = context.owner.newValue(name, tree.pos)
- if (vble.name.toTermName != nme.WILDCARD) {
- if ((mode & ALTmode) != 0)
- VariableInPatternAlternativeError(tree)
- vble = namer.enterInScope(vble)
- }
- val body1 = typed(body, mode, pt)
- vble.setInfo(
- if (treeInfo.isSequenceValued(body)) seqType(body1.tpe)
- else body1.tpe)
- treeCopy.Bind(tree, name, body1) setSymbol vble setType body1.tpe // burak, was: pt
- }
+ def typedBind(name: Name, body: Tree) =
name match {
- case x: TypeName => typedBindType(x)
- case x: TermName => typedBindTerm(x)
+ case name: TypeName => assert(body == EmptyTree, context.unit + " typedBind: " + name.debugString + " " + body + " " + body.getClass)
+ val sym =
+ if (tree.symbol != NoSymbol) tree.symbol
+ else {
+ if (isFullyDefined(pt))
+ context.owner.newAliasType(name, tree.pos) setInfo pt
+ else
+ context.owner.newAbstractType(name, tree.pos) setInfo TypeBounds.empty
+ }
+
+ if (name != tpnme.WILDCARD) namer.enterInScope(sym)
+ else context.scope.enter(sym)
+
+ tree setSymbol sym setType sym.tpe
+
+ case name: TermName =>
+ val sym =
+ if (tree.symbol != NoSymbol) tree.symbol
+ else context.owner.newValue(name, tree.pos)
+
+ if (name != nme.WILDCARD) {
+ if ((mode & ALTmode) != 0) VariableInPatternAlternativeError(tree)
+ namer.enterInScope(sym)
+ }
+
+ val body1 = typed(body, mode, pt)
+ val symTp =
+ if (treeInfo.isSequenceValued(body)) seqType(body1.tpe)
+ else body1.tpe
+ sym setInfo symTp
+
+ // have to imperatively set the symbol for this bind to keep it in sync with the symbols used in the body of a case
+ // when type checking a case we imperatively update the symbols in the body of the case
+ // those symbols are bound by the symbols in the Binds in the pattern of the case,
+ // so, if we set the symbols in the case body, but not in the patterns,
+ // then re-type check the casedef (for a second try in typedApply for example -- SI-1832),
+ // we are no longer in sync: the body has symbols set that do not appear in the patterns
+ // since body1 is not necessarily equal to body, we must return a copied tree,
+ // but we must still mutate the original bind
+ tree setSymbol sym
+ treeCopy.Bind(tree, name, body1) setSymbol sym setType body1.tpe
}
- }
+
def typedArrayValue(elemtpt: Tree, elems: List[Tree]) = {
val elemtpt1 = typedType(elemtpt, mode)
@@ -4509,6 +4521,8 @@ trait Typers extends Modes with Adaptations with Tags {
assert(errorContainer == null, "Cannot set ambiguous error twice for identifier")
errorContainer = tree
}
+
+ val fingerPrint: Long = name.fingerPrint
var defSym: Symbol = tree.symbol // the directly found symbol
var pre: Type = NoPrefix // the prefix type of defSym, if a class member
@@ -4547,7 +4561,10 @@ trait Typers extends Modes with Adaptations with Tags {
var cx = startingIdentContext
while (defSym == NoSymbol && cx != NoContext && (cx.scope ne null)) { // cx.scope eq null arises during FixInvalidSyms in Duplicators
pre = cx.enclClass.prefix
- defEntry = cx.scope.lookupEntry(name)
+ defEntry = {
+ val scope = cx.scope
+ if ((fingerPrint & scope.fingerPrints) != 0) scope.lookupEntry(name) else null
+ }
if ((defEntry ne null) && qualifies(defEntry.sym)) {
// Right here is where SI-1987, overloading in package objects, can be
// seen to go wrong. There is an overloaded symbol, but when referring
diff --git a/src/compiler/scala/tools/nsc/util/DocStrings.scala b/src/compiler/scala/tools/nsc/util/DocStrings.scala
index f4ce6d6ef1..c88414c423 100755
--- a/src/compiler/scala/tools/nsc/util/DocStrings.scala
+++ b/src/compiler/scala/tools/nsc/util/DocStrings.scala
@@ -144,6 +144,12 @@ object DocStrings {
}
/** Optionally start and end index of return section in `str`, or `None`
+ * if `str` does not have a @group. */
+ def groupDoc(str: String, sections: List[(Int, Int)]): Option[(Int, Int)] =
+ sections find (startsWithTag(str, _, "@group"))
+
+
+ /** Optionally start and end index of return section in `str`, or `None`
* if `str` does not have a @return.
*/
def returnDoc(str: String, sections: List[(Int, Int)]): Option[(Int, Int)] =
diff --git a/src/compiler/scala/tools/nsc/util/InterruptReq.scala b/src/compiler/scala/tools/nsc/util/InterruptReq.scala
index 2857823ceb..61aaa1bdcb 100644
--- a/src/compiler/scala/tools/nsc/util/InterruptReq.scala
+++ b/src/compiler/scala/tools/nsc/util/InterruptReq.scala
@@ -19,9 +19,10 @@ abstract class InterruptReq {
try {
result = Some(Left(todo()))
} catch {
- case t => result = Some(Right(t))
+ case t: Throwable => result = Some(Right(t))
+ } finally {
+ notify()
}
- notify()
}
/** To be called from interrupting client to get result for interrupt */
diff --git a/src/compiler/scala/tools/reflect/FastTrack.scala b/src/compiler/scala/tools/reflect/FastTrack.scala
index 63ecfa32b2..237ef813c7 100644
--- a/src/compiler/scala/tools/reflect/FastTrack.scala
+++ b/src/compiler/scala/tools/reflect/FastTrack.scala
@@ -1,7 +1,6 @@
package scala.tools
package reflect
-import scala.reflect.makro.runtime.ContextReifiers
import scala.reflect.reify.Taggers
import scala.tools.nsc.typechecker.{Analyzer, Macros}
@@ -16,7 +15,6 @@ trait FastTrack {
import language.implicitConversions
private implicit def context2taggers(c0: MacroContext): Taggers { val c: c0.type } = new { val c: c0.type = c0 } with Taggers
- private implicit def context2contextreifiers(c0: MacroContext): ContextReifiers { val c: c0.type } = new { val c: c0.type = c0 } with ContextReifiers
private implicit def context2macroimplementations(c0: MacroContext): MacroImplementations { val c: c0.type } = new { val c: c0.type = c0 } with MacroImplementations
implicit def fastTrackEntry2MacroRuntime(entry: FastTrackEntry): MacroRuntime = args => entry.run(args)
@@ -41,7 +39,6 @@ trait FastTrack {
MacroInternal_materializeAbsTypeTag bindTo { case (c, Apply(TypeApply(_, List(tt)), List(u))) => c.materializeTypeTag(u, EmptyTree, tt.tpe, concrete = false) }
MacroInternal_materializeTypeTag bindTo { case (c, Apply(TypeApply(_, List(tt)), List(u))) => c.materializeTypeTag(u, EmptyTree, tt.tpe, concrete = true) }
ApiUniverseReify bindTo { case (c, Apply(TypeApply(_, List(tt)), List(expr))) => c.materializeExpr(c.prefix.tree, EmptyTree, expr) }
- MacroContextReify bindTo { case (c, Apply(TypeApply(_, List(tt)), List(expr))) => c.materializeExprForMacroContext(c.prefix.tree, expr) }
ReflectRuntimeCurrentMirror bindTo { case (c, _) => scala.reflect.runtime.Macros.currentMirror(c).tree }
StringContext_f bindTo { case (c, app@Apply(Select(Apply(_, parts), _), args)) => c.macro_StringInterpolation_f(parts, args, app.pos) }
registry
diff --git a/src/compiler/scala/tools/reflect/MacroImplementations.scala b/src/compiler/scala/tools/reflect/MacroImplementations.scala
index 604bd7cd1a..e1b959cefa 100644
--- a/src/compiler/scala/tools/reflect/MacroImplementations.scala
+++ b/src/compiler/scala/tools/reflect/MacroImplementations.scala
@@ -57,6 +57,9 @@ abstract class MacroImplementations {
)
}
+ val stdContextTags = new { val tc: c.type = c } with StdContextTags
+ import stdContextTags._
+
def conversionType(ch: Char, arg: Tree): Option[Type] = {
ch match {
case 'b' | 'B' =>
@@ -68,11 +71,11 @@ abstract class MacroImplementations {
case 'c' | 'C' =>
checkType(arg, CharTpe, ByteTpe, ShortTpe, IntTpe)
case 'd' | 'o' | 'x' | 'X' =>
- checkType(arg, IntTpe, LongTpe, ByteTpe, ShortTpe, typeOf[BigInt])
+ checkType(arg, IntTpe, LongTpe, ByteTpe, ShortTpe, tagOfBigInt.tpe)
case 'e' | 'E' | 'g' | 'G' | 'f' | 'a' | 'A' =>
- checkType(arg, DoubleTpe, FloatTpe, typeOf[BigDecimal])
+ checkType(arg, DoubleTpe, FloatTpe, tagOfBigDecimal.tpe)
case 't' | 'T' =>
- checkType(arg, LongTpe, typeOf[java.util.Calendar], typeOf[java.util.Date])
+ checkType(arg, LongTpe, tagOfCalendar.tpe, tagOfDate.tpe)
case _ => None
}
}
diff --git a/src/compiler/scala/tools/reflect/StdTags.scala b/src/compiler/scala/tools/reflect/StdTags.scala
index 18cbf9c4b7..25a42a82cd 100644
--- a/src/compiler/scala/tools/reflect/StdTags.scala
+++ b/src/compiler/scala/tools/reflect/StdTags.scala
@@ -4,46 +4,55 @@ package reflect
import java.lang.{Class => jClass}
import scala.reflect.{ClassTag, classTag}
import scala.reflect.base.{MirrorOf, TypeCreator, Universe => BaseUniverse}
-import scala.reflect.runtime.{universe => ru}
// [Eugene++] Before 2.10 is released, I suggest we don't rely on automated type tag generation
// sure, it's convenient, but then refactoring reflection / reification becomes a pain
// `ClassTag` tags are fine, because they don't need a reifier to be generated
-object StdTags {
- // root mirror is fine for these guys, since scala-library.jar is guaranteed to be reachable from the root mirror
- lazy val tagOfString = ru.TypeTag[String](
- ru.rootMirror,
- new TypeCreator {
- def apply[U <: BaseUniverse with Singleton](m: MirrorOf[U]): U # Type = {
- val u = m.universe
- u.definitions.StringClass.asTypeConstructor
- }
- })
- lazy val tagOfListOfString = ru.TypeTag[List[String]](
- ru.rootMirror,
- new TypeCreator {
- def apply[U <: BaseUniverse with Singleton](m: MirrorOf[U]): U # Type = {
- val u = m.universe
- val pre = u.ThisType(m.staticModule("scala.collection.immutable").moduleClass.asInstanceOf[u.Symbol])
- u.TypeRef(pre, u.definitions.ListClass, List(u.definitions.StringClass.asTypeConstructor))
- }
- })
+trait StdTags {
+ val u: BaseUniverse with Singleton
+ val m: MirrorOf[u.type]
- // root mirror is NOT fine for these guys, hence we use the `currentMirror` trick
- private val ourClassloader = getClass.getClassLoader
- private def tagOfStaticClass[T: ClassTag] =
- ru.TypeTag[T](
- ru.runtimeMirror(ourClassloader),
+ lazy val tagOfListOfString: u.TypeTag[List[String]] =
+ u.TypeTag[List[String]](
+ m,
+ new TypeCreator {
+ def apply[U <: BaseUniverse with Singleton](m: MirrorOf[U]): U # Type = {
+ val u = m.universe
+ val pre = u.ThisType(m.staticPackage("scala.collection.immutable").moduleClass.asInstanceOf[u.Symbol])
+ u.TypeRef(pre, u.definitions.ListClass, List(u.definitions.StringClass.asTypeConstructor))
+ }
+ })
+
+ private def tagOfStaticClass[T: ClassTag]: u.TypeTag[T] =
+ u.TypeTag[T](
+ m,
new TypeCreator {
def apply[U <: BaseUniverse with Singleton](m: MirrorOf[U]): U # Type =
m.staticClass(classTag[T].runtimeClass.getName).asTypeConstructor.asInstanceOf[U # Type]
})
- lazy val tagOfInt = ru.TypeTag.Int
+ lazy val tagOfInt = u.TypeTag.Int
+ lazy val tagOfString = tagOfStaticClass[String]
lazy val tagOfFile = tagOfStaticClass[scala.tools.nsc.io.File]
lazy val tagOfDirectory = tagOfStaticClass[scala.tools.nsc.io.Directory]
lazy val tagOfStdReplVals = tagOfStaticClass[scala.tools.nsc.interpreter.StdReplVals]
lazy val tagOfIMain = tagOfStaticClass[scala.tools.nsc.interpreter.IMain]
lazy val tagOfThrowable = tagOfStaticClass[java.lang.Throwable]
lazy val tagOfClassLoader = tagOfStaticClass[java.lang.ClassLoader]
+ lazy val tagOfBigInt = tagOfStaticClass[BigInt]
+ lazy val tagOfBigDecimal = tagOfStaticClass[BigDecimal]
+ lazy val tagOfCalendar = tagOfStaticClass[java.util.Calendar]
+ lazy val tagOfDate = tagOfStaticClass[java.util.Date]
+}
+
+object StdRuntimeTags extends StdTags {
+ val u: scala.reflect.runtime.universe.type = scala.reflect.runtime.universe
+ val m = u.runtimeMirror(getClass.getClassLoader)
+ // we need getClass.getClassLoader to support the stuff from scala-compiler.jar
+}
+
+abstract class StdContextTags extends StdTags {
+ val tc: scala.reflect.makro.Context
+ val u: tc.universe.type = tc.universe
+ val m = tc.mirror
}
diff --git a/src/compiler/scala/tools/util/VerifyClass.scala b/src/compiler/scala/tools/util/VerifyClass.scala
index 5f636f63fb..e0e089d0b2 100644
--- a/src/compiler/scala/tools/util/VerifyClass.scala
+++ b/src/compiler/scala/tools/util/VerifyClass.scala
@@ -13,7 +13,8 @@ object VerifyClass {
Class.forName(name, true, cl)
(name, None)
} catch {
- case x => (name, Some(x.toString))
+ case x: Throwable => // TODO: only catch VerifyError (and related) + ExceptionInInitializationError (for static objects that bomb on classload)
+ (name, Some(x.toString))
}
}
diff --git a/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala b/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala
index 3a1dc87a6a..46c644bcd6 100644
--- a/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala
+++ b/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala
@@ -36,7 +36,7 @@ trait CPSUtils {
lazy val MarkerCPSAdaptMinus = rootMirror.getRequiredClass("scala.util.continuations.cpsMinus")
lazy val Context = rootMirror.getRequiredClass("scala.util.continuations.ControlContext")
- lazy val ModCPS = rootMirror.getRequiredModule("scala.util.continuations")
+ lazy val ModCPS = rootMirror.getRequiredPackage("scala.util.continuations")
lazy val MethShiftUnit = definitions.getMember(ModCPS, cpsNames.shiftUnit)
lazy val MethShiftUnit0 = definitions.getMember(ModCPS, cpsNames.shiftUnit0)
diff --git a/src/library-aux/scala/AnyRef.scala b/src/library-aux/scala/AnyRef.scala
index 1eefb0c806..7d8b9f9e76 100644
--- a/src/library-aux/scala/AnyRef.scala
+++ b/src/library-aux/scala/AnyRef.scala
@@ -10,6 +10,7 @@ package scala
/** Class `AnyRef` is the root class of all ''reference types''.
* All types except the value types descend from this class.
+ * @template
*/
trait AnyRef extends Any {
diff --git a/src/library/scala/Double.scala b/src/library/scala/Double.scala
index 2ff46c433d..510de92a2a 100644
--- a/src/library/scala/Double.scala
+++ b/src/library/scala/Double.scala
@@ -370,9 +370,6 @@ object Double extends AnyValCompanion {
final val PositiveInfinity = java.lang.Double.POSITIVE_INFINITY
final val NegativeInfinity = java.lang.Double.NEGATIVE_INFINITY
- @deprecated("use Double.MinPositiveValue instead", "2.9.0")
- final val Epsilon = MinPositiveValue
-
/** The negative number with the greatest (finite) absolute value which is representable
* by a Double. Note that it differs from [[java.lang.Double.MIN_VALUE]], which
* is the smallest positive value representable by a Double. In Scala that number
diff --git a/src/library/scala/Float.scala b/src/library/scala/Float.scala
index bd7a07fece..b9c116da0b 100644
--- a/src/library/scala/Float.scala
+++ b/src/library/scala/Float.scala
@@ -370,9 +370,6 @@ object Float extends AnyValCompanion {
final val PositiveInfinity = java.lang.Float.POSITIVE_INFINITY
final val NegativeInfinity = java.lang.Float.NEGATIVE_INFINITY
- @deprecated("use Float.MinPositiveValue instead", "2.9.0")
- final val Epsilon = MinPositiveValue
-
/** The negative number with the greatest (finite) absolute value which is representable
* by a Float. Note that it differs from [[java.lang.Float.MIN_VALUE]], which
* is the smallest positive value representable by a Float. In Scala that number
diff --git a/src/library/scala/annotation/static.scala b/src/library/scala/annotation/static.scala
new file mode 100644
index 0000000000..f2955c756c
--- /dev/null
+++ b/src/library/scala/annotation/static.scala
@@ -0,0 +1,20 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.annotation
+
+/**
+ * An annotation that marks a member in the companion object as static
+ * and ensures that the compiler generates static fields/methods for it.
+ * This is important for Java interoperability and performance reasons.
+ *
+ * @since 2.10
+ */
+final class static extends StaticAnnotation {
+ // TODO document exact semantics above!
+}
diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala
index 6fd8d143ee..74dc385f99 100644
--- a/src/library/scala/collection/immutable/List.scala
+++ b/src/library/scala/collection/immutable/List.scala
@@ -62,6 +62,7 @@ import java.io._
* section on `Lists` for more information.
*
* @define coll list
+ * @define Coll `List`
* @define thatinfo the class of the returned collection. In the standard library configuration,
* `That` is always `List[B]` because an implicit of type `CanBuildFrom[List, B, That]`
* is defined in object `List`.
@@ -96,7 +97,7 @@ sealed abstract class List[+A] extends AbstractSeq[A]
*
* @usecase def ::(x: A): List[A]
* @inheritdoc
- *
+ *
* Example:
* {{{1 :: List(2, 3) = List(2, 3).::(1) = List(1, 2, 3)}}}
*/
diff --git a/src/library/scala/collection/immutable/StringOps.scala b/src/library/scala/collection/immutable/StringOps.scala
index 633821ecea..7e60cc7195 100644
--- a/src/library/scala/collection/immutable/StringOps.scala
+++ b/src/library/scala/collection/immutable/StringOps.scala
@@ -25,7 +25,7 @@ import mutable.StringBuilder
* @param repr the actual representation of this string operations object.
*
* @since 2.8
- * @define Coll `StringOps`
+ * @define Coll `String`
* @define coll string
*/
final class StringOps(override val repr: String) extends AnyVal with StringLike[String] {
diff --git a/src/library/scala/collection/immutable/Vector.scala b/src/library/scala/collection/immutable/Vector.scala
index d100bf93df..4dfe147a65 100644
--- a/src/library/scala/collection/immutable/Vector.scala
+++ b/src/library/scala/collection/immutable/Vector.scala
@@ -18,8 +18,14 @@ import scala.collection.parallel.immutable.ParVector
/** Companion object to the Vector class
*/
object Vector extends SeqFactory[Vector] {
+ private[collection] class VectorReusableCBF extends GenericCanBuildFrom[Nothing] {
+ override def apply() = newBuilder[Nothing]
+ }
+
+ private val VectorReusableCBF: GenericCanBuildFrom[Nothing] = new VectorReusableCBF
+
@inline implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Vector[A]] =
- ReusableCBF.asInstanceOf[CanBuildFrom[Coll, A, Vector[A]]]
+ VectorReusableCBF.asInstanceOf[CanBuildFrom[Coll, A, Vector[A]]]
def newBuilder[A]: Builder[A, Vector[A]] = new VectorBuilder[A]
private[immutable] val NIL = new Vector[Nothing](0, 0, 0)
@inline override def empty[A]: Vector[A] = NIL
@@ -140,19 +146,19 @@ override def companion: GenericCompanion[Vector] = Vector
// SeqLike api
- @inline override def updated[B >: A, That](index: Int, elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = {
- // just ignore bf
- updateAt(index, elem).asInstanceOf[That]
+ @inline override def updated[B >: A, That](index: Int, elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = bf match {
+ case _: Vector.VectorReusableCBF => updateAt(index, elem).asInstanceOf[That] // just ignore bf
+ case _ => super.updated(index, elem)(bf)
}
- @inline override def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = {
- // just ignore bf
- appendFront(elem).asInstanceOf[That]
+ @inline override def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = bf match {
+ case _: Vector.VectorReusableCBF => appendFront(elem).asInstanceOf[That] // just ignore bf
+ case _ => super.+:(elem)(bf)
}
- @inline override def :+[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = {
- // just ignore bf
- appendBack(elem).asInstanceOf[That]
+ @inline override def :+[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = bf match {
+ case _: Vector.VectorReusableCBF => appendBack(elem).asInstanceOf[That] // just ignore bf
+ case _ => super.:+(elem)(bf)
}
override def take(n: Int): Vector[A] = {
diff --git a/src/library/scala/collection/mutable/ArrayOps.scala b/src/library/scala/collection/mutable/ArrayOps.scala
index 7a595f211d..21c2aaaec7 100644
--- a/src/library/scala/collection/mutable/ArrayOps.scala
+++ b/src/library/scala/collection/mutable/ArrayOps.scala
@@ -30,7 +30,7 @@ import parallel.mutable.ParArray
*
* @tparam T type of the elements contained in this array.
*
- * @define Coll `ArrayOps`
+ * @define Coll `Array`
* @define orderDependent
* @define orderDependentFold
* @define mayNotTerminateInf
diff --git a/src/library/scala/concurrent/BlockContext.scala b/src/library/scala/concurrent/BlockContext.scala
index a5b878c546..640560a174 100644
--- a/src/library/scala/concurrent/BlockContext.scala
+++ b/src/library/scala/concurrent/BlockContext.scala
@@ -12,9 +12,10 @@ import java.lang.Thread
import scala.concurrent.util.Duration
/**
- * A context to be notified by `scala.concurrent.blocking()` when
+ * A context to be notified by `scala.concurrent.blocking` when
* a thread is about to block. In effect this trait provides
- * the implementation for `scala.concurrent.blocking()`. `scala.concurrent.blocking()`
+ * the implementation for `scala.concurrent.Await`.
+ * `scala.concurrent.Await.result()` and `scala.concurrent.Await.ready()`
* locates an instance of `BlockContext` by first looking for one
* provided through `BlockContext.withBlockContext()` and failing that,
* checking whether `Thread.currentThread` is an instance of `BlockContext`.
@@ -27,11 +28,11 @@ import scala.concurrent.util.Duration
* {{{
* val oldContext = BlockContext.current
* val myContext = new BlockContext {
- * override def internalBlockingCall[T](awaitable: Awaitable[T], atMost: Duration): T = {
+ * override def blockOn[T](thunk: =>T)(implicit permission: CanAwait): T = {
* // you'd have code here doing whatever you need to do
* // when the thread is about to block.
* // Then you'd chain to the previous context:
- * oldContext.internalBlockingCall(awaitable, atMost)
+ * oldContext.blockOn(thunk)
* }
* }
* BlockContext.withBlockContext(myContext) {
@@ -42,35 +43,33 @@ import scala.concurrent.util.Duration
*/
trait BlockContext {
- /** Used internally by the framework; blocks execution for at most
- * `atMost` time while waiting for an `awaitable` object to become ready.
+ /** Used internally by the framework;
+ * Designates (and eventually executes) a thunk which potentially blocks the calling `Thread`.
*
- * Clients should use `scala.concurrent.blocking` instead; this is
- * the implementation of `scala.concurrent.blocking`, generally
- * provided by a `scala.concurrent.ExecutionContext` or `java.util.concurrent.Executor`.
+ * Clients must use `scala.concurrent.blocking` or `scala.concurrent.Await` instead.
*/
- def internalBlockingCall[T](awaitable: Awaitable[T], atMost: Duration): T
+ def blockOn[T](thunk: =>T)(implicit permission: CanAwait): T
}
object BlockContext {
private object DefaultBlockContext extends BlockContext {
- override def internalBlockingCall[T](awaitable: Awaitable[T], atMost: Duration): T =
- awaitable.result(atMost)(Await.canAwaitEvidence)
+ override def blockOn[T](thunk: =>T)(implicit permission: CanAwait): T = thunk
}
- private val contextLocal = new ThreadLocal[BlockContext]() {
- override def initialValue = Thread.currentThread match {
+ private val contextLocal = new ThreadLocal[BlockContext]()
+
+ /** Obtain the current thread's current `BlockContext`. */
+ def current: BlockContext = contextLocal.get match {
+ case null => Thread.currentThread match {
case ctx: BlockContext => ctx
case _ => DefaultBlockContext
}
+ case some => some
}
- /** Obtain the current thread's current `BlockContext`. */
- def current: BlockContext = contextLocal.get
-
/** Pushes a current `BlockContext` while executing `body`. */
def withBlockContext[T](blockContext: BlockContext)(body: => T): T = {
- val old = contextLocal.get
+ val old = contextLocal.get // can be null
try {
contextLocal.set(blockContext)
body
diff --git a/src/library/scala/concurrent/Future.scala b/src/library/scala/concurrent/Future.scala
index f82b79cb18..d24fdbf005 100644
--- a/src/library/scala/concurrent/Future.scala
+++ b/src/library/scala/concurrent/Future.scala
@@ -707,11 +707,9 @@ object Future {
// doesn't need to create defaultExecutionContext as
// a side effect.
private[concurrent] object InternalCallbackExecutor extends ExecutionContext {
- def execute(runnable: Runnable): Unit =
+ override def execute(runnable: Runnable): Unit =
runnable.run()
- def internalBlockingCall[T](awaitable: Awaitable[T], atMost: Duration): T =
- throw new IllegalStateException("bug in scala.concurrent, called blocking() from internal callback")
- def reportFailure(t: Throwable): Unit =
+ override def reportFailure(t: Throwable): Unit =
throw new IllegalStateException("problem in scala.concurrent internal callback", t)
}
}
diff --git a/src/library/scala/concurrent/default/SchedulerImpl.scala.disabled b/src/library/scala/concurrent/default/SchedulerImpl.scala.disabled
deleted file mode 100644
index 241efa8857..0000000000
--- a/src/library/scala/concurrent/default/SchedulerImpl.scala.disabled
+++ /dev/null
@@ -1,44 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-package scala.concurrent
-package default
-
-import scala.concurrent.util.Duration
-
-private[concurrent] final class SchedulerImpl extends Scheduler {
- private val timer =
- new java.util.Timer(true) // the associated thread runs as a daemon
-
- def schedule(delay: Duration, frequency: Duration)(thunk: => Unit): Cancellable = ???
-
- def scheduleOnce(delay: Duration, task: Runnable): Cancellable = {
- val timerTask = new java.util.TimerTask {
- def run(): Unit =
- task.run()
- }
- timer.schedule(timerTask, delay.toMillis)
- new Cancellable {
- def cancel(): Unit =
- timerTask.cancel()
- }
- }
-
- def scheduleOnce(delay: Duration)(task: => Unit): Cancellable = {
- val timerTask = new java.util.TimerTask {
- def run(): Unit =
- task
- }
- timer.schedule(timerTask, delay.toMillis)
- new Cancellable {
- def cancel(): Unit =
- timerTask.cancel()
- }
- }
-
-}
diff --git a/src/library/scala/concurrent/default/TaskImpl.scala.disabled b/src/library/scala/concurrent/default/TaskImpl.scala.disabled
deleted file mode 100644
index 8b4eb12d4f..0000000000
--- a/src/library/scala/concurrent/default/TaskImpl.scala.disabled
+++ /dev/null
@@ -1,313 +0,0 @@
-package scala.concurrent
-package default
-
-
-
-import java.util.concurrent.atomic.AtomicReferenceFieldUpdater
-import scala.concurrent.forkjoin.{ ForkJoinPool, RecursiveAction, ForkJoinWorkerThread }
-import scala.util.Try
-import scala.util
-import scala.concurrent.util.Duration
-import scala.annotation.tailrec
-import scala.util.control.NonFatal
-
-
-private[concurrent] trait Completable[T] {
-self: Future[T] =>
-
- val executor: ExecutionContextImpl
-
- def newPromise[S]: Promise[S] = executor promise
-
- type Callback = Try[T] => Any
-
- def getState: State[T]
-
- def casState(oldv: State[T], newv: State[T]): Boolean
-
- protected def dispatch[U](r: Runnable) = executionContext execute r
-
- protected def processCallbacks(cbs: List[Callback], r: Try[T]) =
- for (cb <- cbs) dispatch(new Runnable {
- override def run() = cb(r)
- })
-
- def future: Future[T] = self
-
- def onComplete[U](callback: Try[T] => U): this.type = {
- @tailrec def tryAddCallback(): Try[T] = {
- getState match {
- case p @ Pending(lst) =>
- val pt = p.asInstanceOf[Pending[T]]
- if (casState(pt, Pending(callback :: pt.callbacks))) null
- else tryAddCallback()
- case Success(res) => util.Success(res)
- case Failure(t) => util.Failure(t)
- }
- }
-
- val res = tryAddCallback()
- if (res != null) dispatch(new Runnable {
- override def run() =
- try callback(res)
- catch handledFutureException andThen {
- t => Console.err.println(t)
- }
- })
-
- this
- }
-
- def isTimedout: Boolean = getState match {
- case Failure(ft: FutureTimeoutException) => true
- case _ => false
- }
-
-}
-
-private[concurrent] class PromiseImpl[T](context: ExecutionContextImpl)
-extends Promise[T] with Future[T] with Completable[T] {
-
- val executor: scala.concurrent.default.ExecutionContextImpl = context
-
- @volatile private var state: State[T] = _
-
- val updater = AtomicReferenceFieldUpdater.newUpdater(classOf[PromiseImpl[T]], classOf[State[T]], "state")
-
- updater.set(this, Pending(List()))
-
- def casState(oldv: State[T], newv: State[T]): Boolean = {
- updater.compareAndSet(this, oldv, newv)
- }
-
- def getState: State[T] = {
- updater.get(this)
- }
-
- @tailrec private def tryCompleteState(completed: State[T]): List[Callback] = (getState: @unchecked) match {
- case p @ Pending(cbs) => if (!casState(p, completed)) tryCompleteState(completed) else cbs
- case _ => null
- }
-
- def tryComplete(r: Try[T]) = r match {
- case util.Failure(t) => tryFailure(t)
- case util.Success(v) => trySuccess(v)
- }
-
- override def trySuccess(value: T): Boolean = {
- val cbs = tryCompleteState(Success(value))
- if (cbs == null)
- false
- else {
- processCallbacks(cbs, util.Success(value))
- this.synchronized {
- this.notifyAll()
- }
- true
- }
- }
-
- override def tryFailure(t: Throwable): Boolean = {
- val wrapped = wrap(t)
- val cbs = tryCompleteState(Failure(wrapped))
- if (cbs == null)
- false
- else {
- processCallbacks(cbs, util.Failure(wrapped))
- this.synchronized {
- this.notifyAll()
- }
- true
- }
- }
-
- def await(atMost: Duration)(implicit canawait: scala.concurrent.CanAwait): T = getState match {
- case Success(res) => res
- case Failure(t) => throw t
- case _ =>
- this.synchronized {
- while (true)
- getState match {
- case Pending(_) => this.wait()
- case Success(res) => return res
- case Failure(t) => throw t
- }
- }
- sys.error("unreachable")
- }
-
-}
-
-private[concurrent] class TaskImpl[T](context: ExecutionContextImpl, body: => T)
-extends RecursiveAction with Task[T] with Future[T] with Completable[T] {
-
- val executor: ExecutionContextImpl = context
-
- @volatile private var state: State[T] = _
-
- val updater = AtomicReferenceFieldUpdater.newUpdater(classOf[TaskImpl[T]], classOf[State[T]], "state")
-
- updater.set(this, Pending(List()))
-
- def casState(oldv: State[T], newv: State[T]): Boolean = {
- updater.compareAndSet(this, oldv, newv)
- }
-
- def getState: State[T] = {
- updater.get(this)
- }
-
- @tailrec private def tryCompleteState(completed: State[T]): List[Callback] = (getState: @unchecked) match {
- case p @ Pending(cbs) => if (!casState(p, completed)) tryCompleteState(completed) else cbs
- }
-
- def compute(): Unit = {
- var cbs: List[Callback] = null
- try {
- val res = body
- processCallbacks(tryCompleteState(Success(res)), util.Success(res))
- } catch {
- case t if NonFatal(t) =>
- processCallbacks(tryCompleteState(Failure(t)), util.Failure(t))
- case t =>
- val ee = new ExecutionException(t)
- processCallbacks(tryCompleteState(Failure(ee)), util.Failure(ee))
- throw t
- }
- }
-
- def start(): Unit = {
- Thread.currentThread match {
- case fj: ForkJoinWorkerThread if fj.getPool eq executor.pool => fork()
- case _ => executor.pool.execute(this)
- }
- }
-
- // TODO FIXME: handle timeouts
- def await(atMost: Duration): this.type =
- await
-
- def await: this.type = {
- this.join()
- this
- }
-
- def tryCancel(): Unit =
- tryUnfork()
-
- def await(atMost: Duration)(implicit canawait: CanAwait): T = {
- join() // TODO handle timeout also
- (updater.get(this): @unchecked) match {
- case Success(r) => r
- case Failure(t) => throw t
- }
- }
-
-}
-
-
-private[concurrent] sealed abstract class State[T]
-
-
-case class Pending[T](callbacks: List[Try[T] => Any]) extends State[T]
-
-
-case class Success[T](result: T) extends State[T]
-
-
-case class Failure[T](throwable: Throwable) extends State[T]
-
-
-private[concurrent] final class ExecutionContextImpl extends ExecutionContext {
- import ExecutionContextImpl._
-
- val pool = {
- val p = new ForkJoinPool
- p.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler {
- def uncaughtException(t: Thread, throwable: Throwable) {
- Console.err.println(throwable.getMessage)
- throwable.printStackTrace(Console.err)
- }
- })
- p
- }
-
- @inline
- private def executeTask(task: RecursiveAction) {
- if (Thread.currentThread.isInstanceOf[ForkJoinWorkerThread])
- task.fork()
- else
- pool execute task
- }
-
- def execute(task: Runnable) {
- val action = new RecursiveAction { def compute() { task.run() } }
- executeTask(action)
- }
-
- def execute[U](body: () => U) {
- val action = new RecursiveAction { def compute() { body() } }
- executeTask(action)
- }
-
- def task[T](body: => T): Task[T] = {
- new TaskImpl(this, body)
- }
-
- def future[T](body: => T): Future[T] = {
- val t = task(body)
- t.start()
- t.future
- }
-
- def promise[T]: Promise[T] =
- new PromiseImpl[T](this)
-
- def blocking[T](atMost: Duration)(body: =>T): T = blocking(body2awaitable(body), atMost)
-
- def blocking[T](awaitable: Awaitable[T], atMost: Duration): T = {
- currentExecutionContext.get match {
- case null => awaitable.await(atMost)(null) // outside - TODO - fix timeout case
- case x if x eq this => this.blockingCall(awaitable) // inside an execution context thread on this executor
- case x => x.blocking(awaitable, atMost)
- }
- }
-
- private def blockingCall[T](b: Awaitable[T]): T = b match {
- case fj: TaskImpl[_] if fj.executor.pool eq pool =>
- fj.await(Duration.fromNanos(0))
- case _ =>
- var res: T = null.asInstanceOf[T]
- @volatile var blockingDone = false
- // TODO add exception handling here!
- val mb = new ForkJoinPool.ManagedBlocker {
- def block() = {
- res = b.await(Duration.fromNanos(0))(CanAwaitEvidence)
- blockingDone = true
- true
- }
- def isReleasable = blockingDone
- }
- ForkJoinPool.managedBlock(mb, true)
- res
- }
-
- def reportFailure(t: Throwable): Unit = {}
-
-}
-
-
-object ExecutionContextImpl {
-
- private[concurrent] def currentExecutionContext: ThreadLocal[ExecutionContext] = new ThreadLocal[ExecutionContext] {
- override protected def initialValue = null
- }
-
-}
-
-
-
-
-
-
-
diff --git a/src/library/scala/concurrent/impl/ExecutionContextImpl.scala b/src/library/scala/concurrent/impl/ExecutionContextImpl.scala
index 98f821652f..875a558887 100644
--- a/src/library/scala/concurrent/impl/ExecutionContextImpl.scala
+++ b/src/library/scala/concurrent/impl/ExecutionContextImpl.scala
@@ -13,7 +13,7 @@ package scala.concurrent.impl
import java.util.concurrent.{ LinkedBlockingQueue, Callable, Executor, ExecutorService, Executors, ThreadFactory, TimeUnit, ThreadPoolExecutor }
import java.util.Collection
import scala.concurrent.forkjoin._
-import scala.concurrent.{ BlockContext, ExecutionContext, Awaitable, ExecutionContextExecutor, ExecutionContextExecutorService }
+import scala.concurrent.{ BlockContext, ExecutionContext, Awaitable, CanAwait, ExecutionContextExecutor, ExecutionContextExecutorService }
import scala.concurrent.util.Duration
import scala.util.control.NonFatal
@@ -37,15 +37,15 @@ private[scala] class ExecutionContextImpl private[impl] (es: Executor, reporter:
def newThread(runnable: Runnable): Thread = wire(new Thread(runnable))
def newThread(fjp: ForkJoinPool): ForkJoinWorkerThread = wire(new ForkJoinWorkerThread(fjp) with BlockContext {
- override def internalBlockingCall[T](awaitable: Awaitable[T], atMost: Duration): T = {
+ override def blockOn[T](thunk: =>T)(implicit permission: CanAwait): T = {
var result: T = null.asInstanceOf[T]
ForkJoinPool.managedBlock(new ForkJoinPool.ManagedBlocker {
@volatile var isdone = false
- def block(): Boolean = {
- result = try awaitable.result(atMost)(scala.concurrent.Await.canAwaitEvidence) finally { isdone = true }
+ override def block(): Boolean = {
+ result = try thunk finally { isdone = true }
true
}
- def isReleasable = isdone
+ override def isReleasable = isdone
})
result
}
diff --git a/src/library/scala/concurrent/impl/Future.scala b/src/library/scala/concurrent/impl/Future.scala
index 132e1d79e7..098008e958 100644
--- a/src/library/scala/concurrent/impl/Future.scala
+++ b/src/library/scala/concurrent/impl/Future.scala
@@ -10,31 +10,13 @@ package scala.concurrent.impl
-import scala.concurrent.util.Duration
-import scala.concurrent.{Awaitable, ExecutionContext, CanAwait}
-import scala.collection.mutable.Stack
+import scala.concurrent.ExecutionContext
import scala.util.control.NonFatal
-private[concurrent] trait Future[+T] extends scala.concurrent.Future[T] with Awaitable[T] {
-
-}
private[concurrent] object Future {
-
- /** Wraps a block of code into an awaitable object. */
- private[concurrent] def body2awaitable[T](body: =>T) = new Awaitable[T] {
- def ready(atMost: Duration)(implicit permit: CanAwait) = {
- body
- this
- }
- def result(atMost: Duration)(implicit permit: CanAwait) = body
- }
-
- def boxedType(c: Class[_]): Class[_] = if (c.isPrimitive) scala.concurrent.Future.toBoxed(c) else c
-
- private[impl] class PromiseCompletingRunnable[T](body: => T)
- extends Runnable {
+ class PromiseCompletingRunnable[T](body: => T) extends Runnable {
val promise = new Promise.DefaultPromise[T]()
override def run() = {
@@ -44,7 +26,7 @@ private[concurrent] object Future {
}
}
- def apply[T](body: =>T)(implicit executor: ExecutionContext): Future[T] = {
+ def apply[T](body: =>T)(implicit executor: ExecutionContext): scala.concurrent.Future[T] = {
val runnable = new PromiseCompletingRunnable(body)
executor.execute(runnable)
runnable.promise.future
diff --git a/src/library/scala/concurrent/impl/Promise.scala b/src/library/scala/concurrent/impl/Promise.scala
index 84638586cf..c2df9ac296 100644
--- a/src/library/scala/concurrent/impl/Promise.scala
+++ b/src/library/scala/concurrent/impl/Promise.scala
@@ -18,7 +18,7 @@ import scala.util.control.NonFatal
-private[concurrent] trait Promise[T] extends scala.concurrent.Promise[T] with Future[T] {
+private[concurrent] trait Promise[T] extends scala.concurrent.Promise[T] with scala.concurrent.Future[T] {
def future: this.type = this
}
diff --git a/src/library/scala/concurrent/package.scala b/src/library/scala/concurrent/package.scala
index 76703bf081..a2ef42fac8 100644
--- a/src/library/scala/concurrent/package.scala
+++ b/src/library/scala/concurrent/package.scala
@@ -9,6 +9,7 @@
package scala
import scala.concurrent.util.Duration
+import scala.annotation.implicitNotFound
/** This package object contains primitives for concurrent and parallel programming.
*/
@@ -36,46 +37,59 @@ package object concurrent {
*/
def promise[T]()(implicit execctx: ExecutionContext): Promise[T] = Promise[T]()
- /** Used to block on a piece of code which potentially blocks.
+ /** Used to designate a piece of code which potentially blocks, allowing the BlockContext to adjust the runtime's behavior.
+ * Properly marking blocking code may improve performance or avoid deadlocks.
*
- * @param body A piece of code which contains potentially blocking or long running calls.
- *
- * Calling this method may throw the following exceptions:
- * - CancellationException - if the computation was cancelled
- * - InterruptedException - in the case that a wait within the blockable object was interrupted
- * - TimeoutException - in the case that the blockable object timed out
- */
- def blocking[T](body: =>T): T = blocking(impl.Future.body2awaitable(body), Duration.Inf)
-
- /** Blocks on an awaitable object.
+ * If you have an `Awaitable` then you should use Await.result instead of `blocking`.
*
- * @param awaitable An object with a `block` method which runs potentially blocking or long running calls.
+ * @param body A piece of code which contains potentially blocking or long running calls.
*
* Calling this method may throw the following exceptions:
* - CancellationException - if the computation was cancelled
* - InterruptedException - in the case that a wait within the blockable object was interrupted
* - TimeoutException - in the case that the blockable object timed out
*/
- def blocking[T](awaitable: Awaitable[T], atMost: Duration): T =
- BlockContext.current.internalBlockingCall(awaitable, atMost)
+ @throws(classOf[Exception])
+ def blocking[T](body: =>T): T = BlockContext.current.blockOn(body)(scala.concurrent.AwaitPermission)
}
-/* concurrency constructs */
package concurrent {
-
+ @implicitNotFound("Don't call `Awaitable` methods directly, use the `Await` object.")
sealed trait CanAwait
+ /**
+ * Internal usage only, implementation detail.
+ */
+ private[concurrent] object AwaitPermission extends CanAwait
+
+ /**
+ * `Await` is what is used to ensure proper handling of blocking for `Awaitable` instances.
+ */
object Await {
- private[concurrent] implicit val canAwaitEvidence = new CanAwait {}
-
- def ready[T](awaitable: Awaitable[T], atMost: Duration): awaitable.type = {
- blocking(awaitable, atMost)
- awaitable
- }
-
- def result[T](awaitable: Awaitable[T], atMost: Duration): T = {
- blocking(awaitable, atMost)
- }
+ /**
+ * Invokes ready() on the awaitable, properly wrapped by a call to `scala.concurrent.blocking`.
+ * ready() blocks until the awaitable has completed or the timeout expires.
+ *
+ * Throws a TimeoutException if the timeout expires, as that is in the contract of `Awaitable.ready`.
+ * @param awaitable the `Awaitable` on which `ready` is to be called
+ * @param atMost the maximum timeout for which to wait
+ * @return the result of `awaitable.ready` which is defined to be the awaitable itself.
+ */
+ @throws(classOf[TimeoutException])
+ def ready[T](awaitable: Awaitable[T], atMost: Duration): awaitable.type =
+ blocking(awaitable.ready(atMost)(AwaitPermission))
+ /**
+ * Invokes result() on the awaitable, properly wrapped by a call to `scala.concurrent.blocking`.
+ * result() blocks until the awaitable has completed or the timeout expires.
+ *
+ * Throws a TimeoutException if the timeout expires, or any exception thrown by `Awaitable.result`.
+ * @param awaitable the `Awaitable` on which `result` is to be called
+ * @param atMost the maximum timeout for which to wait
+ * @return the result of `awaitable.result`
+ */
+ @throws(classOf[Exception])
+ def result[T](awaitable: Awaitable[T], atMost: Duration): T =
+ blocking(awaitable.result(atMost)(AwaitPermission))
}
}
diff --git a/src/library/scala/reflect/base/Base.scala b/src/library/scala/reflect/base/Base.scala
index a4e6256f4d..4457a6cf14 100644
--- a/src/library/scala/reflect/base/Base.scala
+++ b/src/library/scala/reflect/base/Base.scala
@@ -357,6 +357,9 @@ class Base extends Universe { self =>
def staticModule(fullName: String): ModuleSymbol =
mkStatic[ModuleSymbol](fullName)
+ def staticPackage(fullName: String): ModuleSymbol =
+ staticModule(fullName) // this toy universe doesn't care about the distinction between packages and modules
+
private def mkStatic[S <: Symbol : ClassTag](fullName: String): S =
cached(fullName) {
val point = fullName lastIndexOf '.'
diff --git a/src/library/scala/reflect/base/MirrorOf.scala b/src/library/scala/reflect/base/MirrorOf.scala
index 03e035cd81..6dc8090eee 100644
--- a/src/library/scala/reflect/base/MirrorOf.scala
+++ b/src/library/scala/reflect/base/MirrorOf.scala
@@ -15,11 +15,76 @@ abstract class MirrorOf[U <: base.Universe with Singleton] {
/** The symbol corresponding to the globally accessible class with the
* given fully qualified name `fullName`.
+ *
+ * If the name points to a type alias, it's recursively dealiased and its target is returned.
+ * If you need a symbol that corresponds to the type alias itself, load it directly from the package class:
+ *
+ * scala> cm.staticClass("scala.List")
+ * res0: reflect.runtime.universe.ClassSymbol = class List
+ *
+ * scala> res0.fullName
+ * res1: String = scala.collection.immutable.List
+ *
+ * scala> cm.staticPackage("scala")
+ * res2: reflect.runtime.universe.ModuleSymbol = package scala
+ *
+ * scala> res2.moduleClass.typeSignature member newTypeName("List")
+ * res3: reflect.runtime.universe.Symbol = type List
+ *
+ * scala> res3.fullName
+ * res4: String = scala.List
+ *
+ * To be consistent with Scala name resolution rules, in case of ambiguity between
+ * a package and an object, the object is never been considered.
+ *
+ * For example for the following code:
+ *
+ * package foo {
+ * class B
+ * }
+ *
+ * object foo {
+ * class A
+ * class B
+ * }
+ *
+ * staticClass("foo.B") will resolve to the symbol corresponding to the class B declared in the package foo, and
+ * staticClass("foo.A") will throw a MissingRequirementException (which is exactly what scalac would do if this
+ * fully qualified class name is written inside any package in a Scala program).
+ *
+ * In the example above, to load a symbol that corresponds to the class B declared in the object foo,
+ * use staticModule("foo") to load the module symbol and then navigate typeSignature.members of its moduleClass.
*/
def staticClass(fullName: String): U#ClassSymbol
/** The symbol corresponding to the globally accessible object with the
* given fully qualified name `fullName`.
+ *
+ * To be consistent with Scala name resolution rules, in case of ambiguity between
+ * a package and an object, the object is never been considered.
+ *
+ * For example for the following code:
+ *
+ * package foo {
+ * object B
+ * }
+ *
+ * object foo {
+ * object A
+ * object B
+ * }
+ *
+ * staticModule("foo.B") will resolve to the symbol corresponding to the object B declared in the package foo, and
+ * staticModule("foo.A") will throw a MissingRequirementException (which is exactly what scalac would do if this
+ * fully qualified class name is written inside any package in a Scala program).
+ *
+ * In the example above, to load a symbol that corresponds to the object B declared in the object foo,
+ * use staticModule("foo") to load the module symbol and then navigate typeSignature.members of its moduleClass.
*/
def staticModule(fullName: String): U#ModuleSymbol
+
+ /** The symbol corresponding to a package with the
+ * given fully qualified name `fullName`.
+ */
+ def staticPackage(fullName: String): U#ModuleSymbol
}
diff --git a/src/library/scala/reflect/package.scala b/src/library/scala/reflect/package.scala
index 9f9d4089c4..d97f2ec633 100644
--- a/src/library/scala/reflect/package.scala
+++ b/src/library/scala/reflect/package.scala
@@ -65,3 +65,6 @@ package object reflect {
@deprecated("Use `@scala.beans.ScalaBeanInfo` instead", "2.10.0")
type ScalaBeanInfo = scala.beans.ScalaBeanInfo
}
+
+/** An exception that indicates an error during Scala reflection */
+case class ScalaReflectionException(msg: String) extends Exception(msg)
diff --git a/src/partest/scala/tools/partest/CompilerTest.scala b/src/partest/scala/tools/partest/CompilerTest.scala
index 89c1a9c2ca..fec9893099 100644
--- a/src/partest/scala/tools/partest/CompilerTest.scala
+++ b/src/partest/scala/tools/partest/CompilerTest.scala
@@ -50,7 +50,7 @@ abstract class CompilerTest extends DirectTest {
}
class SymsInPackage(pkgName: String) {
- def pkg = rootMirror.getRequiredModule(pkgName)
+ def pkg = rootMirror.getRequiredPackage(pkgName)
def classes = allMembers(pkg) filter (_.isClass)
def modules = allMembers(pkg) filter (_.isModule)
def symbols = classes ++ terms filterNot (_ eq NoSymbol)
diff --git a/src/partest/scala/tools/partest/DirectTest.scala b/src/partest/scala/tools/partest/DirectTest.scala
index 4e7f36bdc9..5b4e1b4b25 100644
--- a/src/partest/scala/tools/partest/DirectTest.scala
+++ b/src/partest/scala/tools/partest/DirectTest.scala
@@ -38,7 +38,8 @@ abstract class DirectTest extends App {
// new compiler
def newCompiler(args: String*): Global = {
val settings = newSettings((CommandLineParser tokenize extraSettings) ++ args.toList)
- new Global(settings)
+ if (settings.Yrangepos.value) new Global(settings) with interactive.RangePositions
+ else new Global(settings)
}
def newSources(sourceCodes: String*) = sourceCodes.toList.zipWithIndex map {
case (src, idx) => new BatchSourceFile("newSource" + (idx + 1), src)
@@ -69,7 +70,7 @@ abstract class DirectTest extends App {
/** Constructor/main body **/
try show()
- catch { case t => println(t) ; t.printStackTrace ; sys.exit(1) }
+ catch { case t => println(t.getMessage) ; t.printStackTrace ; sys.exit(1) }
/** Debugger interest only below this line **/
protected def isDebug = (sys.props contains "partest.debug") || (sys.env contains "PARTEST_DEBUG")
diff --git a/src/partest/scala/tools/partest/ScaladocModelTest.scala b/src/partest/scala/tools/partest/ScaladocModelTest.scala
index de5354d4a0..ffc5e74cc0 100644
--- a/src/partest/scala/tools/partest/ScaladocModelTest.scala
+++ b/src/partest/scala/tools/partest/ScaladocModelTest.scala
@@ -11,6 +11,8 @@ import scala.tools.nsc._
import scala.tools.nsc.util.CommandLineParser
import scala.tools.nsc.doc.{Settings, DocFactory, Universe}
import scala.tools.nsc.doc.model._
+import scala.tools.nsc.doc.model.diagram._
+import scala.tools.nsc.doc.model.comment._
import scala.tools.nsc.reporters.ConsoleReporter
/** A class for testing scaladoc model generation
@@ -102,13 +104,22 @@ abstract class ScaladocModelTest extends DirectTest {
class TemplateAccess(tpl: DocTemplateEntity) {
def _class(name: String): DocTemplateEntity = getTheFirst(_classes(name), tpl.qualifiedName + ".class(" + name + ")")
- def _classes(name: String): List[DocTemplateEntity] = tpl.templates.filter(_.name == name).collect({ case c: Class => c})
+ def _classes(name: String): List[DocTemplateEntity] = tpl.templates.filter(_.name == name).collect({ case c: DocTemplateEntity with Class => c})
+
+ def _classMbr(name: String): MemberTemplateEntity = getTheFirst(_classesMbr(name), tpl.qualifiedName + ".classMember(" + name + ")")
+ def _classesMbr(name: String): List[MemberTemplateEntity] = tpl.templates.filter(_.name == name).collect({ case c: MemberTemplateEntity if c.isClass => c})
def _trait(name: String): DocTemplateEntity = getTheFirst(_traits(name), tpl.qualifiedName + ".trait(" + name + ")")
- def _traits(name: String): List[DocTemplateEntity] = tpl.templates.filter(_.name == name).collect({ case t: Trait => t})
+ def _traits(name: String): List[DocTemplateEntity] = tpl.templates.filter(_.name == name).collect({ case t: DocTemplateEntity with Trait => t})
+
+ def _traitMbr(name: String): MemberTemplateEntity = getTheFirst(_traitsMbr(name), tpl.qualifiedName + ".traitMember(" + name + ")")
+ def _traitsMbr(name: String): List[MemberTemplateEntity] = tpl.templates.filter(_.name == name).collect({ case t: MemberTemplateEntity if t.isTrait => t})
def _object(name: String): DocTemplateEntity = getTheFirst(_objects(name), tpl.qualifiedName + ".object(" + name + ")")
- def _objects(name: String): List[DocTemplateEntity] = tpl.templates.filter(_.name == name).collect({ case o: Object => o})
+ def _objects(name: String): List[DocTemplateEntity] = tpl.templates.filter(_.name == name).collect({ case o: DocTemplateEntity with Object => o})
+
+ def _objectMbr(name: String): MemberTemplateEntity = getTheFirst(_objectsMbr(name), tpl.qualifiedName + ".objectMember(" + name + ")")
+ def _objectsMbr(name: String): List[MemberTemplateEntity] = tpl.templates.filter(_.name == name).collect({ case o: MemberTemplateEntity if o.isObject => o})
def _method(name: String): Def = getTheFirst(_methods(name), tpl.qualifiedName + ".method(" + name + ")")
def _methods(name: String): List[Def] = tpl.methods.filter(_.name == name)
@@ -118,6 +129,18 @@ abstract class ScaladocModelTest extends DirectTest {
def _conversion(name: String): ImplicitConversion = getTheFirst(_conversions(name), tpl.qualifiedName + ".conversion(" + name + ")")
def _conversions(name: String): List[ImplicitConversion] = tpl.conversions.filter(_.conversionQualifiedName == name)
+
+ def _absType(name: String): MemberEntity = getTheFirst(_absTypes(name), tpl.qualifiedName + ".abstractType(" + name + ")")
+ def _absTypes(name: String): List[MemberEntity] = tpl.members.filter(mbr => mbr.name == name && mbr.isAbstractType)
+
+ def _absTypeTpl(name: String): DocTemplateEntity = getTheFirst(_absTypeTpls(name), tpl.qualifiedName + ".abstractType(" + name + ")")
+ def _absTypeTpls(name: String): List[DocTemplateEntity] = tpl.members.collect({ case dtpl: DocTemplateEntity with AbstractType if dtpl.name == name => dtpl })
+
+ def _aliasType(name: String): MemberEntity = getTheFirst(_aliasTypes(name), tpl.qualifiedName + ".aliasType(" + name + ")")
+ def _aliasTypes(name: String): List[MemberEntity] = tpl.members.filter(mbr => mbr.name == name && mbr.isAliasType)
+
+ def _aliasTypeTpl(name: String): DocTemplateEntity = getTheFirst(_aliasTypeTpls(name), tpl.qualifiedName + ".aliasType(" + name + ")")
+ def _aliasTypeTpls(name: String): List[DocTemplateEntity] = tpl.members.collect({ case dtpl: DocTemplateEntity with AliasType if dtpl.name == name => dtpl })
}
class PackageAccess(pack: Package) extends TemplateAccess(pack) {
@@ -140,7 +163,43 @@ abstract class ScaladocModelTest extends DirectTest {
case 1 => list.head
case 0 => sys.error("Error getting " + expl + ": No such element.")
case _ => sys.error("Error getting " + expl + ": " + list.length + " elements with this name. " +
- "All elements in list: [" + list.mkString(", ") + "]")
+ "All elements in list: [" + list.map({
+ case ent: Entity => ent.kind + " " + ent.qualifiedName
+ case other => other.toString
+ }).mkString(", ") + "]")
+ }
+
+ def extractCommentText(c: Any) = {
+ def extractText(body: Any): String = body match {
+ case s: String => s
+ case s: Seq[_] => s.toList.map(extractText(_)).mkString
+ case p: Product => p.productIterator.toList.map(extractText(_)).mkString
+ case _ => ""
+ }
+ c match {
+ case c: Comment =>
+ extractText(c.body)
+ case b: Body =>
+ extractText(b)
+ }
+ }
+
+ def countLinks(c: Comment, p: EntityLink => Boolean) = {
+ def countLinks(body: Any): Int = body match {
+ case el: EntityLink if p(el) => 1
+ case s: Seq[_] => s.toList.map(countLinks(_)).sum
+ case p: Product => p.productIterator.toList.map(countLinks(_)).sum
+ case _ => 0
+ }
+ countLinks(c.body)
+ }
+
+ def testDiagram(doc: DocTemplateEntity, diag: Option[Diagram], nodes: Int, edges: Int) = {
+ assert(diag.isDefined, doc.qualifiedName + " diagram missing")
+ assert(diag.get.nodes.length == nodes,
+ doc.qualifiedName + "'s diagram: node count " + diag.get.nodes.length + " == " + nodes)
+ assert(diag.get.edges.map(_._2.length).sum == edges,
+ doc.qualifiedName + "'s diagram: edge count " + diag.get.edges.length + " == " + edges)
}
}
}
diff --git a/src/partest/scala/tools/partest/nest/DirectRunner.scala b/src/partest/scala/tools/partest/nest/DirectRunner.scala
index 6c239721c3..c254472342 100644
--- a/src/partest/scala/tools/partest/nest/DirectRunner.scala
+++ b/src/partest/scala/tools/partest/nest/DirectRunner.scala
@@ -59,8 +59,12 @@ trait DirectRunner {
val futures = kindFiles map (f => (f, pool submit callable(manager runTest f))) toMap
pool.shutdown()
- if (!pool.awaitTermination(4, TimeUnit.HOURS))
+ try if (!pool.awaitTermination(4, TimeUnit.HOURS))
NestUI.warning("Thread pool timeout elapsed before all tests were complete!")
+ catch { case t: InterruptedException =>
+ NestUI.warning("Thread pool was interrupted")
+ t.printStackTrace()
+ }
for ((file, future) <- futures) yield {
val state = if (future.isCancelled) TestState.Timeout else future.get
diff --git a/src/reflect/scala/reflect/api/Mirrors.scala b/src/reflect/scala/reflect/api/Mirrors.scala
index 348ab3656b..27176a2a2d 100644
--- a/src/reflect/scala/reflect/api/Mirrors.scala
+++ b/src/reflect/scala/reflect/api/Mirrors.scala
@@ -27,28 +27,63 @@ trait Mirrors { self: Universe =>
/** The instance value reflected by this mirror */
def instance: Any
- /** The symbol corresponding to the run-time class of the reflected instance. */
+ /** The symbol corresponding to the run-time class of the reflected instance */
def symbol: ClassSymbol
- /** Get value of field in reflected instance.
- * @field A field symbol that should represent a field of the instance class.
- * @return The value associated with that field in the reflected instance
- * @throws ???
+ /** Reflects against a field symbol and returns a mirror
+ * that can be used to get and, if appropriate, set the value of the field.
+ *
+ * To get a field symbol by the name of the field you would like to reflect,
+ * use `<this mirror>.symbol.typeSignature.member(newTermName(<name of the field>)).asTermSymbol`.
+ * For further information about member lookup refer to `Symbol.typeSignature`.
+ *
+ * The input symbol can be either private or non-private (Scala reflection transparently deals with visibility).
+ * It must be a member (declared or inherited) of the class of the instance underlying this mirror.
+ *
+ * The input symbol can represent either a field itself or one of the corresponding accessors
+ * (in all cases the resulting mirror will refer to the field symbol).
+ *
+ * If a field symbol doesn't correspond to a reflectable entity of the underlying platform,
+ * a `ScalaReflectionException` exception will be thrown. This might happen, for example, for primary constructor parameters.
+ * Typically they produce class fields, however, private parameters that aren't used outside the constructor
+ * remain plain parameters of a constructor method of the class.
*/
def reflectField(field: TermSymbol): FieldMirror
- /** Invokes a method on the reflected instance.
- * @param meth A method symbol that should represent a method of the instance class
- * @param args The arguments to pass to the method
- * @return The result of invoking `meth(args)` on the reflected instance.
- * @throws ???
+ /** Reflects against a method symbol and returns a mirror
+ * that can be used to invoke the method provided.
+ *
+ * To get a method symbol by the name of the method you would like to reflect,
+ * use `<this mirror>.symbol.typeSignature.member(newTermName(<name of the method>)).asMethodSymbol`.
+ * For further information about member lookup refer to `Symbol.typeSignature`.
+ *
+ * The input symbol can be either private or non-private (Scala reflection transparently deals with visibility).
+ * It must be a member (declared or inherited) of the instance underlying this mirror.
*/
def reflectMethod(method: MethodSymbol): MethodMirror
- /** .. */
+ /** Reflects against an inner class symbol and returns a mirror
+ * that can be used to create instances of the class, inspect its companion object or perform further reflections.
+ *
+ * To get a class symbol by the name of the class you would like to reflect,
+ * use `<this mirror>.symbol.typeSignature.member(newTypeName(<name of the class>)).asClassSymbol`.
+ * For further information about member lookup refer to `Symbol.typeSignature`.
+ *
+ * The input symbol can be either private or non-private (Scala reflection transparently deals with visibility).
+ * It must be a member (declared or inherited) of the instance underlying this mirror.
+ */
def reflectClass(cls: ClassSymbol): ClassMirror
- /** .. */
+ /** Reflects against an inner module symbol and returns a mirror
+ * that can be used to get the instance of the object or inspect its companion class.
+ *
+ * To get a module symbol by the name of the object you would like to reflect,
+ * use `<this mirror>.symbol.typeSignature.member(newTermName(<name of the object>)).asModuleSymbol`.
+ * For further information about member lookup refer to `Symbol.typeSignature`.
+ *
+ * The input symbol can be either private or non-private (Scala reflection transparently deals with visibility).
+ * It must be a member (declared or inherited) of the instance underlying this mirror.
+ */
def reflectModule(mod: ModuleSymbol): ModuleMirror
}
@@ -58,13 +93,31 @@ trait Mirrors { self: Universe =>
/** The object containing the field */
def receiver: AnyRef
- /** The field symbol representing the field */
+ /** The field symbol representing the field.
+ *
+ * In Scala `val` and `var` declarations are usually compiled down to a pair of
+ * a backing field and corresponding accessor/accessors, which means that a single
+ * declaration might correspond to up to three different symbols. Nevertheless
+ * the `FieldMirror.symbol` field always points to a backing field symbol.
+ */
def symbol: TermSymbol
- /** Retrieves the value stored in the field */
+ /** Retrieves the value stored in the field.
+ *
+ * Scala reflection uses reflection capabilities of the underlying platform,
+ * so `FieldMirror.get` might throw platform-specific exceptions associated
+ * with getting a field or invoking a getter method of the field.
+ */
def get: Any
- /** Updates the value stored in the field */
+ /** Updates the value stored in the field.
+ *
+ * If a field is immutable, a `ScalaReflectionException` will be thrown.
+ *
+ * Scala reflection uses reflection capabilities of the underlying platform,
+ * so `FieldMirror.get` might throw platform-specific exceptions associated
+ * with setting a field or invoking a setter method of the field.
+ */
def set(value: Any): Unit
}
@@ -77,8 +130,12 @@ trait Mirrors { self: Universe =>
/** The method symbol representing the method */
def symbol: MethodSymbol
- /** The result of applying the method to the given arguments */
- // [Eugene+++] If it's a constructor, it should account for inner classes
+ /** The result of applying the method to the given arguments
+ *
+ * Scala reflection uses reflection capabilities of the underlying platform,
+ * so `FieldMirror.get` might throw platform-specific exceptions associated
+ * with invoking the corresponding method or constructor.
+ */
def apply(args: Any*): Any
}
@@ -97,7 +154,7 @@ trait Mirrors { self: Universe =>
*/
def isStatic: Boolean
- /** The Scala symbol corresponding to the reflected runtime class or module. */
+ /** The Scala symbol corresponding to the reflected runtime class or object */
def symbol: Symbol
/** Optionally, the mirror of the companion reflected by this mirror.
@@ -116,7 +173,7 @@ trait Mirrors { self: Universe =>
/** A mirror that reflects a Scala object definition or the static parts of a runtime class */
trait ModuleMirror extends TemplateMirror {
- /** The Scala module symbol corresponding to the reflected module. */
+ /** The Scala module symbol corresponding to the reflected object */
override def symbol: ModuleSymbol
/** If the reflected runtime class corresponds to a Scala object definition,
@@ -137,15 +194,18 @@ trait Mirrors { self: Universe =>
/** A mirror that reflects the instance parts of a runtime class */
trait ClassMirror extends TemplateMirror {
- /** The Scala class symbol corresponding to the reflected class. */
+ /** The Scala class symbol corresponding to the reflected class */
override def symbol: ClassSymbol
- /** Returns a fresh instance of by invoking that constructor.
- * @throws InstantiationException if the class does not have a public
- * constructor with an empty parameter list.
- * @throws IllegalAccessException if the class or its constructor is not accessible.
- * @throws ExceptionInInitializerError if the initialization of the constructor fails.
- * @throws SecurityException if creating a new instance is not permitted.
+ /** Reflects against a constructor symbol and returns a mirror
+ * that can be used to invoke it and construct instances of this mirror's symbols.
+ *
+ * To get a constructor symbol you would like to reflect,
+ * use `<this mirror>.symbol.typeSignature.member(nme.CONSTRUCTOR).asMethodSymbol`.
+ * For further information about member lookup refer to `Symbol.typeSignature`.
+ *
+ * The input symbol can be either private or non-private (Scala reflection transparently deals with visibility).
+ * It must be a member (declared or inherited) of the class underlying this mirror.
*/
def reflectConstructor(constructor: MethodSymbol): MethodMirror
@@ -161,24 +221,40 @@ trait Mirrors { self: Universe =>
/** A mirror that reflects instances and static classes */
trait ReflectiveMirror extends MirrorOf[Mirrors.this.type] {
- /** A reflective mirror for the given object
- * @param obj An arbitrary value
- * @return The mirror for `obj`.
+ /** A reflective mirror for the given object.
+ *
+ * Such a mirror can be used to further reflect against the members of the object
+ * to get/set fields, invoke methods and inspect inner classes and objects.
*/
def reflect(obj: Any): InstanceMirror
- /** .. */
+ /** Reflects against a static class symbol and returns a mirror
+ * that can be used to create instances of the class, inspect its companion object or perform further reflections.
+ *
+ * To get a class symbol by the name of the class you would like to reflect,
+ * use `<this mirror>.classSymbol(<runtime class loaded by its name>)`.
+ *
+ * The input symbol can be either private or non-private (Scala reflection transparently deals with visibility).
+ * It must be static, i.e. either top-level or nested within one or several static objects.
+ */
def reflectClass(cls: ClassSymbol): ClassMirror
- /** .. */
+ /** Reflects against a static module symbol and returns a mirror
+ * that can be used to get the instance of the object or inspect its companion class.
+ *
+ * To get a module symbol by the name of its companion class you would like to reflect,
+ * use `<this mirror>.classSymbol(<runtime class loaded by its name>).companion.get`.
+ *
+ * The input symbol can be either private or non-private (Scala reflection transparently deals with visibility).
+ * It must be static, i.e. either top-level or nested within one or several static objects.
+ */
def reflectModule(mod: ModuleSymbol): ModuleMirror
}
/** The API of a mirror for a reflective universe */
trait RuntimeMirror extends ReflectiveMirror { self =>
- /** Maps a Scala type to the corresponding Java class object
- */
+ /** Maps a Scala type to the corresponding Java class object */
def runtimeClass(tpe: Type): RuntimeClass
/** Maps a Scala class symbol to the corresponding Java class object
@@ -198,7 +274,7 @@ trait Mirrors { self: Universe =>
def classSymbol(rtcls: RuntimeClass): ClassSymbol
/** A module symbol for the specified runtime class.
- * @return The module symbol for the runtime class in the current class loader.
+ * @return The module symbol for the runtime class in the current class loader.
* @throws java.lang.ClassNotFoundException if no class with that name exists
* @throws scala.reflect.internal.MissingRequirementError if no corresponding symbol exists
* to do: throws anything else?
diff --git a/src/reflect/scala/reflect/api/StandardNames.scala b/src/reflect/scala/reflect/api/StandardNames.scala
index 9ec66b8531..eb1ecda900 100644
--- a/src/reflect/scala/reflect/api/StandardNames.scala
+++ b/src/reflect/scala/reflect/api/StandardNames.scala
@@ -43,7 +43,6 @@ trait StandardNames extends base.StandardNames {
val SUPER_PREFIX_STRING: String
val TRAIT_SETTER_SEPARATOR_STRING: String
- val ANYNAME: TermName
val FAKE_LOCAL_THIS: TermName
val INITIALIZER: TermName
val LAZY_LOCAL: TermName
diff --git a/src/reflect/scala/reflect/internal/AnnotationInfos.scala b/src/reflect/scala/reflect/internal/AnnotationInfos.scala
index c283ae408e..2bcc95b9a8 100644
--- a/src/reflect/scala/reflect/internal/AnnotationInfos.scala
+++ b/src/reflect/scala/reflect/internal/AnnotationInfos.scala
@@ -160,12 +160,7 @@ trait AnnotationInfos extends api.AnnotationInfos { self: SymbolTable =>
*/
final class LazyAnnotationInfo(lazyInfo: => AnnotationInfo) extends AnnotationInfo {
private var forced = false
- private lazy val forcedInfo =
- try {
- val result = lazyInfo
- if (result.pos == NoPosition) result setPos pos
- result
- } finally forced = true
+ private lazy val forcedInfo = try lazyInfo finally forced = true
def atp: Type = forcedInfo.atp
def args: List[Tree] = forcedInfo.args
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala
index cd243b9df0..d9b63529eb 100644
--- a/src/reflect/scala/reflect/internal/Definitions.scala
+++ b/src/reflect/scala/reflect/internal/Definitions.scala
@@ -490,7 +490,6 @@ trait Definitions extends api.StandardDefinitions {
def MacroContextPrefixType = if (MacroContextClass != NoSymbol) getMemberType(MacroContextClass, tpnme.PrefixType) else NoSymbol
def MacroContextUniverse = if (MacroContextClass != NoSymbol) getMemberMethod(MacroContextClass, nme.universe) else NoSymbol
def MacroContextMirror = if (MacroContextClass != NoSymbol) getMemberMethod(MacroContextClass, nme.mirror) else NoSymbol
- def MacroContextReify = if (MacroContextClass != NoSymbol) getMemberMethod(MacroContextClass, nme.reify) else NoSymbol
lazy val MacroImplAnnotation = requiredClass[scala.reflect.makro.internal.macroImpl]
lazy val MacroInternalPackage = getPackageObject("scala.reflect.makro.internal")
def MacroInternal_materializeClassTag = getMemberMethod(MacroInternalPackage, nme.materializeClassTag)
@@ -899,6 +898,7 @@ trait Definitions extends api.StandardDefinitions {
lazy val SwitchClass = requiredClass[scala.annotation.switch]
lazy val TailrecClass = requiredClass[scala.annotation.tailrec]
lazy val VarargsClass = requiredClass[scala.annotation.varargs]
+ lazy val StaticClass = requiredClass[scala.annotation.static]
lazy val uncheckedStableClass = requiredClass[scala.annotation.unchecked.uncheckedStable]
lazy val uncheckedVarianceClass = requiredClass[scala.annotation.unchecked.uncheckedVariance]
diff --git a/src/reflect/scala/reflect/internal/Mirrors.scala b/src/reflect/scala/reflect/internal/Mirrors.scala
index 210af661ee..f7561ae274 100644
--- a/src/reflect/scala/reflect/internal/Mirrors.scala
+++ b/src/reflect/scala/reflect/internal/Mirrors.scala
@@ -36,7 +36,7 @@ trait Mirrors extends api.Mirrors {
if (point > 0) getModuleOrClass(path.toTermName, point)
else RootClass
val name = path subName (point + 1, len)
- val sym = owner.info member name
+ var sym = owner.info member name
val result = if (path.isTermName) sym.suchThat(_ hasFlag MODULE) else sym
if (result != NoSymbol) result
else {
@@ -47,23 +47,39 @@ trait Mirrors extends api.Mirrors {
}
}
- protected def mirrorMissingHook(owner: Symbol, name: Name): Symbol = NoSymbol
-
- protected def symbolTableMissingHook(owner: Symbol, name: Name): Symbol = self.missingHook(owner, name)
-
- private[scala] def missingHook(owner: Symbol, name: Name): Symbol = mirrorMissingHook(owner, name) orElse symbolTableMissingHook(owner, name)
+ /** If you're looking for a class, pass a type name.
+ * If a module, a term name.
+ *
+ * Unlike `getModuleOrClass`, this function
+ * loads unqualified names from the root package.
+ */
+ private def getModuleOrClass(path: Name): Symbol =
+ getModuleOrClass(path, path.length)
/** If you're looking for a class, pass a type name.
* If a module, a term name.
+ *
+ * Unlike `getModuleOrClass`, this function
+ * loads unqualified names from the empty package.
*/
- private def getModuleOrClass(path: Name): Symbol = getModuleOrClass(path, path.length)
+ private def staticModuleOrClass(path: Name): Symbol = {
+ val isPackageless = path.pos('.') == path.length
+ if (isPackageless) EmptyPackageClass.info decl path
+ else getModuleOrClass(path)
+ }
+
+ protected def mirrorMissingHook(owner: Symbol, name: Name): Symbol = NoSymbol
+
+ protected def universeMissingHook(owner: Symbol, name: Name): Symbol = self.missingHook(owner, name)
- override def staticClass(fullName: String): ClassSymbol = getRequiredClass(fullName)
+ private[scala] def missingHook(owner: Symbol, name: Name): Symbol = mirrorMissingHook(owner, name) orElse universeMissingHook(owner, name)
- // todo: get rid of most creation methods and keep just staticClass/Module/Package
+ // todo: get rid of most the methods here and keep just staticClass/Module/Package
- def getClassByName(fullname: Name): ClassSymbol = {
- var result = getModuleOrClass(fullname.toTypeName)
+ /************************ loaders of class symbols ************************/
+
+ private def ensureClassSymbol(fullname: String, sym: Symbol): ClassSymbol = {
+ var result = sym
while (result.isAliasType) result = result.info.typeSymbol
result match {
case x: ClassSymbol => x
@@ -71,45 +87,50 @@ trait Mirrors extends api.Mirrors {
}
}
- override def staticModule(fullName: String): ModuleSymbol = getRequiredModule(fullName)
+ @deprecated("Use getClassByName", "2.10.0")
+ def getClass(fullname: Name): ClassSymbol =
+ getClassByName(fullname)
- def getModule(fullname: Name): ModuleSymbol =
- // [Eugene++] should be a ClassCastException instead?
- getModuleOrClass(fullname.toTermName) match {
- case x: ModuleSymbol => x
- case _ => MissingRequirementError.notFound("object " + fullname)
- }
+ def getClassByName(fullname: Name): ClassSymbol =
+ ensureClassSymbol(fullname.toString, getModuleOrClass(fullname.toTypeName))
- def getPackage(fullname: Name): ModuleSymbol = getModule(fullname)
+ def getRequiredClass(fullname: String): ClassSymbol =
+ getClassByName(newTypeNameCached(fullname))
- def getRequiredPackage(fullname: String): ModuleSymbol =
- getPackage(newTermNameCached(fullname))
+ def requiredClass[T: ClassTag] : ClassSymbol =
+ getRequiredClass(erasureName[T])
- @deprecated("Use getClassByName", "2.10.0")
- def getClass(fullname: Name): ClassSymbol = getClassByName(fullname)
+ def getClassIfDefined(fullname: String): Symbol =
+ getClassIfDefined(newTypeNameCached(fullname))
- def getRequiredClass(fullname: String): ClassSymbol =
- getClassByName(newTypeNameCached(fullname)) match {
- case x: ClassSymbol => x
- case _ => MissingRequirementError.notFound("class " + fullname)
- }
+ def getClassIfDefined(fullname: Name): Symbol =
+ wrapMissing(getClassByName(fullname.toTypeName))
- def getRequiredModule(fullname: String): ModuleSymbol =
- getModule(newTermNameCached(fullname))
+ /** @inheritdoc
+ *
+ * Unlike getClassByName/getRequiredClass this function can also load packageless symbols.
+ * Compiler might ignore them, but they should be loadable with macros.
+ */
+ override def staticClass(fullname: String): ClassSymbol =
+ ensureClassSymbol(fullname, staticModuleOrClass(newTypeNameCached(fullname)))
- def erasureName[T: ClassTag] : String = {
- /** We'd like the String representation to be a valid
- * scala type, so we have to decode the jvm's secret language.
- */
- def erasureString(clazz: Class[_]): String = {
- if (clazz.isArray) "Array[" + erasureString(clazz.getComponentType) + "]"
- else clazz.getName
+ /************************ loaders of module symbols ************************/
+
+ private def ensureModuleSymbol(fullname: String, sym: Symbol, allowPackages: Boolean): ModuleSymbol =
+ sym match {
+ case x: ModuleSymbol if allowPackages || !x.isPackage => x
+ case _ => MissingRequirementError.notFound("object " + fullname)
}
- erasureString(classTag[T].runtimeClass)
- }
- def requiredClass[T: ClassTag] : ClassSymbol =
- getRequiredClass(erasureName[T])
+ @deprecated("Use getModuleByName", "2.10.0")
+ def getModule(fullname: Name): ModuleSymbol =
+ getModuleByName(fullname)
+
+ def getModuleByName(fullname: Name): ModuleSymbol =
+ ensureModuleSymbol(fullname.toString, getModuleOrClass(fullname.toTermName), allowPackages = true)
+
+ def getRequiredModule(fullname: String): ModuleSymbol =
+ getModule(newTermNameCached(fullname))
// TODO: What syntax do we think should work here? Say you have an object
// like scala.Predef. You can't say requiredModule[scala.Predef] since there's
@@ -121,34 +142,60 @@ trait Mirrors extends api.Mirrors {
def requiredModule[T: ClassTag] : ModuleSymbol =
getRequiredModule(erasureName[T] stripSuffix "$")
- def getClassIfDefined(fullname: String): Symbol =
- getClassIfDefined(newTypeName(fullname))
-
- def getClassIfDefined(fullname: Name): Symbol =
- wrapMissing(getClassByName(fullname.toTypeName))
-
def getModuleIfDefined(fullname: String): Symbol =
- getModuleIfDefined(newTermName(fullname))
+ getModuleIfDefined(newTermNameCached(fullname))
def getModuleIfDefined(fullname: Name): Symbol =
wrapMissing(getModule(fullname.toTermName))
+ /** @inheritdoc
+ *
+ * Unlike getModule/getRequiredModule this function can also load packageless symbols.
+ * Compiler might ignore them, but they should be loadable with macros.
+ */
+ override def staticModule(fullname: String): ModuleSymbol =
+ ensureModuleSymbol(fullname, staticModuleOrClass(newTermNameCached(fullname)), allowPackages = false)
+
+ /************************ loaders of package symbols ************************/
+
+ private def ensurePackageSymbol(fullname: String, sym: Symbol, allowModules: Boolean): ModuleSymbol =
+ sym match {
+ case x: ModuleSymbol if allowModules || x.isPackage => x
+ case _ => MissingRequirementError.notFound("package " + fullname)
+ }
+
+ def getPackage(fullname: Name): ModuleSymbol =
+ ensurePackageSymbol(fullname.toString, getModuleOrClass(fullname), allowModules = true)
+
+ def getRequiredPackage(fullname: String): ModuleSymbol =
+ getPackage(newTermNameCached(fullname))
+
def getPackageObject(fullname: String): ModuleSymbol =
- (getModule(newTermName(fullname)).info member nme.PACKAGE) match {
+ (getPackage(newTermName(fullname)).info member nme.PACKAGE) match {
case x: ModuleSymbol => x
case _ => MissingRequirementError.notFound("package object " + fullname)
}
- def getPackageObjectIfDefined(fullname: String): Symbol = {
- val module = getModuleIfDefined(newTermName(fullname))
- if (module == NoSymbol) NoSymbol
- else {
- val packageObject = module.info member nme.PACKAGE
- packageObject match {
- case x: ModuleSymbol => x
- case _ => NoSymbol
- }
+ def getPackageObjectIfDefined(fullname: String): Symbol =
+ getPackageObjectIfDefined(newTermNameCached(fullname))
+
+ def getPackageObjectIfDefined(fullname: Name): Symbol =
+ wrapMissing(getPackageObject(fullname.toTermName))
+
+ override def staticPackage(fullname: String): ModuleSymbol =
+ ensurePackageSymbol(fullname.toString, getModuleOrClass(newTermNameCached(fullname)), allowModules = false)
+
+ /************************ helpers ************************/
+
+ def erasureName[T: ClassTag] : String = {
+ /** We'd like the String representation to be a valid
+ * scala type, so we have to decode the jvm's secret language.
+ */
+ def erasureString(clazz: Class[_]): String = {
+ if (clazz.isArray) "Array[" + erasureString(clazz.getComponentType) + "]"
+ else clazz.getName
}
+ erasureString(classTag[T].runtimeClass)
}
@inline private def wrapMissing(body: => Symbol): Symbol =
@@ -180,7 +227,7 @@ trait Mirrors extends api.Mirrors {
// Still fiddling with whether it's cleaner to do some of this setup here
// or from constructors. The latter approach tends to invite init order issues.
- EmptyPackageClass setInfo ClassInfoType(Nil, newPackageScope(EmptyPackageClass), EmptyPackageClass)
+ EmptyPackageClass setInfo rootLoader
EmptyPackage setInfo EmptyPackageClass.tpe
connectModuleToClass(EmptyPackage, EmptyPackageClass)
@@ -231,7 +278,6 @@ trait Mirrors extends api.Mirrors {
override def isEffectiveRoot = true
override def isStatic = true
override def isNestedClass = false
- override def ownerOfNewSymbols = EmptyPackageClass
}
// The empty package, which holds all top level types without given packages.
final object EmptyPackage extends ModuleSymbol(RootClass, NoPosition, nme.EMPTY_PACKAGE_NAME) with WellKnownSymbol {
diff --git a/src/reflect/scala/reflect/internal/Names.scala b/src/reflect/scala/reflect/internal/Names.scala
index 20da38fd63..72e6707f57 100644
--- a/src/reflect/scala/reflect/internal/Names.scala
+++ b/src/reflect/scala/reflect/internal/Names.scala
@@ -415,6 +415,9 @@ trait Names extends api.Names with LowPriorityNames {
}
else toString
}
+
+ @inline
+ final def fingerPrint: Long = (1L << start)
/** TODO - find some efficiency. */
def append(ch: Char) = newName("" + this + ch)
diff --git a/src/reflect/scala/reflect/internal/Scopes.scala b/src/reflect/scala/reflect/internal/Scopes.scala
index ceacd2afb0..89e3c52de6 100644
--- a/src/reflect/scala/reflect/internal/Scopes.scala
+++ b/src/reflect/scala/reflect/internal/Scopes.scala
@@ -41,10 +41,15 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
* This is necessary because when run from reflection every scope needs to have a
* SynchronizedScope as mixin.
*/
- class Scope protected[Scopes] (initElems: ScopeEntry = null) extends Iterable[Symbol] {
+ class Scope protected[Scopes] (initElems: ScopeEntry = null, initFingerPrints: Long = 0L) extends Iterable[Symbol] {
+
+ /** A bitset containing the last 6 bits of the start value of every name
+ * stored in this scope.
+ */
+ var fingerPrints: Long = initFingerPrints
protected[Scopes] def this(base: Scope) = {
- this(base.elems)
+ this(base.elems, base.fingerPrints)
nestinglevel = base.nestinglevel + 1
}
@@ -95,7 +100,7 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
*
* @param e ...
*/
- protected def enter(e: ScopeEntry) {
+ protected def enterEntry(e: ScopeEntry) {
elemsCache = null
if (hashtable ne null)
enterInHash(e)
@@ -113,7 +118,11 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
*
* @param sym ...
*/
- def enter[T <: Symbol](sym: T): T = { enter(newScopeEntry(sym, this)); sym }
+ def enter[T <: Symbol](sym: T): T = {
+ fingerPrints |= sym.name.fingerPrint
+ enterEntry(newScopeEntry(sym, this))
+ sym
+ }
/** enter a symbol, asserting that no symbol with same name exists in scope
*
@@ -147,6 +156,7 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
}
def rehash(sym: Symbol, newname: Name) {
+ fingerPrints |= newname.fingerPrint
if (hashtable ne null) {
val index = sym.name.start & HASHMASK
var e1 = hashtable(index)
@@ -344,7 +354,7 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
/** The empty scope (immutable).
*/
object EmptyScope extends Scope {
- override def enter(e: ScopeEntry) {
+ override def enterEntry(e: ScopeEntry) {
abort("EmptyScope.enter")
}
}
diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala
index 165e04863c..75962ff9d0 100644
--- a/src/reflect/scala/reflect/internal/StdNames.scala
+++ b/src/reflect/scala/reflect/internal/StdNames.scala
@@ -246,6 +246,7 @@ trait StdNames {
final val BeanPropertyAnnot: NameType = "BeanProperty"
final val BooleanBeanPropertyAnnot: NameType = "BooleanBeanProperty"
final val bridgeAnnot: NameType = "bridge"
+ final val staticAnnot: NameType = "static"
// Classfile Attributes
final val AnnotationDefaultATTR: NameType = "AnnotationDefault"
@@ -297,7 +298,7 @@ trait StdNames {
val WHILE_PREFIX = "while$"
// Compiler internal names
- val ANYNAME: NameType = "<anyname>"
+ val ANYname: NameType = "<anyname>"
val CONSTRUCTOR: NameType = "<init>"
val EQEQ_LOCAL_VAR: NameType = "eqEqTemp$"
val FAKE_LOCAL_THIS: NameType = "this$"
@@ -754,6 +755,7 @@ trait StdNames {
val splice: NameType = "splice"
val staticClass : NameType = "staticClass"
val staticModule : NameType = "staticModule"
+ val staticPackage : NameType = "staticPackage"
val synchronized_ : NameType = "synchronized"
val tail: NameType = "tail"
val `then` : NameType = "then"
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index 759c77f717..636f1e2f01 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -813,11 +813,6 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
*/
def isEffectiveRoot = false
- /** For RootClass, this is EmptyPackageClass. For all other symbols,
- * the symbol itself.
- */
- def ownerOfNewSymbols = this
-
final def isLazyAccessor = isLazy && lazyAccessor != NoSymbol
final def isOverridableMember = !(isClass || isEffectivelyFinal) && (this ne NoSymbol) && owner.isClass
@@ -938,6 +933,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
|| hasAnnotation(SerializableAttr) // last part can be removed, @serializable annotation is deprecated
)
def hasBridgeAnnotation = hasAnnotation(BridgeClass)
+ def hasStaticAnnotation = hasAnnotation(StaticClass)
def isDeprecated = hasAnnotation(DeprecatedAttr)
def deprecationMessage = getAnnotation(DeprecatedAttr) flatMap (_ stringArg 0)
def deprecationVersion = getAnnotation(DeprecatedAttr) flatMap (_ stringArg 1)
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index 2c705b0b5b..7f991176a7 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -14,6 +14,7 @@ import Flags._
import scala.util.control.ControlThrowable
import scala.annotation.tailrec
import util.Statistics
+import scala.runtime.ObjectRef
/* A standard type pattern match:
case ErrorType =>
@@ -668,7 +669,8 @@ trait Types extends api.Types { self: SymbolTable =>
* Note: unfortunately it doesn't work to exclude DEFERRED this way.
*/
def membersBasedOnFlags(excludedFlags: Long, requiredFlags: Long): List[Symbol] =
- findMember(nme.ANYNAME, excludedFlags, requiredFlags, false).alternatives
+ findMembers(excludedFlags, requiredFlags)
+// findMember(nme.ANYNAME, excludedFlags, requiredFlags, false).alternatives
def memberBasedOnName(name: Name, excludedFlags: Long): Symbol =
findMember(name, excludedFlags, 0, false)
@@ -1018,6 +1020,72 @@ trait Types extends api.Types { self: SymbolTable =>
else (baseClasses.head.newOverloaded(this, alts))
}
+ def findMembers(excludedFlags: Long, requiredFlags: Long): List[Symbol] = {
+ // if this type contains type variables, put them to sleep for a while -- don't just wipe them out by
+ // replacing them by the corresponding type parameter, as that messes up (e.g.) type variables in type refinements
+ // without this, the matchesType call would lead to type variables on both sides
+ // of a subtyping/equality judgement, which can lead to recursive types being constructed.
+ // See (t0851) for a situation where this happens.
+ val suspension: List[TypeVar] = if (this.isGround) null else suspendTypeVarsInType(this)
+
+ Statistics.incCounter(findMembersCount)
+ val start = Statistics.pushTimer(typeOpsStack, findMembersNanos)
+
+ //Console.println("find member " + name.decode + " in " + this + ":" + this.baseClasses)//DEBUG
+ var members: Scope = null
+ var required = requiredFlags
+ var excluded = excludedFlags | DEFERRED
+ var continue = true
+ var self: Type = null
+ while (continue) {
+ continue = false
+ val bcs0 = baseClasses
+ var bcs = bcs0
+ while (!bcs.isEmpty) {
+ val decls = bcs.head.info.decls
+ var entry = decls.elems
+ while (entry ne null) {
+ val sym = entry.sym
+ val flags = sym.flags
+ if ((flags & required) == required) {
+ val excl = flags & excluded
+ if (excl == 0L &&
+ (// omit PRIVATE LOCALS unless selector class is contained in class owning the def.
+ (bcs eq bcs0) ||
+ (flags & PrivateLocal) != PrivateLocal ||
+ (bcs0.head.hasTransOwner(bcs.head)))) {
+ if (members eq null) members = newScope
+ var others: ScopeEntry = members.lookupEntry(sym.name)
+ var symtpe: Type = null
+ while ((others ne null) && {
+ val other = others.sym
+ (other ne sym) &&
+ ((other.owner eq sym.owner) ||
+ (flags & PRIVATE) != 0 || {
+ if (self eq null) self = this.narrow
+ if (symtpe eq null) symtpe = self.memberType(sym)
+ !(self.memberType(other) matches symtpe)
+ })}) {
+ others = members lookupNextEntry others
+ }
+ if (others eq null) members enter sym
+ } else if (excl == DEFERRED) {
+ continue = true
+ }
+ }
+ entry = entry.next
+ } // while (entry ne null)
+ // excluded = excluded | LOCAL
+ bcs = bcs.tail
+ } // while (!bcs.isEmpty)
+ required |= DEFERRED
+ excluded &= ~(DEFERRED.toLong)
+ } // while (continue)
+ Statistics.popTimer(typeOpsStack, start)
+ if (suspension ne null) suspension foreach (_.suspended = false)
+ if (members eq null) Nil else members.toList
+ }
+
/**
* Find member(s) in this type. If several members matching criteria are found, they are
* returned in an OverloadedSymbol
@@ -1040,75 +1108,83 @@ trait Types extends api.Types { self: SymbolTable =>
val start = Statistics.pushTimer(typeOpsStack, findMemberNanos)
//Console.println("find member " + name.decode + " in " + this + ":" + this.baseClasses)//DEBUG
- var members: Scope = null
var member: Symbol = NoSymbol
+ var members: List[Symbol] = null
+ var lastM: ::[Symbol] = null
+ var membertpe: Type = null
+ var required = requiredFlags
var excluded = excludedFlags | DEFERRED
var continue = true
var self: Type = null
- var membertpe: Type = null
+ val fingerPrint: Long = name.fingerPrint
+
while (continue) {
continue = false
val bcs0 = baseClasses
var bcs = bcs0
while (!bcs.isEmpty) {
val decls = bcs.head.info.decls
- var entry =
- if (name == nme.ANYNAME) decls.elems else decls.lookupEntry(name)
- while (entry ne null) {
- val sym = entry.sym
- if (sym hasAllFlags requiredFlags) {
- val excl = sym.getFlag(excluded)
- if (excl == 0L &&
- (// omit PRIVATE LOCALS unless selector class is contained in class owning the def.
- (bcs eq bcs0) ||
- !sym.isPrivateLocal ||
- (bcs0.head.hasTransOwner(bcs.head)))) {
- if (name.isTypeName || stableOnly && sym.isStable) {
- Statistics.popTimer(typeOpsStack, start)
- if (suspension ne null) suspension foreach (_.suspended = false)
- return sym
- } else if (member == NoSymbol) {
- member = sym
- } else if (members eq null) {
- if (member.name != sym.name ||
- !(member == sym ||
- member.owner != sym.owner &&
- !sym.isPrivate && {
- if (self eq null) self = this.narrow
- if (membertpe eq null) membertpe = self.memberType(member)
- (membertpe matches self.memberType(sym))
- })) {
- members = newScope
- members enter member
- members enter sym
- }
- } else {
- var prevEntry = members.lookupEntry(sym.name)
- var symtpe: Type = null
- while ((prevEntry ne null) &&
- !(prevEntry.sym == sym ||
- prevEntry.sym.owner != sym.owner &&
- !sym.hasFlag(PRIVATE) && {
- if (self eq null) self = this.narrow
- if (symtpe eq null) symtpe = self.memberType(sym)
- self.memberType(prevEntry.sym) matches symtpe
- })) {
- prevEntry = members lookupNextEntry prevEntry
- }
- if (prevEntry eq null) {
- members enter sym
+ if ((fingerPrint & decls.fingerPrints) != 0) {
+ var entry = decls.lookupEntry(name)
+ while (entry ne null) {
+ val sym = entry.sym
+ val flags = sym.flags
+ if ((flags & required) == required) {
+ val excl = flags & excluded
+ if (excl == 0L &&
+ (// omit PRIVATE LOCALS unless selector class is contained in class owning the def.
+ (bcs eq bcs0) ||
+ (flags & PrivateLocal) != PrivateLocal ||
+ (bcs0.head.hasTransOwner(bcs.head)))) {
+ if (name.isTypeName || stableOnly && sym.isStable) {
+ Statistics.popTimer(typeOpsStack, start)
+ if (suspension ne null) suspension foreach (_.suspended = false)
+ return sym
+ } else if (member eq NoSymbol) {
+ member = sym
+ } else if (members eq null) {
+ if ((member ne sym) &&
+ ((member.owner eq sym.owner) ||
+ (flags & PRIVATE) != 0 || {
+ if (self eq null) self = this.narrow
+ if (membertpe eq null) membertpe = self.memberType(member)
+ !(membertpe matches self.memberType(sym))
+ })) {
+ lastM = new ::(sym, null)
+ members = member :: lastM
+ }
+ } else {
+ var others: List[Symbol] = members
+ var symtpe: Type = null
+ while ((others ne null) && {
+ val other = others.head
+ (other ne sym) &&
+ ((other.owner eq sym.owner) ||
+ (flags & PRIVATE) != 0 || {
+ if (self eq null) self = this.narrow
+ if (symtpe eq null) symtpe = self.memberType(sym)
+ !(self.memberType(other) matches symtpe)
+ })}) {
+ others = others.tail
+ }
+ if (others eq null) {
+ val lastM1 = new ::(sym, null)
+ lastM.tl = lastM1
+ lastM = lastM1
+ }
}
+ } else if (excl == DEFERRED) {
+ continue = true
}
- } else if (excl == DEFERRED.toLong) {
- continue = true
}
- }
- entry = if (name == nme.ANYNAME) entry.next else decls lookupNextEntry entry
- } // while (entry ne null)
+ entry = decls lookupNextEntry entry
+ } // while (entry ne null)
+ } // if (fingerPrint matches)
// excluded = excluded | LOCAL
bcs = if (name == nme.CONSTRUCTOR) Nil else bcs.tail
} // while (!bcs.isEmpty)
- excluded = excludedFlags
+ required |= DEFERRED
+ excluded &= ~(DEFERRED.toLong)
} // while (continue)
Statistics.popTimer(typeOpsStack, start)
if (suspension ne null) suspension foreach (_.suspended = false)
@@ -1117,9 +1193,11 @@ trait Types extends api.Types { self: SymbolTable =>
member
} else {
Statistics.incCounter(multMemberCount)
- baseClasses.head.newOverloaded(this, members.toList)
+ lastM.tl = Nil
+ baseClasses.head.newOverloaded(this, members)
}
}
+
/** The (existential or otherwise) skolems and existentially quantified variables which are free in this type */
def skolemsExceptMethodTypeParams: List[Symbol] = {
var boundSyms: List[Symbol] = List()
@@ -1610,8 +1688,13 @@ trait Types extends api.Types { self: SymbolTable =>
if (period != currentPeriod) {
tpe.baseClassesPeriod = currentPeriod
if (!isValidForBaseClasses(period)) {
- tpe.baseClassesCache = null
- tpe.baseClassesCache = tpe.memo(computeBaseClasses)(tpe.typeSymbol :: _.baseClasses.tail)
+ val start = Statistics.pushTimer(typeOpsStack, baseClassesNanos)
+ try {
+ tpe.baseClassesCache = null
+ tpe.baseClassesCache = tpe.memo(computeBaseClasses)(tpe.typeSymbol :: _.baseClasses.tail)
+ } finally {
+ Statistics.popTimer(typeOpsStack, start)
+ }
}
}
if (tpe.baseClassesCache eq null)
@@ -5080,7 +5163,7 @@ trait Types extends api.Types { self: SymbolTable =>
*/
def needsOuterTest(patType: Type, selType: Type, currentOwner: Symbol) = {
def createDummyClone(pre: Type): Type = {
- val dummy = currentOwner.enclClass.newValue(nme.ANYNAME).setInfo(pre.widen)
+ val dummy = currentOwner.enclClass.newValue(nme.ANYname).setInfo(pre.widen)
singleType(ThisType(currentOwner.enclClass), dummy)
}
def maybeCreateDummyClone(pre: Type, sym: Symbol): Type = pre match {
@@ -6923,14 +7006,17 @@ object TypesStats {
val lubCount = Statistics.newCounter ("#toplevel lubs/glbs")
val nestedLubCount = Statistics.newCounter ("#all lubs/glbs")
val findMemberCount = Statistics.newCounter ("#findMember ops")
+ val findMembersCount = Statistics.newCounter ("#findMembers ops")
val noMemberCount = Statistics.newSubCounter(" of which not found", findMemberCount)
val multMemberCount = Statistics.newSubCounter(" of which multiple overloaded", findMemberCount)
val typerNanos = Statistics.newTimer ("time spent typechecking", "typer")
val lubNanos = Statistics.newStackableTimer("time spent in lubs", typerNanos)
val subtypeNanos = Statistics.newStackableTimer("time spent in <:<", typerNanos)
val findMemberNanos = Statistics.newStackableTimer("time spent in findmember", typerNanos)
+ val findMembersNanos = Statistics.newStackableTimer("time spent in findmembers", typerNanos)
val asSeenFromNanos = Statistics.newStackableTimer("time spent in asSeenFrom", typerNanos)
val baseTypeSeqNanos = Statistics.newStackableTimer("time spent in baseTypeSeq", typerNanos)
+ val baseClassesNanos = Statistics.newStackableTimer("time spent in baseClasses", typerNanos)
val compoundBaseTypeSeqCount = Statistics.newSubCounter(" of which for compound types", baseTypeSeqCount)
val typerefBaseTypeSeqCount = Statistics.newSubCounter(" of which for typerefs", baseTypeSeqCount)
val singletonBaseTypeSeqCount = Statistics.newSubCounter(" of which for singletons", baseTypeSeqCount)
diff --git a/src/reflect/scala/reflect/internal/util/SourceFile.scala b/src/reflect/scala/reflect/internal/util/SourceFile.scala
index 7c80ddd37d..df4a3336c3 100644
--- a/src/reflect/scala/reflect/internal/util/SourceFile.scala
+++ b/src/reflect/scala/reflect/internal/util/SourceFile.scala
@@ -102,17 +102,21 @@ class ScriptSourceFile(underlying: BatchSourceFile, content: Array[Char], overri
}
/** a file whose contents do not change over time */
-class BatchSourceFile(val file : AbstractFile, val content: Array[Char]) extends SourceFile {
-
+class BatchSourceFile(val file : AbstractFile, val content0: Array[Char]) extends SourceFile {
def this(_file: AbstractFile) = this(_file, _file.toCharArray)
def this(sourceName: String, cs: Seq[Char]) = this(new VirtualFile(sourceName), cs.toArray)
def this(file: AbstractFile, cs: Seq[Char]) = this(file, cs.toArray)
- override def equals(that : Any) = that match {
- case that : BatchSourceFile => file.path == that.file.path && start == that.start
- case _ => false
- }
- override def hashCode = file.path.## + start.##
+ // If non-whitespace tokens run all the way up to EOF,
+ // positions go wrong because the correct end of the last
+ // token cannot be used as an index into the char array.
+ // The least painful way to address this was to add a
+ // newline to the array.
+ val content = (
+ if (content0.length == 0 || !content0.last.isWhitespace)
+ content0 :+ '\n'
+ else content0
+ )
val length = content.length
def start = 0
def isSelfContained = true
@@ -158,4 +162,10 @@ class BatchSourceFile(val file : AbstractFile, val content: Array[Char]) extends
lastLine = findLine(0, lines.length, lastLine)
lastLine
}
+
+ override def equals(that : Any) = that match {
+ case that : BatchSourceFile => file.path == that.file.path && start == that.start
+ case _ => false
+ }
+ override def hashCode = file.path.## + start.##
}
diff --git a/src/reflect/scala/reflect/makro/Context.scala b/src/reflect/scala/reflect/makro/Context.scala
index f9858a063c..f093016a38 100644
--- a/src/reflect/scala/reflect/makro/Context.scala
+++ b/src/reflect/scala/reflect/makro/Context.scala
@@ -33,8 +33,4 @@ trait Context extends Aliases
/** The prefix tree from which the macro is selected */
val prefix: Expr[PrefixType]
-
- /** Alias to the underlying mirror's reify */
- // implementation is magically hardwired to `scala.reflect.makro.runtime.ContextReifiers`
- def reify[T](expr: T): Expr[T] = macro ???
}
diff --git a/src/reflect/scala/reflect/makro/Enclosures.scala b/src/reflect/scala/reflect/makro/Enclosures.scala
index 69bd8d09c7..ff5c13a785 100644
--- a/src/reflect/scala/reflect/makro/Enclosures.scala
+++ b/src/reflect/scala/reflect/makro/Enclosures.scala
@@ -36,10 +36,6 @@ trait Enclosures {
*/
val enclosingPosition: Position
- /** Tree that corresponds to the enclosing application, or EmptyTree if not applicable.
- */
- val enclosingApplication: Tree
-
/** Tree that corresponds to the enclosing method, or EmptyTree if not applicable.
*/
val enclosingMethod: Tree
diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
index 185621efa4..0878801715 100644
--- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala
+++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
@@ -72,6 +72,18 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym
override def complete(sym: Symbol) = sym setInfo new LazyPackageType
}
+ // reflective mirrors can't know the exhaustive list of available packages
+ // (that's because compiler mirrors are based on directories and reflective mirrors are based on classloaders,
+ // and unlike directories classloaders might make up stuff on the fly)
+ // hence we need to be optimistic and create packages out of thin air
+ // the same thing is done by the `missingHook` below
+ override def staticPackage(fullname: String): ModuleSymbol =
+ try super.staticPackage(fullname)
+ catch {
+ case _: MissingRequirementError =>
+ makeScalaPackage(fullname)
+ }
+
// ----------- Caching ------------------------------------------------------------------
// [Eugene++ to Martin] not weak? why?
@@ -107,15 +119,28 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym
// ----------- Implementations of mirror operations and classes -------------------
+ private def ErrorInnerClass(wannabe: Symbol) = throw new ScalaReflectionException(s"$wannabe is an inner class, use reflectClass on an InstanceMirror to obtain its ClassMirror")
+ private def ErrorInnerModule(wannabe: Symbol) = throw new ScalaReflectionException(s"$wannabe is an inner module, use reflectModule on an InstanceMirror to obtain its ModuleMirror")
+ private def ErrorStaticClass(wannabe: Symbol) = throw new ScalaReflectionException(s"$wannabe is a static class, use reflectClass on a RuntimeMirror to obtain its ClassMirror")
+ private def ErrorStaticModule(wannabe: Symbol) = throw new ScalaReflectionException(s"$wannabe is a static module, use reflectModule on a RuntimeMirror to obtain its ModuleMirror")
+ private def ErrorNotMember(wannabe: Symbol, owner: Symbol) = throw new ScalaReflectionException(s"expected a member of $owner, you provided ${wannabe.kind} ${wannabe.fullName}")
+ private def ErrorNotField(wannabe: Symbol) = throw new ScalaReflectionException(s"expected a field or an accessor method symbol, you provided $wannabe}")
+ private def ErrorNonExistentField(wannabe: Symbol) = throw new ScalaReflectionException(s"""
+ |Scala field ${wannabe.name} isn't represented as a Java field, neither it has a Java accessor method
+ |note that private parameters of class constructors don't get mapped onto fields and/or accessors,
+ |unless they are used outside of their declaring constructors.
+ """.trim.stripMargin)
+ private def ErrorSetImmutableField(wannabe: Symbol) = throw new ScalaReflectionException(s"cannot set an immutable field ${wannabe.name}")
+
def reflect(obj: Any): InstanceMirror = new JavaInstanceMirror(obj.asInstanceOf[AnyRef])
def reflectClass(cls: ClassSymbol): ClassMirror = {
- if (!cls.isStatic) throw new Error("this is an inner class, use reflectClass on an InstanceMirror to obtain its ClassMirror")
+ if (!cls.isStatic) ErrorInnerClass(cls)
new JavaClassMirror(null, cls)
}
def reflectModule(mod: ModuleSymbol): ModuleMirror = {
- if (!mod.isStatic) throw new Error("this is an inner module, use reflectModule on an InstanceMirror to obtain its ModuleMirror")
+ if (!mod.isStatic) ErrorInnerModule(mod)
new JavaModuleMirror(null, mod)
}
@@ -127,34 +152,39 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym
def moduleSymbol(rtcls: RuntimeClass): ModuleSymbol = classToScala(rtcls).companionModule.asModuleSymbol
+ private def checkMemberOf(wannabe: Symbol, owner: Symbol) =
+ if (!owner.info.member(wannabe.name).alternatives.contains(wannabe)) ErrorNotMember(wannabe, owner)
+
private class JavaInstanceMirror(obj: AnyRef)
extends InstanceMirror {
def instance = obj
def symbol = wholemirror.classSymbol(obj.getClass)
def reflectField(field: TermSymbol): FieldMirror = {
- // [Eugene+++] check whether `field` represents a member of a `symbol`
- if (field.isMethod || field.isModule) throw new Error(s"""
- |expected a field symbol, you provided a ${field.kind} symbol
- |A typical cause of this problem is using a field accessor symbol instead of a field symbol.
- |To obtain a field symbol append nme.LOCAL_SUFFIX_STRING to the name of the field,
- |when searching for a member with Type.members or Type.declarations.
- |This is a temporary inconvenience that will be resolved before 2.10.0-final.
- |More information can be found here: https://issues.scala-lang.org/browse/SI-5895.
- """.trim.stripMargin)
- new JavaFieldMirror(obj, field)
+ checkMemberOf(field, symbol)
+ if ((field.isMethod && !field.isAccessor) || field.isModule) ErrorNotField(field)
+ val name =
+ if (field.isGetter) nme.getterToLocal(field.name)
+ else if (field.isSetter) nme.getterToLocal(nme.setterToGetter(field.name))
+ else field.name
+ val field1 = (field.owner.info decl name).asTermSymbol
+ try fieldToJava(field1)
+ catch {
+ case _: NoSuchFieldException => ErrorNonExistentField(field1)
+ }
+ new JavaFieldMirror(obj, field1)
}
def reflectMethod(method: MethodSymbol): MethodMirror = {
- // [Eugene+++] check whether `method` represents a member of a `symbol`
+ checkMemberOf(method, symbol)
new JavaMethodMirror(obj, method)
}
def reflectClass(cls: ClassSymbol): ClassMirror = {
- // [Eugene+++] check whether `cls` represents a member of a `symbol`
- if (cls.isStatic) throw new Error("this is a static class, use reflectClass on a RuntimeMirror to obtain its ClassMirror")
+ if (cls.isStatic) ErrorStaticClass(cls)
+ checkMemberOf(cls, symbol)
new JavaClassMirror(instance, cls)
}
def reflectModule(mod: ModuleSymbol): ModuleMirror = {
- // [Eugene+++] check whether `mod` represents a member of a `symbol`
- if (mod.isStatic) throw new Error("this is a static module, use reflectModule on a RuntimeMirror to obtain its ModuleMirror")
+ if (mod.isStatic) ErrorStaticModule(mod)
+ checkMemberOf(mod, symbol)
new JavaModuleMirror(instance, mod)
}
}
@@ -168,7 +198,7 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym
}
def get = jfield.get(receiver)
def set(value: Any) = {
- if (!symbol.isMutable) throw new Error("cannot set an immutable field")
+ if (!symbol.isMutable) ErrorSetImmutableField(symbol)
jfield.set(receiver, value)
}
}
@@ -186,7 +216,7 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym
case nme.length => jArray.getLength(receiver)
case nme.apply => jArray.get(receiver, args(0).asInstanceOf[Int])
case nme.update => jArray.set(receiver, args(0).asInstanceOf[Int], args(1))
- case _ => throw new Error(s"unexpected array method $symbol")
+ case _ => assert(false, s"unexpected array method: $symbol")
}
else
jmeth.invoke(receiver, args.asInstanceOf[Seq[AnyRef]]: _*)
@@ -1001,7 +1031,7 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym
private lazy val magicSymbols: Map[(String, Name), Symbol] = {
def mapEntry(sym: Symbol): ((String, Name), Symbol) = (sym.owner.fullName, sym.name) -> sym
- Map() ++ (definitions.magicSymbols filter (_.isClass) map mapEntry)
+ Map() ++ (definitions.magicSymbols filter (_.isType) map mapEntry)
}
/** 1. If `owner` is a package class (but not the empty package) and `name` is a term name, make a new package
diff --git a/src/reflect/scala/reflect/runtime/SymbolLoaders.scala b/src/reflect/scala/reflect/runtime/SymbolLoaders.scala
index 17e3d7581a..95c1bc861b 100644
--- a/src/reflect/scala/reflect/runtime/SymbolLoaders.scala
+++ b/src/reflect/scala/reflect/runtime/SymbolLoaders.scala
@@ -99,8 +99,10 @@ trait SymbolLoaders { self: SymbolTable =>
0 < dp && dp < (name.length - 1)
}
- class PackageScope(pkgClass: Symbol) extends Scope() with SynchronizedScope {
+ class PackageScope(pkgClass: Symbol) extends Scope(initFingerPrints = -1L) // disable fingerprinting as we do not know entries beforehand
+ with SynchronizedScope {
assert(pkgClass.isType)
+ // disable fingerprinting as we do not know entries beforehand
private val negatives = mutable.Set[Name]() // Syncnote: Performance only, so need not be protected.
override def lookupEntry(name: Name): ScopeEntry = {
val e = super.lookupEntry(name)
diff --git a/src/reflect/scala/tools/nsc/io/VirtualFile.scala b/src/reflect/scala/tools/nsc/io/VirtualFile.scala
index b9a946598c..805bc04165 100644
--- a/src/reflect/scala/tools/nsc/io/VirtualFile.scala
+++ b/src/reflect/scala/tools/nsc/io/VirtualFile.scala
@@ -55,7 +55,7 @@ class VirtualFile(val name: String, override val path: String) extends AbstractF
}
}
- def container: AbstractFile = unsupported
+ def container: AbstractFile = NoAbstractFile
/** Is this abstract file a directory? */
def isDirectory: Boolean = false
diff --git a/test/files/jvm/future-spec/FutureTests.scala b/test/files/jvm/future-spec/FutureTests.scala
index ca9ff5090f..30e1a722bf 100644
--- a/test/files/jvm/future-spec/FutureTests.scala
+++ b/test/files/jvm/future-spec/FutureTests.scala
@@ -507,6 +507,12 @@ object FutureTests extends MinimalScalaTest {
}
Await.ready(complex, defaultTimeout).isCompleted mustBe (true)
}
+
+ "should not throw when Await.ready" in {
+ val expected = try Right(5 / 0) catch { case a: ArithmeticException => Left(a) }
+ val f = future(5).map(_ / 0)
+ Await.ready(f, defaultTimeout).value.get.toString mustBe expected.toString
+ }
}
diff --git a/test/files/jvm/future-spec/PromiseTests.scala b/test/files/jvm/future-spec/PromiseTests.scala
index 49bc642b57..d15bb31f36 100644
--- a/test/files/jvm/future-spec/PromiseTests.scala
+++ b/test/files/jvm/future-spec/PromiseTests.scala
@@ -78,7 +78,7 @@ object PromiseTests extends MinimalScalaTest {
"contain a value" in { f((future, result) => future.value mustBe (Some(Right(result)))) }
- "return result with 'blocking'" in { f((future, result) => blocking(future, defaultTimeout) mustBe (result)) }
+ "return when ready with 'Await.ready'" in { f((future, result) => Await.ready(future, defaultTimeout).isCompleted mustBe (true)) }
"return result with 'Await.result'" in { f((future, result) => Await.result(future, defaultTimeout) mustBe (result)) }
@@ -163,12 +163,9 @@ object PromiseTests extends MinimalScalaTest {
})
}
- "throw exception with 'blocking'" in {
+ "throw not throw exception with 'Await.ready'" in {
f {
- (future, message) =>
- intercept[E] {
- blocking(future, defaultTimeout)
- }.getMessage mustBe (message)
+ (future, message) => Await.ready(future, defaultTimeout).isCompleted mustBe (true)
}
}
diff --git a/test/files/jvm/scala-concurrent-tck.scala b/test/files/jvm/scala-concurrent-tck.scala
index 5c9c71f3f8..43d4c9dc71 100644
--- a/test/files/jvm/scala-concurrent-tck.scala
+++ b/test/files/jvm/scala-concurrent-tck.scala
@@ -4,7 +4,9 @@ import scala.concurrent.{
TimeoutException,
SyncVar,
ExecutionException,
- ExecutionContext
+ ExecutionContext,
+ CanAwait,
+ Await
}
import scala.concurrent.{ future, promise, blocking }
import scala.util.{ Try, Success, Failure }
@@ -647,7 +649,7 @@ trait FutureProjections extends TestBase {
val f = future {
throw cause
}
- assert(blocking(f.failed, Duration(500, "ms")) == cause)
+ assert(Await.result(f.failed, Duration(500, "ms")) == cause)
done()
}
@@ -655,7 +657,7 @@ trait FutureProjections extends TestBase {
done =>
val f = future { 0 }
try {
- blocking(f.failed, Duration(500, "ms"))
+ Await.result(f.failed, Duration(500, "ms"))
assert(false)
} catch {
case nsee: NoSuchElementException => done()
@@ -678,7 +680,7 @@ trait Blocking extends TestBase {
def testAwaitSuccess(): Unit = once {
done =>
val f = future { 0 }
- blocking(f, Duration(500, "ms"))
+ Await.result(f, Duration(500, "ms"))
done()
}
@@ -689,7 +691,7 @@ trait Blocking extends TestBase {
throw cause
}
try {
- blocking(f, Duration(500, "ms"))
+ Await.result(f, Duration(500, "ms"))
assert(false)
} catch {
case t =>
@@ -698,9 +700,18 @@ trait Blocking extends TestBase {
}
}
+ def testFQCNForAwaitAPI(): Unit = once {
+ done =>
+
+ assert(classOf[CanAwait].getName == "scala.concurrent.CanAwait")
+ assert(Await.getClass.getName == "scala.concurrent.Await")
+
+ done()
+ }
+
testAwaitSuccess()
testAwaitFailure()
-
+ testFQCNForAwaitAPI()
}
trait BlockContexts extends TestBase {
@@ -708,7 +719,7 @@ trait BlockContexts extends TestBase {
import scala.concurrent.{ Await, Awaitable, BlockContext }
private def getBlockContext(body: => BlockContext): BlockContext = {
- blocking(Future { body }, Duration(500, "ms"))
+ Await.result(Future { body }, Duration(500, "ms"))
}
// test outside of an ExecutionContext
@@ -727,8 +738,7 @@ trait BlockContexts extends TestBase {
def testPushCustom(): Unit = {
val orig = BlockContext.current
val customBC = new BlockContext() {
- override def internalBlockingCall[T](awaitable: Awaitable[T], atMost: Duration): T =
- orig.internalBlockingCall(awaitable, atMost)
+ override def blockOn[T](thunk: =>T)(implicit permission: CanAwait): T = orig.blockOn(thunk)
}
val bc = getBlockContext({
@@ -744,8 +754,7 @@ trait BlockContexts extends TestBase {
def testPopCustom(): Unit = {
val orig = BlockContext.current
val customBC = new BlockContext() {
- override def internalBlockingCall[T](awaitable: Awaitable[T], atMost: Duration): T =
- orig.internalBlockingCall(awaitable, atMost)
+ override def blockOn[T](thunk: =>T)(implicit permission: CanAwait): T = orig.blockOn(thunk)
}
val bc = getBlockContext({
diff --git a/test/files/neg/macro-cyclic.check b/test/files/neg/macro-cyclic.check
index 608381e0e8..7978ec64a5 100644
--- a/test/files/neg/macro-cyclic.check
+++ b/test/files/neg/macro-cyclic.check
@@ -1,4 +1,4 @@
-Impls_Macros_1.scala:5: error: could not find implicit value for parameter e: SourceLocation
- c.reify { implicitly[SourceLocation] }
- ^
-one error found
+Impls_Macros_1.scala:5: error: could not find implicit value for parameter e: SourceLocation
+ c.universe.reify { implicitly[SourceLocation] }
+ ^
+one error found
diff --git a/test/files/neg/macro-cyclic/Impls_Macros_1.scala b/test/files/neg/macro-cyclic/Impls_Macros_1.scala
index 1ea06fc968..2ecdc3416e 100644
--- a/test/files/neg/macro-cyclic/Impls_Macros_1.scala
+++ b/test/files/neg/macro-cyclic/Impls_Macros_1.scala
@@ -2,7 +2,7 @@ import scala.reflect.makro.Context
object Macros {
def impl(c: Context) = {
- c.reify { implicitly[SourceLocation] }
+ c.universe.reify { implicitly[SourceLocation] }
}
implicit def sourceLocation: SourceLocation1 = macro impl
diff --git a/test/files/neg/static-annot.check b/test/files/neg/static-annot.check
new file mode 100644
index 0000000000..66efebdcee
--- /dev/null
+++ b/test/files/neg/static-annot.check
@@ -0,0 +1,19 @@
+static-annot.scala:8: error: Only members of top-level objects and their nested objects can be annotated with @static.
+ @static val bar = 1
+ ^
+static-annot.scala:27: error: @static annotated field bar has the same name as a member of class Conflicting
+ @static val bar = 1
+ ^
+static-annot.scala:37: error: The @static annotation is only allowed on public members.
+ @static private val bar = 1
+ ^
+static-annot.scala:38: error: The @static annotation is only allowed on public members.
+ @static private val baz = 2
+ ^
+static-annot.scala:39: error: The @static annotation is not allowed on lazy members.
+ @static lazy val bam = 3
+ ^
+static-annot.scala:14: error: Only members of top-level objects and their nested objects can be annotated with @static.
+ @static val blah = 2
+ ^
+6 errors found \ No newline at end of file
diff --git a/test/files/neg/static-annot.scala b/test/files/neg/static-annot.scala
new file mode 100644
index 0000000000..c6c626d42b
--- /dev/null
+++ b/test/files/neg/static-annot.scala
@@ -0,0 +1,47 @@
+
+
+import annotation.static
+
+
+
+class StaticInClass {
+ @static val bar = 1
+}
+
+
+class NestedObjectInClass {
+ object Nested {
+ @static val blah = 2
+ }
+}
+
+
+object NestedObjectInObject {
+ object Nested {
+ @static val succeed = 3
+ }
+}
+
+
+object Conflicting {
+ @static val bar = 1
+}
+
+
+class Conflicting {
+ val bar = 45
+}
+
+
+object PrivateProtectedLazy {
+ @static private val bar = 1
+ @static private val baz = 2
+ @static lazy val bam = 3
+}
+
+
+class PrivateProtectedLazy {
+ println(PrivateProtectedLazy.bar)
+ println(PrivateProtectedLazy.baz)
+ println(PrivateProtectedLazy.bam)
+}
diff --git a/test/files/neg/t4069.check b/test/files/neg/t4069.check
index 91bf882cec..08e937bdfe 100644
--- a/test/files/neg/t4069.check
+++ b/test/files/neg/t4069.check
@@ -12,5 +12,5 @@ t4069.scala:4: error: I encountered a '}' where I didn't expect one, maybe this
^
t4069.scala:10: error: '}' expected but eof found.
}
-^
+ ^
5 errors found
diff --git a/test/files/neg/t4425.check b/test/files/neg/t4425.check
index 0f2fe6f2d1..a6a1a1fad4 100644
--- a/test/files/neg/t4425.check
+++ b/test/files/neg/t4425.check
@@ -1,4 +1,5 @@
-t4425.scala:3: error: isInstanceOf cannot test if value types are references.
+t4425.scala:3: error: error during expansion of this match (this is a scalac bug).
+The underlying error was: value _1 is not a member of object Foo.X
42 match { case _ X _ => () }
- ^
+ ^
one error found
diff --git a/test/files/neg/t4584.check b/test/files/neg/t4584.check
index 060160d76a..419f5704b1 100644
--- a/test/files/neg/t4584.check
+++ b/test/files/neg/t4584.check
@@ -1,4 +1,7 @@
-t4584.scala:1: error: incomplete unicode escape
+t4584.scala:1: error: error in unicode escape
+class A { val /u2
+ ^
+t4584.scala:1: error: illegal character '/uffff'
class A { val /u2
^
-one error found
+two errors found
diff --git a/test/files/neg/t5856.check b/test/files/neg/t5856.check
new file mode 100644
index 0000000000..ac49d4b9ac
--- /dev/null
+++ b/test/files/neg/t5856.check
@@ -0,0 +1,31 @@
+t5856.scala:10: error: invalid string interpolation: `$$', `$'ident or `$'BlockExpr expected
+ val s9 = s"$"
+ ^
+t5856.scala:10: error: unclosed string literal
+ val s9 = s"$"
+ ^
+t5856.scala:2: error: error in interpolated string: identifier or block expected
+ val s1 = s"$null"
+ ^
+t5856.scala:3: error: error in interpolated string: identifier or block expected
+ val s2 = s"$false"
+ ^
+t5856.scala:4: error: error in interpolated string: identifier or block expected
+ val s3 = s"$true"
+ ^
+t5856.scala:5: error: error in interpolated string: identifier or block expected
+ val s4 = s"$yield"
+ ^
+t5856.scala:6: error: error in interpolated string: identifier or block expected
+ val s5 = s"$return"
+ ^
+t5856.scala:7: error: error in interpolated string: identifier or block expected
+ val s6 = s"$new"
+ ^
+t5856.scala:8: error: error in interpolated string: identifier or block expected
+ val s7 = s"$s1 $null $super"
+ ^
+t5856.scala:9: error: error in interpolated string: identifier or block expected
+ val s8 = s"$super"
+ ^
+10 errors found
diff --git a/test/files/neg/t5856.scala b/test/files/neg/t5856.scala
new file mode 100644
index 0000000000..2ceee590af
--- /dev/null
+++ b/test/files/neg/t5856.scala
@@ -0,0 +1,11 @@
+object Test {
+ val s1 = s"$null"
+ val s2 = s"$false"
+ val s3 = s"$true"
+ val s4 = s"$yield"
+ val s5 = s"$return"
+ val s6 = s"$new"
+ val s7 = s"$s1 $null $super"
+ val s8 = s"$super"
+ val s9 = s"$"
+} \ No newline at end of file
diff --git a/test/files/neg/t5892.check b/test/files/neg/t5892.check
new file mode 100644
index 0000000000..839bf9de23
--- /dev/null
+++ b/test/files/neg/t5892.check
@@ -0,0 +1,17 @@
+t5892.scala:5: error: type mismatch;
+ found : Boolean(false)
+ required: String
+class C[@annot(false) X] {
+ ^
+t5892.scala:9: error: not found: value b2s
+class D[@annot(b2s(false)) X] {
+ ^
+t5892.scala:13: error: type mismatch;
+ found : Boolean(false)
+ required: String
+@annot(false) class E {
+ ^
+t5892.scala:17: error: not found: value b2s
+@annot(b2s(false)) class F {
+ ^
+four errors found
diff --git a/test/files/neg/t5892.scala b/test/files/neg/t5892.scala
new file mode 100644
index 0000000000..5e3b2f313e
--- /dev/null
+++ b/test/files/neg/t5892.scala
@@ -0,0 +1,25 @@
+import language.implicitConversions
+
+class annot(a: String) extends annotation.StaticAnnotation
+
+class C[@annot(false) X] {
+ implicit def b2s(b: Boolean): String = ""
+}
+
+class D[@annot(b2s(false)) X] {
+ implicit def b2s(b: Boolean): String = ""
+}
+
+@annot(false) class E {
+ implicit def b2s(b: Boolean): String = ""
+}
+
+@annot(b2s(false)) class F {
+ implicit def b2s(b: Boolean): String = ""
+}
+
+object T {
+ implicit def b2s(b: Boolean): String = ""
+ @annot(false) val x = 0
+ @annot(b2s(false)) val y = 0
+}
diff --git a/test/files/neg/unicode-unterminated-quote.check b/test/files/neg/unicode-unterminated-quote.check
index fc5caa6d7e..5085505fb4 100644
--- a/test/files/neg/unicode-unterminated-quote.check
+++ b/test/files/neg/unicode-unterminated-quote.check
@@ -1,4 +1,7 @@
unicode-unterminated-quote.scala:2: error: unclosed string literal
val x = /u0022
^
-one error found
+unicode-unterminated-quote.scala:2: error: '}' expected but eof found.
+ val x = /u0022
+ ^
+two errors found
diff --git a/test/files/pos/t1832.scala b/test/files/pos/t1832.scala
new file mode 100644
index 0000000000..c7b1ffb838
--- /dev/null
+++ b/test/files/pos/t1832.scala
@@ -0,0 +1,8 @@
+trait Cloning {
+ trait Foo
+ def fn(g: Any => Unit): Foo
+
+ implicit def mkStar(i: Int) = new { def *(a: Foo): Foo = null }
+
+ val pool = 4 * fn { case ghostSYMBOL: Int => ghostSYMBOL * 2 }
+} \ No newline at end of file
diff --git a/test/files/pos/t5892.scala b/test/files/pos/t5892.scala
new file mode 100644
index 0000000000..241e59860a
--- /dev/null
+++ b/test/files/pos/t5892.scala
@@ -0,0 +1,5 @@
+class foo(a: String) extends annotation.StaticAnnotation
+object o {
+ implicit def i2s(i: Int) = ""
+ @foo(1: String) def blerg { }
+}
diff --git a/test/files/pos/t5957/T_1.scala b/test/files/pos/t5957/T_1.scala
index 1db5a3891f..339dcbf0f0 100644
--- a/test/files/pos/t5957/T_1.scala
+++ b/test/files/pos/t5957/T_1.scala
@@ -1,6 +1,8 @@
abstract class T {
- def t1: Test$Bar
+ // see: SI-6109
+ // def t1: Test$Bar
def t2: Test#Bar
- def t3: Test$Baz
+ // see: SI-6109
+ // def t3: Test$Baz
def t4: Test.Baz
}
diff --git a/test/files/pos/t6047.flags b/test/files/pos/t6047.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/pos/t6047.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/pos/t6047.scala b/test/files/pos/t6047.scala
new file mode 100644
index 0000000000..66b52b285f
--- /dev/null
+++ b/test/files/pos/t6047.scala
@@ -0,0 +1,20 @@
+import scala.reflect.makro.Context
+import java.io.InputStream
+
+object Macros {
+ def unpack[A](input: InputStream): A = macro unpack_impl[A]
+
+ def unpack_impl[A: c.TypeTag](c: Context)(input: c.Expr[InputStream]): c.Expr[A] = {
+ import c.universe._
+
+ def unpackcode(tpe: c.Type): c.Expr[_] = {
+ if (tpe <:< implicitly[c.AbsTypeTag[Traversable[_]]].tpe) {
+
+ }
+ ???
+ }
+
+ unpackcode(c.typeOf[A])
+ ???
+ }
+ } \ No newline at end of file
diff --git a/test/files/run/existentials-in-compiler.scala b/test/files/run/existentials-in-compiler.scala
index a37005b1c4..14c25849cb 100644
--- a/test/files/run/existentials-in-compiler.scala
+++ b/test/files/run/existentials-in-compiler.scala
@@ -72,7 +72,7 @@ package extest {
"""
def check(source: String, unit: global.CompilationUnit) = {
- getRequiredModule("extest").moduleClass.info.decls.toList.filter(_.isType).map(_.initialize).sortBy(_.name.toString) foreach { clazz =>
+ getRequiredPackage("extest").moduleClass.info.decls.toList.filter(_.isType).map(_.initialize).sortBy(_.name.toString) foreach { clazz =>
exitingTyper {
clazz.info
println(clazz.defString)
diff --git a/test/files/run/inline-ex-handlers.check b/test/files/run/inline-ex-handlers.check
index 7d96c447b0..25e1b2a4dd 100644
--- a/test/files/run/inline-ex-handlers.check
+++ b/test/files/run/inline-ex-handlers.check
@@ -34,11 +34,11 @@
< 101 JUMP 4
<
< 4:
-512c517
+515c520
< blocks: [1,2,3,4,6,7,8,9,10]
---
> blocks: [1,2,3,4,6,7,8,9,10,11,12,13]
-541c546,551
+544c549,554
< 306 THROW(MyException)
---
> ? JUMP 11
@@ -47,7 +47,7 @@
> ? LOAD_LOCAL(variable monitor4)
> 305 MONITOR_EXIT
> ? JUMP 12
-547c557,563
+550c560,566
< ? THROW(Throwable)
---
> ? JUMP 12
@@ -57,7 +57,7 @@
> 304 MONITOR_EXIT
> ? STORE_LOCAL(value t)
> ? JUMP 13
-553c569,582
+556c572,585
< ? THROW(Throwable)
---
> ? STORE_LOCAL(value t)
@@ -74,19 +74,19 @@
> 310 CALL_PRIMITIVE(EndConcat)
> 310 CALL_METHOD scala.Predef.println (dynamic)
> 310 JUMP 2
-577c606
+580c609
< catch (Throwable) in ArrayBuffer(7, 8, 9, 10) starting at: 6
---
> catch (Throwable) in ArrayBuffer(7, 8, 9, 10, 11) starting at: 6
-580c609
+583c612
< catch (Throwable) in ArrayBuffer(4, 6, 7, 8, 9, 10) starting at: 3
---
> catch (Throwable) in ArrayBuffer(4, 6, 7, 8, 9, 10, 11, 12) starting at: 3
-612c641
+615c644
< blocks: [1,2,3,4,5,6,7,9,10]
---
> blocks: [1,2,3,4,5,6,7,9,10,11,12]
-636c665,671
+639c668,674
< 78 THROW(IllegalArgumentException)
---
> ? STORE_LOCAL(value e)
@@ -96,7 +96,7 @@
> 81 LOAD_LOCAL(value e)
> ? STORE_LOCAL(variable exc1)
> ? JUMP 12
-665c700,714
+668c703,717
< 81 THROW(Exception)
---
> ? STORE_LOCAL(variable exc1)
@@ -114,15 +114,15 @@
> 84 STORE_LOCAL(variable result)
> 84 LOAD_LOCAL(variable exc1)
> 84 THROW(Throwable)
-687c736
+690c739
< catch (<none>) in ArrayBuffer(4, 6, 7, 9) starting at: 3
---
> catch (<none>) in ArrayBuffer(4, 6, 7, 9, 11) starting at: 3
-713c762
+716c765
< blocks: [1,2,3,4,5,6,9,12,14,17,18,19,22,25,27,28,30,31]
---
> blocks: [1,2,3,4,5,6,9,12,14,17,18,19,22,25,27,28,30,31,32,33,34]
-737c786,793
+740c789,796
< 172 THROW(MyException)
---
> ? STORE_LOCAL(value ex6)
@@ -133,12 +133,12 @@
> 170 STORE_LOCAL(value x4)
> 170 SCOPE_ENTER value x4
> 170 JUMP 18
-793c849,850
+798c854,855
< 177 THROW(MyException)
---
> ? STORE_LOCAL(value ex6)
> ? JUMP 33
-797c854,861
+802c859,866
< 170 THROW(Throwable)
---
> ? STORE_LOCAL(value ex6)
@@ -149,17 +149,17 @@
> 169 STORE_LOCAL(value x4)
> 169 SCOPE_ENTER value x4
> 169 JUMP 5
-830c894,895
+837c901,902
< 182 THROW(MyException)
---
> ? STORE_LOCAL(variable exc2)
> ? JUMP 34
-834c899,900
+841c906,907
< 169 THROW(Throwable)
---
> ? STORE_LOCAL(variable exc2)
> ? JUMP 34
-835a902,914
+842a909,921
> 34:
> 184 LOAD_MODULE object Predef
> 184 CONSTANT("finally")
@@ -173,19 +173,19 @@
> 185 LOAD_LOCAL(variable exc2)
> 185 THROW(Throwable)
>
-856c935
+863c942
< catch (Throwable) in ArrayBuffer(17, 18, 19, 22, 25, 27, 28, 30) starting at: 4
---
> catch (Throwable) in ArrayBuffer(17, 18, 19, 22, 25, 27, 28, 30, 32) starting at: 4
-859c938
+866c945
< catch (<none>) in ArrayBuffer(4, 5, 6, 9, 12, 17, 18, 19, 22, 25, 27, 28, 30) starting at: 3
---
> catch (<none>) in ArrayBuffer(4, 5, 6, 9, 12, 17, 18, 19, 22, 25, 27, 28, 30, 32, 33) starting at: 3
-885c964
+892c971
< blocks: [1,2,3,6,7,8,11,14,16,17,19]
---
> blocks: [1,2,3,6,7,8,11,14,16,17,19,20]
-909c988,995
+916c995,1002
< 124 THROW(MyException)
---
> ? STORE_LOCAL(value ex6)
@@ -196,15 +196,15 @@
> 122 STORE_LOCAL(value x4)
> 122 SCOPE_ENTER value x4
> 122 JUMP 7
-969c1055
+979c1065
< catch (IllegalArgumentException) in ArrayBuffer(6, 7, 8, 11, 14, 16, 17, 19) starting at: 3
---
> catch (IllegalArgumentException) in ArrayBuffer(6, 7, 8, 11, 14, 16, 17, 19, 20) starting at: 3
-995c1081
+1005c1091
< blocks: [1,2,3,4,5,8,11,15,16,17,19]
---
> blocks: [1,2,3,5,8,11,15,16,17,19,20]
-1019c1105,1114
+1029c1115,1124
< 148 THROW(MyException)
---
> ? STORE_LOCAL(value ex6)
@@ -217,15 +217,15 @@
> 154 LOAD_LOCAL(value x4)
> 154 IS_INSTANCE REF(class MyException)
> 154 CZJUMP (BOOL)NE ? 5 : 11
-1040,1042d1134
+1050,1052d1144
< 145 JUMP 4
<
< 4:
-1275c1367
+1288c1380
< blocks: [1,2,3,4,5,7]
---
> blocks: [1,2,3,4,5,7,8]
-1299c1391,1398
+1312c1404,1411
< 38 THROW(IllegalArgumentException)
---
> ? STORE_LOCAL(value e)
@@ -236,16 +236,16 @@
> 42 CONSTANT("IllegalArgumentException")
> 42 CALL_METHOD scala.Predef.println (dynamic)
> 42 JUMP 2
-1348c1447
+1361c1460
< blocks: [1,2,3,4,5,8,11,13,14,16,17,19]
---
> blocks: [1,2,3,5,8,11,13,14,16,17,19,20]
-1372c1471,1472
+1385c1484,1485
< 203 THROW(MyException)
---
> ? STORE_LOCAL(value ex6)
> ? JUMP 20
-1392c1492,1501
+1405c1505,1514
< 209 THROW(MyException)
---
> ? STORE_LOCAL(value ex6)
@@ -258,15 +258,15 @@
> 212 LOAD_LOCAL(value x4)
> 212 IS_INSTANCE REF(class MyException)
> 212 CZJUMP (BOOL)NE ? 5 : 11
-1405,1407d1513
+1418,1420d1526
< 200 JUMP 4
<
< 4:
-1467c1573
+1483c1589
< blocks: [1,2,3,4,5,7]
---
> blocks: [1,2,3,4,5,7,8]
-1491c1597,1604
+1507c1613,1620
< 58 THROW(IllegalArgumentException)
---
> ? STORE_LOCAL(value e)
@@ -277,11 +277,11 @@
> 62 CONSTANT("RuntimeException")
> 62 CALL_METHOD scala.Predef.println (dynamic)
> 62 JUMP 2
-1540c1653
+1556c1669
< blocks: [1,2,3,4]
---
> blocks: [1,2,3,4,5]
-1560c1673,1678
+1576c1689,1694
< 229 THROW(MyException)
---
> ? JUMP 5
@@ -290,19 +290,19 @@
> ? LOAD_LOCAL(variable monitor1)
> 228 MONITOR_EXIT
> 228 THROW(Throwable)
-1566c1684
+1582c1700
< ? THROW(Throwable)
---
> 228 THROW(Throwable)
-1594c1712
+1610c1728
< locals: value args, variable result, variable monitor2, variable monitorResult1
---
> locals: value exception$1, value args, variable result, variable monitor2, variable monitorResult1
-1596c1714
+1612c1730
< blocks: [1,2,3,4]
---
> blocks: [1,2,3,4,5]
-1619c1737,1745
+1635c1753,1761
< 245 THROW(MyException)
---
> ? STORE_LOCAL(value exception$1)
@@ -314,7 +314,7 @@
> ? LOAD_LOCAL(variable monitor2)
> 244 MONITOR_EXIT
> 244 THROW(Throwable)
-1625c1751
+1641c1767
< ? THROW(Throwable)
---
> 244 THROW(Throwable)
diff --git a/test/files/run/macro-openmacros/Impls_Macros_1.scala b/test/files/run/macro-openmacros/Impls_Macros_1.scala
index ffeccce1e8..6b92834b81 100644
--- a/test/files/run/macro-openmacros/Impls_Macros_1.scala
+++ b/test/files/run/macro-openmacros/Impls_Macros_1.scala
@@ -16,7 +16,7 @@ object Macros {
import c.universe._
val next = if (c.enclosingMacros.length < 3) c.Expr[Unit](Select(Ident(c.mirror.staticModule("Macros")), newTermName("foo"))) else c.literalUnit
- c.reify {
+ c.universe.reify {
println(c.literal(normalizePaths(c.enclosingMacros.toString)).splice)
next.splice
}
diff --git a/test/files/run/macro-reify-basic/Macros_1.scala b/test/files/run/macro-reify-basic/Macros_1.scala
index 7a43ee58be..8f8598e248 100644
--- a/test/files/run/macro-reify-basic/Macros_1.scala
+++ b/test/files/run/macro-reify-basic/Macros_1.scala
@@ -4,7 +4,7 @@ object Macros {
def foo(s: String) = macro Impls.foo
object Impls {
- def foo(c: Ctx)(s: c.Expr[String]) = c.reify {
+ def foo(c: Ctx)(s: c.Expr[String]) = c.universe.reify {
println("hello " + s.splice)
}
}
diff --git a/test/files/run/macro-reify-freevars/Macros_1.scala b/test/files/run/macro-reify-freevars/Macros_1.scala
index eafc7f9a82..df1473511d 100644
--- a/test/files/run/macro-reify-freevars/Macros_1.scala
+++ b/test/files/run/macro-reify-freevars/Macros_1.scala
@@ -7,7 +7,7 @@ object QueryableMacros{
: c.Expr[scala.collection.slick.Queryable[S]] = {
import c.universe._
val code = EmptyTree
- c.reify{
+ c.universe.reify{
Queryable.factory[S]( code.asInstanceOf[reflect.runtime.universe.Tree] )
}
}
diff --git a/test/files/run/macro-reify-nested-a/Impls_Macros_1.scala b/test/files/run/macro-reify-nested-a/Impls_Macros_1.scala
index f9a08df90d..b52b962e31 100644
--- a/test/files/run/macro-reify-nested-a/Impls_Macros_1.scala
+++ b/test/files/run/macro-reify-nested-a/Impls_Macros_1.scala
@@ -30,7 +30,7 @@ object QueryableMacros{
Apply(Select(c.prefix.tree, newTermName( name )), List( projection.tree ))
).asInstanceOf[Tree]
)))
- c.reify{ Queryable.factory[S]( foo.splice )}
+ c.universe.reify{ Queryable.factory[S]( foo.splice )}
}
def map[T:c.TypeTag, S:c.TypeTag]
(c: scala.reflect.makro.Context)
diff --git a/test/files/run/macro-reify-nested-b/Impls_Macros_1.scala b/test/files/run/macro-reify-nested-b/Impls_Macros_1.scala
index f9a08df90d..b52b962e31 100644
--- a/test/files/run/macro-reify-nested-b/Impls_Macros_1.scala
+++ b/test/files/run/macro-reify-nested-b/Impls_Macros_1.scala
@@ -30,7 +30,7 @@ object QueryableMacros{
Apply(Select(c.prefix.tree, newTermName( name )), List( projection.tree ))
).asInstanceOf[Tree]
)))
- c.reify{ Queryable.factory[S]( foo.splice )}
+ c.universe.reify{ Queryable.factory[S]( foo.splice )}
}
def map[T:c.TypeTag, S:c.TypeTag]
(c: scala.reflect.makro.Context)
diff --git a/test/files/run/macro-reify-ref-to-packageless/Impls_1.scala b/test/files/run/macro-reify-ref-to-packageless/Impls_1.scala
index 2f2d05678d..66c0ee1e9b 100644
--- a/test/files/run/macro-reify-ref-to-packageless/Impls_1.scala
+++ b/test/files/run/macro-reify-ref-to-packageless/Impls_1.scala
@@ -2,5 +2,5 @@ import scala.reflect.makro.{Context => Ctx}
object Impls {
val `Answer to the Ultimate Question of Life, the Universe, and Everything` = 42
- def foo(c: Ctx) = c.reify { `Answer to the Ultimate Question of Life, the Universe, and Everything` }
+ def foo(c: Ctx) = c.universe.reify { `Answer to the Ultimate Question of Life, the Universe, and Everything` }
}
diff --git a/test/files/run/macro-reify-splice-splice/Macros_1.scala b/test/files/run/macro-reify-splice-splice/Macros_1.scala
index 4f1b600f63..0de780b5a2 100644
--- a/test/files/run/macro-reify-splice-splice/Macros_1.scala
+++ b/test/files/run/macro-reify-splice-splice/Macros_1.scala
@@ -4,8 +4,8 @@ object Macros {
def foo = macro Impls.foo
object Impls {
- def foo(c: Ctx) = c.reify {
- { c.reify(c.reify("hello world")) }.splice.splice
+ def foo(c: Ctx) = c.universe.reify {
+ { c.universe.reify(c.universe.reify("hello world")) }.splice.splice
}
}
} \ No newline at end of file
diff --git a/test/files/run/macro-reify-staticXXX.check b/test/files/run/macro-reify-staticXXX.check
new file mode 100644
index 0000000000..2894fa5843
--- /dev/null
+++ b/test/files/run/macro-reify-staticXXX.check
@@ -0,0 +1,12 @@
+object
+class
+object > object
+object > class
+package > object
+package > class
+object
+class
+object > object
+object > class
+package > object
+package > class \ No newline at end of file
diff --git a/test/files/run/macro-reify-staticXXX.flags b/test/files/run/macro-reify-staticXXX.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-reify-staticXXX.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-reify-staticXXX/Macros_1.scala b/test/files/run/macro-reify-staticXXX/Macros_1.scala
new file mode 100644
index 0000000000..b0ce6507f8
--- /dev/null
+++ b/test/files/run/macro-reify-staticXXX/Macros_1.scala
@@ -0,0 +1,48 @@
+import scala.reflect.makro.Context
+
+object B { override def toString = "object" }
+class C { override def toString = "class" }
+
+package foo {
+ object B { override def toString = "package > object" }
+ class C { override def toString = "package > class" }
+}
+
+object foo {
+ object B { override def toString = "object > object" }
+ class C { override def toString = "object > class" }
+}
+
+object packageless {
+ def impl(c: Context) = {
+ import c.universe._
+ reify {
+ println(B)
+ println(new C)
+ println(foo.B)
+ println(new foo.C)
+ println(_root_.foo.B)
+ println(new _root_.foo.C)
+ }
+ }
+
+ def test = macro impl
+}
+
+package packageful {
+ object Test {
+ def impl(c: Context) = {
+ import c.universe._
+ reify {
+ println(B)
+ println(new C)
+ println(foo.B)
+ println(new foo.C)
+ println(_root_.foo.B)
+ println(new _root_.foo.C)
+ }
+ }
+
+ def test = macro impl
+ }
+}
diff --git a/test/files/run/macro-reify-staticXXX/Test_2.scala b/test/files/run/macro-reify-staticXXX/Test_2.scala
new file mode 100644
index 0000000000..6e8cc36080
--- /dev/null
+++ b/test/files/run/macro-reify-staticXXX/Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ packageless.test
+ packageful.Test.test
+}
diff --git a/test/files/run/macro-reify-tagful-a/Macros_1.scala b/test/files/run/macro-reify-tagful-a/Macros_1.scala
index 63f117220a..32b09bdcdf 100644
--- a/test/files/run/macro-reify-tagful-a/Macros_1.scala
+++ b/test/files/run/macro-reify-tagful-a/Macros_1.scala
@@ -5,7 +5,7 @@ object Macros {
def foo[T](s: T) = macro Impls.foo[T]
object Impls {
- def foo[T: c.TypeTag](c: Ctx)(s: c.Expr[T]) = c.reify {
+ def foo[T: c.TypeTag](c: Ctx)(s: c.Expr[T]) = c.universe.reify {
List(s.splice)
}
}
diff --git a/test/files/run/macro-reify-tagless-a/Impls_Macros_1.scala b/test/files/run/macro-reify-tagless-a/Impls_Macros_1.scala
index 3796ae99cb..77e4b729d3 100644
--- a/test/files/run/macro-reify-tagless-a/Impls_Macros_1.scala
+++ b/test/files/run/macro-reify-tagless-a/Impls_Macros_1.scala
@@ -4,7 +4,7 @@ object Macros {
def foo[T](s: T) = macro Impls.foo[T]
object Impls {
- def foo[T](c: Ctx)(s: c.Expr[T]) = c.reify {
+ def foo[T](c: Ctx)(s: c.Expr[T]) = c.universe.reify {
List[T](s.splice)
}
}
diff --git a/test/files/run/macro-reify-unreify/Macros_1.scala b/test/files/run/macro-reify-unreify/Macros_1.scala
index 14777506d3..3e9033966d 100644
--- a/test/files/run/macro-reify-unreify/Macros_1.scala
+++ b/test/files/run/macro-reify-unreify/Macros_1.scala
@@ -11,7 +11,7 @@ object Macros {
val greeting = c.reifyTree(c.runtimeUniverse, EmptyTree, c.typeCheck(Apply(Select(Literal(Constant("hello ")), newTermName("$plus")), List(c.unreifyTree(world)))))
val typedGreeting = c.Expr[String](greeting)
- c.reify {
+ c.universe.reify {
println("hello " + s.splice + " = " + typedGreeting.splice)
}
}
diff --git a/test/files/run/macro-settings/Impls_Macros_1.scala b/test/files/run/macro-settings/Impls_Macros_1.scala
index 56e28b506c..20dcdc1bd1 100644
--- a/test/files/run/macro-settings/Impls_Macros_1.scala
+++ b/test/files/run/macro-settings/Impls_Macros_1.scala
@@ -1,7 +1,7 @@
import scala.reflect.makro.Context
object Impls {
- def impl(c: Context) = c.reify {
+ def impl(c: Context) = c.universe.reify {
println(c.literal(c.settings.toString).splice)
}
}
diff --git a/test/files/run/macro-sip19-revised/Impls_Macros_1.scala b/test/files/run/macro-sip19-revised/Impls_Macros_1.scala
index 994421808e..013130d181 100644
--- a/test/files/run/macro-sip19-revised/Impls_Macros_1.scala
+++ b/test/files/run/macro-sip19-revised/Impls_Macros_1.scala
@@ -11,7 +11,7 @@ object Macros {
val fileName = fun.pos.fileInfo.getName
val line = fun.pos.line
val charOffset = fun.pos.point
- c.reify { SourceLocation1(outer.splice, c.literal(fileName).splice, c.literal(line).splice, c.literal(charOffset).splice) }
+ c.universe.reify { SourceLocation1(outer.splice, c.literal(fileName).splice, c.literal(line).splice, c.literal(charOffset).splice) }
}
implicit def sourceLocation: SourceLocation1 = macro impl
diff --git a/test/files/run/macro-sip19/Impls_Macros_1.scala b/test/files/run/macro-sip19/Impls_Macros_1.scala
index c006ceb691..f6636c298c 100644
--- a/test/files/run/macro-sip19/Impls_Macros_1.scala
+++ b/test/files/run/macro-sip19/Impls_Macros_1.scala
@@ -7,7 +7,7 @@ object Macros {
val fileName = fun.pos.fileInfo.getName
val line = fun.pos.line
val charOffset = fun.pos.point
- c.reify { SourceLocation(c.literal(fileName).splice, c.literal(line).splice, c.literal(charOffset).splice) }
+ c.universe.reify { SourceLocation(c.literal(fileName).splice, c.literal(line).splice, c.literal(charOffset).splice) }
}
implicit def sourceLocation: SourceLocation = macro impl
diff --git a/test/files/run/macro-typecheck-macrosdisabled2.check b/test/files/run/macro-typecheck-macrosdisabled2.check
index e440b2c0cb..2160d3800a 100644
--- a/test/files/run/macro-typecheck-macrosdisabled2.check
+++ b/test/files/run/macro-typecheck-macrosdisabled2.check
@@ -15,7 +15,7 @@
private def applyImpl[U >: Nothing <: scala.reflect.api.Universe with Singleton]($m$untyped: scala.reflect.base.MirrorOf[U]): scala.reflect.base.Universe#Tree = {
val $u: U = $m$untyped.universe;
val $m: $u.Mirror = $m$untyped.asInstanceOf[$u.Mirror];
- $u.Apply.apply($u.Select.apply($u.Select.apply($u.build.Ident($m.staticModule("scala")), $u.newTermName("Array")), $u.newTermName("apply")), scala.collection.immutable.List.apply[$u.Literal]($u.Literal.apply($u.Constant.apply(2))))
+ $u.Apply.apply($u.Select.apply($u.Select.apply($u.build.Ident($m.staticPackage("scala")), $u.newTermName("Array")), $u.newTermName("apply")), scala.collection.immutable.List.apply[$u.Literal]($u.Literal.apply($u.Constant.apply(2))))
}
};
new $treecreator1()
@@ -28,7 +28,7 @@
def apply[U >: Nothing <: scala.reflect.base.Universe with Singleton]($m$untyped: scala.reflect.base.MirrorOf[U]): U#Type = {
val $u: U = $m$untyped.universe;
val $m: $u.Mirror = $m$untyped.asInstanceOf[$u.Mirror];
- $u.TypeRef.apply($u.ThisType.apply($m.staticModule("scala").asModuleSymbol.moduleClass), $m.staticClass("scala.Array"), scala.collection.immutable.List.apply[$u.Type]($m.staticClass("scala.Int").asTypeSymbol.asTypeConstructor))
+ $u.TypeRef.apply($u.ThisType.apply($m.staticPackage("scala").asModuleSymbol.moduleClass), $m.staticClass("scala.Array"), scala.collection.immutable.List.apply[$u.Type]($m.staticClass("scala.Int").asTypeSymbol.asTypeConstructor))
}
};
new $typecreator2()
diff --git a/test/files/run/macro-undetparams-consfromsls/Impls_Macros_1.scala b/test/files/run/macro-undetparams-consfromsls/Impls_Macros_1.scala
index b9bb2cfcca..7b921c0e57 100644
--- a/test/files/run/macro-undetparams-consfromsls/Impls_Macros_1.scala
+++ b/test/files/run/macro-undetparams-consfromsls/Impls_Macros_1.scala
@@ -2,12 +2,12 @@ import scala.reflect.runtime.universe._
import scala.reflect.makro.Context
object Macros {
- def cons_impl[A: c.AbsTypeTag](c: Context)(x: c.Expr[A], xs: c.Expr[List[A]]): c.Expr[List[A]] = c.reify {
+ def cons_impl[A: c.AbsTypeTag](c: Context)(x: c.Expr[A], xs: c.Expr[List[A]]): c.Expr[List[A]] = c.universe.reify {
println("A = " + c.literal(implicitly[c.AbsTypeTag[A]].toString).splice)
x.splice :: xs.splice
}
- def nil_impl[B: c.AbsTypeTag](c: Context): c.Expr[List[B]] = c.reify {
+ def nil_impl[B: c.AbsTypeTag](c: Context): c.Expr[List[B]] = c.universe.reify {
println("B = " + c.literal(implicitly[c.AbsTypeTag[B]].toString).splice)
Nil
}
diff --git a/test/files/run/macro-undetparams-macroitself/Impls_Macros_1.scala b/test/files/run/macro-undetparams-macroitself/Impls_Macros_1.scala
index 9b1dd8e017..fdba40623b 100644
--- a/test/files/run/macro-undetparams-macroitself/Impls_Macros_1.scala
+++ b/test/files/run/macro-undetparams-macroitself/Impls_Macros_1.scala
@@ -2,7 +2,7 @@ import scala.reflect.runtime.universe._
import scala.reflect.makro.Context
object Macros {
- def impl[T: c.TypeTag](c: Context)(foo: c.Expr[T]): c.Expr[Unit] = c.reify { println(c.literal(implicitly[c.TypeTag[T]].toString).splice) }
+ def impl[T: c.TypeTag](c: Context)(foo: c.Expr[T]): c.Expr[Unit] = c.universe.reify { println(c.literal(implicitly[c.TypeTag[T]].toString).splice) }
def foo[T](foo: T) = macro impl[T]
} \ No newline at end of file
diff --git a/test/files/run/nullable-lazyvals.check b/test/files/run/nullable-lazyvals.check
new file mode 100644
index 0000000000..4db5783257
--- /dev/null
+++ b/test/files/run/nullable-lazyvals.check
@@ -0,0 +1,3 @@
+
+param1: null
+param2: null
diff --git a/test/files/run/nullable-lazyvals.scala b/test/files/run/nullable-lazyvals.scala
new file mode 100644
index 0000000000..c201e74e75
--- /dev/null
+++ b/test/files/run/nullable-lazyvals.scala
@@ -0,0 +1,36 @@
+
+/** Test that call-by-name parameters are set to null if
+ * they are used only to initialize a lazy value, after the
+ * value has been initialized.
+ */
+
+class Foo(param1: => Object, param2: => String) {
+ lazy val field1 = param1
+ lazy val field2 = try param2 finally println("")
+}
+
+object Test extends App {
+ val foo = new Foo(new Object, "abc")
+
+ foo.field1
+ foo.field2
+
+ for (f <- foo.getClass.getDeclaredFields) {
+ f.setAccessible(true)
+ if (f.getName.startsWith("param")) {
+ println("%s: %s".format(f.getName, f.get(foo)))
+ }
+ }
+
+ // test that try-finally does not generated a liftedTry
+ // helper. This would already fail the first part of the test,
+ // but this check will help diganose it (if the single access to a
+ // private field does not happen directly in the lazy val, it won't
+ // be nulled).
+ for (f <- foo.getClass.getDeclaredMethods) {
+ f.setAccessible(true)
+ if (f.getName.startsWith("lifted")) {
+ println("not expected: %s".format(f))
+ }
+ }
+}
diff --git a/test/files/run/outertest.scala b/test/files/run/outertest.scala
new file mode 100644
index 0000000000..3cc96afa5b
--- /dev/null
+++ b/test/files/run/outertest.scala
@@ -0,0 +1,26 @@
+// A test for the case where the outer field of class B#J should be eliminated.
+// You can verify this by running a javap on B.J
+abstract class A {
+
+ abstract class I {
+
+ }
+
+ val foo = "foo"
+
+}
+
+class B extends A {
+
+ class J extends I {
+ val bar = foo
+ }
+
+}
+
+object Test extends App {
+
+ val b = new B
+ assert((new b.J).bar == b.foo)
+
+}
diff --git a/test/files/run/reflection-constructormirror-inner-badpath.check b/test/files/run/reflection-constructormirror-inner-badpath.check
index 28b936eca1..2fb0610ad6 100644
--- a/test/files/run/reflection-constructormirror-inner-badpath.check
+++ b/test/files/run/reflection-constructormirror-inner-badpath.check
@@ -1,2 +1,2 @@
-this is an inner class, use reflectClass on an InstanceMirror to obtain its ClassMirror
+class R is an inner class, use reflectClass on an InstanceMirror to obtain its ClassMirror
()
diff --git a/test/files/run/reflection-constructormirror-nested-badpath.check b/test/files/run/reflection-constructormirror-nested-badpath.check
index 9ceb603dc2..acd21df9c0 100644
--- a/test/files/run/reflection-constructormirror-nested-badpath.check
+++ b/test/files/run/reflection-constructormirror-nested-badpath.check
@@ -1,2 +1,2 @@
-this is a static class, use reflectClass on a RuntimeMirror to obtain its ClassMirror
+class R is a static class, use reflectClass on a RuntimeMirror to obtain its ClassMirror
()
diff --git a/test/files/run/reflection-constructormirror-toplevel-badpath.check b/test/files/run/reflection-constructormirror-toplevel-badpath.check
index 9ceb603dc2..acd21df9c0 100644
--- a/test/files/run/reflection-constructormirror-toplevel-badpath.check
+++ b/test/files/run/reflection-constructormirror-toplevel-badpath.check
@@ -1,2 +1,2 @@
-this is a static class, use reflectClass on a RuntimeMirror to obtain its ClassMirror
+class R is a static class, use reflectClass on a RuntimeMirror to obtain its ClassMirror
()
diff --git a/test/files/run/reflection-fieldmirror-accessorsareokay.check b/test/files/run/reflection-fieldmirror-accessorsareokay.check
new file mode 100644
index 0000000000..635dcd04ce
--- /dev/null
+++ b/test/files/run/reflection-fieldmirror-accessorsareokay.check
@@ -0,0 +1,6 @@
+true
+42
+2
+true
+2
+2
diff --git a/test/files/run/reflection-fieldmirror-accessorsareokay.scala b/test/files/run/reflection-fieldmirror-accessorsareokay.scala
new file mode 100644
index 0000000000..c586ce9bdd
--- /dev/null
+++ b/test/files/run/reflection-fieldmirror-accessorsareokay.scala
@@ -0,0 +1,29 @@
+import scala.reflect.runtime.universe._
+import scala.reflect.runtime.{currentMirror => cm}
+
+object Test extends App {
+ class A {
+ var x: Int = 42
+ }
+
+ val a = new A
+
+ val im: InstanceMirror = cm.reflect(a)
+ val cs = im.symbol
+
+ def test(f: Symbol) = {
+ try {
+ val fm: FieldMirror = im.reflectField(f.asTermSymbol)
+ println(fm.symbol.isVariable)
+ println(fm.get)
+ fm.set(2)
+ println(fm.get)
+ } catch {
+ case ex: Throwable =>
+ println(ex.getMessage)
+ }
+ }
+
+ test(cs.typeSignature.declaration(newTermName("x")).asTermSymbol)
+ test(cs.typeSignature.declaration(newTermName("x_$eq")).asTermSymbol)
+}
diff --git a/test/files/run/reflection-fieldmirror-ctorparam.check b/test/files/run/reflection-fieldmirror-ctorparam.check
index 8b99a6f772..31f6491b14 100644
--- a/test/files/run/reflection-fieldmirror-ctorparam.check
+++ b/test/files/run/reflection-fieldmirror-ctorparam.check
@@ -1 +1,3 @@
-class java.lang.NoSuchFieldException: Test$A$$x
+class scala.ScalaReflectionException: Scala field x isn't represented as a Java field, neither it has a Java accessor method
+note that private parameters of class constructors don't get mapped onto fields and/or accessors,
+unless they are used outside of their declaring constructors.
diff --git a/test/files/run/reflection-fieldmirror-getsetval.check b/test/files/run/reflection-fieldmirror-getsetval.check
index 707bbcccce..e1927f68d0 100644
--- a/test/files/run/reflection-fieldmirror-getsetval.check
+++ b/test/files/run/reflection-fieldmirror-getsetval.check
@@ -1,2 +1,2 @@
42
-cannot set an immutable field
+cannot set an immutable field x
diff --git a/test/files/run/reflection-fieldmirror-sanitycheck.check b/test/files/run/reflection-fieldmirror-sanitycheck.check
deleted file mode 100644
index e5134de4e3..0000000000
--- a/test/files/run/reflection-fieldmirror-sanitycheck.check
+++ /dev/null
@@ -1,6 +0,0 @@
-expected a field symbol, you provided a method symbol
-A typical cause of this problem is using a field accessor symbol instead of a field symbol.
-To obtain a field symbol append nme.LOCAL_SUFFIX_STRING to the name of the field,
-when searching for a member with Type.members or Type.declarations.
-This is a temporary inconvenience that will be resolved before 2.10.0-final.
-More information can be found here: https://issues.scala-lang.org/browse/SI-5895.
diff --git a/test/files/run/reflection-fieldmirror-sanitycheck.scala b/test/files/run/reflection-fieldmirror-sanitycheck.scala
deleted file mode 100644
index 6a992dd282..0000000000
--- a/test/files/run/reflection-fieldmirror-sanitycheck.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-import scala.reflect.runtime.universe._
-import scala.reflect.runtime.{currentMirror => cm}
-
-object Test extends App {
- class A {
- var x: Int = 42
- }
-
- val a = new A
-
- val im: InstanceMirror = cm.reflect(a)
- val cs = im.symbol
- //val f = cs.typeSignature.declaration(newTermName("x" + nme.LOCAL_SUFFIX_STRING)).asTermSymbol
- val f = cs.typeSignature.declaration(newTermName("x")).asTermSymbol
- try {
- val fm: FieldMirror = im.reflectField(f)
- println("this indicates a failure")
- } catch {
- case ex: Throwable =>
- println(ex.getMessage)
- }
-}
diff --git a/test/files/run/reflection-magicsymbols-repl.check b/test/files/run/reflection-magicsymbols-repl.check
new file mode 100644
index 0000000000..d2ef4ad3cd
--- /dev/null
+++ b/test/files/run/reflection-magicsymbols-repl.check
@@ -0,0 +1,39 @@
+Type in expressions to have them evaluated.
+Type :help for more information.
+
+scala>
+
+scala> import scala.reflect.runtime.universe._
+import scala.reflect.runtime.universe._
+
+scala> class A {
+ def foo1(x: Int*) = ???
+ def foo2(x: => Int) = ???
+ def foo3(x: Any) = ???
+ def foo4(x: AnyRef) = ???
+ def foo5(x: AnyVal) = ???
+ def foo6(x: Null) = ???
+ def foo7(x: Nothing) = ???
+ def foo8(x: Singleton) = ???
+}
+defined class A
+
+scala> def test(n: Int): Unit = {
+ val sig = typeOf[A] member newTermName("foo" + n) typeSignature
+ val x = sig.asInstanceOf[MethodType].params.head
+ println(x.typeSignature)
+}
+warning: there were 1 feature warnings; re-run with -feature for details
+test: (n: Int)Unit
+
+scala> for (i <- 1 to 8) test(i)
+scala.Int*
+=> scala.Int
+scala.Any
+scala.AnyRef
+scala.AnyVal
+scala.Null
+scala.Nothing
+scala.Singleton
+
+scala>
diff --git a/test/files/run/reflection-magicsymbols-repl.scala b/test/files/run/reflection-magicsymbols-repl.scala
new file mode 100644
index 0000000000..26127b8661
--- /dev/null
+++ b/test/files/run/reflection-magicsymbols-repl.scala
@@ -0,0 +1,23 @@
+import scala.tools.partest.ReplTest
+
+object Test extends ReplTest {
+ def code = """
+ |import scala.reflect.runtime.universe._
+ |class A {
+ | def foo1(x: Int*) = ???
+ | def foo2(x: => Int) = ???
+ | def foo3(x: Any) = ???
+ | def foo4(x: AnyRef) = ???
+ | def foo5(x: AnyVal) = ???
+ | def foo6(x: Null) = ???
+ | def foo7(x: Nothing) = ???
+ | def foo8(x: Singleton) = ???
+ |}
+ |def test(n: Int): Unit = {
+ | val sig = typeOf[A] member newTermName("foo" + n) typeSignature
+ | val x = sig.asInstanceOf[MethodType].params.head
+ | println(x.typeSignature)
+ |}
+ |for (i <- 1 to 8) test(i)
+ |""".stripMargin
+}
diff --git a/test/files/run/reflection-magicsymbols-vanilla.check b/test/files/run/reflection-magicsymbols-vanilla.check
new file mode 100644
index 0000000000..4f4e8d94a9
--- /dev/null
+++ b/test/files/run/reflection-magicsymbols-vanilla.check
@@ -0,0 +1,8 @@
+Int*
+=> Int
+Any
+AnyRef
+AnyVal
+Null
+Nothing
+Singleton
diff --git a/test/files/run/reflection-magicsymbols-vanilla.scala b/test/files/run/reflection-magicsymbols-vanilla.scala
new file mode 100644
index 0000000000..32819dcc46
--- /dev/null
+++ b/test/files/run/reflection-magicsymbols-vanilla.scala
@@ -0,0 +1,20 @@
+class A {
+ def foo1(x: Int*) = ???
+ def foo2(x: => Int) = ???
+ def foo3(x: Any) = ???
+ def foo4(x: AnyRef) = ???
+ def foo5(x: AnyVal) = ???
+ def foo6(x: Null) = ???
+ def foo7(x: Nothing) = ???
+ def foo8(x: Singleton) = ???
+}
+
+object Test extends App {
+ import scala.reflect.runtime.universe._
+ def test(n: Int): Unit = {
+ val sig = typeOf[A] member newTermName("foo" + n) typeSignature
+ val x = sig.asInstanceOf[MethodType].params.head
+ println(x.typeSignature)
+ }
+ for (i <- 1 to 8) test(i)
+}
diff --git a/test/files/run/reflection-magicsymbols.check b/test/files/run/reflection-magicsymbols.check
deleted file mode 100644
index 2600847d99..0000000000
--- a/test/files/run/reflection-magicsymbols.check
+++ /dev/null
@@ -1,22 +0,0 @@
-Type in expressions to have them evaluated.
-Type :help for more information.
-
-scala>
-
-scala> import scala.reflect.runtime.universe._
-import scala.reflect.runtime.universe._
-
-scala> class A { def foo(x: Int*) = 1 }
-defined class A
-
-scala> val sig = typeOf[A] member newTermName("foo") typeSignature
-warning: there were 1 feature warnings; re-run with -feature for details
-sig: reflect.runtime.universe.Type = (x: <?>)scala.Int
-
-scala> val x = sig.asInstanceOf[MethodType].params.head
-x: reflect.runtime.universe.Symbol = value x
-
-scala> println(x.typeSignature)
-scala.Int*
-
-scala>
diff --git a/test/files/run/reflection-magicsymbols.scala b/test/files/run/reflection-magicsymbols.scala
deleted file mode 100644
index a40845d6ac..0000000000
--- a/test/files/run/reflection-magicsymbols.scala
+++ /dev/null
@@ -1,11 +0,0 @@
-import scala.tools.partest.ReplTest
-
-object Test extends ReplTest {
- def code = """
- |import scala.reflect.runtime.universe._
- |class A { def foo(x: Int*) = 1 }
- |val sig = typeOf[A] member newTermName("foo") typeSignature
- |val x = sig.asInstanceOf[MethodType].params.head
- |println(x.typeSignature)
- |""".stripMargin
-}
diff --git a/test/files/run/reflection-modulemirror-inner-badpath.check b/test/files/run/reflection-modulemirror-inner-badpath.check
index d3fe43336e..1e990ec900 100644
--- a/test/files/run/reflection-modulemirror-inner-badpath.check
+++ b/test/files/run/reflection-modulemirror-inner-badpath.check
@@ -1,2 +1,2 @@
-this is an inner module, use reflectModule on an InstanceMirror to obtain its ModuleMirror
-()
+object R is an inner module, use reflectModule on an InstanceMirror to obtain its ModuleMirror
+()
diff --git a/test/files/run/reflection-modulemirror-nested-badpath.check b/test/files/run/reflection-modulemirror-nested-badpath.check
index 16a5b10390..f7980b9986 100644
--- a/test/files/run/reflection-modulemirror-nested-badpath.check
+++ b/test/files/run/reflection-modulemirror-nested-badpath.check
@@ -1,2 +1,2 @@
-this is a static module, use reflectModule on a RuntimeMirror to obtain its ModuleMirror
-()
+object R is a static module, use reflectModule on a RuntimeMirror to obtain its ModuleMirror
+()
diff --git a/test/files/run/reflection-modulemirror-toplevel-badpath.check b/test/files/run/reflection-modulemirror-toplevel-badpath.check
index 16a5b10390..f7980b9986 100644
--- a/test/files/run/reflection-modulemirror-toplevel-badpath.check
+++ b/test/files/run/reflection-modulemirror-toplevel-badpath.check
@@ -1,2 +1,2 @@
-this is a static module, use reflectModule on a RuntimeMirror to obtain its ModuleMirror
-()
+object R is a static module, use reflectModule on a RuntimeMirror to obtain its ModuleMirror
+()
diff --git a/test/files/run/reflection-sanitychecks.check b/test/files/run/reflection-sanitychecks.check
new file mode 100644
index 0000000000..d977e0ed66
--- /dev/null
+++ b/test/files/run/reflection-sanitychecks.check
@@ -0,0 +1,8 @@
+field: 1
+method: 2
+class: CC
+object: java.lang.Error: inner and nested modules are not supported yet
+field: scala.ScalaReflectionException: expected a member of class C, you provided value D.foo
+method: scala.ScalaReflectionException: expected a member of class C, you provided method D.bar
+class: scala.ScalaReflectionException: expected a member of class C, you provided class D.C
+object: scala.ScalaReflectionException: expected a member of class C, you provided object D.O
diff --git a/test/files/run/reflection-sanitychecks.scala b/test/files/run/reflection-sanitychecks.scala
new file mode 100644
index 0000000000..a6a24088a4
--- /dev/null
+++ b/test/files/run/reflection-sanitychecks.scala
@@ -0,0 +1,30 @@
+class C {
+ val foo = 1
+ def bar = 2
+ class C { override def toString = "CC" }
+ object O { override def toString = "CO" }
+}
+
+class D {
+ val foo = 3
+ def bar = 4
+ class C { override def toString = "DC" }
+ object O { override def toString = "DO" }
+}
+
+object Test extends App {
+ import scala.reflect.runtime.universe._
+ import scala.reflect.runtime.{currentMirror => cm}
+ val im = cm.reflect(new C)
+
+ def test(tpe: Type): Unit = {
+ def failsafe(action: => Any): Any = try action catch { case ex: Throwable => ex.toString }
+ println("field: " + failsafe(im.reflectField(tpe.member(newTermName("foo")).asTermSymbol).get))
+ println("method: " + failsafe(im.reflectMethod(tpe.member(newTermName("bar")).asMethodSymbol)()))
+ println("class: " + failsafe(im.reflectClass(tpe.member(newTypeName("C")).asClassSymbol).reflectConstructor(typeOf[C].member(newTypeName("C")).asClassSymbol.typeSignature.member(newTermName("<init>")).asMethodSymbol)()))
+ println("object: " + failsafe(im.reflectModule(tpe.member(newTermName("O")).asModuleSymbol).instance))
+ }
+
+ test(typeOf[C])
+ test(typeOf[D])
+} \ No newline at end of file
diff --git a/test/files/run/reify-staticXXX.check b/test/files/run/reify-staticXXX.check
new file mode 100644
index 0000000000..5762ec47d6
--- /dev/null
+++ b/test/files/run/reify-staticXXX.check
@@ -0,0 +1,24 @@
+object
+object
+class
+class
+object > object
+object > object
+object > class
+object > class
+package > object
+package > object
+package > class
+package > class
+object
+object
+class
+class
+object > object
+object > object
+object > class
+object > class
+package > object
+package > object
+package > class
+package > class
diff --git a/test/files/run/reify-staticXXX.scala b/test/files/run/reify-staticXXX.scala
new file mode 100644
index 0000000000..dc861f843e
--- /dev/null
+++ b/test/files/run/reify-staticXXX.scala
@@ -0,0 +1,56 @@
+import scala.reflect.runtime.universe._
+import scala.tools.reflect.Eval
+
+object B { override def toString = "object" }
+class C { override def toString = "class" }
+
+package foo {
+ object B { override def toString = "package > object" }
+ class C { override def toString = "package > class" }
+}
+
+object foo {
+ object B { override def toString = "object > object" }
+ class C { override def toString = "object > class" }
+}
+
+object packageless {
+ def test = {
+ println(B)
+ println(reify(B).eval)
+ println(new C)
+ println(reify(new C).eval)
+ println(foo.B)
+ println(reify(foo.B).eval)
+ println(new foo.C)
+ println(reify(new foo.C).eval)
+ println(_root_.foo.B)
+ println(reify(_root_.foo.B).eval)
+ println(new _root_.foo.C)
+ println(reify(new _root_.foo.C).eval)
+ }
+}
+
+package packageful {
+ object Test {
+ def test = {
+ println(B)
+ println(reify(B).eval)
+ println(new C)
+ println(reify(new C).eval)
+ println(foo.B)
+ println(reify(foo.B).eval)
+ println(new foo.C)
+ println(reify(new foo.C).eval)
+ println(_root_.foo.B)
+ println(reify(_root_.foo.B).eval)
+ println(new _root_.foo.C)
+ println(reify(new _root_.foo.C).eval)
+ }
+ }
+}
+
+object Test extends App {
+ packageless.test
+ packageful.Test.test
+}
diff --git a/test/files/run/static-annot/field.scala b/test/files/run/static-annot/field.scala
new file mode 100644
index 0000000000..a7d8158321
--- /dev/null
+++ b/test/files/run/static-annot/field.scala
@@ -0,0 +1,243 @@
+
+
+
+import java.lang.reflect.Modifier
+import annotation.static
+import reflect._
+
+
+
+/* TEST 1 */
+
+/* A @static-annotated field in the companion object should yield
+ * a static field in its companion class.
+ */
+object Foo {
+ @static val bar = 17
+}
+
+
+class Foo
+
+
+trait Check {
+ def checkStatic(cls: Class[_]) {
+ cls.getDeclaredFields.find(_.getName == "bar") match {
+ case Some(f) => assert(Modifier.isStatic(f.getModifiers), "no static modifier")
+ case None => assert(false, "no static field bar in class")
+ }
+ }
+
+ def test(): Unit
+}
+
+
+object Test1 extends Check {
+ def test() {
+ checkStatic(classOf[Foo])
+ assert(Foo.bar == 17, "Companion object field should be 17.")
+ }
+}
+
+
+/* TEST 2 */
+
+class Foo2
+
+
+/** The order of declaring the class and its companion is inverted now. */
+object Foo2 {
+ @static val bar = 199
+}
+
+
+object Test2 extends Check {
+ def test() {
+ checkStatic(Class.forName("Foo3"))
+ assert(Foo3.bar == 1984, "Companion object field should be 1984.")
+ }
+}
+
+
+/* TEST 3 */
+
+/** The case where there is no explicit companion class */
+object Foo3 {
+ @static val bar = 1984
+}
+
+
+object Test3 extends Check {
+ def test() {
+ checkStatic(Class.forName("Foo3"))
+ assert(Foo3.bar == 1984, "Companion object field should be 1984.")
+ }
+}
+
+
+/* TEST 4 */
+
+/** We want to be able to generate atomic reference field updaters on the companion object
+ * so that they are created only once per class declaration, but we want them to actually
+ * be initialize __in the static initializer of the class itself__.
+ * This is extremely important, because otherwise the creation of the ARFU fails, since it uses
+ * trickery to detect the caller and compare it to the owner of the field being modified.
+ * Previously, this used to be circumvented through the use of Java base classes. A pain.
+ */
+class ArfuTarget {
+ @volatile var strfield = ArfuTarget.STR
+
+ def CAS(ov: String, nv: String): Boolean = {
+ ArfuTarget.arfu.compareAndSet(this, ov, nv)
+ }
+}
+
+
+object ArfuTarget {
+ @static val arfu = java.util.concurrent.atomic.AtomicReferenceFieldUpdater.newUpdater(classOf[ArfuTarget], classOf[String], "strfield")
+ val STR = "Some string"
+}
+
+
+object Test4 extends Check {
+ def checkArfu() {
+ val at = new ArfuTarget
+ assert(at.strfield == ArfuTarget.STR)
+ at.CAS(ArfuTarget.STR, null)
+ assert(at.strfield == null)
+ }
+
+ def test() {
+ checkArfu()
+ }
+}
+
+
+/* TEST 5 */
+
+/** Although our main use-case is to use final static fields, we should be able to use non-final too.
+ * Here we set the static field of the class by using the setters in the companion object.
+ * It is legal to do so using the reference to `Foo` directly (in which case the callsites
+ * are rewritten to access the static field directly), or through an interface `Var` (in
+ * which case the getter and the setter for `field` access the static field in `Var`).
+ */
+trait Var {
+ var field: Int
+}
+
+object VarHolder extends Var {
+ @static var field = 1
+}
+
+
+object Test5 extends Check {
+ def test() {
+ assert(VarHolder.field == 1)
+ VarHolder.field = 2
+ assert(VarHolder.field == 2)
+ val vh: Var = VarHolder
+ vh.field = 3
+ assert(vh.field == 3)
+ }
+}
+
+
+/* TEST 6 */
+
+/** Here we test flattening the static ctor body and changing the owners of local definitions. */
+object Foo6 {
+ var companionField = 101
+ @static val staticField = {
+ val intermediate = companionField + 1
+ intermediate * 2
+ }
+}
+
+
+object Test6 extends Check {
+ def test() {
+ assert(Foo6.staticField == 204)
+ }
+}
+
+
+
+/* TEST 7 */
+
+/** Here we test objects nested in top-level objects */
+object Foo7 {
+ object AndHisFriend {
+ @static val bar = "string"
+ }
+ class AndHisFriend
+}
+
+
+object Test7 extends Check {
+ def test() {
+ checkStatic(classOf[Foo7.AndHisFriend])
+ assert(Foo7.AndHisFriend.bar == "string")
+ }
+}
+
+
+
+/* TEST 8 */
+
+object Foo8 {
+ @static val field = 7
+
+ val function: () => Int = () => {
+ field + 1
+ }
+
+ val anon = new Runnable {
+ def run() {
+ assert(field == 7, "runnable asserting field is 7")
+ }
+ }
+
+ @static var mutable = 10
+
+ val mutation: () => Unit = () => {
+ mutable += 1
+ }
+}
+
+object Test8 {
+ def test() {
+ assert(Foo8.function() == 8, "function must return 8")
+ Foo8.anon.run()
+ assert(Foo8.mutable == 10, "mutable is 10")
+ Foo8.mutation()
+ assert(Foo8.mutable == 11, "mutable is 11")
+ Foo8.mutation()
+ assert(Foo8.mutable == 12, "mutable is 12")
+ }
+}
+
+
+
+
+/* main */
+
+object Test {
+
+ def main(args: Array[String]) {
+ Test1.test()
+ Test2.test()
+ Test3.test()
+ Test4.test()
+ Test5.test()
+ Test6.test()
+ Test7.test()
+ Test8.test()
+ }
+
+}
+
+
+
+
+
+
diff --git a/test/files/run/t4897.check b/test/files/run/t4897.check
new file mode 100644
index 0000000000..17dda56fe1
--- /dev/null
+++ b/test/files/run/t4897.check
@@ -0,0 +1 @@
+joepie
diff --git a/test/files/run/t4897.scala b/test/files/run/t4897.scala
new file mode 100644
index 0000000000..a2ec3de37f
--- /dev/null
+++ b/test/files/run/t4897.scala
@@ -0,0 +1,10 @@
+class CSuper {
+ object A
+}
+class C extends CSuper {
+ def f = (A: AnyRef) match { case _: A.type => "joepie" }
+}
+
+object Test extends C with App {
+ println(f)
+} \ No newline at end of file
diff --git a/test/files/run/t5158.check b/test/files/run/t5158.check
new file mode 100644
index 0000000000..573541ac97
--- /dev/null
+++ b/test/files/run/t5158.check
@@ -0,0 +1 @@
+0
diff --git a/test/files/run/t5158.scala b/test/files/run/t5158.scala
new file mode 100644
index 0000000000..3028ffa9e0
--- /dev/null
+++ b/test/files/run/t5158.scala
@@ -0,0 +1,17 @@
+case class B(var x: Int) {
+ def succ() {
+ x = x + 1
+ }
+}
+
+object Test {
+ def main(args: Array[String]) {
+ val b = B(0)
+ b match {
+ case B(x) =>
+ //println(x)
+ b.succ()
+ println(x)
+ }
+ }
+} \ No newline at end of file
diff --git a/test/files/run/t5385.check b/test/files/run/t5385.check
new file mode 100644
index 0000000000..1df74fcfb5
--- /dev/null
+++ b/test/files/run/t5385.check
@@ -0,0 +1,8 @@
+[0:9] class Azz
+[0:9] class Bzz
+[0:9] class Czz
+[0:9] class Dzz
+[0:11] class Ezz
+[0:11] class Fzz
+[0:13] class Gzz
+[0:13] class Hzz
diff --git a/test/files/run/t5385.scala b/test/files/run/t5385.scala
new file mode 100644
index 0000000000..b803897e71
--- /dev/null
+++ b/test/files/run/t5385.scala
@@ -0,0 +1,16 @@
+import scala.tools.partest._
+
+object Test extends CompilerTest {
+ import global._
+ override def extraSettings = super.extraSettings + " -Yrangepos"
+ override def sources = List(
+ "class Azz", "class Bzz ", "class Czz ", "class Dzz\n",
+ "class Ezz{}", "class Fzz{} ", "class Gzz { }", "class Hzz { } "
+ )
+ def check(source: String, unit: CompilationUnit) {
+ unit.body foreach {
+ case cdef: ClassDef => println("%-15s class %s".format(cdef.pos.show, cdef.name))
+ case _ =>
+ }
+ }
+}
diff --git a/test/files/run/t5713/Impls_Macros_1.scala b/test/files/run/t5713/Impls_Macros_1.scala
index d16299a0c8..c041d36523 100644
--- a/test/files/run/t5713/Impls_Macros_1.scala
+++ b/test/files/run/t5713/Impls_Macros_1.scala
@@ -16,13 +16,13 @@ private object LoggerMacros {
type LoggerContext = Context { type PrefixType = Logger.type }
def error(c: LoggerContext)(message: c.Expr[String]): c.Expr[Unit] =
- log(c)(c.reify(Level.Error), message)
+ log(c)(c.universe.reify(Level.Error), message)
private def log(c: LoggerContext)(level: c.Expr[Level.Value], message: c.Expr[String]): c.Expr[Unit] =
// was: if (level.splice.id < 4) // TODO Remove hack!
if (c.eval(level).id < 4) // TODO Remove hack!
- c.reify(())
+ c.universe.reify(())
else {
- c.reify(println(message.splice))
+ c.universe.reify(println(message.splice))
}
} \ No newline at end of file
diff --git a/test/files/run/t5856.scala b/test/files/run/t5856.scala
new file mode 100644
index 0000000000..d1e9bd6e58
--- /dev/null
+++ b/test/files/run/t5856.scala
@@ -0,0 +1,10 @@
+object Test extends App {
+ override def toString = "Test"
+
+ assert(s"$this" == "Test")
+ assert(s"$this$this" == "TestTest")
+ assert(s"$this$$" == "Test$")
+ assert(s"$this.##" == "Test.##")
+ assert(s"$this.toString" == "Test.toString")
+ assert(s"$this=THIS" == "Test=THIS")
+} \ No newline at end of file
diff --git a/test/files/run/t5937.scala b/test/files/run/t5937.scala
new file mode 100644
index 0000000000..e5bf6617af
--- /dev/null
+++ b/test/files/run/t5937.scala
@@ -0,0 +1,12 @@
+
+
+
+import collection._
+
+
+
+object Test extends App {
+
+ val list: List[Int] = (immutable.Vector(1, 2, 3) :+ 4)(breakOut)
+
+}
diff --git a/test/files/run/t6070.check b/test/files/run/t6070.check
new file mode 100644
index 0000000000..00750edc07
--- /dev/null
+++ b/test/files/run/t6070.check
@@ -0,0 +1 @@
+3
diff --git a/test/files/run/t6070.scala b/test/files/run/t6070.scala
new file mode 100644
index 0000000000..b6af48ef21
--- /dev/null
+++ b/test/files/run/t6070.scala
@@ -0,0 +1,36 @@
+abstract class Bomb {
+ type T
+ val x: T
+
+ def size(that: T): Int
+}
+
+class StringBomb extends Bomb {
+ type T = String
+ val x = "abc"
+ def size(that: String): Int = that.length
+}
+
+class IntBomb extends Bomb {
+ type T = Int
+ val x = 10
+
+ def size(that: Int) = x + that
+}
+
+case class Mean(var bomb: Bomb)
+
+object Test extends App {
+ def foo(x: Mean) = x match {
+ case Mean(b) =>
+ // BUG: b is assumed to be a stable identifier, but it can actually be mutated
+ println(b.size({ mutate(); b.x }))
+ }
+
+ def mutate() {
+ m.bomb = new IntBomb
+ }
+
+ val m = Mean(new StringBomb)
+ foo(m) // should print 3
+} \ No newline at end of file
diff --git a/test/files/run/t6086-repl.check b/test/files/run/t6086-repl.check
new file mode 100644
index 0000000000..f868aa18d0
--- /dev/null
+++ b/test/files/run/t6086-repl.check
@@ -0,0 +1,12 @@
+Type in expressions to have them evaluated.
+Type :help for more information.
+
+scala>
+
+scala> case class X(s: String)
+defined class X
+
+scala> scala.reflect.runtime.universe.typeOf[X]
+res0: reflect.runtime.universe.Type = X
+
+scala>
diff --git a/test/files/run/t6086-repl.scala b/test/files/run/t6086-repl.scala
new file mode 100644
index 0000000000..87f94ec9f6
--- /dev/null
+++ b/test/files/run/t6086-repl.scala
@@ -0,0 +1,8 @@
+import scala.tools.partest.ReplTest
+
+object Test extends ReplTest {
+ def code = """
+ |case class X(s: String)
+ |scala.reflect.runtime.universe.typeOf[X]
+ |""".stripMargin
+}
diff --git a/test/files/run/t6086-vanilla.check b/test/files/run/t6086-vanilla.check
new file mode 100644
index 0000000000..fd66be08d0
--- /dev/null
+++ b/test/files/run/t6086-vanilla.check
@@ -0,0 +1 @@
+X
diff --git a/test/files/run/t6086-vanilla.scala b/test/files/run/t6086-vanilla.scala
new file mode 100644
index 0000000000..b4de581ad5
--- /dev/null
+++ b/test/files/run/t6086-vanilla.scala
@@ -0,0 +1,6 @@
+case class X(s: String)
+
+object Test extends App {
+ import scala.reflect.runtime.universe._
+ println(typeOf[X])
+} \ No newline at end of file
diff --git a/test/files/run/t6089.check b/test/files/run/t6089.check
new file mode 100644
index 0000000000..a8d4424106
--- /dev/null
+++ b/test/files/run/t6089.check
@@ -0,0 +1 @@
+scala.MatchError: Foo(0) (of class Foo)
diff --git a/test/files/run/t6089.scala b/test/files/run/t6089.scala
new file mode 100644
index 0000000000..c72d7ba792
--- /dev/null
+++ b/test/files/run/t6089.scala
@@ -0,0 +1,13 @@
+case class Foo(x: Int)
+
+object Test {
+ def bippo(result: Boolean): Boolean = result
+ def bungus(m: Foo): Boolean =
+ bippo(m match { case Foo(2) => bungus(m) })
+
+ def main(args: Array[String]): Unit = try {
+ bungus(Foo(0))
+ } catch {
+ case x: MatchError => println(x)
+ }
+} \ No newline at end of file
diff --git a/test/files/run/t6104.check b/test/files/run/t6104.check
new file mode 100644
index 0000000000..9766475a41
--- /dev/null
+++ b/test/files/run/t6104.check
@@ -0,0 +1 @@
+ok
diff --git a/test/files/run/t6104.scala b/test/files/run/t6104.scala
new file mode 100644
index 0000000000..8ab12c7752
--- /dev/null
+++ b/test/files/run/t6104.scala
@@ -0,0 +1,8 @@
+class A { Self =>
+ val ok = "ok"
+ this match {
+ case me@Self => println(me.ok)
+ }
+}
+
+object Test extends A with App \ No newline at end of file
diff --git a/test/files/run/toolbox_typecheck_macrosdisabled2.check b/test/files/run/toolbox_typecheck_macrosdisabled2.check
index 2e1e2696ab..53041e328d 100644
--- a/test/files/run/toolbox_typecheck_macrosdisabled2.check
+++ b/test/files/run/toolbox_typecheck_macrosdisabled2.check
@@ -15,7 +15,7 @@
private def applyImpl[U <: scala.reflect.api.Universe with Singleton]($m$untyped: scala.reflect.base.MirrorOf[U]): scala.reflect.base.Universe#Tree = {
val $u: U = $m$untyped.universe;
val $m: $u.Mirror = $m$untyped.asInstanceOf[$u.Mirror];
- $u.Apply.apply($u.Select.apply($u.Select.apply($u.build.Ident($m.staticModule("scala")), $u.newTermName("Array")), $u.newTermName("apply")), scala.collection.immutable.List.apply[$u.Literal]($u.Literal.apply($u.Constant.apply(2))))
+ $u.Apply.apply($u.Select.apply($u.Select.apply($u.build.Ident($m.staticPackage("scala")), $u.newTermName("Array")), $u.newTermName("apply")), scala.collection.immutable.List.apply[$u.Literal]($u.Literal.apply($u.Constant.apply(2))))
}
};
new $treecreator1()
@@ -28,7 +28,7 @@
def apply[U <: scala.reflect.base.Universe with Singleton]($m$untyped: scala.reflect.base.MirrorOf[U]): U#Type = {
val $u: U = $m$untyped.universe;
val $m: $u.Mirror = $m$untyped.asInstanceOf[$u.Mirror];
- $u.TypeRef.apply($u.ThisType.apply($m.staticModule("scala").asModuleSymbol.moduleClass), $m.staticClass("scala.Array"), scala.collection.immutable.List.apply[$u.Type]($m.staticClass("scala.Int").asTypeSymbol.asTypeConstructor))
+ $u.TypeRef.apply($u.ThisType.apply($m.staticPackage("scala").asModuleSymbol.moduleClass), $m.staticClass("scala.Array"), scala.collection.immutable.List.apply[$u.Type]($m.staticClass("scala.Int").asTypeSymbol.asTypeConstructor))
}
};
new $typecreator2()
diff --git a/test/pending/run/macro-expand-implicit-macro-defeats-type-inference/Impls_1.scala b/test/pending/run/macro-expand-implicit-macro-defeats-type-inference/Impls_1.scala
index 1740f40daf..599ddf5ed9 100644
--- a/test/pending/run/macro-expand-implicit-macro-defeats-type-inference/Impls_1.scala
+++ b/test/pending/run/macro-expand-implicit-macro-defeats-type-inference/Impls_1.scala
@@ -1,7 +1,7 @@
import scala.reflect.makro.Context
object Impls {
- def foo[T: c.TypeTag](c: Context): c.Expr[List[T]] = c.reify {
+ def foo[T: c.TypeTag](c: Context): c.Expr[List[T]] = c.universe.reify {
println("openImplicits are: " + c.literal(c.openImplicits.toString).splice)
println("enclosingImplicits are: " + c.literal(c.enclosingImplicits.toString).splice)
println("typetag is: " + c.literal(c.tag[T].toString).splice)
diff --git a/test/pending/run/macro-reify-array/Macros_1.scala b/test/pending/run/macro-reify-array/Macros_1.scala
index c1bd4187a6..4b4cb05884 100644
--- a/test/pending/run/macro-reify-array/Macros_1.scala
+++ b/test/pending/run/macro-reify-array/Macros_1.scala
@@ -4,7 +4,7 @@ object Macros {
def foo[T](s: String) = macro Impls.foo[T]
object Impls {
- def foo[T: c.TypeTag](c: Ctx)(s: c.Expr[T]) = c.reify {
+ def foo[T: c.TypeTag](c: Ctx)(s: c.Expr[T]) = c.universe.reify {
Array(s.splice)
}
}
diff --git a/test/pending/run/macro-reify-tagful-b/Macros_1.scala b/test/pending/run/macro-reify-tagful-b/Macros_1.scala
index 04cf46d3a5..f730bb51f1 100644
--- a/test/pending/run/macro-reify-tagful-b/Macros_1.scala
+++ b/test/pending/run/macro-reify-tagful-b/Macros_1.scala
@@ -4,7 +4,7 @@ object Macros {
def foo[T](s: T) = macro Impls.foo[List[T]]
object Impls {
- def foo[T: c.TypeTag](c: Ctx)(s: c.Expr[T]) = c.reify {
+ def foo[T: c.TypeTag](c: Ctx)(s: c.Expr[T]) = c.universe.reify {
List(s.splice)
}
}
diff --git a/test/pending/run/macro-reify-tagless-b/Impls_Macros_1.scala b/test/pending/run/macro-reify-tagless-b/Impls_Macros_1.scala
index 04366353eb..2c5079ea54 100644
--- a/test/pending/run/macro-reify-tagless-b/Impls_Macros_1.scala
+++ b/test/pending/run/macro-reify-tagless-b/Impls_Macros_1.scala
@@ -4,7 +4,7 @@ object Macros {
def foo[T](s: T) = macro Impls.foo[List[T]]
object Impls {
- def foo[T](c: Ctx)(s: c.Expr[T]) = c.reify {
+ def foo[T](c: Ctx)(s: c.Expr[T]) = c.universe.reify {
List(s.splice)
}
}
diff --git a/test/pending/run/t5692/Impls_Macros_1.scala b/test/pending/run/t5692/Impls_Macros_1.scala
index f9c1e5f12b..7d0e788bd6 100644
--- a/test/pending/run/t5692/Impls_Macros_1.scala
+++ b/test/pending/run/t5692/Impls_Macros_1.scala
@@ -1,7 +1,7 @@
import scala.reflect.makro.Context
object Impls {
- def impl[A](c: reflect.makro.Context) = c.reify(())
+ def impl[A](c: reflect.makro.Context) = c.universe.reify(())
}
object Macros {
diff --git a/test/pending/run/t5695.check b/test/pending/run/t5695.check
deleted file mode 100644
index d50069ab4f..0000000000
--- a/test/pending/run/t5695.check
+++ /dev/null
@@ -1,2 +0,0 @@
-..
-..
diff --git a/test/pending/run/t5695/part_1.scala b/test/pending/run/t5695/part_1.scala
deleted file mode 100644
index b8e8f8e52f..0000000000
--- a/test/pending/run/t5695/part_1.scala
+++ /dev/null
@@ -1,12 +0,0 @@
-import language.experimental.macros
-import scala.reflect.makro.Context
-
-object Defs {
-
- def mkInt = macro mkIntImpl
- def mkIntImpl(c: Context): c.Expr[Any] = {
- println(c.enclosingApplication)
- c.reify{ 23 }
- }
-
-}
diff --git a/test/pending/run/t5695/part_2.scala b/test/pending/run/t5695/part_2.scala
deleted file mode 100644
index d34219437d..0000000000
--- a/test/pending/run/t5695/part_2.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-import Defs._
-
-object Test extends App {
-
- val i1 = mkInt
- val i2 = identity(mkInt)
-
-}
diff --git a/test/scaladoc/resources/SI-3314-diagrams.scala b/test/scaladoc/resources/SI-3314-diagrams.scala
new file mode 100644
index 0000000000..b80a97b522
--- /dev/null
+++ b/test/scaladoc/resources/SI-3314-diagrams.scala
@@ -0,0 +1,78 @@
+package scala.test.scaladoc {
+
+ /** Check the interaction between SI-3314 and diagrams
+ * - the three enumerations below should get valid content diagrams:
+ * Value
+ * __________/|\__________
+ * / / / | \ \ \
+ * Mon Tue Wed Thu Fri Sat Sun
+ *
+ * - each member should receive an inhertiance diagram:
+ * Value
+ * |
+ * |
+ * {Mon,Tue,Wed,Thu,Fri,Sat,Sun}
+ */
+ package diagrams {
+
+ /** @contentDiagram
+ * @inheritanceDiagram hideDiagram */
+ trait WeekDayTraitWithDiagram extends Enumeration {
+ type WeekDay = Value
+ /** @inheritanceDiagram */
+ object Mon extends WeekDay
+ /** @inheritanceDiagram */
+ object Tue extends WeekDay
+ /** @inheritanceDiagram */
+ object Wed extends WeekDay
+ /** @inheritanceDiagram */
+ object Thu extends WeekDay
+ /** @inheritanceDiagram */
+ object Fri extends WeekDay
+ /** @inheritanceDiagram */
+ object Sat extends WeekDay
+ /** @inheritanceDiagram */
+ object Sun extends WeekDay
+ }
+
+ /** @contentDiagram
+ * @inheritanceDiagram hideDiagram */
+ class WeekDayClassWithDiagram extends Enumeration {
+ type WeekDay = Value
+ /** @inheritanceDiagram */
+ object Mon extends WeekDay
+ /** @inheritanceDiagram */
+ object Tue extends WeekDay
+ /** @inheritanceDiagram */
+ object Wed extends WeekDay
+ /** @inheritanceDiagram */
+ object Thu extends WeekDay
+ /** @inheritanceDiagram */
+ object Fri extends WeekDay
+ /** @inheritanceDiagram */
+ object Sat extends WeekDay
+ /** @inheritanceDiagram */
+ object Sun extends WeekDay
+ }
+
+ /** @contentDiagram
+ * @inheritanceDiagram hideDiagram */
+ object WeekDayObjectWithDiagram extends Enumeration {
+ type WeekDay = Value
+ /** @inheritanceDiagram */
+ object Mon extends WeekDay
+ /** @inheritanceDiagram */
+ object Tue extends WeekDay
+ /** @inheritanceDiagram */
+ object Wed extends WeekDay
+ /** @inheritanceDiagram */
+ object Thu extends WeekDay
+ /** @inheritanceDiagram */
+ object Fri extends WeekDay
+ /** @inheritanceDiagram */
+ object Sat extends WeekDay
+ /** @inheritanceDiagram */
+ object Sun extends WeekDay
+ }
+ }
+} \ No newline at end of file
diff --git a/test/scaladoc/resources/SI-3314.scala b/test/scaladoc/resources/SI-3314.scala
new file mode 100644
index 0000000000..9e0afdce9d
--- /dev/null
+++ b/test/scaladoc/resources/SI-3314.scala
@@ -0,0 +1,85 @@
+package scala.test.scaladoc {
+
+ // testing inherited <documented> templates (Enum.Value is included in the source, thus is documented in scaladoc)
+ package test1 {
+ class Enum {
+ abstract class Value
+ class Val extends Value
+ def Value(): Value = new Val
+ }
+
+ object Constants extends Enum {
+ def a = Value
+ }
+ }
+
+ // testing inherited <not documented> templates (scala.Enumeration.Value is taken from the library, thus is not
+ // documented in the scaladoc pages -- but should be inherited to make things clear!)
+ package test2 {
+ trait WeekDayTrait extends Enumeration {
+ type WeekDay = Value
+ val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
+ }
+
+ class WeekDayClass extends Enumeration {
+ type WeekDay = Value
+ val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
+ }
+
+ object WeekDayObject extends Enumeration {
+ type WeekDay = Value
+ val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
+ }
+
+ object UserObject {
+ def isWorkingDay1(d: scala.test.scaladoc.test2.WeekDayClass#Value) = false
+ def isWorkingDay2(d: scala.test.scaladoc.test2.WeekDayClass#WeekDay) = false
+ def isWorkingDay3(d: scala.test.scaladoc.test2.WeekDayTrait#Value) = false
+ def isWorkingDay4(d: scala.test.scaladoc.test2.WeekDayTrait#WeekDay) = false
+ def isWorkingDay5(d: scala.test.scaladoc.test2.WeekDayObject.Value) = false
+ def isWorkingDay6(d: scala.test.scaladoc.test2.WeekDayObject.WeekDay) = false
+ import WeekDayObject._
+ def isWorkingDay7(d: Value) = ! (d == Sat || d == Sun)
+ def isWorkingDay8(d: WeekDay) = ! (d == Sat || d == Sun)
+ def isWorkingDay9(d: WeekDayObject.Value) = ! (d == Sat || d == Sun)
+ }
+
+ class UserClass {
+ def isWorkingDay1(d: scala.test.scaladoc.test2.WeekDayClass#Value) = false
+ def isWorkingDay2(d: scala.test.scaladoc.test2.WeekDayClass#WeekDay) = false
+ def isWorkingDay3(d: scala.test.scaladoc.test2.WeekDayTrait#Value) = false
+ def isWorkingDay4(d: scala.test.scaladoc.test2.WeekDayTrait#WeekDay) = false
+ def isWorkingDay5(d: scala.test.scaladoc.test2.WeekDayObject.Value) = false
+ def isWorkingDay6(d: scala.test.scaladoc.test2.WeekDayObject.WeekDay) = false
+ import WeekDayObject._
+ def isWorkingDay7(d: Value) = ! (d == Sat || d == Sun)
+ def isWorkingDay8(d: WeekDay) = ! (d == Sat || d == Sun)
+ def isWorkingDay9(d: WeekDayObject.Value) = ! (d == Sat || d == Sun)
+ }
+
+ trait UserTrait {
+ def isWorkingDay1(d: scala.test.scaladoc.test2.WeekDayClass#Value) = false
+ def isWorkingDay2(d: scala.test.scaladoc.test2.WeekDayClass#WeekDay) = false
+ def isWorkingDay3(d: scala.test.scaladoc.test2.WeekDayTrait#Value) = false
+ def isWorkingDay4(d: scala.test.scaladoc.test2.WeekDayTrait#WeekDay) = false
+ def isWorkingDay5(d: scala.test.scaladoc.test2.WeekDayObject.Value) = false
+ def isWorkingDay6(d: scala.test.scaladoc.test2.WeekDayObject.WeekDay) = false
+ import WeekDayObject._
+ def isWorkingDay7(d: Value) = ! (d == Sat || d == Sun)
+ def isWorkingDay8(d: WeekDay) = ! (d == Sat || d == Sun)
+ def isWorkingDay9(d: WeekDayObject.Value) = ! (d == Sat || d == Sun)
+ }
+ }
+
+ // testing type lambdas and useless prefixes (should be referenced as T instead of foo.T in the first example)
+ package test3 {
+ import language.higherKinds
+ object `package` {
+ trait T
+ trait A
+ trait X
+ def foo[T](x: T) = 7
+ def bar[A](x: ({type Lambda[X] <: Either[A, X]})#Lambda[String]) = 5
+ }
+ }
+}
diff --git a/test/scaladoc/resources/SI-4360.scala b/test/scaladoc/resources/SI-4360.scala
new file mode 100644
index 0000000000..8e8b96afd5
--- /dev/null
+++ b/test/scaladoc/resources/SI-4360.scala
@@ -0,0 +1,42 @@
+package scala.test.scaladoc.prefix {
+ package pack1 {
+
+ class A {
+ class Z
+ }
+
+ class B extends A
+
+ package a {
+ class C
+ }
+
+ package b {
+ class C
+ }
+
+ package c {
+ class C
+
+ class L extends pack2.Z
+
+ class TEST {
+ // test inherited classes
+ def fooCA(x: pack1.A#Z) = 1
+ def fooCB(x: pack1.B#Z) = 1
+ def fooCS(x: pack2.Z#Z) = 1
+ def fooCL(x: L#Z) = 1
+ // test in packages
+ def fooPA(x: pack1.a.C) = 1
+ def fooPB(x: pack1.b.C) = 1
+ def fooPC(x: pack1.c.C) = 1
+ }
+
+ class A extends pack1.A
+ }
+ }
+
+ package pack2 {
+ class Z extends pack1.A
+ }
+} \ No newline at end of file
diff --git a/test/scaladoc/resources/SI-5558.scala b/test/scaladoc/resources/SI-5558.scala
new file mode 100644
index 0000000000..6523438b86
--- /dev/null
+++ b/test/scaladoc/resources/SI-5558.scala
@@ -0,0 +1,6 @@
+package test {
+ class T
+ object `package` {
+ def foo = ???
+ }
+}
diff --git a/test/scaladoc/resources/SI-5784.scala b/test/scaladoc/resources/SI-5784.scala
new file mode 100644
index 0000000000..3731d4998c
--- /dev/null
+++ b/test/scaladoc/resources/SI-5784.scala
@@ -0,0 +1,28 @@
+package test.templates {
+ object `package` {
+ /** @template */
+ type String = java.lang.String
+ val String = new StringCompanion
+ class StringCompanion { def boo = ??? }
+ }
+
+ /** @contentDiagram */
+ trait Base {
+ /** @documentable */
+ type String = test.templates.String
+ /** @template
+ * @inheritanceDiagram */
+ type T <: Foo
+ val T: FooExtractor
+ trait Foo { def foo: Int }
+ trait FooExtractor { def apply(foo: Int); def unapply(t: Foo): Option[Int] }
+ }
+
+ /** @contentDiagram */
+ trait Api extends Base {
+ /** @documentable
+ * @inheritanceDiagram */
+ override type T <: FooApi
+ trait FooApi extends Foo { def bar: String }
+ }
+}
diff --git a/test/scaladoc/resources/SI_4676.scala b/test/scaladoc/resources/SI_4676.scala
deleted file mode 100644
index 00c0fc7ea9..0000000000
--- a/test/scaladoc/resources/SI_4676.scala
+++ /dev/null
@@ -1,4 +0,0 @@
-class SI_4676 {
- type SS = (String,String)
- def x(ss: SS): Int = 3
-}
diff --git a/test/scaladoc/resources/Trac3484.scala b/test/scaladoc/resources/Trac3484.scala
deleted file mode 100644
index 9656ec268d..0000000000
--- a/test/scaladoc/resources/Trac3484.scala
+++ /dev/null
@@ -1,27 +0,0 @@
-class cbf[A, B, C]
-
-/**
- * @define Coll Traversable
- * @define bfreturn $Coll
- */
-class Collection[A] {
- /** What map does...
- *
- * $bfreturn
- * @usecase def map[B](f: A => B): $bfreturn[B]
- *
- */
- def map[B, That](f: A => B)(implicit fact: cbf[Collection[A], B, That]) =
- null
-}
-
-/**
- * @define b John
- * @define a Mister $b
- */
-class SR704 {
- /**
- * Hello $a.
- */
- def foo = 123
-}
diff --git a/test/scaladoc/resources/doc-root/AnyRef.scala b/test/scaladoc/resources/doc-root/AnyRef.scala
index 1eefb0c806..7d8b9f9e76 100644
--- a/test/scaladoc/resources/doc-root/AnyRef.scala
+++ b/test/scaladoc/resources/doc-root/AnyRef.scala
@@ -10,6 +10,7 @@ package scala
/** Class `AnyRef` is the root class of all ''reference types''.
* All types except the value types descend from this class.
+ * @template
*/
trait AnyRef extends Any {
diff --git a/test/scaladoc/resources/implicits-known-type-classes-res.scala b/test/scaladoc/resources/implicits-known-type-classes-res.scala
new file mode 100644
index 0000000000..9ad652947d
--- /dev/null
+++ b/test/scaladoc/resources/implicits-known-type-classes-res.scala
@@ -0,0 +1,38 @@
+/** Tests the "known type classes" feature of scaladoc implicits
+ * if the test fails, please update the correct qualified name of
+ * the type class in src/compiler/scala/tools/nsc/doc/Settings.scala
+ * in the knownTypeClasses map. Thank you! */
+package scala.test.scaladoc.implicits.typeclasses {
+ class A[T]
+ object A {
+ import language.implicitConversions
+ import scala.reflect.{ClassTag, TypeTag}
+ implicit def convertNumeric [T: Numeric] (a: A[T]) = new B(implicitly[Numeric[T]])
+ implicit def convertIntegral [T: Integral] (a: A[T]) = new B(implicitly[Integral[T]])
+ implicit def convertFractional [T: Fractional] (a: A[T]) = new B(implicitly[Fractional[T]])
+ implicit def convertManifest [T: Manifest] (a: A[T]) = new B(implicitly[Manifest[T]])
+ implicit def convertClassManifest [T: ClassManifest] (a: A[T]) = new B(implicitly[ClassManifest[T]])
+ implicit def convertOptManifest [T: OptManifest] (a: A[T]) = new B(implicitly[OptManifest[T]])
+ implicit def convertClassTag [T: ClassTag] (a: A[T]) = new B(implicitly[ClassTag[T]])
+ implicit def convertTypeTag [T: TypeTag] (a: A[T]) = new B(implicitly[TypeTag[T]])
+ type K[X] = Numeric[X]
+ type L[X] = Integral[X]
+ type M[X] = Fractional[X]
+ type N[X] = Manifest[X]
+ type O[X] = ClassManifest[X]
+ type P[X] = OptManifest[X]
+ type Q[X] = ClassTag[X]
+ type R[X] = TypeTag[X]
+ implicit def convertK [T: K] (a: A[T]) = new B(implicitly[K[T]])
+ implicit def convertL [T: L] (a: A[T]) = new B(implicitly[L[T]])
+ implicit def convertM [T: M] (a: A[T]) = new B(implicitly[M[T]])
+ implicit def convertN [T: N] (a: A[T]) = new B(implicitly[N[T]])
+ implicit def convertO [T: O] (a: A[T]) = new B(implicitly[O[T]])
+ implicit def convertP [T: P] (a: A[T]) = new B(implicitly[P[T]])
+ implicit def convertQ [T: Q] (a: A[T]) = new B(implicitly[Q[T]])
+ implicit def convertR [T: R] (a: A[T]) = new B(implicitly[R[T]])
+ }
+ class B[T](t: T) {
+ def typeClass: T = t
+ }
+} \ No newline at end of file
diff --git a/test/scaladoc/resources/implicits-scopes-res.scala b/test/scaladoc/resources/implicits-scopes-res.scala
index aaeb43f95b..c675a645bd 100644
--- a/test/scaladoc/resources/implicits-scopes-res.scala
+++ b/test/scaladoc/resources/implicits-scopes-res.scala
@@ -22,7 +22,7 @@ package test2 {
package classes {
class A
class B { def b = "" }
- object test { /* (new A).b won't compile */ }
+ object test { (new A).b }
}
}
diff --git a/test/scaladoc/resources/links.scala b/test/scaladoc/resources/links.scala
new file mode 100644
index 0000000000..679d0b0dce
--- /dev/null
+++ b/test/scaladoc/resources/links.scala
@@ -0,0 +1,57 @@
+// that would be:
+// SI-5079 "Scaladoc can't link to an object (only a class or trait)"
+// SI-4497 "Links in ScalaDoc - Spec and implementation unsufficient"
+// SI-4224 "Wiki-links should support method targets"
+// SI-3695 "support non-fully-qualified type links in scaladoc comments"
+package scala.test.scaladoc.links {
+ import language.higherKinds
+ class C
+
+ trait Target {
+ type T
+ type S = String
+ class C
+ def foo(i: Int) = 2
+ def foo(s: String) = 3
+ def foo[A[_]](x: A[String]) = 5
+ def foo[A[_[_]]](x: A[List]) = 6
+ val bar: Boolean
+ def baz(c: scala.test.scaladoc.links.C) = 7
+ }
+
+ object Target {
+ type T = Int => Int
+ type S = Int
+ class C
+ def foo(i: Int) = 2
+ def foo(z: String) = 3
+ def foo[A[_]](x: A[String]) = 5
+ def foo[A[_[_]]](x: A[List]) = 6
+ val bar: Boolean = false
+ val onlyInObject = 1
+ def baz(c: scala.test.scaladoc.links.C) = 7
+ }
+
+ /**
+ * Links to the trait:
+ * - [[scala.test.scaladoc.links.Target!.T trait Target -> type T]]
+ * - [[test.scaladoc.links.Target!.S trait Target -> type S]]
+ * - [[scaladoc.links.Target!.foo(Int)* trait Target -> def foo]]
+ * - [[links.Target!.bar trait Target -> def bar]]
+ * - [[[[Target!.foo[A[_[_]]]* trait Target -> def foo with 3 nested tparams]]]] (should exercise nested parens)
+ * - [[Target$.T object Target -> type T]]
+ * - [[Target$.S object Target -> type S]]
+ * - [[Target$.foo(Str* object Target -> def foo]]
+ * - [[Target$.bar object Target -> def bar]]
+ * - [[[[Target$.foo[A[_[_]]]* trait Target -> def foo with 3 nested tparams]]]] (should exercise nested parens)
+ * - [[Target.onlyInObject object Target -> def foo]] (should find the object)
+ * - [[Target$.C object Target -> class C]] (should link directly to C, not as a member)
+ * - [[Target!.C trait Target -> class C]] (should link directly to C, not as a member)
+ * - [[Target$.baz(links\.C)* object Target -> def baz]] (should use dots in prefix)
+ * - [[Target!.baz(links\.C)* trait Target -> def baz]] (should use dots in prefix)
+ * - [[localMethod object TEST -> localMethod]] (should use the current template to resolve link instead of inTpl, that's the package)
+ */
+ object TEST {
+ def localMethod = 3
+ }
+}
diff --git a/test/scaladoc/resources/package-object-res.scala b/test/scaladoc/resources/package-object-res.scala
index 17d5c0a499..f1f714dd1f 100644
--- a/test/scaladoc/resources/package-object-res.scala
+++ b/test/scaladoc/resources/package-object-res.scala
@@ -1,4 +1,4 @@
-/** This package have A and B.
+/** This package has A and B.
*/
package test {
trait A { def hi = "hello" }
diff --git a/test/scaladoc/run/SI-3314-diagrams.check b/test/scaladoc/run/SI-3314-diagrams.check
new file mode 100644
index 0000000000..619c56180b
--- /dev/null
+++ b/test/scaladoc/run/SI-3314-diagrams.check
@@ -0,0 +1 @@
+Done.
diff --git a/test/scaladoc/run/SI-3314-diagrams.scala b/test/scaladoc/run/SI-3314-diagrams.scala
new file mode 100644
index 0000000000..050c6e7f48
--- /dev/null
+++ b/test/scaladoc/run/SI-3314-diagrams.scala
@@ -0,0 +1,28 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.partest.ScaladocModelTest
+
+object Test extends ScaladocModelTest {
+
+ override def resourceFile = "SI-3314-diagrams.scala"
+
+ // no need for special settings
+ def scaladocSettings = "-diagrams"
+
+ def testModel(rootPackage: Package) = {
+ // get the quick access implicit defs in scope (_package(s), _class(es), _trait(s), object(s) _method(s), _value(s))
+ import access._
+
+ // just need to check the member exists, access methods will throw an error if there's a problem
+ val base = rootPackage._package("scala")._package("test")._package("scaladoc")
+
+ val diagrams = base._package("diagrams")
+ val templates = List(diagrams._trait("WeekDayTraitWithDiagram"), diagrams._class("WeekDayClassWithDiagram"), diagrams._object("WeekDayObjectWithDiagram"))
+
+ for (template <- templates) {
+ testDiagram(template, template.contentDiagram, 8, 7)
+ val subtemplates = List("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun").map(template._object(_))
+ for (subtemplate <- subtemplates)
+ testDiagram(subtemplate, subtemplate.inheritanceDiagram, 2, 1)
+ }
+ }
+} \ No newline at end of file
diff --git a/test/scaladoc/run/SI-3314.check b/test/scaladoc/run/SI-3314.check
new file mode 100644
index 0000000000..619c56180b
--- /dev/null
+++ b/test/scaladoc/run/SI-3314.check
@@ -0,0 +1 @@
+Done.
diff --git a/test/scaladoc/run/SI-3314.scala b/test/scaladoc/run/SI-3314.scala
new file mode 100644
index 0000000000..fe220b08af
--- /dev/null
+++ b/test/scaladoc/run/SI-3314.scala
@@ -0,0 +1,91 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.partest.ScaladocModelTest
+
+object Test extends ScaladocModelTest {
+
+ override def resourceFile = "SI-3314.scala"
+
+ // no need for special settings
+ def scaladocSettings = "-feature"
+
+ def testModel(rootPackage: Package) = {
+ // get the quick access implicit defs in scope (_package(s), _class(es), _trait(s), object(s) _method(s), _value(s))
+ import access._
+
+ // just need to check the member exists, access methods will throw an error if there's a problem
+ val base = rootPackage._package("scala")._package("test")._package("scaladoc")
+
+
+
+ // test1
+
+ val test1 = base._package("test1")
+ val test1Value = test1._class("Enum")._method("Value").resultType
+ assert(test1Value.name == "Value", test1Value.name + " == Value")
+ assert(test1Value.refEntity.size == 1, test1Value.refEntity.size + " == 1")
+
+ val test1Constants = test1._object("Constants")._method("a").resultType
+ assert(test1Constants.name == "Value", test1Constants.name + " == Value")
+ assert(test1Constants.refEntity.size == 1, test1Constants.refEntity.size + " == 1")
+ assert(test1Constants.refEntity(0)._1 == LinkToMember(test1._object("Constants")._class("Value"), test1._object("Constants")),
+ test1Constants.refEntity(0)._1 + " == LinkToMember(test1.Enum.Value)")
+
+
+ // test2
+
+ val test2 = base._package("test2")
+ def testDefinition(doc: DocTemplateEntity) = {
+ for (day <- List("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun")) {
+ assert(doc._value(day).resultType.name == "Value",
+ doc._value(day).resultType.name + " == Value")
+ assert(doc._value(day).resultType.refEntity.size == 1,
+ doc._value(day).resultType.refEntity.size + " == 1")
+ assert(doc._value(day).resultType.refEntity(0)._1 == LinkToMember(doc._classMbr("Value"), doc),
+ doc._value(day).resultType.refEntity(0)._1 + " == LinkToMember(" + doc.qualifiedName + ".Value)")
+ }
+ }
+ testDefinition(test2._trait("WeekDayTrait"))
+ testDefinition(test2._class("WeekDayClass"))
+ testDefinition(test2._object("WeekDayObject"))
+
+ def testUsage(doc: DocTemplateEntity) = {
+ val ValueInClass = test2._class("WeekDayClass")._classMbr("Value")
+ val ValueInTrait = test2._trait("WeekDayTrait")._classMbr("Value")
+ val ValueInObject = test2._object("WeekDayObject")._classMbr("Value")
+ val WeekDayInObject = test2._object("WeekDayObject")._member("WeekDay")
+
+ val expected = List(
+ ("isWorkingDay1", "WeekDayClass.Value", ValueInClass),
+ ("isWorkingDay2", "WeekDayClass.Value", ValueInClass),
+ ("isWorkingDay3", "WeekDayTrait.Value", ValueInTrait),
+ ("isWorkingDay4", "WeekDayTrait.Value", ValueInTrait),
+ ("isWorkingDay5", "WeekDayObject.Value", ValueInObject),
+ ("isWorkingDay6", "WeekDay", WeekDayInObject),
+ ("isWorkingDay7", "WeekDayObject.Value", ValueInObject),
+ ("isWorkingDay8", "WeekDay", WeekDayInObject),
+ ("isWorkingDay9", "WeekDayObject.Value", ValueInObject))
+
+ for ((method, name, ref) <- expected) {
+ assert(doc._method(method).valueParams(0)(0).resultType.name == name,
+ doc._method(method).valueParams(0)(0).resultType.name + " == " + name + " (in " + doc + "." + method + ")")
+ assert(doc._method(method).valueParams(0)(0).resultType.refEntity.size == 1,
+ doc._method(method).valueParams(0)(0).resultType.refEntity.size + " == " + 1 + " (in " + doc + "." + method + ")")
+ assert(doc._method(method).valueParams(0)(0).resultType.refEntity(0)._1 == LinkToMember(ref, ref.inTemplate),
+ doc._method(method).valueParams(0)(0).resultType.refEntity(0)._1 + " == LinkToMember(" + ref.qualifiedName + ") (in " + doc + "." + method + ")")
+ }
+ }
+ testUsage(test2._object("UserObject"))
+ testUsage(test2._class("UserClass"))
+ testUsage(test2._trait("UserTrait"))
+
+
+ // test3
+ val test3 = base._package("test3")
+ val foo = test3._method("foo")
+ assert(foo.valueParams(0)(0).resultType.name == "T",
+ foo.valueParams(0)(0).resultType.name + " == T")
+ val bar = test3._method("bar")
+ assert(bar.valueParams(0)(0).resultType.name == "(AnyRef { type Lambda[X] <: Either[A,X] })#Lambda[String]",
+ bar.valueParams(0)(0).resultType.name + " == (AnyRef { type Lambda[X] <: Either[A,X] })#Lambda[String]")
+ }
+} \ No newline at end of file
diff --git a/test/scaladoc/run/SI-3448.check b/test/scaladoc/run/SI-3448.check
new file mode 100644
index 0000000000..619c56180b
--- /dev/null
+++ b/test/scaladoc/run/SI-3448.check
@@ -0,0 +1 @@
+Done.
diff --git a/test/scaladoc/run/SI-3448.scala b/test/scaladoc/run/SI-3448.scala
new file mode 100644
index 0000000000..a2d3f59596
--- /dev/null
+++ b/test/scaladoc/run/SI-3448.scala
@@ -0,0 +1,38 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.partest.ScaladocModelTest
+
+object Test extends ScaladocModelTest {
+
+ // Working around the fact that usecases have the form Coll[T] and not Coll[T, U], as required by Map
+ override def code = """
+ /**
+ * @define Coll C[T]
+ */
+ class C[T] {
+ /**
+ * @usecase def foo[T]: $Coll[T]
+ */
+ def foo[T: Numeric]: C[T]
+ }
+
+
+ /**
+ * @define Coll D1[T]
+ */
+ class D[U, T] extends C[T] {
+ protected type D1[Z] = D[U, Z]
+ }
+ """
+
+ // no need for special settings
+ def scaladocSettings = ""
+
+ def testModel(rootPackage: Package) = {
+ // get the quick access implicit defs in scope (_package(s), _class(es), _trait(s), object(s) _method(s), _value(s))
+ import access._
+
+ // just need to check the member exists, access methods will throw an error if there's a problem
+ assert(rootPackage._class("D")._method("foo").resultType.name == "D[U, T]",
+ rootPackage._class("D")._method("foo").resultType.name + " == D[U, T]")
+ }
+} \ No newline at end of file
diff --git a/test/scaladoc/run/SI-3484.check b/test/scaladoc/run/SI-3484.check
new file mode 100644
index 0000000000..619c56180b
--- /dev/null
+++ b/test/scaladoc/run/SI-3484.check
@@ -0,0 +1 @@
+Done.
diff --git a/test/scaladoc/run/SI-3484.scala b/test/scaladoc/run/SI-3484.scala
new file mode 100644
index 0000000000..297aebee8f
--- /dev/null
+++ b/test/scaladoc/run/SI-3484.scala
@@ -0,0 +1,52 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.nsc.doc.model.diagram._
+import scala.tools.partest.ScaladocModelTest
+
+object Test extends ScaladocModelTest {
+
+ override def code = """
+ class cbf[A, B, C]
+
+ /**
+ * @define Coll Collection
+ * @define bfreturn $Coll
+ */
+ class Collection[A] {
+ /** What map does...
+ *
+ * $bfreturn
+ * @usecase def map[B](f: A => B): $bfreturn[B]
+ *
+ */
+ def map[B, That](f: A => B)(implicit fact: cbf[Collection[A], B, That]) =
+ null
+ }
+
+ /**
+ * @define b John
+ * @define a Mister $b
+ */
+ class SR704 {
+ /**
+ * Hello $a.
+ */
+ def foo = 123
+ }
+ """
+
+ // diagrams must be started. In case there's an error with dot, it should not report anything
+ def scaladocSettings = ""
+
+ def testModel(rootPackage: Package) = {
+ // get the quick access implicit defs in scope (_package(s), _class(es), _trait(s), object(s) _method(s), _value(s))
+ import access._
+
+ // check correct expansion of the use case signature
+ val map = rootPackage._class("Collection")._method("map")
+ assert(map.resultType.name == "Collection[B]", map.resultType.name + " == Traversable[B]")
+
+ val foo = rootPackage._class("SR704")._method("foo")
+ assert(extractCommentText(foo.comment.get).contains("Hello Mister John."),
+ extractCommentText(foo.comment.get) + ".contains(Hello Mister John.)")
+ }
+} \ No newline at end of file
diff --git a/test/scaladoc/run/SI-4324.check b/test/scaladoc/run/SI-4324.check
new file mode 100644
index 0000000000..619c56180b
--- /dev/null
+++ b/test/scaladoc/run/SI-4324.check
@@ -0,0 +1 @@
+Done.
diff --git a/test/scaladoc/run/SI-4324.scala b/test/scaladoc/run/SI-4324.scala
new file mode 100644
index 0000000000..686a133dc0
--- /dev/null
+++ b/test/scaladoc/run/SI-4324.scala
@@ -0,0 +1,24 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.partest.ScaladocModelTest
+
+object Test extends ScaladocModelTest {
+
+ override def code = """
+ case class Test4324(arg11: String, arg12: Int)(arg21: String, arg22: Int)(arg31: Int, arg32: String)
+ """
+
+ // no need for special settings
+ def scaladocSettings = ""
+
+ def testModel(rootPackage: Package) = {
+ // get the quick access implicit defs in scope (_package(s), _class(es), _trait(s), object(s) _method(s), _value(s))
+ import access._
+
+ // just need to check the member exists, access methods will throw an error if there's a problem
+ rootPackage._class("Test4324").asInstanceOf[Class].valueParams match {
+ case List(List(arg11, arg12), List(arg21, arg22), List(arg31, arg32)) => //yeeey, do nothing
+ case other =>
+ assert(false, "Incorrect valueParams generated: " + other + " instead of (arg11, arg12)(arg21, arg22)(arg31, arg32)")
+ }
+ }
+} \ No newline at end of file
diff --git a/test/scaladoc/run/SI-4360.check b/test/scaladoc/run/SI-4360.check
new file mode 100644
index 0000000000..619c56180b
--- /dev/null
+++ b/test/scaladoc/run/SI-4360.check
@@ -0,0 +1 @@
+Done.
diff --git a/test/scaladoc/run/SI-4360.scala b/test/scaladoc/run/SI-4360.scala
new file mode 100644
index 0000000000..3abc61c267
--- /dev/null
+++ b/test/scaladoc/run/SI-4360.scala
@@ -0,0 +1,48 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.partest.ScaladocModelTest
+
+object Test extends ScaladocModelTest {
+
+ override def resourceFile = "SI-4360.scala"
+
+ // no need for special settings
+ def scaladocSettings = ""
+
+ def testModel(rootPackage: Package) = {
+ // get the quick access implicit defs in scope (_package(s), _class(es), _trait(s), object(s) _method(s), _value(s))
+ import access._
+
+ // just need to check the member exists, access methods will throw an error if there's a problem
+ val base = rootPackage._package("scala")._package("test")._package("scaladoc")._package("prefix")
+
+ val TEST = base._package("pack1")._package("c")._class("TEST")
+ val fooCA = TEST._method("fooCA")
+ val fooCB = TEST._method("fooCB")
+ val fooCS = TEST._method("fooCS")
+ val fooCL = TEST._method("fooCL")
+ val fooPA = TEST._method("fooPA")
+ val fooPB = TEST._method("fooPB")
+ val fooPC = TEST._method("fooPC")
+
+ val expected = List(
+ (fooCA, "Z", 1),
+ (fooCB, "B.Z", 1),
+ (fooCS, "pack2.Z.Z", 1),
+ (fooCL, "L.Z", 1),
+ (fooPA, "a.C", 1),
+ (fooPB, "b.C", 1),
+ (fooPC, "C", 1)
+ )
+
+ for ((method, name, refs) <- expected) {
+ assert(method.valueParams(0)(0).resultType.name == name,
+ method.valueParams(0)(0).resultType.name + " == " + name + " (in " + method.qualifiedName + ")")
+ assert(method.valueParams(0)(0).resultType.refEntity.size == refs,
+ method.valueParams(0)(0).resultType.refEntity.size + " == " + refs + " (in " + method.qualifiedName + ")")
+ }
+
+ val A = base._package("pack1")._package("c")._class("A")
+ assert(A.linearizationTypes(0).name == "pack1.A", A.linearizationTypes(0).name + " == pack1.A")
+ assert(A.linearizationTypes(0).refEntity.size == 1, A.linearizationTypes(0).refEntity.size + " == 1")
+ }
+} \ No newline at end of file
diff --git a/test/scaladoc/run/SI-4676.check b/test/scaladoc/run/SI-4676.check
new file mode 100644
index 0000000000..619c56180b
--- /dev/null
+++ b/test/scaladoc/run/SI-4676.check
@@ -0,0 +1 @@
+Done.
diff --git a/test/scaladoc/run/SI-4676.scala b/test/scaladoc/run/SI-4676.scala
new file mode 100644
index 0000000000..b83a59a472
--- /dev/null
+++ b/test/scaladoc/run/SI-4676.scala
@@ -0,0 +1,26 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.nsc.doc.model.diagram._
+import scala.tools.partest.ScaladocModelTest
+
+object Test extends ScaladocModelTest {
+
+ override def code = """
+ class SI_4676 {
+ type SS = (String,String)
+ def x(ss: SS): Int = 3
+ }
+ class cbf[A, B, C]
+ """
+
+ // diagrams must be started. In case there's an error with dot, it should not report anything
+ def scaladocSettings = ""
+
+ def testModel(rootPackage: Package) = {
+ // get the quick access implicit defs in scope (_package(s), _class(es), _trait(s), object(s) _method(s), _value(s))
+ import access._
+
+ // check correct expansion of the use case signature
+ val x = rootPackage._class("SI_4676")._method("x")
+ assert(x.valueParams(0)(0).resultType.name == "(String, String)", "parameter ss of method x has type (String, String")
+ }
+} \ No newline at end of file
diff --git a/test/scaladoc/run/SI-4887.check b/test/scaladoc/run/SI-4887.check
new file mode 100644
index 0000000000..619c56180b
--- /dev/null
+++ b/test/scaladoc/run/SI-4887.check
@@ -0,0 +1 @@
+Done.
diff --git a/test/scaladoc/run/SI-4887.scala b/test/scaladoc/run/SI-4887.scala
new file mode 100644
index 0000000000..af83344613
--- /dev/null
+++ b/test/scaladoc/run/SI-4887.scala
@@ -0,0 +1,46 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.partest.ScaladocModelTest
+
+object Test extends ScaladocModelTest {
+
+ override def code = """
+ package scala.test.scaladoc.existentials {
+ import language.higherKinds
+ import language.existentials
+
+ class X[T, U, V]
+
+ trait TEST {
+ type T
+ type U
+ type A
+ def foo1(x: X[T, U, _]) = 3
+ def foo2(x: X[Z[_], U, z.type] forSome {type Z[_] <: { def z: String }; val z: Z[_ <: Int]}) = 4
+ def foo3(x: X[Z, Z, V] forSome { type Z <: T; type V <: T }) = 6
+ }
+ }
+ """
+
+ // no need for special settings
+ def scaladocSettings = "-feature"
+
+ def testModel(rootPackage: Package) = {
+ // get the quick access implicit defs in scope (_package(s), _class(es), _trait(s), object(s) _method(s), _value(s))
+ import access._
+
+ val base = rootPackage._package("scala")._package("test")._package("scaladoc")._package("existentials")
+ val TEST = base._trait("TEST")
+
+ val foo1 = TEST._method("foo1")
+ assert(foo1.valueParams(0)(0).resultType.name == "X[T, U, _]",
+ foo1.valueParams(0)(0).resultType.name + " == X[T, U, _]")
+
+ val foo2 = TEST._method("foo2")
+ assert(foo2.valueParams(0)(0).resultType.name == "X[Z[_], U, _ <: [_]AnyRef { def z: String } with Singleton]",
+ foo2.valueParams(0)(0).resultType.name + " == X[Z[_], U, _ <: [_]AnyRef { def z: String } with Singleton]")
+
+ val foo3 = TEST._method("foo3")
+ assert(foo3.valueParams(0)(0).resultType.name == "X[Z, Z, V] forSome {type Z <: T, type V <: T}",
+ foo3.valueParams(0)(0).resultType.name + " == X[Z, Z, V] forSome {type Z <: T, type V <: T}")
+ }
+} \ No newline at end of file
diff --git a/test/scaladoc/run/SI-5235.check b/test/scaladoc/run/SI-5235.check
new file mode 100644
index 0000000000..d9acfd063b
--- /dev/null
+++ b/test/scaladoc/run/SI-5235.check
@@ -0,0 +1,4 @@
+newSource:10: warning: Could not find the type $Coll points to while expanding it for the usecase signature of method reverse in trait SpecificColl.In this context, $Coll = "BullSh".
+ * @usecase def reverse(): $Coll
+ ^
+Done.
diff --git a/test/scaladoc/run/SI-5235.scala b/test/scaladoc/run/SI-5235.scala
new file mode 100644
index 0000000000..6295fc7786
--- /dev/null
+++ b/test/scaladoc/run/SI-5235.scala
@@ -0,0 +1,87 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.nsc.doc.model.diagram._
+import scala.tools.partest.ScaladocModelTest
+
+object Test extends ScaladocModelTest {
+
+ override def code = """
+ package scala.test.scaladoc.SI5235 {
+ trait Builder[From, To]
+
+ /**
+ * @define Coll `GenericColl`
+ */
+ class GenericColl {
+ /**
+ * @usecase def reverse(): $Coll
+ * Returns the reversed $Coll.
+ */
+ def reverse[T](implicit something: Builder[GenericColl, T]): T
+ def foo1: GenericColl = ???
+ }
+
+ /** Nooo, don't point to this */
+ trait MyCollection
+
+ package specific {
+ /**
+ * @define Coll `BullSh`
+ */
+ trait SpecificColl extends GenericColl {
+ def foo2: SpecificColl = ???
+ }
+ }
+
+ package mycoll {
+ /**
+ * @define Coll `mycoll.MyCollection`
+ */
+ class MyCollection extends specific.SpecificColl {
+ def foo3: MyCollection = ???
+ }
+ }
+ }
+ """
+
+ // diagrams must be started. In case there's an error with dot, it should not report anything
+ def scaladocSettings = ""
+
+ def testModel(rootPackage: Package) = {
+ // get the quick access implicit defs in scope (_package(s), _class(es), _trait(s), object(s) _method(s), _value(s))
+ import access._
+
+ val base = rootPackage._package("scala")._package("test")._package("scaladoc")._package("SI5235")
+
+ val GenericColl = base._class("GenericColl")
+ val SpecificColl = base._package("specific")._trait("SpecificColl")
+ val MyCollection = base._package("mycoll")._class("MyCollection")
+
+ // check comment text
+ val gcComment = extractCommentText(GenericColl._method("reverse").comment.get)
+ val scComment = extractCommentText(SpecificColl._method("reverse").comment.get)
+ val mcComment = extractCommentText(MyCollection._method("reverse").comment.get)
+ assert(gcComment.contains("Returns the reversed GenericColl."),
+ gcComment + ".contains(\"Returns the reversed GenericColl.\")")
+ assert(scComment.contains("Returns the reversed BullSh."),
+ scComment + ".contains(\"Returns the reversed BullSh.\")")
+ assert(mcComment.contains("Returns the reversed mycoll.MyCollection."),
+ mcComment + ".contains(\"Returns the reversed mycoll.MyCollection.\")")
+
+ // check signatures
+ val gcReverse = GenericColl._method("reverse")
+ val scReverse = SpecificColl._method("reverse")
+ val mcReverse = MyCollection._method("reverse")
+ val gcReverseType = gcReverse.resultType
+ val scReverseType = scReverse.resultType
+ val mcReverseType = mcReverse.resultType
+ assert(gcReverseType.name == "GenericColl", gcReverseType.name + " == GenericColl")
+ assert(scReverseType.name == "BullSh", scReverseType.name + " == BullSh")
+ assert(mcReverseType.name == "MyCollection",mcReverseType.name + " == MyCollection")
+ assert(gcReverseType.refEntity(0)._1 == LinkToTpl(GenericColl),
+ gcReverse.qualifiedName + "'s return type has a link to " + GenericColl.qualifiedName)
+ assert(scReverseType.refEntity(0)._1 == Tooltip("BullSh"),
+ scReverseType.refEntity(0)._1 + " == Tooltip(\"BullSh\")")
+ assert(mcReverseType.refEntity(0)._1 == LinkToTpl(MyCollection),
+ mcReverse.qualifiedName + "'s return type has a link to " + MyCollection.qualifiedName)
+ }
+} \ No newline at end of file
diff --git a/test/scaladoc/run/SI-5533.check b/test/scaladoc/run/SI-5533.check
new file mode 100644
index 0000000000..619c56180b
--- /dev/null
+++ b/test/scaladoc/run/SI-5533.check
@@ -0,0 +1 @@
+Done.
diff --git a/test/scaladoc/run/SI-5533.scala b/test/scaladoc/run/SI-5533.scala
new file mode 100644
index 0000000000..989d9aa13a
--- /dev/null
+++ b/test/scaladoc/run/SI-5533.scala
@@ -0,0 +1,39 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.partest.ScaladocModelTest
+
+object Test extends ScaladocModelTest {
+
+ // Working around the fact that usecases have the form Coll[T] and not Coll[T, U], as required by Map
+ override def code = """
+ package a {
+ class A { class Z }
+ class C extends b.B { class X extends Y }
+ }
+
+ package b {
+ /** @contentDiagram */
+ class B extends a.A { class Y extends Z }
+ /** @contentDiagram */
+ class D extends a.C { class V extends X }
+ }
+ """
+
+ // no need for special settings
+ def scaladocSettings = "-diagrams -skip-packages a"
+
+ def testModel(rootPackage: Package) = {
+ // get the quick access implicit defs in scope (_package(s), _class(es), _trait(s), object(s) _method(s), _value(s))
+ import access._
+
+ // just need to check the member exists, access methods will throw an error if there's a problem
+ assert(!rootPackage.templates.exists(_.name == "a"), "package a should not exist in the root package")
+ assert(rootPackage.templates.exists(_.name == "b"), "package b should exist in the root package")
+ val b = rootPackage._package("b")
+ val B = b._class("B")
+ val D = b._class("D")
+ testDiagram(B, B.contentDiagram, 2, 1)
+ // unfortunately not all packages, as B1 extends A.this.A1 and it gets the wrong member -- maybe we should model
+ // things as we do for symbols?
+ testDiagram(D, D.contentDiagram, 3, 2)
+ }
+} \ No newline at end of file
diff --git a/test/scaladoc/run/SI-5784.check b/test/scaladoc/run/SI-5784.check
new file mode 100644
index 0000000000..619c56180b
--- /dev/null
+++ b/test/scaladoc/run/SI-5784.check
@@ -0,0 +1 @@
+Done.
diff --git a/test/scaladoc/run/SI-5784.scala b/test/scaladoc/run/SI-5784.scala
new file mode 100644
index 0000000000..318eb78b2a
--- /dev/null
+++ b/test/scaladoc/run/SI-5784.scala
@@ -0,0 +1,44 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.partest.ScaladocModelTest
+
+object Test extends ScaladocModelTest {
+
+ override def resourceFile: String = "SI-5784.scala"
+
+ // no need for special settings
+ def scaladocSettings = "-diagrams"
+
+ def testModel(rootPackage: Package) = {
+ // get the quick access implicit defs in scope (_package(s), _class(es), _trait(s), object(s) _method(s), _value(s))
+ import access._
+
+ val main = rootPackage._package("test")._package("templates")
+
+ val String = main._aliasTypeTpl("String")
+ assert(String.companion.isDefined, "test.templates.String should have a pseudo-companion object")
+
+ val Base = main._trait("Base")
+ assert(Base.members.filter(_.inDefinitionTemplates.head == Base).length == 5, Base.members.filter(_.inDefinitionTemplates.head == Base).length + " == 5")
+ assert(Base.members.collect{case d: DocTemplateEntity => d}.length == 4, Base.members.collect{case d: DocTemplateEntity => d}.length == 4)
+ testDiagram(Base, Base.contentDiagram, 2, 1)
+
+ val BaseT = Base._absTypeTpl("T")
+ val Foo = Base._trait("Foo")
+ assert(BaseT.members.filter(_.inDefinitionTemplates.head == Base).length == 0, BaseT.members.filter(_.inDefinitionTemplates.head == Base).length + " == 0")
+ assert(BaseT.members.map(_.name).sorted == Foo.members.map(_.name).sorted, BaseT.members.map(_.name).sorted + " == " + Foo.members.map(_.name).sorted)
+ assert(BaseT.companion.isDefined, "test.templates.Base.T should have a pseudo-companion object")
+ testDiagram(BaseT, BaseT.inheritanceDiagram, 2, 1)
+
+ val Api = main._trait("Api")
+ assert(Api.members.filter(_.inDefinitionTemplates.head == Api).length == 2, Api.members.filter(_.inDefinitionTemplates.head == Api).length + " == 2") // FooApi and override type T
+ assert(Api.members.collect{case d: DocTemplateEntity => d}.length == 5, Api.members.collect{case d: DocTemplateEntity => d}.length == 5)
+ testDiagram(Api, Api.contentDiagram, 3, 2)
+
+ val ApiT = Api._absTypeTpl("T")
+ val FooApi = Api._trait("FooApi")
+ assert(ApiT.members.filter(_.inDefinitionTemplates.head == Api).length == 0, ApiT.members.filter(_.inDefinitionTemplates.head == Api).length + " == 0")
+ assert(ApiT.members.map(_.name).sorted == FooApi.members.map(_.name).sorted, ApiT.members.map(_.name).sorted + " == " + FooApi.members.map(_.name).sorted)
+ assert(ApiT.companion.isDefined, "test.templates.Api.T should have a pseudo-companion object")
+ testDiagram(ApiT, ApiT.inheritanceDiagram, 2, 1)
+ }
+} \ No newline at end of file
diff --git a/test/scaladoc/run/SI-5965.check b/test/scaladoc/run/SI-5965.check
new file mode 100644
index 0000000000..619c56180b
--- /dev/null
+++ b/test/scaladoc/run/SI-5965.check
@@ -0,0 +1 @@
+Done.
diff --git a/test/scaladoc/run/SI-5965.scala b/test/scaladoc/run/SI-5965.scala
new file mode 100644
index 0000000000..6f4540d239
--- /dev/null
+++ b/test/scaladoc/run/SI-5965.scala
@@ -0,0 +1,24 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.partest.ScaladocModelTest
+
+object Test extends ScaladocModelTest {
+
+ override def code = """
+ abstract class Param
+ class Test
+ object Test {
+ def apply(i: Int): Test = new Test
+ def apply(i: Int, p: Param = new Param { }): Test = new Test
+ }
+ """
+
+ // no need for special settings
+ def scaladocSettings = ""
+
+ def testModel(rootPackage: Package) = {
+ import access._
+
+ // just need to make sure the model exists
+ val base = rootPackage._object("Test")
+ }
+} \ No newline at end of file
diff --git a/test/scaladoc/run/diagrams-base.scala b/test/scaladoc/run/diagrams-base.scala
index 38bed06502..b7aeed51d2 100644
--- a/test/scaladoc/run/diagrams-base.scala
+++ b/test/scaladoc/run/diagrams-base.scala
@@ -42,7 +42,7 @@ object Test extends ScaladocModelTest {
assert(diag.nodes.filter(_.isThisNode).length == 1)
// 1. check class E diagram
- assert(diag.isClassDiagram)
+ assert(diag.isInheritanceDiagram)
val (incoming, outgoing) = diag.edges.partition(!_._1.isThisNode)
assert(incoming.length == 5)
@@ -56,14 +56,14 @@ object Test extends ScaladocModelTest {
assert(incomingSubclass.length == 2)
assert(incomingImplicit.length == 3)
- val classDiag = diag.asInstanceOf[ClassDiagram]
+ val classDiag = diag.asInstanceOf[InheritanceDiagram]
assert(classDiag.incomingImplicits.length == 3)
assert(classDiag.outgoingImplicits.length == 1)
// 2. check package diagram
// NOTE: Z should be eliminated because it's isolated
val packDiag = base.contentDiagram.get
- assert(packDiag.isPackageDiagram)
+ assert(packDiag.isContentDiagram)
assert(packDiag.nodes.length == 8) // check singular object removal
assert(packDiag.edges.length == 4)
assert(packDiag.edges.foldLeft(0)(_ + _._2.length) == 6)
diff --git a/test/scaladoc/run/diagrams-determinism.scala b/test/scaladoc/run/diagrams-determinism.scala
index 6c8db05d78..2b6f8eecc7 100644
--- a/test/scaladoc/run/diagrams-determinism.scala
+++ b/test/scaladoc/run/diagrams-determinism.scala
@@ -49,19 +49,19 @@ object Test extends ScaladocModelTest {
assert(run2 == run3)
// 2. check the order in the diagram: this node, subclasses, and then implicit conversions
- def assertRightOrder(diagram: Diagram) = {
+ def assertRightOrder(template: DocTemplateEntity, diagram: Diagram) =
for ((node, subclasses) <- diagram.edges)
assert(subclasses == subclasses.filter(_.isThisNode) :::
- subclasses.filter(_.isNormalNode) :::
- subclasses.filter(_.isImplicitNode))
- }
+ subclasses.filter(node => node.isNormalNode || node.isOutsideNode) :::
+ subclasses.filter(_.isImplicitNode),
+ "Diagram order for " + template + ": " + subclasses)
val base = rootPackage._package("scala")._package("test")._package("scaladoc")._package("diagrams")
- assertRightOrder(base.contentDiagram.get)
- assertRightOrder(base._trait("A").inheritanceDiagram.get)
- assertRightOrder(base._trait("B").inheritanceDiagram.get)
- assertRightOrder(base._trait("C").inheritanceDiagram.get)
- assertRightOrder(base._trait("D").inheritanceDiagram.get)
- assertRightOrder(base._trait("E").inheritanceDiagram.get)
+ assertRightOrder(base, base.contentDiagram.get)
+ assertRightOrder(base._trait("A"), base._trait("A").inheritanceDiagram.get)
+ assertRightOrder(base._trait("B"), base._trait("B").inheritanceDiagram.get)
+ assertRightOrder(base._trait("C"), base._trait("C").inheritanceDiagram.get)
+ assertRightOrder(base._trait("D"), base._trait("D").inheritanceDiagram.get)
+ assertRightOrder(base._trait("E"), base._trait("E").inheritanceDiagram.get)
}
} \ No newline at end of file
diff --git a/test/scaladoc/run/diagrams-filtering.scala b/test/scaladoc/run/diagrams-filtering.scala
index 8cb32180a1..54e3e9ac63 100644
--- a/test/scaladoc/run/diagrams-filtering.scala
+++ b/test/scaladoc/run/diagrams-filtering.scala
@@ -65,7 +65,7 @@ object Test extends ScaladocModelTest {
assert(!C.inheritanceDiagram.isDefined)
// trait G
- val G = base._trait("G")
+ val G = base._class("G")
assert(!G.inheritanceDiagram.isDefined)
// trait E
diff --git a/test/scaladoc/run/groups.check b/test/scaladoc/run/groups.check
new file mode 100644
index 0000000000..619c56180b
--- /dev/null
+++ b/test/scaladoc/run/groups.check
@@ -0,0 +1 @@
+Done.
diff --git a/test/scaladoc/run/groups.scala b/test/scaladoc/run/groups.scala
new file mode 100644
index 0000000000..05324c2ec9
--- /dev/null
+++ b/test/scaladoc/run/groups.scala
@@ -0,0 +1,119 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.partest.ScaladocModelTest
+
+object Test extends ScaladocModelTest {
+
+ override def code = """
+ package test.scaladoc.groups {
+
+ /**
+ * The trait A
+ * @groupdesc A Group A is the group that contains functions starting with f
+ * For example:
+ * {{{
+ * this is an example
+ * }}}
+ * @groupdesc B Group B is the group that contains functions starting with b
+ * @groupname B Group B has a nice new name and a high priority
+ * @groupprio B -10
+ * @group Traits
+ * @note This is a note
+ */
+ trait A {
+ /** foo description
+ * @group A */
+ def foo = 1
+
+ /** bar description
+ * @group B */
+ def bar = 2
+ }
+
+ /** The trait B
+ * @group Traits
+ * @groupdesc C Group C is introduced by B
+ */
+ trait B {
+ /** baz descriptopn
+ * @group C */
+ def baz = 3
+ }
+
+ /** The class C which inherits from both A and B
+ * @group Classes
+ * @groupdesc B Look ma, I'm overriding group descriptions!!!
+ * @groupname B And names
+ */
+ class C extends A with B {
+ /** Oh noes, I lost my group -- or did I?!? */
+ override def baz = 4
+ }
+ }
+ """
+
+ // no need for special settings
+ def scaladocSettings = "-feature"
+
+ def testModel(rootPackage: Package) = {
+ // get the quick access implicit defs in scope (_package(s), _class(es), _trait(s), object(s) _method(s), _value(s))
+ import access._
+
+ // just need to check the member exists, access methods will throw an error if there's a problem
+ val base = rootPackage._package("test")._package("scaladoc")._package("groups")
+
+ def checkGroup(mbr: MemberEntity, grp: String) =
+ assert(mbr.group == grp, "Incorrect group for " + mbr.qualifiedName + ": " + mbr.group + " instead of " + grp)
+
+ def checkGroupDesc(dtpl: DocTemplateEntity, grp: String, grpDesc: String) = {
+ assert(dtpl.groupDescription(grp).isDefined,
+ "Group description for " + grp + " not defined in " + dtpl.qualifiedName)
+ assert(extractCommentText(dtpl.groupDescription(grp).get).contains(grpDesc),
+ "Group description for " + grp + " in " + dtpl.qualifiedName + " does not contain \"" + grpDesc + "\": \"" +
+ extractCommentText(dtpl.groupDescription(grp).get) + "\"")
+ }
+
+ def checkGroupName(dtpl: DocTemplateEntity, grp: String, grpName: String) =
+ // TODO: See why we need trim here, we already do trimming in the CommentFactory
+ assert(dtpl.groupName(grp) == grpName,
+ "Group name for " + grp + " in " + dtpl.qualifiedName + " does not equal \"" + grpName + "\": \"" + dtpl.groupName(grp) + "\"")
+
+ def checkGroupPrio(dtpl: DocTemplateEntity, grp: String, grpPrio: Int) =
+ assert(dtpl.groupPriority(grp) == grpPrio,
+ "Group priority for " + grp + " in " + dtpl.qualifiedName + " does not equal " + grpPrio + ": " + dtpl.groupPriority(grp))
+
+
+ val A = base._trait("A")
+ val B = base._trait("B")
+ val C = base._class("C")
+ checkGroup(A, "Traits")
+ checkGroup(B, "Traits")
+ checkGroup(C, "Classes")
+ checkGroup(A._method("foo"), "A")
+ checkGroup(A._method("bar"), "B")
+ checkGroup(B._method("baz"), "C")
+ checkGroup(C._method("foo"), "A")
+ checkGroup(C._method("bar"), "B")
+ checkGroup(C._method("baz"), "C")
+
+ checkGroupDesc(A, "A", "Group A is the group that contains functions starting with f")
+ checkGroupName(A, "A", "A")
+ checkGroupPrio(A, "A", 0)
+ checkGroupDesc(A, "B", "Group B is the group that contains functions starting with b")
+ checkGroupName(A, "B", "Group B has a nice new name and a high priority")
+ checkGroupPrio(A, "B", -10)
+
+ checkGroupDesc(B, "C", "Group C is introduced by B")
+ checkGroupName(B, "C", "C")
+ checkGroupPrio(B, "C", 0)
+
+ checkGroupDesc(C, "A", "Group A is the group that contains functions starting with f")
+ checkGroupName(C, "A", "A")
+ checkGroupPrio(C, "A", 0)
+ checkGroupDesc(C, "B", "Look ma, I'm overriding group descriptions!!!")
+ checkGroupName(C, "B", "And names")
+ checkGroupPrio(C, "B", -10)
+ checkGroupDesc(C, "C", "Group C is introduced by B")
+ checkGroupName(C, "C", "C")
+ checkGroupPrio(C, "C", 0)
+ }
+} \ No newline at end of file
diff --git a/test/scaladoc/run/implicits-ambiguating.scala b/test/scaladoc/run/implicits-ambiguating.scala
index 1420593b74..05daf1f805 100644
--- a/test/scaladoc/run/implicits-ambiguating.scala
+++ b/test/scaladoc/run/implicits-ambiguating.scala
@@ -17,7 +17,7 @@ object Test extends ScaladocModelTest {
mbr.byConversion.map(_.source.implicitsShadowing.get(mbr).map(_.isAmbiguous).getOrElse(false)).getOrElse(false)
// SEE THE test/resources/implicits-chaining-res.scala FOR THE EXPLANATION OF WHAT'S CHECKED HERE:
- val base = root._package("scala")._package("test")._package("scaladoc")._package("implicits")._object("ambiguating")
+ val base = root._package("scala")._package("test")._package("scaladoc")._package("implicits")._package("ambiguating")
var conv1: ImplicitConversion = null
var conv2: ImplicitConversion = null
diff --git a/test/scaladoc/run/implicits-known-type-classes.check b/test/scaladoc/run/implicits-known-type-classes.check
new file mode 100644
index 0000000000..619c56180b
--- /dev/null
+++ b/test/scaladoc/run/implicits-known-type-classes.check
@@ -0,0 +1 @@
+Done.
diff --git a/test/scaladoc/run/implicits-known-type-classes.scala b/test/scaladoc/run/implicits-known-type-classes.scala
new file mode 100644
index 0000000000..9f4ca372b0
--- /dev/null
+++ b/test/scaladoc/run/implicits-known-type-classes.scala
@@ -0,0 +1,33 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.partest.ScaladocModelTest
+import language._
+
+object Test extends ScaladocModelTest {
+
+ // test a file instead of a piece of code
+ override def resourceFile = "implicits-known-type-classes-res.scala"
+
+ // start implicits
+ def scaladocSettings = "-implicits"
+
+ def testModel(root: Package) = {
+ // get the quick access implicit defs in scope (_package(s), _class(es), _trait(s), object(s) _method(s), _value(s))
+ import access._
+
+ /** Tests the "known type classes" feature of scaladoc implicits
+ * if the test fails, please update the correct qualified name of
+ * the type class in src/compiler/scala/tools/nsc/doc/Settings.scala
+ * in the knownTypeClasses map. Thank you! */
+
+ val base = root._package("scala")._package("test")._package("scaladoc")._package("implicits")._package("typeclasses")
+ var conv: ImplicitConversion = null
+
+ val A = base._class("A")
+
+ for (conversion <- A.conversions if !conversion.isCommonConversion) {
+ assert(conversion.constraints.length == 1, conversion.constraints.length + " == 1 (in " + conversion + ")")
+ assert(conversion.constraints.head.isInstanceOf[KnownTypeClassConstraint],
+ conversion.constraints.head + " is not a known type class constraint!")
+ }
+ }
+}
diff --git a/test/scaladoc/run/implicits-scopes.scala b/test/scaladoc/run/implicits-scopes.scala
index 7b9e80e148..d91deba326 100644
--- a/test/scaladoc/run/implicits-scopes.scala
+++ b/test/scaladoc/run/implicits-scopes.scala
@@ -24,7 +24,7 @@ object Test extends ScaladocModelTest {
val test1 = base._package("test1")
val A = test1._class("A")
- conv = A._conversion(test1.qualifiedName + ".package.toB") // the .package means it's the package object
+ conv = A._conversion(test1.qualifiedName + ".toB")
assert(conv.members.length == 1)
assert(conv.constraints.length == 0)
}
@@ -36,7 +36,9 @@ object Test extends ScaladocModelTest {
val classes = test2._package("classes")
val A = classes._class("A")
- assert(A._conversions(test2.qualifiedName + ".toB").isEmpty)
+ conv = A._conversion(test2.qualifiedName + ".toB")
+ assert(conv.members.length == 1)
+ assert(conv.constraints.length == 0)
}
//// test3 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/test/scaladoc/run/implicits-shadowing.scala b/test/scaladoc/run/implicits-shadowing.scala
index 2827d31122..6869b12a94 100644
--- a/test/scaladoc/run/implicits-shadowing.scala
+++ b/test/scaladoc/run/implicits-shadowing.scala
@@ -17,7 +17,7 @@ object Test extends ScaladocModelTest {
mbr.byConversion.map(_.source.implicitsShadowing.get(mbr).map(_.isShadowed).getOrElse(false)).getOrElse(false)
// SEE THE test/resources/implicits-chaining-res.scala FOR THE EXPLANATION OF WHAT'S CHECKED HERE:
- val base = root._package("scala")._package("test")._package("scaladoc")._package("implicits")._object("shadowing")
+ val base = root._package("scala")._package("test")._package("scaladoc")._package("implicits")._package("shadowing")
var conv: ImplicitConversion = null
//// class A ///////////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/test/scaladoc/run/implicits-var-exp.scala b/test/scaladoc/run/implicits-var-exp.scala
index 16569fe3c2..94d2990d29 100644
--- a/test/scaladoc/run/implicits-var-exp.scala
+++ b/test/scaladoc/run/implicits-var-exp.scala
@@ -6,25 +6,36 @@ object Test extends ScaladocModelTest {
override def code = """
package scala.test.scaladoc.variable.expansion {
- /**
- * Blah blah blah
- */
+ /** @define coll WROOOONG-A */
class A
object A {
import language.implicitConversions
- implicit def aToB(a: A) = new B
+ implicit def aToC(a: A) = new C
+ implicit def aToE(a: A) = new E with F
}
- /**
- * @define coll collection
- */
+ /** @define coll WROOOONG-B */
class B {
- /**
- * foo returns a $coll
- */
+ /** foo returns a $coll */
def foo: Nothing = ???
}
+
+ /** @define coll collection */
+ class C extends B
+
+ /** @define coll WROOOONG-D */
+ trait D {
+ /** bar returns a $coll */
+ def bar: Nothing = ???
+ }
+
+ /** @define coll result */
+ //trait E { self: D => override def bar: Nothing = ??? }
+ trait E extends D { override def bar: Nothing = ??? }
+
+ /** @define coll WROOOONG-F */
+ trait F
}
"""
@@ -37,7 +48,9 @@ object Test extends ScaladocModelTest {
val base = rootPackage._package("scala")._package("test")._package("scaladoc")._package("variable")._package("expansion")
val foo = base._class("A")._method("foo")
-
assert(foo.comment.get.body.toString.contains("foo returns a collection"), "\"" + foo.comment.get.body.toString + "\".contains(\"foo returns a collection\")")
+
+ val bar = base._class("A")._method("bar")
+ assert(bar.comment.get.body.toString.contains("bar returns a result"), "\"" + bar.comment.get.body.toString + "\".contains(\"bar returns a result\")")
}
} \ No newline at end of file
diff --git a/test/scaladoc/run/links.check b/test/scaladoc/run/links.check
new file mode 100644
index 0000000000..619c56180b
--- /dev/null
+++ b/test/scaladoc/run/links.check
@@ -0,0 +1 @@
+Done.
diff --git a/test/scaladoc/run/links.scala b/test/scaladoc/run/links.scala
new file mode 100644
index 0000000000..40ce6368ce
--- /dev/null
+++ b/test/scaladoc/run/links.scala
@@ -0,0 +1,28 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.partest.ScaladocModelTest
+
+// SI-5079 "Scaladoc can't link to an object (only a class or trait)"
+// SI-4497 "Links in ScalaDoc - Spec and implementation unsufficient"
+// SI-4224 "Wiki-links should support method targets"
+// SI-3695 "support non-fully-qualified type links in scaladoc comments"
+object Test extends ScaladocModelTest {
+
+ override def resourceFile = "links.scala"
+
+ // no need for special settings
+ def scaladocSettings = ""
+
+ def testModel(rootPackage: Package) = {
+ // get the quick access implicit defs in scope (_package(s), _class(es), _trait(s), object(s) _method(s), _value(s))
+ import access._
+
+ // just need to check the member exists, access methods will throw an error if there's a problem
+ val base = rootPackage._package("scala")._package("test")._package("scaladoc")._package("links")
+ val TEST = base._object("TEST")
+
+ val memberLinks = countLinks(TEST.comment.get, _.link.isInstanceOf[LinkToMember])
+ val templateLinks = countLinks(TEST.comment.get, _.link.isInstanceOf[LinkToTpl])
+ assert(memberLinks == 14, memberLinks + " == 14 (the member links in object TEST)")
+ assert(templateLinks == 2, templateLinks + " == 2 (the template links in object TEST)")
+ }
+} \ No newline at end of file
diff --git a/test/scaladoc/scalacheck/CommentFactoryTest.scala b/test/scaladoc/scalacheck/CommentFactoryTest.scala
index b576ba5544..5e3141bdc0 100644
--- a/test/scaladoc/scalacheck/CommentFactoryTest.scala
+++ b/test/scaladoc/scalacheck/CommentFactoryTest.scala
@@ -10,7 +10,13 @@ import scala.tools.nsc.doc.model.diagram._
class Factory(val g: Global, val s: doc.Settings)
extends doc.model.ModelFactory(g, s) {
- thisFactory: Factory with ModelFactoryImplicitSupport with DiagramFactory with CommentFactory with doc.model.TreeFactory =>
+ thisFactory: Factory
+ with ModelFactoryImplicitSupport
+ with ModelFactoryTypeSupport
+ with DiagramFactory
+ with CommentFactory
+ with doc.model.TreeFactory
+ with MemberLookup =>
def strip(c: Comment): Option[Inline] = {
c.body match {
@@ -31,7 +37,13 @@ object Test extends Properties("CommentFactory") {
val settings = new doc.Settings((str: String) => {})
val reporter = new scala.tools.nsc.reporters.ConsoleReporter(settings)
val g = new Global(settings, reporter)
- (new Factory(g, settings) with ModelFactoryImplicitSupport with DiagramFactory with CommentFactory with doc.model.TreeFactory)
+ (new Factory(g, settings)
+ with ModelFactoryImplicitSupport
+ with ModelFactoryTypeSupport
+ with DiagramFactory
+ with CommentFactory
+ with doc.model.TreeFactory
+ with MemberLookup)
}
def parse(src: String, dst: Inline) = {
diff --git a/test/scaladoc/scalacheck/HtmlFactoryTest.scala b/test/scaladoc/scalacheck/HtmlFactoryTest.scala
index 5b6f75426e..13eacf79a5 100644
--- a/test/scaladoc/scalacheck/HtmlFactoryTest.scala
+++ b/test/scaladoc/scalacheck/HtmlFactoryTest.scala
@@ -235,30 +235,6 @@ object Test extends Properties("HtmlFactory") {
}
}
- property("Trac #3484") = {
- val files = createTemplates("Trac3484.scala")
-
- files("Collection.html") match {
- case node: scala.xml.Node => {
- val s = node.toString
- s.contains("""<span class="result">: Traversable[B]</span>""")
- }
- case _ => false
- }
- }
-
- property("Trac #3484 - SR704") = {
- val files = createTemplates("Trac3484.scala")
-
- files("SR704.html") match {
- case node: scala.xml.Node => {
- val s = node.toString
- s.contains("Hello Mister John.")
- }
- case _ => false
- }
- }
-
property("Trac #4325 - files") = {
val files = createTemplates("Trac4325.scala")
@@ -303,7 +279,7 @@ object Test extends Properties("HtmlFactory") {
case _ => false
}
}
- //
+ //
// property("Trac #484 - refinements and existentials") = {
// val files = createTemplates("Trac484.scala")
// val lines = """
@@ -315,7 +291,7 @@ object Test extends Properties("HtmlFactory") {
// |def j(x: Int): Bar
// |def k(): AnyRef { type Dingus <: T forSome { type T <: String } }
// """.stripMargin.trim.lines map (_.trim)
- //
+ //
// files("RefinementAndExistentials.html") match {
// case node: scala.xml.Node => {
// val s = node.text.replaceAll("\\s+", " ")
@@ -397,26 +373,17 @@ object Test extends Properties("HtmlFactory") {
}
}
- property("Should decode symbolic type alias name.") = {
+ property("SI-4714: Should decode symbolic type alias name.") = {
createTemplate("SI_4715.scala") match {
case node: scala.xml.Node => {
val html = node.toString
- html.contains(">: :+:[<")
- }
- case _ => false
- }
- }
-
- property("Shouldn't drop type arguments to aliased tuple.") = {
- createTemplate("SI_4676.scala") match {
- case node: scala.xml.Node => {
- node.toString.contains(">ss: (String, String)<")
+ html.contains(">:+:<")
}
case _ => false
}
}
- property("Default arguments of synthesized constructor") = {
+ property("SI-4287: Default arguments of synthesized constructor") = {
val files = createTemplates("SI_4287.scala")
files("ClassWithSugar.html") match {
@@ -427,7 +394,7 @@ object Test extends Properties("HtmlFactory") {
}
}
- property("Default arguments of synthesized constructor") = {
+ property("SI-4507: Default arguments of synthesized constructor") = {
createTemplate("SI_4507.scala") match {
case node: scala.xml.Node =>
! node.toString.contains("<li>returns silently when evaluating true and true</li>")
@@ -435,40 +402,40 @@ object Test extends Properties("HtmlFactory") {
}
}
- property("Use cases and links should not crash scaladoc") = {
+ property("SI-4898: Use cases and links should not crash scaladoc") = {
createTemplate("SI_4898.scala")
true
}
- property("Use cases should override their original members") =
+ property("SI-5054: Use cases should override their original members") =
checkText("SI_5054_q1.scala")(
(None,"""def test(): Int""", true)
//Disabled because the full signature is now displayed
//(None,"""def test(implicit lost: Int): Int""", false)
)
- property("Use cases should keep their flags - final should not be lost") =
+ property("SI-5054: Use cases should keep their flags - final should not be lost") =
checkText("SI_5054_q2.scala")((None, """final def test(): Int""", true))
- property("Use cases should keep their flags - implicit should not be lost") =
+ property("SI-5054: Use cases should keep their flags - implicit should not be lost") =
checkText("SI_5054_q3.scala")((None, """implicit def test(): Int""", true))
- property("Use cases should keep their flags - real abstract should not be lost") =
+ property("SI-5054: Use cases should keep their flags - real abstract should not be lost") =
checkText("SI_5054_q4.scala")((None, """abstract def test(): Int""", true))
- property("Use cases should keep their flags - traits should not be affected") =
+ property("SI-5054: Use cases should keep their flags - traits should not be affected") =
checkText("SI_5054_q5.scala")((None, """def test(): Int""", true))
- property("Use cases should keep their flags - traits should not be affected") =
+ property("SI-5054: Use cases should keep their flags - traits should not be affected") =
checkText("SI_5054_q6.scala")((None, """abstract def test(): Int""", true))
- property("Use case individual signature test") =
+ property("SI-5054: Use case individual signature test") =
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\"") =
+ property("SI-5287: Display correct \"Definition classes\"") =
checkText("SI_5287.scala")(
(None,
"""def method(): Int
@@ -477,7 +444,7 @@ object Test extends Properties("HtmlFactory") {
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") =
+ property("Comment inheritance: Correct comment inheritance for overriding") =
checkText("implicit-inheritance-override.scala")(
(Some("Base"),
"""def function[T](arg1: T, arg2: String): Double
@@ -521,7 +488,7 @@ object Test extends Properties("HtmlFactory") {
)
for (useCaseFile <- List("UseCaseInheritance", "UseCaseOverrideInheritance")) {
- property("Correct comment inheritance for usecases") =
+ property("Comment inheritance: Correct comment inheritance for usecases") =
checkText("implicit-inheritance-usecase.scala")(
(Some(useCaseFile),
"""def missing_arg[T](arg1: T): Double
@@ -588,7 +555,7 @@ object Test extends Properties("HtmlFactory") {
)
}
- property("Correct explicit inheritance for override") =
+ property("Comment inheritance: Correct explicit inheritance for override") =
checkText("explicit-inheritance-override.scala")(
(Some("InheritDocDerived"),
"""def function[T](arg1: T, arg2: String): Double
@@ -614,7 +581,7 @@ object Test extends Properties("HtmlFactory") {
See also StartSee The Manual EndSee
""", true))
- property("Correct explicit inheritance for usecase") =
+ property("Comment inheritance: Correct explicit inheritance for usecase") =
checkText("explicit-inheritance-usecase.scala")(
(Some("UseCaseInheritDoc"),
"""def function[T](arg1: T, arg2: String): Double
@@ -639,7 +606,7 @@ object Test extends Properties("HtmlFactory") {
See also StartSee The Manual EndSee
""", true))
- property("Correct explicit inheritance in corner cases") =
+ property("Comment inheritance: Correct explicit inheritance in corner cases") =
checkText("inheritdoc-corner-cases.scala")(
(Some("D"),
"""def hello1: Int
diff --git a/test/scaladoc/scalacheck/IndexTest.scala b/test/scaladoc/scalacheck/IndexTest.scala
index 29e337da2b..bf385898fc 100644
--- a/test/scaladoc/scalacheck/IndexTest.scala
+++ b/test/scaladoc/scalacheck/IndexTest.scala
@@ -16,7 +16,7 @@ object Test extends Properties("Index") {
val morepaths = Thread.currentThread.getContextClassLoader.getParent.asInstanceOf[URLClassLoader].getURLs.map(u => URLDecoder.decode(u.getPath))
(paths ++ morepaths).mkString(java.io.File.pathSeparator)
}
-
+
val docFactory = {
val settings = new doc.Settings({Console.err.println(_)})
@@ -27,9 +27,9 @@ object Test extends Properties("Index") {
new doc.DocFactory(reporter, settings)
}
-
+
val indexModelFactory = doc.model.IndexModelFactory
-
+
def createIndex(path: String): Option[Index] = {
val maybeUniverse = {
@@ -79,4 +79,11 @@ object Test extends Properties("Index") {
case None => false
}
}
+ property("package objects in index") = {
+ createIndex("test/scaladoc/resources/SI-5558.scala") match {
+ case Some(index) =>
+ index.index.firstLetterIndex('f') isDefinedAt "foo"
+ case None => false
+ }
+ }
}