diff options
Diffstat (limited to 'src')
34 files changed, 374 insertions, 1492 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala index 1a0b4cdec0..4abcc774da 100644 --- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala +++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala @@ -486,7 +486,8 @@ abstract class ExplicitOuter extends InfoTransform // since we can't fix SI-4440 properly (we must drop the outer accessors of final classes when there's no immediate reference to them in sight) // at least don't crash... this duplicates maybeOmittable from constructors (acc.owner.isEffectivelyFinal && !acc.isOverridingSymbol)) { - currentRun.reporting.uncheckedWarning(tree.pos, "The outer reference in this type test cannot be checked at run time.") + if (!base.tpe.hasAnnotation(UncheckedClass)) + currentRun.reporting.uncheckedWarning(tree.pos, "The outer reference in this type test cannot be checked at run time.") transform(TRUE) // urgh... drop condition if there's no accessor (or if it may disappear after constructors) } else { // println("(base, acc)= "+(base, acc)) diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala index ab3b25e76b..2b16995f0b 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala @@ -351,7 +351,7 @@ trait MatchApproximation extends TreeAndTypeAnalysis with ScalaLogic with MatchT object condStrategy extends TypeTestTreeMaker.TypeTestCondStrategy { type Result = Prop def and(a: Result, b: Result) = And(a, b) - def outerTest(testedBinder: Symbol, expectedTp: Type) = True // TODO OuterEqProp(testedBinder, expectedType) + def withOuterTest(testedBinder: Symbol, expectedTp: Type) = True // TODO OuterEqProp(testedBinder, expectedType) def typeTest(b: Symbol, pt: Type) = { // a type test implies the tested path is non-null (null.isInstanceOf[T] is false for all T) val p = binderToUniqueTree(b); And(uniqueNonNullProp(p), uniqueTypeProp(p, uniqueTp(pt))) } diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala index c6e7f8fcda..8c59ced28f 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala @@ -316,7 +316,7 @@ trait MatchTreeMaking extends MatchCodeGen with Debugging { trait TypeTestCondStrategy { type Result - def outerTest(testedBinder: Symbol, expectedTp: Type): Result + def withOuterTest(orig: Result)(testedBinder: Symbol, expectedTp: Type): Result = orig // TODO: can probably always widen def typeTest(testedBinder: Symbol, expectedTp: Type): Result def nonNullTest(testedBinder: Symbol): Result @@ -336,18 +336,34 @@ trait MatchTreeMaking extends MatchCodeGen with Debugging { def equalsTest(pat: Tree, testedBinder: Symbol) = codegen._equals(pat, testedBinder) def eqTest(pat: Tree, testedBinder: Symbol) = REF(testedBinder) OBJ_EQ pat - def outerTest(testedBinder: Symbol, expectedTp: Type): Tree = { - val expectedOuter = expectedTp.prefix match { - case ThisType(clazz) => This(clazz) - case NoType => mkTRUE // fallback for SI-6183 - case pre => REF(pre.prefix, pre.termSymbol) + override def withOuterTest(orig: Tree)(testedBinder: Symbol, expectedTp: Type): Tree = { + val expectedPrefix = expectedTp.prefix + val testedPrefix = testedBinder.info.prefix + + // Check if a type is defined in a static location. Unlike `tp.isStatic` before `flatten`, + // this also includes methods and (possibly nested) objects inside of methods. + def definedInStaticLocation(tp: Type): Boolean = { + def isStatic(tp: Type): Boolean = + if (tp == NoType || tp.typeSymbol.isPackageClass || tp == NoPrefix) true + else if (tp.typeSymbol.isModuleClass) isStatic(tp.prefix) + else false + tp.typeSymbol.owner == tp.prefix.typeSymbol && isStatic(tp.prefix) } - // ExplicitOuter replaces `Select(q, outerSym) OBJ_EQ expectedPrefix` by `Select(q, outerAccessor(outerSym.owner)) OBJ_EQ expectedPrefix` - // if there's an outer accessor, otherwise the condition becomes `true` -- TODO: can we improve needsOuterTest so there's always an outerAccessor? - val outer = expectedTp.typeSymbol.newMethod(vpmName.outer, newFlags = SYNTHETIC | ARTIFACT) setInfo expectedTp.prefix - - (Select(codegen._asInstanceOf(testedBinder, expectedTp), outer)) OBJ_EQ expectedOuter + if ((expectedPrefix eq NoPrefix) + || definedInStaticLocation(expectedTp) + || testedPrefix =:= expectedPrefix) orig + else gen.mkAttributedQualifierIfPossible(expectedPrefix) match { + case None => orig + case Some(expectedOuterRef) => + // ExplicitOuter replaces `Select(q, outerSym) OBJ_EQ expectedPrefix` + // by `Select(q, outerAccessor(outerSym.owner)) OBJ_EQ expectedPrefix` + // if there's an outer accessor, otherwise the condition becomes `true` + // TODO: centralize logic whether there's an outer accessor and use here? + val synthOuterGetter = expectedTp.typeSymbol.newMethod(vpmName.outer, newFlags = SYNTHETIC | ARTIFACT) setInfo expectedPrefix + val outerTest = (Select(codegen._asInstanceOf(testedBinder, expectedTp), synthOuterGetter)) OBJ_EQ expectedOuterRef + and(orig, outerTest) + } } } @@ -356,7 +372,6 @@ trait MatchTreeMaking extends MatchCodeGen with Debugging { def typeTest(testedBinder: Symbol, expectedTp: Type): Result = true - def outerTest(testedBinder: Symbol, expectedTp: Type): Result = false def nonNullTest(testedBinder: Symbol): Result = false def equalsTest(pat: Tree, testedBinder: Symbol): Result = false def eqTest(pat: Tree, testedBinder: Symbol): Result = false @@ -368,7 +383,6 @@ trait MatchTreeMaking extends MatchCodeGen with Debugging { type Result = Boolean def typeTest(testedBinder: Symbol, expectedTp: Type): Result = testedBinder eq binder - def outerTest(testedBinder: Symbol, expectedTp: Type): Result = false def nonNullTest(testedBinder: Symbol): Result = testedBinder eq binder def equalsTest(pat: Tree, testedBinder: Symbol): Result = false // could in principle analyse pat and see if it's statically known to be non-null def eqTest(pat: Tree, testedBinder: Symbol): Result = false // could in principle analyse pat and see if it's statically known to be non-null @@ -405,12 +419,6 @@ trait MatchTreeMaking extends MatchCodeGen with Debugging { import TypeTestTreeMaker._ debug.patmat("TTTM"+((prevBinder, extractorArgTypeTest, testedBinder, expectedTp, nextBinderTp))) - lazy val outerTestNeeded = ( - (expectedTp.prefix ne NoPrefix) - && !expectedTp.prefix.typeSymbol.isPackageClass - && needsOuterTest(expectedTp, testedBinder.info, matchOwner) - ) - // the logic to generate the run-time test that follows from the fact that // a `prevBinder` is expected to have type `expectedTp` // the actual tree-generation logic is factored out, since the analyses generate Cond(ition)s rather than Trees @@ -429,12 +437,11 @@ trait MatchTreeMaking extends MatchCodeGen with Debugging { def isExpectedPrimitiveType = isAsExpected && isPrimitiveValueType(expectedTp) def isExpectedReferenceType = isAsExpected && (expectedTp <:< AnyRefTpe) def mkNullTest = nonNullTest(testedBinder) - def mkOuterTest = outerTest(testedBinder, expectedTp) def mkTypeTest = typeTest(testedBinder, expectedWide) def mkEqualsTest(lhs: Tree): cs.Result = equalsTest(lhs, testedBinder) def mkEqTest(lhs: Tree): cs.Result = eqTest(lhs, testedBinder) - def addOuterTest(res: cs.Result): cs.Result = if (outerTestNeeded) and(res, mkOuterTest) else res + def addOuterTest(res: cs.Result): cs.Result = withOuterTest(res)(testedBinder, expectedTp) // If we conform to expected primitive type: // it cannot be null and cannot have an outer pointer. No further checking. diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 9261d6b851..da269168ec 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -1507,9 +1507,8 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans } } - private def transformCaseApply(tree: Tree, ifNot: => Unit) = { + private def isSimpleCaseApply(tree: Tree): Boolean = { val sym = tree.symbol - def isClassTypeAccessible(tree: Tree): Boolean = tree match { case TypeApply(fun, targs) => isClassTypeAccessible(fun) @@ -1517,40 +1516,36 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans ( // SI-4859 `CaseClass1().InnerCaseClass2()` must not be rewritten to `new InnerCaseClass2()`; // {expr; Outer}.Inner() must not be rewritten to `new Outer.Inner()`. treeInfo.isQualifierSafeToElide(module) && - // SI-5626 Classes in refinement types cannot be constructed with `new`. In this case, - // the companion class is actually not a ClassSymbol, but a reference to an abstract type. - module.symbol.companionClass.isClass - ) + // SI-5626 Classes in refinement types cannot be constructed with `new`. In this case, + // the companion class is actually not a ClassSymbol, but a reference to an abstract type. + module.symbol.companionClass.isClass + ) } - val doTransform = - sym.isSourceMethod && + sym.isSourceMethod && sym.isCase && sym.name == nme.apply && isClassTypeAccessible(tree) && - !tree.tpe.resultType.typeSymbol.primaryConstructor.isLessAccessibleThan(tree.symbol) - - if (doTransform) { - def loop(t: Tree): Unit = t match { - case Ident(_) => - checkUndesiredProperties(t.symbol, t.pos) - case Select(qual, _) => - checkUndesiredProperties(t.symbol, t.pos) - loop(qual) - case _ => - } - tree foreach { - case i@Ident(_) => - enterReference(i.pos, i.symbol) // SI-5390 need to `enterReference` for `a` in `a.B()` - case _ => - } - loop(tree) - toConstructor(tree.pos, tree.tpe) + !tree.tpe.finalResultType.typeSymbol.primaryConstructor.isLessAccessibleThan(tree.symbol) + } + + private def transformCaseApply(tree: Tree) = { + def loop(t: Tree): Unit = t match { + case Ident(_) => + checkUndesiredProperties(t.symbol, t.pos) + case Select(qual, _) => + checkUndesiredProperties(t.symbol, t.pos) + loop(qual) + case _ => } - else { - ifNot - tree + + tree foreach { + case i@Ident(_) => + enterReference(i.pos, i.symbol) // SI-5390 need to `enterReference` for `a` in `a.B()` + case _ => } + loop(tree) + toConstructor(tree.pos, tree.tpe) } private def transformApply(tree: Apply): Tree = tree match { @@ -1590,12 +1585,24 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans // term should have been eliminated by super accessors assert(!(qual.symbol.isTrait && sym.isTerm && mix == tpnme.EMPTY), (qual.symbol, sym, mix)) - transformCaseApply(tree, + // Rewrite eligible calls to monomorphic case companion apply methods to the equivalent constructor call. + // + // Note: for generic case classes the rewrite needs to be handled at the enclosing `TypeApply` to transform + // `TypeApply(Select(C, apply), targs)` to `Select(New(C[targs]), <init>)`. In case such a `TypeApply` + // was deemed ineligible for transformation (e.g. the case constructor was private), the refchecks transform + // will recurse to this point with `Select(C, apply)`, which will have a type `[T](...)C[T]`. + // + // We don't need to perform the check on the Select node, and `!isHigherKinded will guard against this + // redundant (and previously buggy, SI-9546) consideration. + if (!tree.tpe.isHigherKinded && isSimpleCaseApply(tree)) { + transformCaseApply(tree) + } else { qual match { case Super(_, mix) => checkSuper(mix) case _ => } - ) + tree + } } private def transformIf(tree: If): Tree = { val If(cond, thenpart, elsepart) = tree @@ -1720,7 +1727,10 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans case TypeApply(fn, args) => checkBounds(tree, NoPrefix, NoSymbol, fn.tpe.typeParams, args map (_.tpe)) - transformCaseApply(tree, ()) + if (isSimpleCaseApply(tree)) + transformCaseApply(tree) + else + tree case x @ Apply(_, _) => transformApply(x) @@ -1739,12 +1749,11 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans case Ident(name) => checkUndesiredProperties(sym, tree.pos) - transformCaseApply(tree, - if (name != nme.WILDCARD && name != tpnme.WILDCARD_STAR) { - assert(sym != NoSymbol, "transformCaseApply: name = " + name.debugString + " tree = " + tree + " / " + tree.getClass) //debug - enterReference(tree.pos, sym) - } - ) + if (name != nme.WILDCARD && name != tpnme.WILDCARD_STAR) { + assert(sym != NoSymbol, "transformCaseApply: name = " + name.debugString + " tree = " + tree + " / " + tree.getClass) //debug + enterReference(tree.pos, sym) + } + tree case x @ Select(_, _) => transformSelect(x) diff --git a/src/intellij/scala-build.iml.SAMPLE b/src/intellij/scala-build.iml.SAMPLE index bf722e464f..0232e9e576 100644 --- a/src/intellij/scala-build.iml.SAMPLE +++ b/src/intellij/scala-build.iml.SAMPLE @@ -34,32 +34,32 @@ <root url="jar://$USER_HOME$/.ivy2/cache/org.codehaus.plexus/plexus-classworlds/bundles/plexus-classworlds-2.5.2.jar!/" /> <root url="jar://$USER_HOME$/.ivy2/cache/biz.aQute.bnd/biz.aQute.bnd/jars/biz.aQute.bnd-2.4.1.jar!/" /> <root url="jar://$USER_HOME$/.sbt/boot/scala-2.10.5/lib/scala-library.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/sbt/jars/sbt-0.13.9.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/main/jars/main-0.13.9.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/actions/jars/actions-0.13.9.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/classpath/jars/classpath-0.13.9.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/sbt/jars/sbt-0.13.11.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/main/jars/main-0.13.11.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/actions/jars/actions-0.13.11.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/classpath/jars/classpath-0.13.11.jar!/" /> <root url="jar://$USER_HOME$/.sbt/boot/scala-2.10.5/lib/scala-compiler.jar!/" /> <root url="jar://$USER_HOME$/.sbt/boot/scala-2.10.5/lib/scala-reflect.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/interface/jars/interface-0.13.9.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/io/jars/io-0.13.9.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/control/jars/control-0.13.9.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/interface/jars/interface-0.13.11.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/io/jars/io-0.13.11.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/control/jars/control-0.13.11.jar!/" /> <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/launcher-interface/jars/launcher-interface-1.0.0-M1.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/completion/jars/completion-0.13.9.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/collections/jars/collections-0.13.9.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/completion/jars/completion-0.13.11.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/collections/jars/collections-0.13.11.jar!/" /> <root url="jar://$USER_HOME$/.ivy2/cache/jline/jline/jars/jline-2.11.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/api/jars/api-0.13.9.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/compiler-integration/jars/compiler-integration-0.13.9.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/incremental-compiler/jars/incremental-compiler-0.13.9.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/logging/jars/logging-0.13.9.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/process/jars/process-0.13.9.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/relation/jars/relation-0.13.9.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/compile/jars/compile-0.13.9.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/classfile/jars/classfile-0.13.9.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/persist/jars/persist-0.13.9.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/api/jars/api-0.13.11.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/compiler-integration/jars/compiler-integration-0.13.11.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/incremental-compiler/jars/incremental-compiler-0.13.11.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/logging/jars/logging-0.13.11.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/process/jars/process-0.13.11.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/relation/jars/relation-0.13.11.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/compile/jars/compile-0.13.11.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/classfile/jars/classfile-0.13.11.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/persist/jars/persist-0.13.11.jar!/" /> <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-tools.sbinary/sbinary_2.10/jars/sbinary_2.10-0.4.2.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/compiler-ivy-integration/jars/compiler-ivy-integration-0.13.9.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/ivy/jars/ivy-0.13.9.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/cross/jars/cross-0.13.9.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/compiler-ivy-integration/jars/compiler-ivy-integration-0.13.11.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/ivy/jars/ivy-0.13.11.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/cross/jars/cross-0.13.11.jar!/" /> <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt.ivy/ivy/jars/ivy-2.3.0-sbt-c5d1b95fdcc1e1007740ffbecf4eb07abc51ec93.jar!/" /> <root url="jar://$USER_HOME$/.ivy2/cache/com.jcraft/jsch/jars/jsch-0.1.46.jar!/" /> <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/serialization_2.10/jars/serialization_2.10-0.1.1.jar!/" /> @@ -70,40 +70,40 @@ <root url="jar://$USER_HOME$/.ivy2/cache/com.thoughtworks.paranamer/paranamer/jars/paranamer-2.6.jar!/" /> <root url="jar://$USER_HOME$/.ivy2/cache/org.spire-math/jawn-parser_2.10/jars/jawn-parser_2.10-0.6.0.jar!/" /> <root url="jar://$USER_HOME$/.ivy2/cache/org.spire-math/json4s-support_2.10/jars/json4s-support_2.10-0.6.0.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/run/jars/run-0.13.9.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/task-system/jars/task-system-0.13.9.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/tasks/jars/tasks-0.13.9.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/tracking/jars/tracking-0.13.9.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/cache/jars/cache-0.13.9.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/testing/jars/testing-0.13.9.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/test-agent/jars/test-agent-0.13.9.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/run/jars/run-0.13.11.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/task-system/jars/task-system-0.13.11.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/tasks/jars/tasks-0.13.11.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/tracking/jars/tracking-0.13.11.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/cache/jars/cache-0.13.11.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/testing/jars/testing-0.13.11.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/test-agent/jars/test-agent-0.13.11.jar!/" /> <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/test-interface/jars/test-interface-1.0.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/main-settings/jars/main-settings-0.13.9.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/apply-macro/jars/apply-macro-0.13.9.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/command/jars/command-0.13.9.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/logic/jars/logic-0.13.9.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/compiler-interface/jars/compiler-interface-bin-0.13.9.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/compiler-interface/jars/compiler-interface-src-0.13.9.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/precompiled-2_8_2/jars/compiler-interface-bin-0.13.9.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/precompiled-2_9_2/jars/compiler-interface-bin-0.13.9.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/precompiled-2_9_3/jars/compiler-interface-bin-0.13.9.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/main-settings/jars/main-settings-0.13.11.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/apply-macro/jars/apply-macro-0.13.11.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/command/jars/command-0.13.11.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/logic/jars/logic-0.13.11.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/compiler-interface/jars/compiler-interface-bin-0.13.11.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/compiler-interface/jars/compiler-interface-src-0.13.11.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/precompiled-2_8_2/jars/compiler-interface-bin-0.13.11.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/precompiled-2_9_2/jars/compiler-interface-bin-0.13.11.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/precompiled-2_9_3/jars/compiler-interface-bin-0.13.11.jar!/" /> </CLASSES> <JAVADOC /> <SOURCES> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/main/srcs/main-0.13.9-sources.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/main/srcs/main-0.13.11-sources.jar!/" /> <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-lang/scala-library/srcs/scala-library-2.10.5-sources.jar!/" /> <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-lang/scala-reflect/srcs/scala-reflect-2.10.5-sources.jar!/" /> <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-lang/scala-compiler/srcs/scala-compiler-2.10.5-sources.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/actions/srcs/actions-0.13.9-sources.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/sbt/srcs/sbt-0.13.9-sources.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/run/srcs/run-0.13.9-sources.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/actions/srcs/actions-0.13.11-sources.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/sbt/srcs/sbt-0.13.11-sources.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/run/srcs/run-0.13.11-sources.jar!/" /> <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/test-interface/srcs/test-interface-1.0-sources.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/testing/srcs/testing-0.13.9-sources.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/tasks/srcs/tasks-0.13.9-sources.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/ivy/srcs/ivy-0.13.9-sources.jar!/" /> - <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/completion/srcs/completion-0.13.9-sources.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/testing/srcs/testing-0.13.11-sources.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/tasks/srcs/tasks-0.13.11-sources.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/ivy/srcs/ivy-0.13.11-sources.jar!/" /> + <root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/completion/srcs/completion-0.13.11-sources.jar!/" /> </SOURCES> </library> </orderEntry> </component> -</module>
\ No newline at end of file +</module> diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala index 50a53732f1..9cd2a2b8de 100644 --- a/src/library/scala/Predef.scala +++ b/src/library/scala/Predef.scala @@ -28,13 +28,11 @@ import scala.io.StdIn * constructors ([[scala.collection.immutable.::]] and * [[scala.collection.immutable.Nil]]). * - * === Console I/O === - * Predef provides a number of simple functions for console I/O, such as - * `print`, `println`, `readLine`, `readInt`, etc. These functions are all - * aliases of the functions provided by [[scala.Console]]. + * === Console Output === + * For basic console output, `Predef` provides convenience methods [[print(x:Any* print]] and [[println(x:Any* println]], + * which are aliases of the methods in the object [[scala.Console]]. * * === Assertions === - * * A set of `assert` functions are provided for use as a way to document * and dynamically check invariants in code. Invocations of `assert` can be elided * at compile time by providing the command line option `-Xdisable-assertions`, @@ -146,9 +144,9 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { /** Tests an expression, throwing an `AssertionError` if false. * Calls to this method will not be generated if `-Xelide-below` - * is at least `ASSERTION`. + * is greater than `ASSERTION`. * - * @see elidable + * @see [[scala.annotation.elidable elidable]] * @param assertion the expression to test */ @elidable(ASSERTION) @@ -159,9 +157,9 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { /** Tests an expression, throwing an `AssertionError` if false. * Calls to this method will not be generated if `-Xelide-below` - * is at least `ASSERTION`. + * is greater than `ASSERTION`. * - * @see elidable + * @see [[scala.annotation.elidable elidable]] * @param assertion the expression to test * @param message a String to include in the failure message */ @@ -175,9 +173,9 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { * This method differs from assert only in the intent expressed: * assert contains a predicate which needs to be proven, while * assume contains an axiom for a static checker. Calls to this method - * will not be generated if `-Xelide-below` is at least `ASSERTION`. + * will not be generated if `-Xelide-below` is greater than `ASSERTION`. * - * @see elidable + * @see [[scala.annotation.elidable elidable]] * @param assumption the expression to test */ @elidable(ASSERTION) @@ -190,9 +188,9 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { * This method differs from assert only in the intent expressed: * assert contains a predicate which needs to be proven, while * assume contains an axiom for a static checker. Calls to this method - * will not be generated if `-Xelide-below` is at least `ASSERTION`. + * will not be generated if `-Xelide-below` is greater than `ASSERTION`. * - * @see elidable + * @see [[scala.annotation.elidable elidable]] * @param assumption the expression to test * @param message a String to include in the failure message */ @@ -304,9 +302,37 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { // printing ----------------------------------------------------------- + /** Prints an object to `out` using its `toString` method. + * + * @param x the object to print; may be null. + */ def print(x: Any) = Console.print(x) + + /** Prints a newline character on the default output. + */ def println() = Console.println() + + /** Prints out an object to the default output, followed by a newline character. + * + * @param x the object to print. + */ def println(x: Any) = Console.println(x) + + /** Prints its arguments as a formatted string to the default output, + * based on a string pattern (in a fashion similar to printf in C). + * + * The interpretation of the formatting patterns is described in + * <a href="" target="contentFrame" class="java/util/Formatter"> + * `java.util.Formatter`</a>. + * + * Consider using the [[scala.StringContext.f f interpolator]] as more type safe and idiomatic. + * + * @param text the pattern for formatting the arguments. + * @param args the arguments used to instantiating the pattern. + * @throws java.lang.IllegalArgumentException if there was a problem with the format string or arguments + * + * @see [[scala.StringContext.f StringContext.f]] + */ def printf(text: String, xs: Any*) = Console.print(text.format(xs: _*)) // views -------------------------------------------------------------- diff --git a/src/library/scala/collection/BitSetLike.scala b/src/library/scala/collection/BitSetLike.scala index 29369447d1..209b00ebf9 100644 --- a/src/library/scala/collection/BitSetLike.scala +++ b/src/library/scala/collection/BitSetLike.scala @@ -204,6 +204,27 @@ trait BitSetLike[+This <: BitSetLike[This] with SortedSet[Int]] extends SortedSe def subsetOf(other: BitSet): Boolean = (0 until nwords) forall (idx => (this.word(idx) & ~ other.word(idx)) == 0L) + override def head: Int = { + val n = nwords + var i = 0 + while (i < n) { + val wi = word(i) + if (wi != 0L) return WordLength*i + java.lang.Long.numberOfTrailingZeros(wi) + i += 1 + } + throw new NoSuchElementException("Empty BitSet") + } + + override def last: Int = { + var i = nwords - 1 + while (i >= 0) { + val wi = word(i) + if (wi != 0L) return WordLength*i + 63 - java.lang.Long.numberOfLeadingZeros(wi) + i += 1 + } + throw new NoSuchElementException("Empty BitSet") + } + override def addString(sb: StringBuilder, start: String, sep: String, end: String) = { sb append start var pre = "" diff --git a/src/library/scala/collection/JavaConversions.scala b/src/library/scala/collection/JavaConversions.scala index 7bfa60771f..f9a34f78d5 100644 --- a/src/library/scala/collection/JavaConversions.scala +++ b/src/library/scala/collection/JavaConversions.scala @@ -16,12 +16,12 @@ import convert._ * * The following conversions are supported: *{{{ - * scala.collection.Iterable <=> java.lang.Iterable - * scala.collection.Iterable <=> java.util.Collection - * scala.collection.Iterator <=> java.util.{ Iterator, Enumeration } + * scala.collection.Iterable <=> java.lang.Iterable + * scala.collection.Iterable <=> java.util.Collection + * scala.collection.Iterator <=> java.util.{ Iterator, Enumeration } * scala.collection.mutable.Buffer <=> java.util.List - * scala.collection.mutable.Set <=> java.util.Set - * scala.collection.mutable.Map <=> java.util.{ Map, Dictionary } + * scala.collection.mutable.Set <=> java.util.Set + * scala.collection.mutable.Map <=> java.util.{ Map, Dictionary } * scala.collection.concurrent.Map <=> java.util.concurrent.ConcurrentMap *}}} * In all cases, converting from a source type to a target type and back diff --git a/src/library/scala/collection/JavaConverters.scala b/src/library/scala/collection/JavaConverters.scala index 86e86d4584..58fbc5afa5 100644 --- a/src/library/scala/collection/JavaConverters.scala +++ b/src/library/scala/collection/JavaConverters.scala @@ -19,14 +19,14 @@ import convert._ * Scala and Java collections using `asScala` and `asJava` methods. * * The following conversions are supported via `asJava`, `asScala` - * - * - `scala.collection.Iterable` <=> `java.lang.Iterable` - * - `scala.collection.Iterator` <=> `java.util.Iterator` - * - `scala.collection.mutable.Buffer` <=> `java.util.List` - * - `scala.collection.mutable.Set` <=> `java.util.Set` - * - `scala.collection.mutable.Map` <=> `java.util.Map` - * - `scala.collection.mutable.concurrent.Map` <=> `java.util.concurrent.ConcurrentMap` - * + *{{{ + * scala.collection.Iterable <=> java.lang.Iterable + * scala.collection.Iterator <=> java.util.Iterator + * scala.collection.mutable.Buffer <=> java.util.List + * scala.collection.mutable.Set <=> java.util.Set + * scala.collection.mutable.Map <=> java.util.Map + * scala.collection.mutable.concurrent.Map <=> java.util.concurrent.ConcurrentMap + *}}} * In all cases, converting from a source type to a target type and back * again will return the original source object, e.g. * {{{ @@ -40,22 +40,22 @@ import convert._ * The following conversions are also supported, but the * direction from Scala to Java is done by the more specifically named methods: * `asJavaCollection`, `asJavaEnumeration`, `asJavaDictionary`. - * - * - `scala.collection.Iterable` <=> `java.util.Collection` - * - `scala.collection.Iterator` <=> `java.util.Enumeration` - * - `scala.collection.mutable.Map` <=> `java.util.Dictionary` - * + *{{{ + * scala.collection.Iterable <=> java.util.Collection + * scala.collection.Iterator <=> java.util.Enumeration + * scala.collection.mutable.Map <=> java.util.Dictionary + *}}} * In addition, the following one way conversions are provided via `asJava`: - * - * - `scala.collection.Seq` => `java.util.List` - * - `scala.collection.mutable.Seq` => `java.util.List` - * - `scala.collection.Set` => `java.util.Set` - * - `scala.collection.Map` => `java.util.Map` - * + *{{{ + * scala.collection.Seq => java.util.List + * scala.collection.mutable.Seq => java.util.List + * scala.collection.Set => java.util.Set + * scala.collection.Map => java.util.Map + *}}} * The following one way conversion is provided via `asScala`: - * - * - `java.util.Properties` => `scala.collection.mutable.Map` - * + *{{{ + * java.util.Properties => scala.collection.mutable.Map + *}}} * @since 2.8.1 */ object JavaConverters extends DecorateAsJava with DecorateAsScala diff --git a/src/library/scala/collection/convert/DecorateAsJava.scala b/src/library/scala/collection/convert/DecorateAsJava.scala index e6aa5da067..0ed67a86d7 100644 --- a/src/library/scala/collection/convert/DecorateAsJava.scala +++ b/src/library/scala/collection/convert/DecorateAsJava.scala @@ -20,14 +20,14 @@ import scala.language.implicitConversions * Scala and Java collections using `asScala` and `asJava` methods. * * The following conversions are supported via `asJava`, `asScala` - * - * - `scala.collection.Iterable` <=> `java.lang.Iterable` - * - `scala.collection.Iterator` <=> `java.util.Iterator` - * - `scala.collection.mutable.Buffer` <=> `java.util.List` - * - `scala.collection.mutable.Set` <=> `java.util.Set` - * - `scala.collection.mutable.Map` <=> `java.util.Map` - * - `scala.collection.mutable.concurrent.Map` <=> `java.util.concurrent.ConcurrentMap` - * + *{{{ + * scala.collection.Iterable <=> java.lang.Iterable + * scala.collection.Iterator <=> java.util.Iterator + * scala.collection.mutable.Buffer <=> java.util.List + * scala.collection.mutable.Set <=> java.util.Set + * scala.collection.mutable.Map <=> java.util.Map + * scala.collection.mutable.concurrent.Map <=> java.util.concurrent.ConcurrentMap + *}}} * In all cases, converting from a source type to a target type and back * again will return the original source object, e.g. * {{{ @@ -41,22 +41,22 @@ import scala.language.implicitConversions * The following conversions are also supported, but the * direction from Scala to Java is done by the more specifically named methods: * `asJavaCollection`, `asJavaEnumeration`, `asJavaDictionary`. - * - * - `scala.collection.Iterable` <=> `java.util.Collection` - * - `scala.collection.Iterator` <=> `java.util.Enumeration` - * - `scala.collection.mutable.Map` <=> `java.util.Dictionary` - * + *{{{ + * scala.collection.Iterable <=> java.util.Collection + * scala.collection.Iterator <=> java.util.Enumeration + * scala.collection.mutable.Map <=> java.util.Dictionary + *}}} * In addition, the following one way conversions are provided via `asJava`: - * - * - `scala.collection.Seq` => `java.util.List` - * - `scala.collection.mutable.Seq` => `java.util.List` - * - `scala.collection.Set` => `java.util.Set` - * - `scala.collection.Map` => `java.util.Map` - * + *{{{ + * scala.collection.Seq => java.util.List + * scala.collection.mutable.Seq => java.util.List + * scala.collection.Set => java.util.Set + * scala.collection.Map => java.util.Map + *}}} * The following one way conversion is provided via `asScala`: - * - * - `java.util.Properties` => `scala.collection.mutable.Map` - * + *{{{ + * java.util.Properties => scala.collection.mutable.Map + *}}} * @since 2.8.1 */ trait DecorateAsJava { diff --git a/src/library/scala/collection/immutable/BitSet.scala b/src/library/scala/collection/immutable/BitSet.scala index 846bc22182..6bb1f116fe 100644 --- a/src/library/scala/collection/immutable/BitSet.scala +++ b/src/library/scala/collection/immutable/BitSet.scala @@ -103,6 +103,7 @@ object BitSet extends BitSetFactory[BitSet] { else new BitSetN(elems) } + @SerialVersionUID(2260107458435649300L) class BitSet1(val elems: Long) extends BitSet { protected def nwords = 1 protected def word(idx: Int) = if (idx == 0) elems else 0L @@ -110,6 +111,12 @@ object BitSet extends BitSetFactory[BitSet] { if (idx == 0) new BitSet1(w) else if (idx == 1) new BitSet2(elems, w) else fromBitMaskNoCopy(updateArray(Array(elems), idx, w)) + override def head: Int = + if (elems == 0L) throw new NoSuchElementException("Empty BitSet") + else java.lang.Long.numberOfTrailingZeros(elems) + override def tail: BitSet = + if (elems == 0L) throw new NoSuchElementException("Empty BitSet") + else new BitSet1(elems - java.lang.Long.lowestOneBit(elems)) } class BitSet2(val elems0: Long, elems1: Long) extends BitSet { @@ -119,6 +126,18 @@ object BitSet extends BitSetFactory[BitSet] { if (idx == 0) new BitSet2(w, elems1) else if (idx == 1) new BitSet2(elems0, w) else fromBitMaskNoCopy(updateArray(Array(elems0, elems1), idx, w)) + override def head: Int = + if (elems0 == 0L) { + if (elems1 == 0) throw new NoSuchElementException("Empty BitSet") + 64 + java.lang.Long.numberOfTrailingZeros(elems1) + } + else java.lang.Long.numberOfTrailingZeros(elems0) + override def tail: BitSet = + if (elems0 == 0L) { + if (elems1 == 0L) throw new NoSuchElementException("Empty BitSet") + new BitSet2(elems0, elems1 - java.lang.Long.lowestOneBit(elems1)) + } + else new BitSet2(elems0 - java.lang.Long.lowestOneBit(elems0), elems1) } /** The implementing class for bit sets with elements >= 128 (exceeding @@ -131,5 +150,15 @@ object BitSet extends BitSetFactory[BitSet] { protected def nwords = elems.length protected def word(idx: Int) = if (idx < nwords) elems(idx) else 0L protected def updateWord(idx: Int, w: Long): BitSet = fromBitMaskNoCopy(updateArray(elems, idx, w)) + override def tail: BitSet = { + val n = nwords + var i = 0 + while (i < n) { + val wi = word(i) + if (wi != 0L) return fromBitMaskNoCopy(updateArray(elems, i, wi - java.lang.Long.lowestOneBit(wi))) + i += 1 + } + throw new NoSuchElementException("Empty BitSet") + } } } diff --git a/src/library/scala/collection/immutable/HashMap.scala b/src/library/scala/collection/immutable/HashMap.scala index 92d915fe8b..3c41e1ba11 100644 --- a/src/library/scala/collection/immutable/HashMap.scala +++ b/src/library/scala/collection/immutable/HashMap.scala @@ -65,6 +65,8 @@ class HashMap[A, +B] extends AbstractMap[A, B] def - (key: A): HashMap[A, B] = removed0(key, computeHash(key), 0) + override def tail: HashMap[A, B] = this - head._1 + override def filter(p: ((A, B)) => Boolean) = { val buffer = new Array[HashMap[A, B]](bufferSize(size)) nullToEmpty(filter0(p, false, 0, buffer, 0)) @@ -156,7 +158,10 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int { implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), HashMap[A, B]] = new MapCanBuildFrom[A, B] def empty[A, B]: HashMap[A, B] = EmptyHashMap.asInstanceOf[HashMap[A, B]] - private object EmptyHashMap extends HashMap[Any, Nothing] { } + private object EmptyHashMap extends HashMap[Any, Nothing] { + override def head: (Any, Nothing) = throw new NoSuchElementException("Empty Map") + override def tail: HashMap[Any, Nothing] = throw new NoSuchElementException("Empty Map") + } // utility method to create a HashTrieMap from two leaf HashMaps (HashMap1 or HashMapCollision1) with non-colliding hash code) private def makeHashTrieMap[A, B](hash0:Int, elem0:HashMap[A, B], hash1:Int, elem1:HashMap[A, B], level:Int, size:Int) : HashTrieMap[A, B] = { diff --git a/src/library/scala/collection/immutable/HashSet.scala b/src/library/scala/collection/immutable/HashSet.scala index 07758bf5a2..2d8cc0b386 100644 --- a/src/library/scala/collection/immutable/HashSet.scala +++ b/src/library/scala/collection/immutable/HashSet.scala @@ -162,6 +162,8 @@ class HashSet[A] extends AbstractSet[A] def - (e: A): HashSet[A] = nullToEmpty(removed0(e, computeHash(e), 0)) + override def tail: HashSet[A] = this - head + override def filter(p: A => Boolean) = { val buffer = new Array[HashSet[A]](bufferSize(size)) nullToEmpty(filter0(p, false, 0, buffer, 0)) @@ -213,7 +215,10 @@ object HashSet extends ImmutableSetFactory[HashSet] { /** $setCanBuildFromInfo */ implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, HashSet[A]] = setCanBuildFrom[A] - private object EmptyHashSet extends HashSet[Any] { } + private object EmptyHashSet extends HashSet[Any] { + override def head: Any = throw new NoSuchElementException("Empty Set") + override def tail: HashSet[Any] = throw new NoSuchElementException("Empty Set") + } private[collection] def emptyInstance: HashSet[Any] = EmptyHashSet // utility method to create a HashTrieSet from two leaf HashSets (HashSet1 or HashSetCollision1) with non-colliding hash code) diff --git a/src/library/scala/collection/immutable/ListMap.scala b/src/library/scala/collection/immutable/ListMap.scala index f30c0cbf8e..5bbcf44201 100644 --- a/src/library/scala/collection/immutable/ListMap.scala +++ b/src/library/scala/collection/immutable/ListMap.scala @@ -20,6 +20,9 @@ import scala.annotation.tailrec * @see [[http://docs.scala-lang.org/overviews/collections/concrete-immutable-collection-classes.html#list_maps "Scala's Collection Library overview"]] * section on `List Maps` for more information. * + * Note that `ListMap` is built in reverse order to canonical traversal order (traversal order is oldest first). + * Thus, `head` and `tail` are O(n). To rapidly partition a `ListMap` into elements, use `last` and `init` instead. These are O(1). + * * @define Coll immutable.ListMap * @define coll immutable list map */ @@ -33,6 +36,8 @@ object ListMap extends ImmutableMapFactory[ListMap] { private object EmptyListMap extends ListMap[Any, Nothing] { override def apply(key: Any) = throw new NoSuchElementException("key not found: " + key) override def contains(key: Any) = false + override def last: (Any, Nothing) = throw new NoSuchElementException("Empty ListMap") + override def init: ListMap[Any, Nothing] = throw new NoSuchElementException("Empty ListMap") } } @@ -216,5 +221,9 @@ extends AbstractMap[A, B] remove0(k, cur.next, cur::acc) override protected def next: ListMap[A, B1] = ListMap.this + + override def last: (A, B1) = (key, value) + + override def init: ListMap[A, B1] = next } } diff --git a/src/library/scala/collection/immutable/Set.scala b/src/library/scala/collection/immutable/Set.scala index 031e5248c1..3a8ee8b0be 100644 --- a/src/library/scala/collection/immutable/Set.scala +++ b/src/library/scala/collection/immutable/Set.scala @@ -103,10 +103,11 @@ object Set extends ImmutableSetFactory[Set] { if (p(elem1)) Some(elem1) else None } + override def head: A = elem1 + override def tail: Set[A] = Set.empty // Why is Set1 non-final? Need to fix that! @deprecatedOverriding("This immutable set should do nothing on toSet but cast itself to a Set with a wider element type.", "2.11.8") override def toSet[B >: A]: Set[B] = this.asInstanceOf[Set1[B]] - } /** An optimized representation for immutable sets of size 2 */ @@ -138,6 +139,8 @@ object Set extends ImmutableSetFactory[Set] { else if (p(elem2)) Some(elem2) else None } + override def head: A = elem1 + override def tail: Set[A] = new Set1(elem2) // Why is Set2 non-final? Need to fix that! @deprecatedOverriding("This immutable set should do nothing on toSet but cast itself to a Set with a wider element type.", "2.11.8") override def toSet[B >: A]: Set[B] = this.asInstanceOf[Set2[B]] @@ -174,6 +177,8 @@ object Set extends ImmutableSetFactory[Set] { else if (p(elem3)) Some(elem3) else None } + override def head: A = elem1 + override def tail: Set[A] = new Set2(elem2, elem3) // Why is Set3 non-final? Need to fix that! @deprecatedOverriding("This immutable set should do nothing on toSet but cast itself to a Set with a wider element type.", "2.11.8") override def toSet[B >: A]: Set[B] = this.asInstanceOf[Set3[B]] @@ -212,6 +217,8 @@ object Set extends ImmutableSetFactory[Set] { else if (p(elem4)) Some(elem4) else None } + override def head: A = elem1 + override def tail: Set[A] = new Set3(elem2, elem3, elem4) // Why is Set4 non-final? Need to fix that! @deprecatedOverriding("This immutable set should do nothing on toSet but cast itself to a Set with a wider element type.", "2.11.8") override def toSet[B >: A]: Set[B] = this.asInstanceOf[Set4[B]] diff --git a/src/library/scala/collection/mutable/ListMap.scala b/src/library/scala/collection/mutable/ListMap.scala index 2ea5b1fa7c..e963af4a8a 100644 --- a/src/library/scala/collection/mutable/ListMap.scala +++ b/src/library/scala/collection/mutable/ListMap.scala @@ -15,7 +15,7 @@ package mutable import generic._ import annotation.tailrec -/** A simple mutable map backed by a list. +/** A simple mutable map backed by a list, so it preserves insertion order. * * @tparam A the type of the keys contained in this list map. * @tparam B the type of the values assigned to keys in this list map. diff --git a/src/manual/scala/man1/scalac.scala b/src/manual/scala/man1/scalac.scala index 811fb2d94e..6ffcccea25 100644 --- a/src/manual/scala/man1/scalac.scala +++ b/src/manual/scala/man1/scalac.scala @@ -5,10 +5,6 @@ package scala.man1 -/** - * @author Stephane Micheloud - * @version 1.0 - */ object scalac extends Command { import _root_.scala.tools.docutil.ManPage._ @@ -77,7 +73,7 @@ object scalac extends Command { SeqPara( "Specify where to find user class files (on Unix-based systems " & "a colon-separated list of paths, on Windows-based systems, a " & - "semicolon-separate list of paths). This does not override the " & + "semicolon-separated list of paths). This does not override the " & "built-in (" & Mono("\"boot\"") & ") search path.", "The default class path is the current directory. Setting the " & Mono("CLASSPATH") & " variable or using the " & Mono("-classpath") & " " & @@ -153,7 +149,7 @@ object scalac extends Command { "Specify location(s) of source files."), Definition( CmdOptionBound("target:", "{jvm-1.8}"), - SeqPara( + SeqPara( Mono("\"jvm-1.8\"") & " target JVM 1.8 (default)")), Definition( CmdOption("toolcp", Argument("path")), @@ -193,7 +189,7 @@ object scalac extends Command { Definition( CmdOption("Xcheckinit"), "Wrap field accessors to throw an exception on uninitialized access."), - Definition( + Definition( CmdOption("Xdev"), "Enable warnings for developers working on the Scala compiler"), Definition( @@ -209,7 +205,7 @@ object scalac extends Command { Definition( CmdOption("Xfatal-warnings"), "Fail the compilation if there are any warnings."), - Definition( + Definition( CmdOption("Xfull-lubs"), "Retain pre 2.10 behavior of less aggressive truncation of least upper bounds."), Definition( @@ -221,25 +217,25 @@ object scalac extends Command { Definition( CmdOption("Xlint"), "Enable recommended additional warnings."), - Definition( + Definition( CmdOption("Xlog-free-terms"), "Print a message when reification creates a free term."), - Definition( + Definition( CmdOption("Xlog-free-types"), "Print a message when reification resorts to generating a free type."), - Definition( + Definition( CmdOption("Xlog-implicit-conversions"), "Print a message whenever an implicit conversion is inserted."), Definition( CmdOption("Xlog-implicits"), "Show more detail on why some implicits are not applicable."), - Definition( + Definition( CmdOption("Xlog-reflective-calls"), "Print a message when a reflective method call is generated."), - Definition( + Definition( CmdOptionBound("Xmacro-settings:", Argument("option")), "Custom settings for macros."), - Definition( + Definition( CmdOption("Xmain-class", Argument("path")), "Class for manifest's Main-Class entry (only useful with -d <jar>)."), Definition( @@ -251,7 +247,7 @@ object scalac extends Command { Definition( CmdOption("Xno-forwarders"), "Do not generate static forwarders in mirror classes."), - Definition( + Definition( CmdOption("Xno-patmat-analysis"), "Don't perform exhaustivity/unreachability analysis. Also, ignore " & MItalic("@switch") & " annotation."), Definition( @@ -309,16 +305,21 @@ object scalac extends Command { Definition( CmdOptionBound("Xsource:", Argument("version")), "Treat compiler input as Scala source for the specified version, see SI-8126."), - Definition( + Definition( CmdOption("Xsource-reader", Argument("classname")), "Specify a custom method for reading source files."), - Definition( + Definition( CmdOption("Xstrict-inference"), "Don't infer known-unsound types."), Definition( CmdOption("Xverify"), "Verify generic signatures in generated bytecode (asm backend only)."), Definition( + CmdOptionBound("Xxml:", "{coalescing}"), + SeqPara( + "Configure XML parsing.", + Mono("\"coalescing\"") & " convert PCData to Text and coalesce sibling nodes (default in 2.11).")), + Definition( CmdOption("Y"), "Print a synopsis of private options.") ) @@ -332,34 +333,34 @@ object scalac extends Command { Definition( MItalic("namer"), "resolve names, attach symbols to named trees"), - Definition( + Definition( MItalic("packageobjects"), "load package objects"), - Definition( + Definition( MItalic("typer"), "the meat and potatoes: type the trees"), Definition( MItalic("patmat"), "translate match expressions"), - Definition( + Definition( MItalic("superaccessors"), "add super accessors in traits and nested classes"), - Definition( + Definition( MItalic("extmethods"), "add extension methods for inline classes"), - Definition( + Definition( MItalic("pickler"), "serialize symbol tables"), Definition( MItalic("refchecks"), "reference/override checking, translate nested objects"), - Definition( + Definition( MItalic("selectiveanf"), "ANF pre-transform for " & MItalic("@cps") & " (CPS plugin)"), - Definition( + Definition( MItalic("selectivecps"), MItalic("@cps") & "-driven transform of selectiveanf assignments (CPS plugin)"), - Definition( + Definition( MItalic("uncurry"), "uncurry, translate function values to anonymous classes"), Definition( diff --git a/src/reflect/scala/reflect/internal/TreeGen.scala b/src/reflect/scala/reflect/internal/TreeGen.scala index 2933aa3892..ec6426558c 100644 --- a/src/reflect/scala/reflect/internal/TreeGen.scala +++ b/src/reflect/scala/reflect/internal/TreeGen.scala @@ -117,6 +117,30 @@ abstract class TreeGen { case _ => qual } + + + // val selType = testedBinder.info + // + // // See the test for SI-7214 for motivation for dealias. Later `treeCondStrategy#outerTest` + // // generates an outer test based on `patType.prefix` with automatically dealises. + // // Prefixes can have all kinds of shapes SI-9110 + // val patPre = expectedTp.dealiasWiden.prefix + // val selPre = selType.dealiasWiden.prefix + // + // // Optimization: which prefixes can we disqualify from the need for an outer reference check? + // // - classes in static owners do not get outer pointers + // // - if the prefixes are statically known to be equal, the type system ensures an outer test is redundant + // !((patPre eq NoPrefix) || (selPre eq NoPrefix) + // || patPre.typeSymbol.isPackageClass + // || selPre =:= patPre) + + def mkAttributedQualifierIfPossible(prefix: Type): Option[Tree] = prefix match { + case NoType | NoPrefix | ErrorType => None + case TypeRef(_, sym, _) if sym.isModule || sym.isClass || sym.isType => None + case pre => Some(mkAttributedQualifier(prefix)) + } + + /** Builds a reference to given symbol with given stable prefix. */ def mkAttributedRef(pre: Type, sym: Symbol): RefTree = { val qual = mkAttributedQualifier(pre) diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 685c9f7476..24709cf379 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -3946,47 +3946,6 @@ trait Types check(tp1, tp2) && check(tp2, tp1) } - /** Does a pattern of type `patType` need an outer test when executed against - * selector type `selType` in context defined by `currentOwner`? - */ - def needsOuterTest(patType: Type, selType: Type, currentOwner: Symbol) = { - def createDummyClone(pre: Type): Type = { - val dummy = currentOwner.enclClass.newValue(nme.ANYname).setInfo(pre.widen) - singleType(ThisType(currentOwner.enclClass), dummy) - } - def maybeCreateDummyClone(pre: Type, sym: Symbol): Type = pre match { - case SingleType(pre1, sym1) => - if (sym1.isModule && sym1.isStatic) { - if (sym.owner == sym1 || sym.isJavaDefined || sym.owner.sourceModule.isStaticModule) NoType - else pre - } else if (sym1.isModule && sym.owner == sym1.moduleClass) { - val pre2 = maybeCreateDummyClone(pre1, sym1) - if (pre2 eq NoType) pre2 - else singleType(pre2, sym1) - } else { - createDummyClone(pre) - } - case ThisType(clazz) => - if (clazz.isModuleClass) - maybeCreateDummyClone(clazz.typeOfThis, sym) - else if (sym.owner == clazz && (sym.hasFlag(PRIVATE) || sym.privateWithin == clazz)) - NoType - else - createDummyClone(pre) - case _ => - NoType - } - // See the test for SI-7214 for motivation for dealias. Later `treeCondStrategy#outerTest` - // generates an outer test based on `patType.prefix` with automatically dealises. - patType.dealias match { - case TypeRef(pre, sym, args) => - val pre1 = maybeCreateDummyClone(pre, sym) - (pre1 ne NoType) && isPopulated(copyTypeRef(patType, pre1, sym, args), selType) - case _ => - false - } - } - def normalizePlus(tp: Type): Type = { if (isRawType(tp)) rawToExistential(tp) else tp.normalize match { diff --git a/src/reflect/scala/reflect/internal/util/WeakHashSet.scala b/src/reflect/scala/reflect/internal/util/WeakHashSet.scala index f8dfa720d5..fffe4dd881 100644 --- a/src/reflect/scala/reflect/internal/util/WeakHashSet.scala +++ b/src/reflect/scala/reflect/internal/util/WeakHashSet.scala @@ -56,9 +56,9 @@ final class WeakHashSet[A <: AnyRef](val initialCapacity: Int, val loadFactor: D /** * the limit at which we'll increase the size of the hash table */ - var threshhold = computeThreshHold + private[this] var threshold = computeThreshold - private[this] def computeThreshHold: Int = (table.size * loadFactor).ceil.toInt + private[this] def computeThreshold: Int = (table.size * loadFactor).ceil.toInt /** * find the bucket associated with an element's hash code @@ -121,7 +121,7 @@ final class WeakHashSet[A <: AnyRef](val initialCapacity: Int, val loadFactor: D private[this] def resize() { val oldTable = table table = new Array[Entry[A]](oldTable.size * 2) - threshhold = computeThreshHold + threshold = computeThreshold @tailrec def tableLoop(oldBucket: Int): Unit = if (oldBucket < oldTable.size) { @@ -176,7 +176,7 @@ final class WeakHashSet[A <: AnyRef](val initialCapacity: Int, val loadFactor: D def add() = { table(bucket) = new Entry(elem, hash, oldHead, queue) count += 1 - if (count > threshhold) resize() + if (count > threshold) resize() elem } @@ -206,7 +206,7 @@ final class WeakHashSet[A <: AnyRef](val initialCapacity: Int, val loadFactor: D def add() { table(bucket) = new Entry(elem, hash, oldHead, queue) count += 1 - if (count > threshhold) resize() + if (count > threshold) resize() } @tailrec @@ -252,7 +252,7 @@ final class WeakHashSet[A <: AnyRef](val initialCapacity: Int, val loadFactor: D // empty this set override def clear(): Unit = { table = new Array[Entry[A]](table.size) - threshhold = computeThreshHold + threshold = computeThreshold count = 0 // drain the queue - doesn't do anything because we're throwing away all the values anyway diff --git a/src/scaladoc/scala/tools/nsc/doc/DocFactory.scala b/src/scaladoc/scala/tools/nsc/doc/DocFactory.scala index 47ddfb8aa9..fb6c39d7e3 100644 --- a/src/scaladoc/scala/tools/nsc/doc/DocFactory.scala +++ b/src/scaladoc/scala/tools/nsc/doc/DocFactory.scala @@ -111,11 +111,6 @@ class DocFactory(val reporter: Reporter, val settings: doc.Settings) { processor case universer: Universer => val universe = makeUniverse(Left(files)) getOrElse { throw NoCompilerRunException } universer setUniverse universe - - docletInstance match { - case indexer: Indexer => indexer setIndex model.IndexModelFactory.makeIndex(universe) - case _ => () - } case _ => () } docletInstance.generate() diff --git a/src/scaladoc/scala/tools/nsc/doc/Settings.scala b/src/scaladoc/scala/tools/nsc/doc/Settings.scala index de86acb6d6..59380dd782 100644 --- a/src/scaladoc/scala/tools/nsc/doc/Settings.scala +++ b/src/scaladoc/scala/tools/nsc/doc/Settings.scala @@ -48,7 +48,7 @@ class Settings(error: String => Unit, val printMsg: String => Unit = println(_)) val docfooter = StringSetting ( "-doc-footer", "footer", - "A footer on every Scaladoc page, by default the EPFL/Typesafe copyright notice. Can be overridden with a custom footer.", + "A footer on every Scaladoc page, by default the EPFL/Lightbend copyright notice. Can be overridden with a custom footer.", "" ) diff --git a/src/scaladoc/scala/tools/nsc/doc/doclet/Generator.scala b/src/scaladoc/scala/tools/nsc/doc/doclet/Generator.scala index 42b56aa927..b4ede6d358 100644 --- a/src/scaladoc/scala/tools/nsc/doc/doclet/Generator.scala +++ b/src/scaladoc/scala/tools/nsc/doc/doclet/Generator.scala @@ -9,7 +9,6 @@ import scala.collection._ * to configure what data is actually available to the generator: * - A `Universer` provides a `Universe` data structure representing the interfaces and comments of the documented * program. - * - An `Indexer` provides precalculated indexing information about a universe. * To implement this class only requires defining method `generateImpl`. */ abstract class Generator { diff --git a/src/scaladoc/scala/tools/nsc/doc/doclet/Indexer.scala b/src/scaladoc/scala/tools/nsc/doc/doclet/Indexer.scala deleted file mode 100644 index 12fee69cca..0000000000 --- a/src/scaladoc/scala/tools/nsc/doc/doclet/Indexer.scala +++ /dev/null @@ -1,21 +0,0 @@ -package scala.tools.nsc -package doc -package doclet - -/** A `Generator` may implement the `Indexer` trait to gain access to pre-calculated indexing information */ -trait Indexer extends Generator with Universer { - - protected var indexField: Index = null - - def index: Index = indexField - - def setIndex(i: Index) { - assert(indexField == null) - indexField = i - } - - checks += { () => - indexField != null - } - -} diff --git a/src/scaladoc/scala/tools/nsc/doc/html/Doclet.scala b/src/scaladoc/scala/tools/nsc/doc/html/Doclet.scala index cad7cf3298..541266e4cc 100644 --- a/src/scaladoc/scala/tools/nsc/doc/html/Doclet.scala +++ b/src/scaladoc/scala/tools/nsc/doc/html/Doclet.scala @@ -11,10 +11,10 @@ import doclet._ /** The default doclet used by the scaladoc command line tool * when no user-provided doclet is provided. */ -class Doclet extends Generator with Universer with Indexer { +class Doclet extends Generator with Universer { def generateImpl() { - new html.HtmlFactory(universe, index, new ScalaDocReporter(universe.settings)).generate() + new html.HtmlFactory(universe, new ScalaDocReporter(universe.settings)).generate() } } diff --git a/src/scaladoc/scala/tools/nsc/doc/html/HtmlFactory.scala b/src/scaladoc/scala/tools/nsc/doc/html/HtmlFactory.scala index 4f332f1dbe..9d61cd2e2b 100644 --- a/src/scaladoc/scala/tools/nsc/doc/html/HtmlFactory.scala +++ b/src/scaladoc/scala/tools/nsc/doc/html/HtmlFactory.scala @@ -16,7 +16,7 @@ import page.diagram._ /** A class that can generate Scaladoc sites to some fixed root folder. * @author David Bernard * @author Gilles Dubochet */ -class HtmlFactory(val universe: doc.Universe, index: doc.Index, val reporter: ScalaDocReporter) { +class HtmlFactory(val universe: doc.Universe, val reporter: ScalaDocReporter) { import page.{IndexScript, EntityPage} /** The character encoding to be used for generated Scaladoc sites. @@ -99,16 +99,10 @@ class HtmlFactory(val universe: doc.Universe, index: doc.Index, val reporter: Sc libResources foreach (s => copyResource("lib/" + s)) - IndexScript(universe, index) writeFor this + IndexScript(universe) writeFor this - if (index.hasDeprecatedMembers) - new page.DeprecatedIndex(universe, index, reporter) writeFor this try { writeTemplates(_ writeFor this) - - for (letter <- index.firstLetterIndex) { - new html.page.ReferenceIndex(letter._1, index, universe, reporter) writeFor this - } } finally { DiagramStats.printStats(universe.settings) universe.dotRunner.cleanup() diff --git a/src/scaladoc/scala/tools/nsc/doc/html/page/DeprecatedIndex.scala b/src/scaladoc/scala/tools/nsc/doc/html/page/DeprecatedIndex.scala deleted file mode 100644 index e8cb58c732..0000000000 --- a/src/scaladoc/scala/tools/nsc/doc/html/page/DeprecatedIndex.scala +++ /dev/null @@ -1,60 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2007-2013 LAMP/EPFL - */ - -package scala -package tools -package nsc -package doc -package html -package page - -import doc.model._ - -class DeprecatedIndex(universe: Universe, index: doc.Index, rep: ScalaDocReporter) extends HtmlPage { - - def reporter = rep - - def path = List("deprecated-list.html") - - def title = { - val s = universe.settings - ( if (!s.doctitle.isDefault) s.doctitle.value else "" ) + - ( if (!s.docversion.isDefault) (" " + s.docversion.value) else "" ) - } - - def headers = - <xml:group> - <link href={ relativeLinkTo(List("ref-index.css", "lib")) } media="screen" type="text/css" rel="stylesheet"/> - <script type="text/javascript" src={ relativeLinkTo{List("jquery.js", "lib")} }></script> - </xml:group> - - - private def entry(name: String, methods: Iterable[MemberEntity]) = { - val occurrences = methods.filter(_.deprecation.isDefined).map(method => - templateToHtml(method.inDefinitionTemplates.head) - ).toList.distinct - - <div class="entry"> - <div class="name">{ name }</div> - <div class="occurrences">{ - for (owner <- occurrences) yield owner ++ scala.xml.Text(" ") - }</div> - </div> - } - - def deprecatedEntries = { - val available = ('_' +: ('a' to 'z')).flatMap(index.firstLetterIndex.get) - - for (group <- available; - value <- group if value._2.find(_.deprecation.isDefined).isDefined) - yield value - } - - def body = - <body>{ - for(value <- deprecatedEntries) yield - entry(value._1, value._2.view) - }</body> - -} diff --git a/src/scaladoc/scala/tools/nsc/doc/html/page/Entity.scala b/src/scaladoc/scala/tools/nsc/doc/html/page/Entity.scala index 55a85474f6..e45847da78 100644 --- a/src/scaladoc/scala/tools/nsc/doc/html/page/Entity.scala +++ b/src/scaladoc/scala/tools/nsc/doc/html/page/Entity.scala @@ -404,7 +404,7 @@ trait EntityPage extends HtmlPage { { if (Set("epfl", "EPFL").contains(tpl.universe.settings.docfooter.value)) - <div id="footer">Scala programming documentation. Copyright (c) 2003-2016 <a href="http://www.epfl.ch" target="_top">EPFL</a>, with contributions from <a href="http://typesafe.com" target="_top">Typesafe</a>.</div> + <div id="footer">Scala programming documentation. Copyright (c) 2003-2016 <a href="http://www.epfl.ch" target="_top">EPFL</a>, with contributions from <a href="http://www.lightbend.com" target="_top">Lightbend</a>.</div> else <div id="footer"> { tpl.universe.settings.docfooter.value } </div> } @@ -585,7 +585,7 @@ trait EntityPage extends HtmlPage { <br/> ++ scala.xml.Text("To access this member you can use a ") ++ <a href="http://stackoverflow.com/questions/2087250/what-is-the-purpose-of-type-ascription-in-scala" target="_blank">type ascription</a> ++ scala.xml.Text(":") ++ - <br/> ++ <div class="cmt"><pre>{"(" + Template.lowerFirstLetter(tpl.name) + ": " + conv.targetType.name + ")." + mbr.name + params }</pre></div> + <br/> ++ <div class="cmt"><pre>{"(" + EntityPage.lowerFirstLetter(tpl.name) + ": " + conv.targetType.name + ")." + mbr.name + params }</pre></div> } val shadowingWarning: NodeSeq = @@ -1129,4 +1129,8 @@ object EntityPage { def tpl = docTpl def reporter = rep } + + /* 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 lowerFirstLetter(s: String) = if (s.length >= 1) s.substring(0,1).toLowerCase() + s.substring(1) else s } diff --git a/src/scaladoc/scala/tools/nsc/doc/html/page/Index.scala b/src/scaladoc/scala/tools/nsc/doc/html/page/Index.scala deleted file mode 100644 index 8204f413fd..0000000000 --- a/src/scaladoc/scala/tools/nsc/doc/html/page/Index.scala +++ /dev/null @@ -1,75 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2007-2013 LAMP/EPFL - * @author David Bernard, Manohar Jonnalagedda, Felix Mulder - */ - -package scala.tools.nsc -package doc -package html -package page - -import model._ -import scala.collection._ -import scala.xml._ - -class Index(universe: doc.Universe, val index: doc.Index, rep: ScalaDocReporter) extends HtmlPage { - - def reporter = rep - - def path = List("index.html") - - def title = "" - - val headers = - <xml:group> - <link href={ relativeLinkTo{List("index.css", "lib")} } media="screen" type="text/css" rel="stylesheet"/> - <script type="text/javascript" src={ relativeLinkTo{List("jquery.js", "lib")} }></script> - <script type="text/javascript" src={ relativeLinkTo{List("index.js", "lib")} }></script> - <script type="text/javascript" src="index.js"></script> - <script type="text/javascript" src={ relativeLinkTo{List("scheduler.js", "lib")} }></script> - </xml:group> - - val body = - <body> - { search } - <div id="search-results"> - <div id="results-content"> - <div id="entity-results"></div> - <div id="member-results"></div> - </div> - </div> - <div id="content" style="-webkit-overflow-scrolling: touch;"> - <iframe id="template" name="template" src={ relativeLinkTo{List("package.html")} }/> - </div> - </body> - - def search = - <div id="search"> - <span id="doc-title"> - {universe.settings.doctitle.value} - <span id="doc-version"> - { - val version = universe.settings.docversion.value - - if (version.length > "XX.XX.XX-XXX".length) { - reporter.warning(null, - s"doc-version ($version) is too long to be displayed in the webview") - "" - } else version - } - </span> - </span> - <span class="close-results"><span class="left"><</span> Back</span> - <div id="textfilter"> - <span class="input"> - <input autocapitalize="none" placeholder="Search" id="index-input" type="text" accesskey="/"/> - <span class="clear">✖</span> - </span> - </div> - </div> - - def packageQualifiedName(ety: DocTemplateEntity): String = - if (ety.inTemplate.isPackage) ety.name - else (packageQualifiedName(ety.inTemplate) + "." + ety.name) - -} diff --git a/src/scaladoc/scala/tools/nsc/doc/html/page/IndexScript.scala b/src/scaladoc/scala/tools/nsc/doc/html/page/IndexScript.scala index 2c38036bb6..dd242e6b3b 100644 --- a/src/scaladoc/scala/tools/nsc/doc/html/page/IndexScript.scala +++ b/src/scaladoc/scala/tools/nsc/doc/html/page/IndexScript.scala @@ -12,7 +12,7 @@ import scala.tools.nsc.doc.model.{Package, DocTemplateEntity} import scala.tools.nsc.doc.html.{Page, HtmlFactory} import scala.util.parsing.json.{JSONObject, JSONArray, JSONType} -class IndexScript(universe: doc.Universe, index: doc.Index) extends Page { +class IndexScript(universe: doc.Universe) extends Page { import model._ import scala.tools.nsc.doc.base.comment.Text import scala.collection.immutable.Map @@ -140,6 +140,5 @@ class IndexScript(universe: doc.Universe, index: doc.Index) extends Page { } object IndexScript { - def apply(universe: doc.Universe, index: doc.Index) = - new IndexScript(universe, index) + def apply(universe: doc.Universe) = new IndexScript(universe) } diff --git a/src/scaladoc/scala/tools/nsc/doc/html/page/ReferenceIndex.scala b/src/scaladoc/scala/tools/nsc/doc/html/page/ReferenceIndex.scala deleted file mode 100644 index 6780f17a8c..0000000000 --- a/src/scaladoc/scala/tools/nsc/doc/html/page/ReferenceIndex.scala +++ /dev/null @@ -1,63 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2007-2013 LAMP/EPFL - * @author Pedro Furlanetto - */ - -package scala -package tools -package nsc -package doc -package html -package page - -import doc.model._ - -class ReferenceIndex(letter: Char, index: doc.Index, universe: Universe, rep: ScalaDocReporter) extends HtmlPage { - - def reporter = rep - - def path = List("index-"+letter+".html", "index") - - def title = { - val s = universe.settings - ( if (!s.doctitle.isDefault) s.doctitle.value else "" ) + - ( if (!s.docversion.isDefault) (" " + s.docversion.value) else "" ) - } - - def headers = - <xml:group> - <link href={ relativeLinkTo(List("ref-index.css", "lib")) } media="screen" type="text/css" rel="stylesheet"/> - <script type="text/javascript" src={ relativeLinkTo{List("jquery.js", "lib")} }></script> - </xml:group> - - - private def entry(name: String, methods: Iterable[MemberEntity]) = { - val occurrences = methods.map(method => { - val html = templateToHtml(method.inDefinitionTemplates.head) - if (method.deprecation.isDefined) { - <strike>{ html }</strike> - } else { - html - } - }).toList.distinct - - <div class="entry"> - <div class="name">{ - if (methods.find { ! _.deprecation.isDefined } != None) - name - else - <strike>{ name }</strike> - }</div> - <div class="occurrences">{ - for (owner <- occurrences) yield owner ++ scala.xml.Text(" ") - }</div> - </div> - } - - def body = - <body>{ - for(groups <- index.firstLetterIndex(letter)) yield - entry(groups._1, groups._2.view) - }</body> - -} diff --git a/src/scaladoc/scala/tools/nsc/doc/html/page/Template.scala b/src/scaladoc/scala/tools/nsc/doc/html/page/Template.scala deleted file mode 100644 index f5e909cf90..0000000000 --- a/src/scaladoc/scala/tools/nsc/doc/html/page/Template.scala +++ /dev/null @@ -1,987 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2007-2013 LAMP/EPFL - * @author David Bernard, Manohar Jonnalagedda - */ - -package scala -package tools -package nsc -package doc -package html -package page - -import base._ -import base.comment._ - -import scala.collection.mutable -import scala.xml.{NodeSeq, Text, UnprefixedAttribute} -import scala.language.postfixOps - -import model._ -import model.diagram._ -import diagram._ - -class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemplateEntity, rep: ScalaDocReporter) extends HtmlPage { - - def reporter = rep - - val path = templateToPath(tpl) - - def title = { - val s = universe.settings - ( if (!s.doctitle.isDefault) s.doctitle.value + " " else "" ) + - ( if (!s.docversion.isDefault) s.docversion.value else "" ) + - ( if ((!s.doctitle.isDefault || !s.docversion.isDefault) && tpl.qualifiedName != "_root_") " - " + tpl.qualifiedName else "" ) - } - - val headers = - <xml:group> - <link href={ relativeLinkTo{List("template.css", "lib")} } media="screen" type="text/css" rel="stylesheet"/> - <link href={ relativeLinkTo{List("diagrams.css", "lib")} } media="screen" type="text/css" rel="stylesheet" id="diagrams-css" /> - <script type="text/javascript" src={ relativeLinkTo{List("jquery.js", "lib")} } id="jquery-js"></script> - <script type="text/javascript" src={ relativeLinkTo{List("jquery.panzoom.min.js", "lib")} }></script> - <script type="text/javascript" src={ relativeLinkTo{List("jquery.mousewheel.min.js", "lib")} }></script> - <script type="text/javascript" src={ relativeLinkTo{List("template.js", "lib")} }></script> - <script type="text/javascript" src={ relativeLinkTo{List("tools.tooltip.js", "lib")} }></script> - { if (universe.settings.docDiagrams.value) { - <script type="text/javascript" src={ relativeLinkTo{List("modernizr.custom.js", "lib")} }></script> - <script type="text/javascript" src={ relativeLinkTo{List("diagrams.js", "lib")} } id="diagrams-js"></script> - } else NodeSeq.Empty } - <script type="text/javascript"> - if(top === self) {{ - var url = '{ val p = templateToPath(tpl); "../" * (p.size - 1) + "index.html" }'; - var hash = '{ val p = templateToPath(tpl); (p.tail.reverse ::: List(p.head.replace(".html", ""))).mkString(".") }'; - var anchor = window.location.hash; - var anchor_opt = ''; - if (anchor.length { scala.xml.Unparsed(">=") /* unless we use Unparsed, it gets escaped and crashes the script */ } 1) - anchor_opt = '@' + anchor.substring(1); - window.location.href = url + '#' + hash + anchor_opt; - }} - </script> - </xml:group> - - val valueMembers = - tpl.methods ++ tpl.values ++ tpl.templates.filter(x => x.isObject || x.isPackage) sorted - - val (absValueMembers, nonAbsValueMembers) = - valueMembers partition (_.isAbstract) - - val (deprValueMembers, nonDeprValueMembers) = - nonAbsValueMembers partition (_.deprecation.isDefined) - - val (concValueMembers, shadowedImplicitMembers) = - nonDeprValueMembers partition (!_.isShadowedOrAmbiguousImplicit) - - val typeMembers = - 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 - case _ => Nil - }) - - /* for body, there is a special case for AnyRef, otherwise AnyRef appears - * like a package/object this problem should be fixed, this implementation - * is just a patch. */ - val body = { - val templateName = if (tpl.isRootPackage) "root package" else tpl.name - val displayName = tpl.companion match { - case Some(companion) if (companion.visibility.isPublic && companion.inSource != None) => - <a href={relativeLinkTo(companion)} title={docEntityKindToCompanionTitle(tpl)}>{ templateName }</a> - case _ => - templateName - } - val owner = { - if (tpl.isRootPackage || tpl.inTemplate.isRootPackage) - NodeSeq.Empty - else - <p id="owner">{ templatesToHtml(tpl.inTemplate.toRoot.reverse.tail, scala.xml.Text(".")) }</p> - } - - <body class={ tpl.kind + (if (tpl.isType) " type" else " value") }> - <div id="definition"> - { - val (src, alt) = docEntityKindToBigImage(tpl) - - val identifier = alt.toString.substring(0,2).toLowerCase - - tpl.companion match { - case Some(companion) if (companion.visibility.isPublic && companion.inSource != None) => - <a href={relativeLinkTo(companion)} title={docEntityKindToCompanionTitle(tpl)}><div class={s"big-circle companion $identifier"}>{ identifier.substring(0,1) }</div></a> - case _ => - <div class={ "big-circle " + alt.toString.toLowerCase }>{ identifier.substring(0,1) }</div> - }} - { owner } - <h1>{ displayName }</h1>{ - if (tpl.isPackage) NodeSeq.Empty else <h3>{companionAndPackage(tpl)}</h3> - }{ permalink(tpl) } - { signature(tpl, isSelf = true) } - </div> - - { memberToCommentHtml(tpl, tpl.inTemplate, isSelf = true) } - - <div id="mbrsel"> - <div class='toggle'></div> - <div id='textfilter'><span class='input'><input id='mbrsel-input' placeholder='Filter members' type='text' accesskey='/'/></span><span class='clear'>✖</span></div> - <div id='filterby'> - { 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> - { - 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 - { - if (!tpl.linearizationTemplates.isEmpty) - <div class="ancestors"> - <span class="filtertype">Inherited<br/> - </span> - <ol id="linearization"> - { (tpl :: tpl.linearizationTemplates).map(wte => <li class="in" name={ wte.qualifiedName }><span>{ wte.name }</span></li>) } - </ol> - </div> - else NodeSeq.Empty - } ++ { - if (!tpl.conversions.isEmpty) - <div class="ancestors"> - <span class="filtertype">Implicitly<br/> - </span> - <ol id="implicits"> { - tpl.conversions.map { conv => - val name = conv.conversionQualifiedName - val hide = universe.settings.hiddenImplicits(name) - <li class="in" name={ name } data-hidden={ hide.toString }><span>{ "by " + conv.conversionShortName }</span></li> - } - } - </ol> - </div> - else NodeSeq.Empty - } ++ - <div class="ancestors"> - <span class="filtertype"></span> - <ol> - <li class="hideall out"><span>Hide All</span></li> - <li class="showall in"><span>Show All</span></li> - </ol> - </div> - } - { - <div id="visbl"> - <span class="filtertype">Visibility</span> - <ol><li class="public in"><span>Public</span></li><li class="all out"><span>All</span></li></ol> - </div> - } - </div> - </div> - - <div id="template"> - <div id="allMembers"> - { if (constructors.isEmpty) NodeSeq.Empty else - <div id="constructors" class="members"> - <h3>Instance Constructors</h3> - <ol>{ constructors map (memberToHtml(_, tpl)) }</ol> - </div> - } - - { if (typeMembers.isEmpty) NodeSeq.Empty else - <div id="types" class="types members"> - <h3>Type Members</h3> - <ol>{ typeMembers map (memberToHtml(_, tpl)) }</ol> - </div> - } - - { if (absValueMembers.isEmpty) NodeSeq.Empty else - <div class="values members"> - <h3>Abstract Value Members</h3> - <ol>{ absValueMembers map (memberToHtml(_, tpl)) }</ol> - </div> - } - - { if (concValueMembers.isEmpty) NodeSeq.Empty else - <div class="values members"> - <h3>{ if (absValueMembers.isEmpty) "Value Members" else "Concrete Value Members" }</h3> - <ol>{ concValueMembers map (memberToHtml(_, tpl)) }</ol> - </div> - } - - { if (shadowedImplicitMembers.isEmpty) NodeSeq.Empty else - <div class="values members"> - <h3>Shadowed Implicit Value Members</h3> - <ol>{ shadowedImplicitMembers map (memberToHtml(_, tpl)) }</ol> - </div> - } - - { if (deprValueMembers.isEmpty) NodeSeq.Empty else - <div class="values members"> - <h3>Deprecated Value Members</h3> - <ol>{ deprValueMembers map (memberToHtml(_, tpl)) }</ol> - </div> - } - </div> - - <div id="inheritedMembers"> - { - // linearization - NodeSeq fromSeq (for ((superTpl, superType) <- (tpl.linearizationTemplates zip tpl.linearizationTypes)) yield - <div class="parent" name={ superTpl.qualifiedName }> - <h3>Inherited from { - typeToHtmlWithStupidTypes(tpl, superTpl, superType) - }</h3> - </div> - ) - } - { - // implicitly inherited - NodeSeq fromSeq (for (conversion <- (tpl.conversions)) yield - <div class="conversion" name={ conversion.conversionQualifiedName }> - <h3>Inherited by implicit conversion { conversion.conversionShortName } from - { typeToHtml(tpl.resultType, hasLinks = true) } to { typeToHtml(conversion.targetType, hasLinks = true) } - </h3> - </div> - ) - } - </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> - - { - if (Set("epfl", "EPFL").contains(tpl.universe.settings.docfooter.value)) - <div id="footer">Scala programming documentation. Copyright (c) 2003-2016 <a href="http://www.epfl.ch" target="_top">EPFL</a>, with contributions from <a href="http://typesafe.com" target="_top">Typesafe</a>.</div> - else - <div id="footer"> { tpl.universe.settings.docfooter.value } </div> - } - </body> - } - - def memberToHtml(mbr: MemberEntity, inTpl: DocTemplateEntity): NodeSeq = { - // Sometimes it's same, do we need signatureCompat still? - val sig = if (mbr.signature == mbr.signatureCompat) { - <a id={ mbr.signature }/> - } else { - <a id={ mbr.signature }/><a id={ mbr.signatureCompat }/> - } - - val memberComment = memberToCommentHtml(mbr, inTpl, isSelf = 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" } - group={ mbr.group }> - { sig } - { signature(mbr, isSelf = false) } - { memberComment } - </li> - } - - def memberToCommentHtml(mbr: MemberEntity, inTpl: DocTemplateEntity, isSelf: Boolean): NodeSeq = { - mbr match { - case dte: DocTemplateEntity if isSelf => - // comment of class itself - <xml:group> - <div id="comment" class="fullcommenttop">{ memberToCommentBodyHtml(mbr, inTpl, isSelf = true) }</div> - </xml:group> - case _ => - // comment of non-class member or non-documentented inner class - val commentBody = memberToCommentBodyHtml(mbr, inTpl, isSelf = false) - if (commentBody.isEmpty) - NodeSeq.Empty - else { - val shortComment = memberToShortCommentHtml(mbr, isSelf) - val longComment = memberToUseCaseCommentHtml(mbr, isSelf) ++ memberToCommentBodyHtml(mbr, inTpl, isSelf) - - val includedLongComment = if (shortComment.text.trim == longComment.text.trim) - NodeSeq.Empty - else - <div class="fullcomment">{ longComment }</div> - - shortComment ++ includedLongComment - } - } - } - - def memberToUseCaseCommentHtml(mbr: MemberEntity, isSelf: Boolean): NodeSeq = { - mbr match { - case nte: NonTemplateMemberEntity if nte.isUseCase => - inlineToHtml(comment.Text("[use case] ")) - case _ => NodeSeq.Empty - } - } - - def memberToShortCommentHtml(mbr: MemberEntity, isSelf: Boolean): NodeSeq = - mbr.comment.fold(NodeSeq.Empty) { comment => - <p class="shortcomment cmt">{ memberToUseCaseCommentHtml(mbr, isSelf) }{ inlineToHtml(comment.short) }</p> - } - - def memberToInlineCommentHtml(mbr: MemberEntity, isSelf: Boolean): NodeSeq = - <p class="comment cmt">{ inlineToHtml(mbr.comment.get.short) }</p> - - def memberToCommentBodyHtml(mbr: MemberEntity, inTpl: DocTemplateEntity, isSelf: Boolean, isReduced: Boolean = false): NodeSeq = { - val s = universe.settings - - val memberComment = - if (mbr.comment.isEmpty) NodeSeq.Empty - else <div class="comment cmt">{ commentToHtml(mbr.comment) }</div> - - val authorComment = - if (! s.docAuthor || mbr.comment.isEmpty || - mbr.comment.isDefined && mbr.comment.get.authors.isEmpty) NodeSeq.Empty - else <div class="comment cmt"> - {if (mbr.comment.get.authors.size > 1) <h6>Authors:</h6> else <h6>Author:</h6>} - { mbr.comment.get.authors map bodyToHtml} - </div> - - val paramComments = { - val prs: List[ParameterEntity] = mbr match { - case cls: Class => cls.typeParams ::: cls.valueParams.flatten - case trt: Trait => trt.typeParams - case dfe: Def => dfe.typeParams ::: dfe.valueParams.flatten - case ctr: Constructor => ctr.valueParams.flatten - case _ => Nil - } - - def paramCommentToHtml(prs: List[ParameterEntity], comment: Comment): NodeSeq = prs match { - - case (tp: TypeParam) :: rest => - val paramEntry: NodeSeq = { - <dt class="tparam">{ tp.name }</dt><dd class="cmt">{ bodyToHtml(comment.typeParams(tp.name)) }</dd> - } - paramEntry ++ paramCommentToHtml(rest, comment) - - case (vp: ValueParam) :: rest => - val paramEntry: NodeSeq = { - <dt class="param">{ vp.name }</dt><dd class="cmt">{ bodyToHtml(comment.valueParams(vp.name)) }</dd> - } - paramEntry ++ paramCommentToHtml(rest, comment) - - case _ => - NodeSeq.Empty - } - - mbr.comment.fold(NodeSeq.Empty) { comment => - val cmtedPrs = prs filter { - case tp: TypeParam => comment.typeParams isDefinedAt tp.name - case vp: ValueParam => comment.valueParams isDefinedAt vp.name - } - if (cmtedPrs.isEmpty && comment.result.isEmpty) NodeSeq.Empty - else { - <dl class="paramcmts block">{ - paramCommentToHtml(cmtedPrs, comment) ++ ( - comment.result match { - case None => NodeSeq.Empty - case Some(cmt) => - <dt>returns</dt><dd class="cmt">{ bodyToHtml(cmt) }</dd> - }) - }</dl> - } - } - } - - val implicitInformation = mbr.byConversion match { - case Some(conv) => - <dt class="implicit">Implicit information</dt> ++ - { - val targetType = typeToHtml(conv.targetType, hasLinks = true) - val conversionMethod = conv.convertorMethod match { - case Left(member) => Text(member.name) - case Right(name) => Text(name) - } - - // strip off the package object endings, they make things harder to follow - val conversionOwnerQualifiedNane = conv.convertorOwner.qualifiedName.stripSuffix(".package") - val conversionOwner = templateToHtml(conv.convertorOwner, conversionOwnerQualifiedNane) - - val constraintText = conv.constraints match { - case Nil => - NodeSeq.Empty - case List(constraint) => - scala.xml.Text("This conversion will take place only if ") ++ constraintToHtml(constraint) ++ scala.xml.Text(".") - case List(constraint1, constraint2) => - scala.xml.Text("This conversion will take place only if ") ++ constraintToHtml(constraint1) ++ - scala.xml.Text(" and at the same time ") ++ constraintToHtml(constraint2) ++ scala.xml.Text(".") - case constraints => - <br/> ++ "This conversion will take place only if all of the following constraints are met:" ++ <br/> ++ { - var index = 0 - constraints map { constraint => scala.xml.Text({ index += 1; index } + ". ") ++ constraintToHtml(constraint) ++ <br/> } - } - } - - <dd> - This member is added by an implicit conversion from { typeToHtml(inTpl.resultType, hasLinks = true) } to - { targetType } performed by method { conversionMethod } in { conversionOwner }. - { constraintText } - </dd> - } ++ { - if (mbr.isShadowedOrAmbiguousImplicit) { - // These are the members that are shadowing or ambiguating the current implicit - // see ImplicitMemberShadowing trait for more information - val shadowingSuggestion = { - val params = mbr match { - case d: Def => d.valueParams map (_ map (_ name) mkString("(", ", ", ")")) mkString - case _ => "" // no parameters - } - <br/> ++ scala.xml.Text("To access this member you can use a ") ++ - <a href="http://stackoverflow.com/questions/2087250/what-is-the-purpose-of-type-ascription-in-scala" - target="_blank">type ascription</a> ++ scala.xml.Text(":") ++ - <br/> ++ <div class="cmt"><pre>{"(" + Template.lowerFirstLetter(tpl.name) + ": " + conv.targetType.name + ")." + mbr.name + params }</pre></div> - } - - val shadowingWarning: NodeSeq = - if (mbr.isShadowedImplicit) - scala.xml.Text("This implicitly inherited member is shadowed by one or more members in this " + - "class.") ++ shadowingSuggestion - else if (mbr.isAmbiguousImplicit) - scala.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 - else NodeSeq.Empty - - <dt class="implicit">Shadowing</dt> ++ - <dd>{ shadowingWarning }</dd> - - } else NodeSeq.Empty - } - case _ => - NodeSeq.Empty - } - - // --- start attributes block vals - val attributes: NodeSeq = { - val fvs: List[comment.Paragraph] = visibility(mbr).toList - if (fvs.isEmpty || isReduced) NodeSeq.Empty - else { - <dt>Attributes</dt> - <dd>{ fvs map { fv => { inlineToHtml(fv.text) ++ scala.xml.Text(" ") } } }</dd> - } - } - - val definitionClasses: NodeSeq = { - val inDefTpls = mbr.inDefinitionTemplates - if ((inDefTpls.tail.isEmpty && (inDefTpls.head == inTpl)) || isReduced) NodeSeq.Empty - else { - <dt>Definition Classes</dt> - <dd>{ templatesToHtml(inDefTpls, scala.xml.Text(" → ")) }</dd> - } - } - - val fullSignature: NodeSeq = { - mbr match { - case nte: NonTemplateMemberEntity if nte.isUseCase => - <div class="full-signature-block toggleContainer"> - <span class="toggle">Full Signature</span> - <div class="hiddenContent full-signature-usecase">{ signature(nte.useCaseOf.get,isSelf = true) }</div> - </div> - case _ => NodeSeq.Empty - } - } - - val selfType: NodeSeq = mbr match { - case dtpl: DocTemplateEntity if (isSelf && !dtpl.selfType.isEmpty && !isReduced) => - <dt>Self Type</dt> - <dd>{ typeToHtml(dtpl.selfType.get, hasLinks = true) }</dd> - case _ => NodeSeq.Empty - } - - val annotations: NodeSeq = { - // A list of annotations which don't show their arguments, e. g. because they are shown separately. - val annotationsWithHiddenArguments = List("deprecated", "Deprecated", "migration") - - def showArguments(annotation: Annotation) = - !(annotationsWithHiddenArguments.contains(annotation.qualifiedName)) - - if (!mbr.annotations.isEmpty) { - <dt>Annotations</dt> - <dd>{ - mbr.annotations.map { annot => - <xml:group> - <span class="name">@{ templateToHtml(annot.annotationClass) }</span>{ - if (showArguments(annot)) argumentsToHtml(annot.arguments) else NodeSeq.Empty - } - </xml:group> - } - } - </dd> - } else NodeSeq.Empty - } - - val sourceLink: NodeSeq = mbr match { - case dtpl: DocTemplateEntity if (isSelf && dtpl.sourceUrl.isDefined && dtpl.inSource.isDefined && !isReduced) => - val (absFile, _) = dtpl.inSource.get - <dt>Source</dt> - <dd>{ <a href={ dtpl.sourceUrl.get.toString } target="_blank">{ Text(absFile.file.getName) }</a> }</dd> - case _ => NodeSeq.Empty - } - - val deprecation: NodeSeq = - mbr.deprecation match { - case Some(deprecation) if !isReduced => - <dt>Deprecated</dt> - <dd class="cmt">{ bodyToHtml(deprecation) }</dd> - case _ => NodeSeq.Empty - } - - val migration: NodeSeq = - mbr.migration match { - case Some(migration) if !isReduced => - <dt>Migration</dt> - <dd class="cmt">{ bodyToHtml(migration) }</dd> - case _ => NodeSeq.Empty - } - - val mainComment: NodeSeq = mbr.comment match { - case Some(comment) if (! isReduced) => - def orEmpty[T](it: Iterable[T])(gen: =>NodeSeq): NodeSeq = - if (it.isEmpty) NodeSeq.Empty else gen - - val example = - orEmpty(comment.example) { - <div class="block">Example{ if (comment.example.length > 1) "s" else ""}: - <ol>{ - val exampleXml: List[NodeSeq] = for (ex <- comment.example) yield - <li class="cmt">{ bodyToHtml(ex) }</li> - exampleXml.reduceLeft(_ ++ Text(", ") ++ _) - }</ol> - </div> - } - - val version: NodeSeq = - orEmpty(comment.version) { - <dt>Version</dt> - <dd>{ for(body <- comment.version.toList) yield bodyToHtml(body) }</dd> - } - - val sinceVersion: NodeSeq = - orEmpty(comment.since) { - <dt>Since</dt> - <dd>{ for(body <- comment.since.toList) yield bodyToHtml(body) }</dd> - } - - val note: NodeSeq = - orEmpty(comment.note) { - <dt>Note</dt> - <dd>{ - val noteXml: List[NodeSeq] = for(note <- comment.note ) yield <span class="cmt">{bodyToHtml(note)}</span> - noteXml.reduceLeft(_ ++ Text(", ") ++ _) - }</dd> - } - - val seeAlso: NodeSeq = - orEmpty(comment.see) { - <dt>See also</dt> - <dd>{ - val seeXml: List[NodeSeq] = for(see <- comment.see ) yield <span class="cmt">{bodyToHtml(see)}</span> - seeXml.reduceLeft(_ ++ _) - }</dd> - } - - val exceptions: NodeSeq = - orEmpty(comment.throws) { - <dt>Exceptions thrown</dt> - <dd>{ - val exceptionsXml: List[NodeSeq] = - for((name, body) <- comment.throws.toList.sortBy(_._1) ) yield - <span class="cmt">{bodyToHtml(body)}</span> - exceptionsXml.reduceLeft(_ ++ Text("") ++ _) - }</dd> - } - - val todo: NodeSeq = - orEmpty(comment.todo) { - <dt>To do</dt> - <dd>{ - val todoXml: List[NodeSeq] = (for(todo <- comment.todo ) yield <span class="cmt">{bodyToHtml(todo)}</span> ) - todoXml.reduceLeft(_ ++ _) - }</dd> - } - - example ++ version ++ sinceVersion ++ exceptions ++ todo ++ note ++ seeAlso - - case _ => NodeSeq.Empty - } - // end attributes block vals --- - - val attributesInfo = implicitInformation ++ attributes ++ definitionClasses ++ fullSignature ++ selfType ++ annotations ++ deprecation ++ migration ++ sourceLink ++ mainComment - val attributesBlock = - if (attributesInfo.isEmpty) - NodeSeq.Empty - else - <dl class="attributes block"> { attributesInfo }</dl> - - val linearization = mbr match { - case dtpl: DocTemplateEntity if isSelf && !isReduced && dtpl.linearizationTemplates.nonEmpty => - <div class="toggleContainer block"> - <span class="toggle">Linear Supertypes</span> - <div class="superTypes hiddenContent">{ - typesToHtml(dtpl.linearizationTypes, hasLinks = true, sep = scala.xml.Text(", ")) - }</div> - </div> - case _ => NodeSeq.Empty - } - - val subclasses = mbr match { - case dtpl: DocTemplateEntity if isSelf && !isReduced => - val subs = mutable.HashSet.empty[DocTemplateEntity] - def transitive(dtpl: DocTemplateEntity) { - for (sub <- dtpl.directSubClasses if !(subs contains sub)) { - subs add sub - transitive(sub) - } - } - transitive(dtpl) - if (subs.nonEmpty) - <div class="toggleContainer block"> - <span class="toggle">Known Subclasses</span> - <div class="subClasses hiddenContent">{ - templatesToHtml(subs.toList.sorted(Entity.EntityOrdering), scala.xml.Text(", ")) - }</div> - </div> - else NodeSeq.Empty - case _ => NodeSeq.Empty - } - - def createDiagram(f: DocTemplateEntity => Option[Diagram], description: String, id: String): NodeSeq = - if (s.docDiagrams.value) mbr match { - case dtpl: DocTemplateEntity if isSelf && !isReduced => - val diagram = f(dtpl) - if (diagram.isDefined) { - 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> - <div class="diagram" id={ id }>{ diagramSvg }</div> - <div id="diagram-controls" class="hiddenContent"> - <button id="diagram-zoom-out" class="diagram-btn"><i class="material-icons"></i></button> - <button id="diagram-zoom-in" class="diagram-btn"><i class="material-icons"></i></button> - <button title="Toggle full-screen" id="diagram-fs" class="diagram-btn to-full"><i class="material-icons"></i></button> - </div> - </div> - } else NodeSeq.Empty - } else NodeSeq.Empty - case _ => NodeSeq.Empty - } else NodeSeq.Empty // diagrams not generated - - val typeHierarchy = createDiagram(_.inheritanceDiagram, "Type Hierarchy", "inheritance-diagram") - val contentHierarchy = createDiagram(_.contentDiagram, "Content Hierarchy", "content-diagram") - - memberComment ++ authorComment ++ paramComments ++ attributesBlock ++ linearization ++ subclasses ++ typeHierarchy ++ contentHierarchy - } - - 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 - case Some(tpe) => scala.xml.Text(pre) ++ typeToHtml(tpe, hasLinks) - } - bound0(lo, " >: ") ++ bound0(hi, " <: ") - } - - def visibility(mbr: MemberEntity): Option[comment.Paragraph] = { - import comment._ - import comment.{ Text => CText } - mbr.visibility match { - case PrivateInInstance() => - Some(Paragraph(CText("private[this]"))) - case PrivateInTemplate(owner) if (owner == mbr.inTemplate) => - Some(Paragraph(CText("private"))) - case PrivateInTemplate(owner) => - 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(comment.Text(owner.qualifiedName), LinkToTpl(owner)), CText("]"))))) - case Public() => - None - } - } - - /** name, tparams, params, result */ - def signature(mbr: MemberEntity, isSelf: Boolean, isReduced: Boolean = false): NodeSeq = { - - def inside(hasLinks: Boolean, nameLink: String = ""): NodeSeq = - <xml:group> - <span class="modifier_kind"> - <span class="modifier">{ mbr.flags.map(flag => inlineToHtml(flag.text) ++ scala.xml.Text(" ")) }</span> - <span class="kind">{ kindToString(mbr) }</span> - </span> - <span class="symbol"> - { - val nameClass = - if (mbr.isImplicitlyInherited) - if (mbr.isShadowedOrAmbiguousImplicit) - "implicit shadowed" - else - "implicit" - else - "name" - - val nameHtml = { - val value = if (mbr.isConstructor) tpl.name else mbr.name - val span = if (mbr.deprecation.isDefined) - <span class={ nameClass + " deprecated"} title={"Deprecated: "+bodyToStr(mbr.deprecation.get)}>{ value }</span> - else - <span class={ nameClass }>{ value }</span> - val encoded = scala.reflect.NameTransformer.encode(value) - if (encoded != value) { - span % new UnprefixedAttribute("title", - "gt4s: " + encoded + - span.attribute("title").map( - node => ". " + node - ).getOrElse(""), - scala.xml.Null) - } else { - span - } - } - if (!nameLink.isEmpty) - <a href={nameLink}>{nameHtml}</a> - else nameHtml - }{ - def tparamsToHtml(mbr: Any): NodeSeq = mbr match { - case hk: HigherKinded => - val tpss = hk.typeParams - if (tpss.isEmpty) NodeSeq.Empty else { - def tparam0(tp: TypeParam): NodeSeq = - <span name={ tp.name }>{ tp.variance + tp.name }{ tparamsToHtml(tp) }{ boundsToHtml(tp.hi, tp.lo, hasLinks)}</span> - def tparams0(tpss: List[TypeParam]): NodeSeq = (tpss: @unchecked) match { - case tp :: Nil => tparam0(tp) - case tp :: tps => tparam0(tp) ++ Text(", ") ++ tparams0(tps) - } - <span class="tparams">[{ tparams0(tpss) }]</span> - } - case _ => NodeSeq.Empty - } - tparamsToHtml(mbr) - }{ - if (isReduced) NodeSeq.Empty else { - def paramsToHtml(vlsss: List[List[ValueParam]]): NodeSeq = { - def param0(vl: ValueParam): NodeSeq = - // notice the }{ in the next lines, they are necessary to avoid an undesired whitespace in output - <span name={ vl.name }>{ - Text(vl.name) - }{ Text(": ") ++ typeToHtml(vl.resultType, hasLinks) }{ - vl.defaultValue match { - case Some(v) => Text(" = ") ++ treeToHtml(v) - case None => NodeSeq.Empty - } - }</span> - - def params0(vlss: List[ValueParam]): NodeSeq = vlss match { - case Nil => NodeSeq.Empty - case vl :: Nil => param0(vl) - case vl :: vls => param0(vl) ++ Text(", ") ++ params0(vls) - } - def implicitCheck(vlss: List[ValueParam]): NodeSeq = vlss match { - case vl :: vls => if(vl.isImplicit) { <span class="implicit">implicit </span> } else Text("") - case _ => Text("") - } - vlsss map { vlss => <span class="params">({implicitCheck(vlss) ++ params0(vlss) })</span> } - } - mbr match { - case cls: Class => paramsToHtml(cls.valueParams) - case ctr: Constructor => paramsToHtml(ctr.valueParams) - case dfe: Def => paramsToHtml(dfe.valueParams) - case _ => NodeSeq.Empty - } - } - }{ if (isReduced) NodeSeq.Empty else { - mbr match { - case tme: MemberEntity if (tme.isDef || tme.isVal || tme.isLazyVal || tme.isVar) => - <span class="result">: { typeToHtml(tme.resultType, hasLinks) }</span> - - 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: 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 - } - }} - </span> - </xml:group> - mbr match { - case dte: DocTemplateEntity if !isSelf => - <h4 class="signature">{ inside(hasLinks = true, nameLink = relativeLinkTo(dte)) }</h4> ++ permalink(dte, isSelf) - case _ if isSelf => - <h4 id="signature" class="signature">{ inside(hasLinks = true) }</h4> - case _ => - <h4 class="signature">{ inside(hasLinks = true) }</h4> ++ permalink(mbr) - } - - } - - /** */ - def treeToHtml(tree: TreeEntity): NodeSeq = { - - /** Makes text good looking in the html page : newlines and basic indentation, - * You must change this function if you want to improve pretty printing of default Values - */ - def codeStringToXml(text: String): NodeSeq = { - var goodLookingXml: NodeSeq = NodeSeq.Empty - var indent = 0 - for (c <- text) c match { - case '{' => indent+=1 - goodLookingXml ++= Text("{") - case '}' => indent-=1 - goodLookingXml ++= Text("}") - case '\n' => - goodLookingXml++= <br/> ++ indentation - case _ => goodLookingXml ++= Text(c.toString) - } - def indentation:NodeSeq = { - var indentXml = NodeSeq.Empty - for (x <- 1 to indent) indentXml ++= Text(" ") - indentXml - } - goodLookingXml - } - - var index = 0 - val str = tree.expression - val length = str.length - var myXml: NodeSeq = NodeSeq.Empty - for ((from, (member, to)) <- tree.refEntity.toSeq) { - if (index < from) { - myXml ++= codeStringToXml(str.substring(index,from)) - index = from - } - if (index == from) { - member match { - case mbr: DocTemplateEntity => - val link = relativeLinkTo(mbr) - myXml ++= <span class="name"><a href={link}>{str.substring(from, to)}</a></span> - case mbr: MemberEntity => - 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 - } - } - - if (index <= length-1) - myXml ++= codeStringToXml(str.substring(index, length )) - - if (length < 36) - <span class="symbol">{ myXml }</span> - else - <span class="defval" name={ myXml }>{ "..." }</span> - } - - private def argumentsToHtml(argss: List[ValueArgument]): NodeSeq = { - def argumentsToHtml0(argss: List[ValueArgument]): NodeSeq = argss match { - case Nil => NodeSeq.Empty - case arg :: Nil => argumentToHtml(arg) - case arg :: args => argumentToHtml(arg) ++ scala.xml.Text(", ") ++ argumentsToHtml0(args) - } - <span class="args">({ argumentsToHtml0(argss) })</span> - } - - private def argumentToHtml(arg: ValueArgument): NodeSeq = { - <span> - { - arg.parameter match { - case Some(param) => Text(param.name + " = ") - case None => NodeSeq.Empty - } - } - { treeToHtml(arg.value) } - </span> - } - - private def bodyToStr(body: comment.Body): String = - body.blocks flatMap (blockToStr(_)) mkString "" - - private def blockToStr(block: comment.Block): String = block match { - case comment.Paragraph(in) => inlineToStr(in) - case _ => block.toString - } - - private def typeToHtmlWithStupidTypes(tpl: TemplateEntity, superTpl: TemplateEntity, superType: TypeEntity): NodeSeq = - if (tpl.universe.settings.useStupidTypes.value) - superTpl match { - case dtpl: DocTemplateEntity => - val sig = signature(dtpl, isSelf = false, isReduced = true) \ "_" - sig - case tpl: TemplateEntity => - Text(tpl.name) - } - else - typeToHtml(superType, hasLinks = true) - - private def constraintToHtml(constraint: Constraint): NodeSeq = constraint match { - case ktcc: KnownTypeClassConstraint => - scala.xml.Text(ktcc.typeExplanation(ktcc.typeParamName) + " (" + ktcc.typeParamName + ": ") ++ - templateToHtml(ktcc.typeClassEntity) ++ scala.xml.Text(")") - case tcc: TypeClassConstraint => - scala.xml.Text(tcc.typeParamName + " is ") ++ - <a href="http://stackoverflow.com/questions/2982276/what-is-a-context-bound-in-scala" target="_blank"> - context-bounded</a> ++ scala.xml.Text(" by " + tcc.typeClassEntity.qualifiedName + " (" + tcc.typeParamName + ": ") ++ - templateToHtml(tcc.typeClassEntity) ++ scala.xml.Text(")") - case impl: ImplicitInScopeConstraint => - scala.xml.Text("an implicit value of type ") ++ typeToHtml(impl.implicitType, hasLinks = true) ++ scala.xml.Text(" is in scope") - case eq: EqualTypeParamConstraint => - scala.xml.Text(eq.typeParamName + " is " + eq.rhs.name + " (" + eq.typeParamName + " =:= ") ++ - typeToHtml(eq.rhs, hasLinks = true) ++ scala.xml.Text(")") - case bt: BoundedTypeParamConstraint => - scala.xml.Text(bt.typeParamName + " is a superclass of " + bt.lowerBound.name + " and a subclass of " + - bt.upperBound.name + " (" + bt.typeParamName + " >: ") ++ - typeToHtml(bt.lowerBound, hasLinks = true) ++ scala.xml.Text(" <: ") ++ - typeToHtml(bt.upperBound, hasLinks = true) ++ scala.xml.Text(")") - case lb: LowerBoundedTypeParamConstraint => - scala.xml.Text(lb.typeParamName + " is a superclass of " + lb.lowerBound.name + " (" + lb.typeParamName + " >: ") ++ - typeToHtml(lb.lowerBound, hasLinks = true) ++ scala.xml.Text(")") - case ub: UpperBoundedTypeParamConstraint => - scala.xml.Text(ub.typeParamName + " is a subclass of " + ub.upperBound.name + " (" + ub.typeParamName + " <: ") ++ - typeToHtml(ub.upperBound, hasLinks = true) ++ scala.xml.Text(")") - } -} - -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 lowerFirstLetter(s: String) = if (s.length >= 1) s.substring(0,1).toLowerCase() + s.substring(1) else s -} diff --git a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/index.js b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/index.js index 494ad91cc8..55224eae52 100644 --- a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/index.js +++ b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/index.js @@ -33,14 +33,11 @@ $(document).ready(function() { configureTextFilter(); - $("#index-input").on("focus", function(e) { - $("#textfilter > .input > .clear").show(); - }); - - $("#index-input").on("blur", function() { - setTimeout(function() { + $("#index-input").on("input", function(e) { + if($(this).val().length > 0) + $("#textfilter > .input > .clear").show(); + else $("#textfilter > .input > .clear").hide(); - }, 10); }); }); @@ -229,6 +226,8 @@ function configureTextFilter() { $("div#search-results").hide(); $("#search > span.close-results").hide(); $("#search > span#doc-title").show(); + + $(this).hide(); }); }); diff --git a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.js b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.js index ae39f83852..5f42dfa114 100644 --- a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.js +++ b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.js @@ -147,10 +147,10 @@ $(document).ready(function() { }); $("#memberfilter > .clear").click(function() { $("#memberfilter input").attr("value", ""); + $(this).hide(); filter(); }); $(document).keydown(function(event) { - if (event.keyCode == 9) { // tab $("#index-input", window.parent.document).focus(); input.attr("value", ""); @@ -162,8 +162,7 @@ $(document).ready(function() { if ($(this).hasClass("in")) { $(this).removeClass("in"); $(this).addClass("out"); - } - else if ($(this).hasClass("out")) { + } else if ($(this).hasClass("out")) { $(this).removeClass("out"); $(this).addClass("in"); } @@ -174,8 +173,7 @@ $(document).ready(function() { if ($(this).hasClass("in")) { $(this).removeClass("in"); $(this).addClass("out"); - } - else if ($(this).hasClass("out")) { + } else if ($(this).hasClass("out")) { $(this).removeClass("out"); $(this).addClass("in"); } @@ -307,14 +305,11 @@ $(document).ready(function() { exposeMember(jqElem); } - $("#mbrsel-input").on("focus", function() { - $("#memberfilter > .clear").show(); - }); - - $("#mbrsel-input").on("blur", function() { - setTimeout(function() { + $("#mbrsel-input").on("input", function() { + if ($(this).val().length > 0) + $("#memberfilter > .clear").show(); + else $("#memberfilter > .clear").hide(); - }, 10); }); }); |