summaryrefslogblamecommitdiff
path: root/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
blob: 4a14bef96a5116376d9a0fe0f20d4b40faee8c6b (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13

                       
 
                                          








                                                                 

                                              




                                                                                               





























                                                                                                                  
                                                                                                                



                                                        

                                                     




                           
 











                                   
 

                                                            


                                                            
                                                          
 
                                                         
                                                          
     








                                                                            


                                                         
                                                                     
 




                                                                      








                                                                          

                                                 


                                              
                                                                           
     


                                                     





                                                                                               
                                                                
                                                    
     



                                                                        
     


                                                            
 
                                                                                                 
     
                                                          
                                                           
 
                                                                                               
     
                                                                                   
                                                                         
 











                                                                                              

                                                                                                     
     
                                                                 
                                                                
 
                                                                 
                                                                                
     
                                                                          
                                                                   
 
                                                                 

                                              
                                                                           
                                                                    

                                                                            

                                                  
 


                                                                                               
                                              

                                                                      
                                                 
 

                                                                                     
 
 
                                                                
 


                                                                                                

                                           


                                                                                                
                                           
 
package scala.tools.nsc
package interactive

import scala.util.control.ControlThrowable
import scala.tools.nsc.io.AbstractFile
import scala.tools.nsc.util.{SourceFile, Position, WorkScheduler}
import scala.tools.nsc.symtab._
import scala.tools.nsc.ast._

/** Interface of interactive compiler to a client such as an IDE
 */
trait CompilerControl { self: Global =>

  abstract class WorkItem extends (() => Unit)

  case class ReloadItem(sources: List[SourceFile], response: Response[Unit]) extends WorkItem {
    def apply() = reload(sources, response)
    override def toString = "reload "+sources
  }

  class AskTypeAtItem(val pos: Position, response: Response[Tree]) extends WorkItem {
    def apply() = self.getTypedTreeAt(pos, response)
    override def toString = "typeat "+pos.source+" "+pos.show
  }

  class AskTypeItem(val source: SourceFile, val forceReload: Boolean, response: Response[Tree]) extends WorkItem {
    def apply() = self.getTypedTree(source, forceReload, response)
    override def toString = "typecheck"
  }

  class AskLastTypeItem(val source: SourceFile, response: Response[Tree]) extends WorkItem {
    def apply() = self.getLastTypedTree(source, response)
    override def toString = "reconcile"
  }

  class AskTypeCompletionItem(val pos: Position, response: Response[List[Member]]) extends WorkItem {
    def apply() = self.getTypeCompletion(pos, response)
    override def toString = "type completion "+pos.source+" "+pos.show
  }

  class AskScopeCompletionItem(val pos: Position, response: Response[List[Member]]) extends WorkItem {
    def apply() = self.getScopeCompletion(pos, response)
    override def toString = "scope completion "+pos.source+" "+pos.show
  }

  class AskToDoFirstItem(val source: SourceFile) extends WorkItem {
    def apply() = moveToFront(List(source))
    override def toString = "dofirst "+source
  }

  class AskLinkPosItem(val sym: Symbol, val source: SourceFile, response: Response[Position]) extends WorkItem {
    def apply() = self.getLinkPos(sym, source, response)
    override def toString = "linkpos "+sym+" in "+source
  }

  /** Info given for every member found by completion
   */
  abstract class Member {
    val sym: Symbol
    val tpe: Type
    val accessible: Boolean
  }

  case class TypeMember(
    sym: Symbol,
    tpe: Type,
    accessible: Boolean,
    inherited: Boolean,
    viaView: Symbol) extends Member

  case class ScopeMember(
    sym: Symbol,
    tpe: Type,
    accessible: Boolean,
    viaImport: Tree) extends Member

  type Response[T] = scala.tools.nsc.interactive.Response[T]

  /** The scheduler by which client and compiler communicate
   *  Must be initialized before starting compilerRunner
   */
  protected[interactive] val scheduler = new WorkScheduler

  /** The compilation unit corresponding to a source file
   *  if it does not yet exist create a new one atomically
   */
  def unitOf(s: SourceFile): RichCompilationUnit = unitOfFile.synchronized {
    unitOfFile get s.file match {
      case Some(unit) =>
        unit
      case None =>
        val unit = new RichCompilationUnit(s)
        unitOfFile(s.file) = unit
        unit
    }
  }

  /** The compilation unit corresponding to a position */
  def unitOf(pos: Position): RichCompilationUnit = unitOf(pos.source)

  /** Remove the CompilationUnit corresponding to the given SourceFile
   *  from consideration for recompilation.
   */
  def removeUnitOf(s: SourceFile) = unitOfFile remove s.file

  /* returns the top level classes and objects that were deleted
   * in the editor since last time recentlyDeleted() was called.
   */
  def recentlyDeleted(): List[Symbol] = deletedTopLevelSyms.synchronized {
    val result = deletedTopLevelSyms
    deletedTopLevelSyms.clear()
    result.toList
  }

  /** Locate smallest tree that encloses position
   */
  def locateTree(pos: Position): Tree =
    new Locator(pos) locateIn unitOf(pos).body

  /** 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 `response` on completion.
   */
  def askReload(sources: List[SourceFile], response: Response[Unit]) = {
    val superseeded = scheduler.dequeueAll {
      case ri: ReloadItem if ri.sources == sources => Some(ri)
      case _ => None
    }
    superseeded foreach (_.response.set())
    scheduler postWorkItem new ReloadItem(sources, response)
  }

  /** Set sync var `response` to the smallest fully attributed tree that encloses position `pos`.
   */
  def askTypeAt(pos: Position, response: Response[Tree]) =
    scheduler postWorkItem new AskTypeAtItem(pos, response)

  /** Set sync var `response` to the fully attributed & typechecked tree contained in `source`.
   */
  def askType(source: SourceFile, forceReload: Boolean, response: Response[Tree]) =
    scheduler postWorkItem new AskTypeItem(source, forceReload, response)

  /** Set sync var `response` to the position of the definition of the given link in
   *  the given sourcefile.
   *
   *  @param   sym      The symbol referenced by the link (might come from a classfile)
   *  @param   source   The source file that's supposed to contain the definition
   *  @param   response A response that will be set to the following:
   *                    If `source` contains a definition that is referenced by the given link
   *                    the position of that definition, otherwise NoPosition.
   */
  def askLinkPos(sym: Symbol, source: SourceFile, response: Response[Position]) =
    scheduler postWorkItem new AskLinkPosItem(sym, source, response)

  /** Set sync var `response` to the last fully attributed & typechecked tree produced from `source`.
   *  If no such tree exists yet, do a normal askType(source, false, response)
   */
  def askLastType(source: SourceFile, response: Response[Tree]) =
    scheduler postWorkItem new AskLastTypeItem(source, response)

  /** Set sync var `response' to list of members that are visible
   *  as members of the tree enclosing `pos`, possibly reachable by an implicit.
   */
  def askTypeCompletion(pos: Position, response: Response[List[Member]]) =
    scheduler postWorkItem new AskTypeCompletionItem(pos, response)

  /** Set sync var `response' to list of members that are visible
   *  as members of the scope enclosing `pos`.
   */
  def askScopeCompletion(pos: Position, response: Response[List[Member]]) =
    scheduler postWorkItem new AskScopeCompletionItem(pos, response)

  /** Ask to do unit first on present and subsequent type checking passes */
  def askToDoFirst(f: SourceFile) =
    scheduler postWorkItem new AskToDoFirstItem(f)

  /** Cancel current compiler run and start a fresh one where everything will be re-typechecked
   *  (but not re-loaded).
   */
  def askReset() = scheduler raise FreshRunReq

  /** Tell the compile server to shutdown, and do not restart again */
  def askShutdown() = scheduler raise ShutdownReq

  /** Ask for a computation to be done quickly on the presentation compiler thread */
  def ask[A](op: () => A): A = scheduler doQuickly op
}

  // ---------------- Interpreted exceptions -------------------

/** Signals a request for a fresh background compiler run.
 *  Note: The object has to stay top-level so that the PresentationCompilerThread may access it.
 */
object FreshRunReq extends ControlThrowable

/** Signals a request for a shutdown of the presentation compiler.
 *  Note: The object has to stay top-level so that the PresentationCompilerThread may access it.
 */
object ShutdownReq extends ControlThrowable