@@ -9,7 +9,7 @@ import java.io.{ PrintWriter, StringWriter, FileReader, FileWriter }
99import collection .mutable .{ArrayBuffer , ListBuffer , SynchronizedBuffer , HashMap }
1010
1111import scala .collection .mutable
12- import mutable .{LinkedHashMap , SynchronizedMap ,LinkedHashSet , SynchronizedSet }
12+ import mutable .{LinkedHashMap , SynchronizedMap , HashSet , LinkedHashSet , SynchronizedSet }
1313import scala .concurrent .SyncVar
1414import scala .util .control .ControlThrowable
1515import scala .tools .nsc .io .{ AbstractFile , LogReplay , Logger , NullLogger , Replayer }
@@ -84,10 +84,16 @@ class Global(settings: Settings, reporter: Reporter, projectName: String = "")
8484 }
8585 }
8686
87- /** A list containing all those files that need to be removed
87+ /** A set containing all those files that need to be removed
8888 * Units are removed by getUnit, typically once a unit is finished compiled.
8989 */
90- protected val toBeRemoved = new ArrayBuffer [AbstractFile ] with SynchronizedBuffer [AbstractFile ]
90+ protected val toBeRemoved : mutable.Set [AbstractFile ] =
91+ new HashSet [AbstractFile ] with SynchronizedSet [AbstractFile ]
92+
93+ /** A set containing all those files that need to be removed after a full background compiler run
94+ */
95+ protected val toBeRemovedAfterRun : mutable.Set [AbstractFile ] =
96+ new HashSet [AbstractFile ] with SynchronizedSet [AbstractFile ]
9197
9298 class ResponseMap extends MultiHashMap [SourceFile , Response [Tree ]] {
9399 override def += (binding : (SourceFile , Set [Response [Tree ]])) = {
@@ -488,6 +494,9 @@ class Global(settings: Settings, reporter: Reporter, projectName: String = "")
488494 }
489495 }
490496
497+ // move units removable after this run to the "to-be-removed" buffer
498+ toBeRemoved ++= toBeRemovedAfterRun
499+
491500 // clean out stale waiting responses
492501 cleanAllResponses()
493502
@@ -614,6 +623,8 @@ class Global(settings: Settings, reporter: Reporter, projectName: String = "")
614623 private def reloadSource (source : SourceFile ) {
615624 val unit = new RichCompilationUnit (source)
616625 unitOfFile(source.file) = unit
626+ toBeRemoved -= source.file
627+ toBeRemovedAfterRun -= source.file
617628 reset(unit)
618629 // parseAndEnter(unit)
619630 }
@@ -649,14 +660,20 @@ class Global(settings: Settings, reporter: Reporter, projectName: String = "")
649660 demandNewCompilerRun()
650661 }
651662
663+ /** Arrange for unit to be removed after run, to give a chance to typecheck the unit fully.
664+ * If we do just removeUnit, some problems with default parameters can ensue.
665+ * Calls to this method could probably be replaced by removeUnit once default parameters are handled more robustly.
666+ */
667+ private def afterRunRemoveUnitOf (source : SourceFile ) {
668+ toBeRemovedAfterRun += source.file
669+ }
652670
653671 /** A fully attributed tree located at position `pos` */
654672 private def typedTreeAt (pos : Position ): Tree = getUnit(pos.source) match {
655673 case None =>
656674 reloadSources(List (pos.source))
657- val result = typedTreeAt(pos)
658- removeUnitOf(pos.source)
659- result
675+ try typedTreeAt(pos)
676+ finally afterRunRemoveUnitOf(pos.source)
660677 case Some (unit) =>
661678 informIDE(" typedTreeAt " + pos)
662679 parseAndEnter(unit)
@@ -708,43 +725,52 @@ class Global(settings: Settings, reporter: Reporter, projectName: String = "")
708725
709726 /** Implements CompilerControl.askLinkPos */
710727 private [interactive] def getLinkPos (sym : Symbol , source : SourceFile , response : Response [Position ]) {
711- informIDE( " getLinkPos " + sym + " " + source)
712- respond(response) {
713- val preExisting = unitOfFile isDefinedAt source.file
728+
729+ /** Find position of symbol `sym` in unit `unit`. Pre: `unit is loaded. */
730+ def findLinkPos ( unit : RichCompilationUnit ) : Position = {
714731 val originalTypeParams = sym.owner.typeParams
715- reloadSources(List (source))
716- parseAndEnter(getUnit(source).get)
717- val owner = sym.owner
718- if (owner.isClass) {
719- val pre = adaptToNewRunMap(ThisType (owner))
720- val newsym = pre.decl(sym.name) filter { alt =>
721- sym.isType || {
722- try {
723- val tp1 = pre.memberType(alt) onTypeError NoType
724- val tp2 = adaptToNewRunMap(sym.tpe) substSym (originalTypeParams, owner.typeParams)
725- matchesType(tp1, tp2, false )
726- } catch {
727- case ex : Throwable =>
728- println(" error in hyperlinking: " + ex)
729- ex.printStackTrace()
730- false
731- }
732+ parseAndEnter(unit)
733+ val pre = adaptToNewRunMap(ThisType (sym.owner))
734+ val newsym = pre.decl(sym.name) filter { alt =>
735+ sym.isType || {
736+ try {
737+ val tp1 = pre.memberType(alt) onTypeError NoType
738+ val tp2 = adaptToNewRunMap(sym.tpe) substSym (originalTypeParams, sym.owner.typeParams)
739+ matchesType(tp1, tp2, false )
740+ } catch {
741+ case ex : Throwable =>
742+ println(" error in hyperlinking: " + ex)
743+ ex.printStackTrace()
744+ false
732745 }
733746 }
734- if (! preExisting) removeUnitOf(source)
735- if (newsym == NoSymbol ) {
736- debugLog(" link not found " + sym+ " " + source+ " " + pre)
737- NoPosition
738- } else if (newsym.isOverloaded) {
739- settings.uniqid.value = true
740- debugLog(" link ambiguous " + sym+ " " + source+ " " + pre+ " " + newsym.alternatives)
741- NoPosition
742- } else {
743- debugLog(" link found for " + newsym+ " : " + newsym.pos)
744- newsym.pos
747+ }
748+ if (newsym == NoSymbol ) {
749+ debugLog(" link not found " + sym + " " + source + " " + pre)
750+ NoPosition
751+ } else if (newsym.isOverloaded) {
752+ settings.uniqid.value = true
753+ debugLog(" link ambiguous " + sym + " " + source + " " + pre + " " + newsym.alternatives)
754+ NoPosition
755+ } else {
756+ debugLog(" link found for " + newsym + " : " + newsym.pos)
757+ newsym.pos
758+ }
759+ }
760+
761+ informIDE(" getLinkPos " + sym+ " " + source)
762+ respond(response) {
763+ if (sym.owner.isClass) {
764+ getUnit(source) match {
765+ case None =>
766+ reloadSources(List (source))
767+ try findLinkPos(getUnit(source).get)
768+ finally afterRunRemoveUnitOf(source)
769+ case Some (unit) =>
770+ findLinkPos(unit)
745771 }
746772 } else {
747- debugLog(" link not in class " + sym+ " " + source+ " " + owner)
773+ debugLog(" link not in class " + sym+ " " + source+ " " + sym. owner)
748774 NoPosition
749775 }
750776 }
0 commit comments