summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2009-07-31 16:27:28 +0000
committerMartin Odersky <odersky@gmail.com>2009-07-31 16:27:28 +0000
commit1a4566278cdaed86891f7c675c3d52a52379f029 (patch)
tree0520278c6bd0955ad42bac643c1afb4f1996e294 /src/compiler/scala/tools/nsc
parent24471facbd9ece2a972e47dfe792b0fae3356c50 (diff)
downloadscala-1a4566278cdaed86891f7c675c3d52a52379f029.tar.gz
scala-1a4566278cdaed86891f7c675c3d52a52379f029.tar.bz2
scala-1a4566278cdaed86891f7c675c3d52a52379f029.zip
hooks for scope completion; background presenta...
hooks for scope completion; background presentation compiler is no more incremental. Refactorings in IDE support
Diffstat (limited to 'src/compiler/scala/tools/nsc')
-rw-r--r--src/compiler/scala/tools/nsc/interactive/CompilerControl.scala27
-rwxr-xr-xsrc/compiler/scala/tools/nsc/interactive/ContextTrees.scala2
-rwxr-xr-xsrc/compiler/scala/tools/nsc/interactive/Global.scala111
-rw-r--r--src/compiler/scala/tools/nsc/interactive/REPL.scala2
-rw-r--r--src/compiler/scala/tools/nsc/interactive/RichCompilationUnits.scala15
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala7
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala2
7 files changed, 109 insertions, 57 deletions
diff --git a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
index d46b5b4b89..942a6f5c86 100644
--- a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
+++ b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
@@ -54,11 +54,17 @@ trait CompilerControl { self: Global =>
def locateTree(pos: Position): Tree =
new Locator(pos) locateIn unitOf(pos).body
- /** Locate smallest context that encloses position
+ /** Locates smallest context that encloses position as an optional value.
*/
def locateContext(pos: Position): Option[Context] =
locateContext(unitOf(pos).contexts, pos)
+ /** Returns the smallest context that contains given `pos`, throws FatalError if none exists.
+ */
+ def doLocateContext(pos: Position): Context = locateContext(pos) getOrElse {
+ throw new FatalError("no context found for "+pos)
+ }
+
/** Make sure a set of compilation units is loaded and parsed.
* Return () to syncvar `result` on completion.
*/
@@ -76,10 +82,23 @@ trait CompilerControl { self: Global =>
override def toString = "typeat "+pos.source+" "+pos.show
}
- def askCompletion(pos: Position, result: Response[List[Member]]) =
+ /** Set sync var `result' to list of members that are visible
+ * as members of the tree enclosing `pos`, possibly reachable by an implicit.
+ * - if `selection` is false, as identifiers in the scope enclosing `pos`
+ */
+ def askTypeCompletion(pos: Position, result: Response[List[Member]]) =
+ scheduler postWorkItem new WorkItem {
+ def apply() = self.getTypeCompletion(pos, result)
+ override def toString = "type completion "+pos.source+" "+pos.show
+ }
+
+ /** Set sync var `result' to list of members that are visible
+ * as members of the scope enclosing `pos`.
+ */
+ def askScopeCompletion(pos: Position, result: Response[List[Member]]) =
scheduler postWorkItem new WorkItem {
- def apply() = self.completion(pos, result)
- override def toString = "completion "+pos.source+" "+pos.show
+ def apply() = self.getScopeCompletion(pos, result)
+ override def toString = "scope completion "+pos.source+" "+pos.show
}
/** Ask to do unit first on present and subsequent type checking passes */
diff --git a/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala b/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala
index 70557ac5c6..aea858c68b 100755
--- a/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala
+++ b/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala
@@ -24,7 +24,7 @@ trait ContextTrees { self: Global =>
override def toString = "ContextTree("+pos+", "+children+")"
}
- /** Optionally return the smallest context that contains given `pos`, or None if none exists.
+ /** Optionally returns the smallest context that contains given `pos`, or None if none exists.
*/
def locateContext(contexts: Contexts, pos: Position): Option[Context] = {
if (contexts.isEmpty) None
diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala
index a4ba711d95..4b87a9e030 100755
--- a/src/compiler/scala/tools/nsc/interactive/Global.scala
+++ b/src/compiler/scala/tools/nsc/interactive/Global.scala
@@ -45,15 +45,12 @@ self =>
/** Is a background compiler run needed? */
private var outOfDate = false
+ /** Units compiled by a run with id >= minRunId are considered up-to-date */
+ private[interactive] var minRunId = 1
+
/** Is a reload/background compiler currently running? */
private var acting = false
- /** The status value of a unit that has not yet been loaded */
- final val NotLoaded = -1
-
- /** The status value of a unit that has not yet been typechecked */
- final val JustParsed = 0
-
// ----------- Overriding hooks in nsc.Global -----------------------
/** Called from typechecker, which signal hereby that a node has been completely typechecked.
@@ -113,7 +110,11 @@ self =>
def pollForWork() {
scheduler.pollException() match {
case Some(ex: CancelActionReq) => if (acting) throw ex
- case Some(ex: FreshRunReq) => if (outOfDate) throw ex
+ case Some(ex: FreshRunReq) =>
+ currentTyperRun = new TyperRun()
+ minRunId = currentRunId
+ if (outOfDate) throw ex
+ else outOfDate = true
case Some(ex: Throwable) => throw ex
case _ =>
}
@@ -121,14 +122,14 @@ self =>
case Some(action) =>
try {
acting = true
- //println("picked up work item: "+action)
+ println("picked up work item: "+action)
action()
- //println("done with work item: "+action)
+ println("done with work item: "+action)
} catch {
case ex: CancelActionReq =>
- //println("cancelled work item: "+action)
+ println("cancelled work item: "+action)
} finally {
- //println("quitting work item: "+action)
+ println("quitting work item: "+action)
acting = false
}
case None =>
@@ -159,7 +160,7 @@ self =>
}
val completionResponse = new Response[List[Member]]
- askCompletion(pos, completionResponse)
+ askTypeCompletion(pos, completionResponse)
val completion = completionResponse.get.left.toOption match {
case Some(members) =>
members mkString "\n"
@@ -210,13 +211,13 @@ self =>
/** Compile all given units
*/
private def backgroundCompile() {
- //inform("Starting new presentation compiler type checking pass")
+ inform("Starting new presentation compiler type checking pass")
reporter.reset
firsts = firsts filter (s => unitOfFile contains (s.file))
val prefix = firsts map unitOf
- val units = prefix ::: (unitOfFile.values.toList diff prefix)
+ val units = prefix ::: (unitOfFile.values.toList diff prefix) filter (!_.isUpToDate)
recompile(units)
- //inform("Everything is now up to date")
+ inform("Everything is now up to date")
}
/** Reset unit to just-parsed state */
@@ -312,42 +313,50 @@ self =>
import analyzer.{SearchResult, ImplicitSearch}
- def completion(pos: Position, result: Response[List[Member]]) {
- respond(result) {
- val tree = typedTreeAt(pos)
- locateContext(pos) match {
- case Some(context) =>
- val superAccess = tree.isInstanceOf[Super]
- val pre = stabilizedType(tree)
- def member(sym: Symbol, inherited: Boolean) = new Member(
- sym,
- pre memberType sym,
- context.isAccessible(sym, pre, superAccess),
- inherited,
- NoSymbol
- )
- def implicitMembers(s: SearchResult): List[Member] = {
- val vtree = viewApply(s, tree, context)
- val vpre = stabilizedType(vtree)
- vtree.tpe.members map { sym => new Member(
- sym,
- vpre memberType sym,
- context.isAccessible(sym, vpre, false),
- false,
- s.tree.symbol
- )}
- }
- println("completion at "+tree+" "+tree.tpe)
- val decls = tree.tpe.decls.toList map (member(_, false))
- val inherited = tree.tpe.members.toList diff decls map (member(_, true))
- val implicits = applicableViews(tree, context) flatMap implicitMembers
- def isVisible(m: Member) =
- !(decls exists (_.shadows(m))) && !(inherited exists (_.shadows(m)))
- decls ::: inherited ::: (implicits filter isVisible)
- case None =>
- throw new FatalError("no context found for "+pos)
- }
+ def getScopeCompletion(pos: Position, result: Response[List[Member]]) {
+ respond(result) { scopeMembers(pos) }
+ }
+
+ def scopeMembers(pos: Position): List[Member] = {
+ val context = doLocateContext(pos)
+ List() // to be completed
+ }
+
+ def getTypeCompletion(pos: Position, result: Response[List[Member]]) {
+ respond(result) { typeMembers(pos) }
+ }
+
+ def typeMembers(pos: Position): List[Member] = {
+ val tree = typedTreeAt(pos)
+ val context = doLocateContext(pos)
+ val superAccess = tree.isInstanceOf[Super]
+ val pre = stabilizedType(tree)
+ def member(sym: Symbol, inherited: Boolean) = new Member(
+ sym,
+ pre memberType sym,
+ context.isAccessible(sym, pre, superAccess),
+ inherited,
+ NoSymbol
+ )
+ def implicitMembers(s: SearchResult): List[Member] = {
+ val vtree = viewApply(s, tree, context)
+ val vpre = stabilizedType(vtree)
+ vtree.tpe.members map { sym => new Member(
+ sym,
+ vpre memberType sym,
+ context.isAccessible(sym, vpre, false),
+ false,
+ s.tree.symbol
+ )}
}
+ println("typeMembers at "+tree+" "+tree.tpe)
+ val decls = tree.tpe.decls.toList map (member(_, false))
+ val inherited = tree.tpe.members.toList diff decls map (member(_, true))
+ val implicits = applicableViews(tree, context) flatMap implicitMembers
+ def isVisible(m: Member) =
+ !(decls exists (_.shadows(m))) && !(inherited exists (_.shadows(m)))
+ val allMembers = decls ::: inherited ::: (implicits filter isVisible)
+ allMembers // filter (_.sym.name.startsWith(prefix))
}
def applicableViews(tree: Tree, context: Context): List[SearchResult] =
@@ -394,6 +403,8 @@ self =>
/** The typer run */
class TyperRun extends Run {
+ println("new typer run")
+
// units is always empty
// symSource, symData are ignored
override def compiles(sym: Symbol) = false
diff --git a/src/compiler/scala/tools/nsc/interactive/REPL.scala b/src/compiler/scala/tools/nsc/interactive/REPL.scala
index 993dd617b8..f3b1900ef2 100644
--- a/src/compiler/scala/tools/nsc/interactive/REPL.scala
+++ b/src/compiler/scala/tools/nsc/interactive/REPL.scala
@@ -92,7 +92,7 @@ object REPL {
show(typeatResult)
}
def doComplete(pos: Position) {
- comp.askCompletion(pos, completeResult)
+ comp.askTypeCompletion(pos, completeResult)
show(completeResult)
}
loop { line =>
diff --git a/src/compiler/scala/tools/nsc/interactive/RichCompilationUnits.scala b/src/compiler/scala/tools/nsc/interactive/RichCompilationUnits.scala
index 8e6ba614e6..5c71ab4f73 100644
--- a/src/compiler/scala/tools/nsc/interactive/RichCompilationUnits.scala
+++ b/src/compiler/scala/tools/nsc/interactive/RichCompilationUnits.scala
@@ -5,6 +5,12 @@ import scala.tools.nsc.util.{SourceFile, Position, NoPosition}
trait RichCompilationUnits { self: Global =>
+ /** The status value of a unit that has not yet been loaded */
+ final val NotLoaded = -1
+
+ /** The status value of a unit that has not yet been typechecked */
+ final val JustParsed = 0
+
class RichCompilationUnit(source: SourceFile) extends CompilationUnit(source) {
/** The runid of the latest compiler run that typechecked this unit,
@@ -12,6 +18,15 @@ trait RichCompilationUnits { self: Global =>
*/
var status: Int = NotLoaded
+ /** Unit has been parsed */
+ def isParsed: Boolean = status >= JustParsed
+
+ /** Unit has been typechecked, but maybe not in latest runs */
+ def isTypeChecked: Boolean = status > JustParsed
+
+ /** Unit has been typechecked and is up to date */
+ def isUpToDate: Boolean = status >= minRunId
+
/** the current edit point offset */
var editPoint: Int = -1
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index 364ed5432d..c551fcc240 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -622,6 +622,12 @@ trait Symbols {
def ownerChain: List[Symbol] = this :: owner.ownerChain
+ def ownersIterator: Iterator[Symbol] = new Iterator[Symbol] {
+ private var current = Symbol.this
+ def hasNext = current ne NoSymbol
+ def next = { val r = current; current = current.owner; r }
+ }
+
// same as ownerChain contains sym, but more efficient
def hasTransOwner(sym: Symbol) = {
var o = this
@@ -1869,6 +1875,7 @@ trait Symbols {
override def owner: Symbol = throw new Error("no-symbol does not have owner")
override def sourceFile: AbstractFile = null
override def ownerChain: List[Symbol] = List()
+ override def ownersIterator: Iterator[Symbol] = Iterator.empty
override def alternatives: List[Symbol] = List()
override def reset(completer: Type) {}
override def info: Type = NoType
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index bd969eb13f..78b2e29048 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -392,7 +392,7 @@ trait Contexts { self: Analyzer =>
def isAccessible(sym: Symbol, pre: Type, superAccess: Boolean): Boolean = {
/** Are we inside definition of `sym'? */
- def accessWithin(sym: Symbol): Boolean = this.owner.ownerChain contains sym
+ def accessWithin(sym: Symbol): Boolean = this.owner.ownersIterator contains sym
/*
var c = this
while (c != NoContext && c.owner != owner) {