Skip to content

Commit c157d85

Browse files
committed
Merge pull request #14 from lrytz/typeat
show type at a selection
2 parents 3d99255 + 01556a2 commit c157d85

File tree

5 files changed

+69
-1
lines changed

5 files changed

+69
-1
lines changed

src/compiler/scala/tools/nsc/backend/JavaPlatform.scala

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,27 @@ trait JavaPlatform extends Platform {
2121

2222
private[nsc] var currentClassPath: Option[MergedClassPath[AbstractFile]] = None
2323

24+
val forceIndexPackages: collection.mutable.Set[String] = collection.mutable.Set.empty
25+
val classPathIndexByClassName: collection.mutable.Map[String, Set[String]] = collection.mutable.Map.empty
26+
27+
def addForceIndexPackages(packages: Set[String]) = {
28+
forceIndexPackages ++= packages
29+
}
30+
31+
def updateIndex() = {
32+
def addIfInitialized(pkg: Symbol): Unit = {
33+
if (pkg.hasCompleteInfo || forceIndexPackages.exists(p => p startsWith pkg.fullName)) {
34+
for (m <- pkg.info.members if m != pkg) { // _root_ is member of _root_ it seems, so filter m != pkg
35+
if (m.isClass)
36+
classPathIndexByClassName(m.name.toString) = classPathIndexByClassName.getOrElse(m.name.toString, Set.empty) + m.fullName
37+
if (m.moduleClass.isPackageClass)
38+
addIfInitialized(m.moduleClass)
39+
}
40+
}
41+
}
42+
addIfInitialized(rootMirror.getPackage("_root_": TermName))
43+
}
44+
2445
def classPath: ClassPath[AbstractFile] = {
2546
assert(settings.YclasspathImpl.value == ClassPathRepresentationType.Recursive,
2647
"To use recursive classpath representation you must enable it with -YclasspathImpl:recursive compiler option.")

src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,15 @@ trait ContextErrors {
245245
NormalTypeError(tree, "reference to " + name + " is ambiguous;\n" + msg)
246246

247247
def SymbolNotFoundError(tree: Tree, name: Name, owner: Symbol, startingIdentCx: Context) = {
248-
NormalTypeError(tree, "not found: "+decodeWithKind(name, owner))
248+
platform.updateIndex()
249+
lazy val candidatesString = name match {
250+
case tn: TypeName =>
251+
val cs = platform.classPathIndexByClassName.getOrElse(tn.toString, Set.empty)
252+
if (cs.nonEmpty) cs.mkString(". You may want to import one of the following classes from your classpath:\n ", "\n ", "")
253+
else ""
254+
case _ => ""
255+
}
256+
NormalTypeError(tree, "not found: "+decodeWithKind(name, owner) + candidatesString)
249257
}
250258

251259
// typedAppliedTypeTree

src/repl/scala/tools/nsc/interpreter/IMain.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ import java.io.File
6464
class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Settings, protected val out: JPrintWriter) extends AbstractScriptEngine with Compilable with Imports with PresentationCompilation {
6565
imain =>
6666

67+
val api = new PresentationCompilerAPI(this)
68+
6769
setBindings(createBindings, ScriptContext.ENGINE_SCOPE)
6870
object replOutput extends ReplOutput(settings.Yreploutdir) { }
6971

@@ -1025,6 +1027,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
10251027
import interactiveGlobal._
10261028
val run = new TyperRun()
10271029
val unit = new RichCompilationUnit(newCompilationUnit(code).source)
1030+
unitOfFile(unit.source.file) = unit
10281031
typeCheck(unit)
10291032
PresentationCompileResult(this, interactiveGlobal)(unit, ObjectSourceCode.preambleLength)
10301033
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package scala.tools.nsc.interpreter
2+
3+
import scala.reflect.internal.util.RangePosition
4+
import scala.tools.nsc.typechecker.TypeStrings
5+
6+
class PresentationCompilerAPI(interpreter: IMain) {
7+
/**
8+
* Index the top-level classes in the the provided packages for the `not found: Class` error
9+
* message.
10+
*/
11+
def scanPackagesForClassNotFoundMessage(packages: Set[String]): Unit = {
12+
interpreter.global.platform.addForceIndexPackages(packages)
13+
}
14+
15+
def typeAt(code: String, selectionStart: Int, selectionEnd: Int): Option[String] = {
16+
interpreter.presentationCompile(code, synthetic = false) match {
17+
case Left(_) => None
18+
case Right(result) =>
19+
val start = selectionStart + result.preambleLength
20+
val end = selectionEnd + result.preambleLength
21+
val pos = new RangePosition(result.unit.source, start, start, end)
22+
val tree = result.compiler.typedTreeAt(pos)
23+
Some(interpreter.global.exitingTyper(tree.tpe.toString))
24+
}
25+
}
26+
}

src/repl/scala/tools/nsc/interpreter/PresentationCompilerCompleter.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@ class PresentationCompilerCompleter(intp: IMain) extends ScalaCompleter {
1111
val request = new Request(buf, cursor)
1212
if (request == lastRequest) tabCount += 1 else { tabCount = 0; lastRequest = request}
1313
val printMode = buf.matches(""".*// *print *$""") && cursor == buf.length
14+
val (typeAtMode, start, end) = {
15+
val R = """.*// *typeAt *(\d+) *(\d+) *$""".r
16+
buf match {
17+
case R(s, e) if cursor == buf.length => (true, s.toInt, e.toInt)
18+
case _ => (false, -1, -1)
19+
}
20+
}
1421
intp.presentationCompile(buf) match {
1522
case Left(_) => Completion.NoCandidates
1623
case Right(result) => try {
@@ -24,6 +31,9 @@ class PresentationCompilerCompleter(intp: IMain) extends ScalaCompleter {
2431
}
2532
val printed = showCode(tree)
2633
Candidates(cursor, "" :: printed :: Nil)
34+
} else if (typeAtMode) {
35+
val tp = intp.api.typeAt(buf, start, end)
36+
Candidates(cursor, "" :: tp ++: Nil)
2737
} else {
2838
import result.CompletionResult._
2939
result.completionsOf(buf, cursor) match {

0 commit comments

Comments
 (0)