summaryrefslogtreecommitdiff
path: root/test/files/presentation/infix-completion.check
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2015-02-17 15:21:03 +1000
committerJason Zaugg <jzaugg@gmail.com>2015-02-17 15:53:20 +1000
commita8ec6c97ea7edbf25ffffe2e798b2deedcd5955f (patch)
treee5070955dd45536a1804606af9d6d380de4c2036 /test/files/presentation/infix-completion.check
parent5a89475526fc91f677d7002b6063bef9e549f0cc (diff)
downloadscala-a8ec6c97ea7edbf25ffffe2e798b2deedcd5955f.tar.gz
scala-a8ec6c97ea7edbf25ffffe2e798b2deedcd5955f.tar.bz2
scala-a8ec6c97ea7edbf25ffffe2e798b2deedcd5955f.zip
SI-9153 More complete and stable results for completions
Three items of background are needed to understand this bug. 1. When typechecking an application like `qual.m({stats; expr})`, the argument is typechecked using the formal parameter type of `m` as the expected type. If this fails with a type error located within in `expr`, the typer instead re-typechecks under `ContextMode.ReTyping` without an expected type, and then searches for an implicit adaptation to enable `view(qual).m(args)`. Under this mode, `Typer#typed1` clears the type of incoming trees. 2. The presentation compiler performs targetted operations like type completions by: - typechecking the enclosing tree, registering all typechecker `Context`s created in the process (`registerContext`) - finding the smallest enclosing `Context` around the target position (`doLocateContext`) - Using this context to perform implicit search, which can contribute members to the completion. (`applicableViews` within `interactive.Global#typeMembers`) 3. When verifiying whether or not a candidate implicit is applicable as a view from `F => T`, implicit search typechecks a dummy call of the form `q"candiate(${Ident("<argument>").setType(typeOf[F])})". Now, picture yourself at the nexus of these three storms. In the enclosed test case, we search for completions at: x + 1.<caret> 1. Because the code is incomplete, the application of `Int#+` doesn't typecheck, and the typer also tries to adapt `x` to a method applicable to the re-typechecked argument. 2. This process registers a context with `retypechecking` set to true. (If multiple contexts at the same position are registered, the last one wins.) 3. Implicit search uses this context to typecheck `Predef.Ensuring(<argument>.setType(Int))`, but the argument is promptly stripped of its type and retypechecking fails as there is no definition named `<argument>` in scope. As such, we missed out on extension methods, like `ensuring` in the list of completions. This commit changes the presentation compiler to turn off retyping mode in the context before starting to work with it. (Are the other modes that might cause similar bugs?) Once I made that change, I noticed that the results the enclosed test was not stable. I tracked this down to the use of a `HashMap` to carry the applicable implicit views, together with the way that the presentation compiler removes duplicates. This commit switched to a `LinkedHashMap`.
Diffstat (limited to 'test/files/presentation/infix-completion.check')
-rw-r--r--test/files/presentation/infix-completion.check194
1 files changed, 194 insertions, 0 deletions
diff --git a/test/files/presentation/infix-completion.check b/test/files/presentation/infix-completion.check
new file mode 100644
index 0000000000..84b5325448
--- /dev/null
+++ b/test/files/presentation/infix-completion.check
@@ -0,0 +1,194 @@
+reload: Snippet.scala
+
+askTypeCompletion at Snippet.scala(1,34)
+================================================================================
+[response] askTypeCompletion at (1,34)
+retrieved 193 members
+[inaccessible] protected def integralNum: math.Numeric.DoubleAsIfIntegral.type
+[inaccessible] protected def num: math.Numeric.DoubleIsFractional.type
+[inaccessible] protected def ord: math.Ordering.Double.type
+[inaccessible] protected def unifiedPrimitiveEquals(x: Any): Boolean
+[inaccessible] protected def unifiedPrimitiveHashcode(): Int
+[inaccessible] protected[package lang] def clone(): Object
+[inaccessible] protected[package lang] def finalize(): Unit
+def !=(x: Byte): Boolean
+def !=(x: Char): Boolean
+def !=(x: Double): Boolean
+def !=(x: Float): Boolean
+def !=(x: Int): Boolean
+def !=(x: Long): Boolean
+def !=(x: Short): Boolean
+def %(x: Byte): Int
+def %(x: Char): Int
+def %(x: Double): Double
+def %(x: Float): Float
+def %(x: Int): Int
+def %(x: Long): Long
+def %(x: Short): Int
+def &(x: Byte): Int
+def &(x: Char): Int
+def &(x: Int): Int
+def &(x: Long): Long
+def &(x: Short): Int
+def *(x: Byte): Int
+def *(x: Char): Int
+def *(x: Double): Double
+def *(x: Float): Float
+def *(x: Int): Int
+def *(x: Long): Long
+def *(x: Short): Int
+def +(x: Byte): Int
+def +(x: Char): Int
+def +(x: Double): Double
+def +(x: Float): Float
+def +(x: Int): Int
+def +(x: Long): Long
+def +(x: Short): Int
+def +(x: String): String
+def -(x: Byte): Int
+def -(x: Char): Int
+def -(x: Double): Double
+def -(x: Float): Float
+def -(x: Int): Int
+def -(x: Long): Long
+def -(x: Short): Int
+def ->[B](y: B): (Int, B)
+def /(x: Byte): Int
+def /(x: Char): Int
+def /(x: Double): Double
+def /(x: Float): Float
+def /(x: Int): Int
+def /(x: Long): Long
+def /(x: Short): Int
+def <(x: Byte): Boolean
+def <(x: Char): Boolean
+def <(x: Double): Boolean
+def <(x: Float): Boolean
+def <(x: Int): Boolean
+def <(x: Long): Boolean
+def <(x: Short): Boolean
+def <<(x: Int): Int
+def <<(x: Long): Int
+def <=(x: Byte): Boolean
+def <=(x: Char): Boolean
+def <=(x: Double): Boolean
+def <=(x: Float): Boolean
+def <=(x: Int): Boolean
+def <=(x: Long): Boolean
+def <=(x: Short): Boolean
+def ==(x: Byte): Boolean
+def ==(x: Char): Boolean
+def ==(x: Double): Boolean
+def ==(x: Float): Boolean
+def ==(x: Int): Boolean
+def ==(x: Long): Boolean
+def ==(x: Short): Boolean
+def >(x: Byte): Boolean
+def >(x: Char): Boolean
+def >(x: Double): Boolean
+def >(x: Float): Boolean
+def >(x: Int): Boolean
+def >(x: Long): Boolean
+def >(x: Short): Boolean
+def >=(x: Byte): Boolean
+def >=(x: Char): Boolean
+def >=(x: Double): Boolean
+def >=(x: Float): Boolean
+def >=(x: Int): Boolean
+def >=(x: Long): Boolean
+def >=(x: Short): Boolean
+def >>(x: Int): Int
+def >>(x: Long): Int
+def >>>(x: Int): Int
+def >>>(x: Long): Int
+def ^(x: Byte): Int
+def ^(x: Char): Int
+def ^(x: Int): Int
+def ^(x: Long): Long
+def ^(x: Short): Int
+def byteValue(): Byte
+def ceil: Double
+def compare(y: Double): Int
+def compare(y: Long): Int
+def compareTo(that: Double): Int
+def compareTo(that: Long): Int
+def compareTo(x$1: Double): Int
+def compareTo(x$1: Long): Int
+def doubleValue(): Double
+def ensuring(cond: Boolean): Int
+def ensuring(cond: Boolean,msg: => Any): Int
+def ensuring(cond: Int => Boolean): Int
+def ensuring(cond: Int => Boolean,msg: => Any): Int
+def equals(x$1: Any): Boolean
+def floatValue(): Float
+def floor: Double
+def formatted(fmtstr: String): String
+def hashCode(): Int
+def intValue(): Int
+def isInfinite(): Boolean
+def isInfinity: Boolean
+def isNaN(): Boolean
+def isNegInfinity: Boolean
+def isPosInfinity: Boolean
+def isValidLong: Boolean
+def longValue(): Long
+def round: Long
+def shortValue(): Short
+def to(end: Double): Range.Partial[Double,scala.collection.immutable.NumericRange[Double]]
+def to(end: Double,step: Double): scala.collection.immutable.NumericRange.Inclusive[Double]
+def to(end: Long): scala.collection.immutable.NumericRange.Inclusive[Long]
+def to(end: Long,step: Long): scala.collection.immutable.NumericRange.Inclusive[Long]
+def toBinaryString: String
+def toByte: Byte
+def toChar: Char
+def toDegrees: Double
+def toDouble: Double
+def toFloat: Float
+def toHexString: String
+def toInt: Int
+def toLong: Long
+def toOctalString: String
+def toRadians: Double
+def toShort: Short
+def toString(): String
+def unary_+: Int
+def unary_-: Int
+def unary_~: Int
+def underlying(): AnyRef
+def until(end: Double): Range.Partial[Double,scala.collection.immutable.NumericRange[Double]]
+def until(end: Double,step: Double): scala.collection.immutable.NumericRange.Exclusive[Double]
+def until(end: Long): scala.collection.immutable.NumericRange.Exclusive[Long]
+def until(end: Long,step: Long): scala.collection.immutable.NumericRange.Exclusive[Long]
+def |(x: Byte): Int
+def |(x: Char): Int
+def |(x: Int): Int
+def |(x: Long): Long
+def |(x: Short): Int
+def →[B](y: B): (Int, B)
+final def !=(x$1: Any): Boolean
+final def ##(): Int
+final def ==(x$1: Any): Boolean
+final def asInstanceOf[T0]: T0
+final def eq(x$1: AnyRef): Boolean
+final def isInstanceOf[T0]: Boolean
+final def ne(x$1: AnyRef): Boolean
+final def notify(): Unit
+final def notifyAll(): Unit
+final def synchronized[T0](x$1: T0): T0
+final def wait(): Unit
+final def wait(x$1: Long): Unit
+final def wait(x$1: Long,x$2: Int): Unit
+override def abs: Double
+override def isValidByte: Boolean
+override def isValidChar: Boolean
+override def isValidInt: Boolean
+override def isValidShort: Boolean
+override def isWhole(): Boolean
+override def max(that: Double): Double
+override def max(that: Long): Long
+override def min(that: Double): Double
+override def min(that: Long): Long
+override def signum: Int
+private[this] val self: Double
+type ResultWithoutStep = Range.Partial[Double,scala.collection.immutable.NumericRange[Double]]
+================================================================================