Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Created a custom Tree Traverser to traverse TypeTree nodes
The available compiler's ``Traverser`` does not recurse inside ``TypeTree`` nodes This is inconvenient as compiler's tree's type such as ``ExistentialTypeTree`` are "hidden" inside ``TypeTree`` node. Therefore I have created a custom tree traverser ``TypeTreeTraverser`` that tries to traverse ``TypeTree`` nodes when possible. This makes the ``SafeSymbol.safeSymbol`` routine simpler as it does no longer need to unroll ``TypeTree`` nodes.
- Loading branch information
Showing
2 changed files
with
70 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
68 changes: 68 additions & 0 deletions
68
....sdt.core/src/scala/tools/eclipse/semantichighlighting/classifier/TypeTreeTraverser.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package scala.tools.eclipse.semantichighlighting.classifier | ||
|
||
import scala.tools.eclipse.javaelements.ScalaCompilationUnit | ||
import scala.collection.mutable.ListBuffer | ||
|
||
trait TypeTreeTraverser { | ||
val global: tools.nsc.Global | ||
|
||
import global._ | ||
|
||
implicit def tree2treeWrapper(tree: Tree): TreeWrapper = new TreeWrapper(tree) | ||
|
||
/** | ||
* Monadic wrapper for a Tree. The wrapper is actually very similar | ||
* to {{{TreeOps}}}, with the difference that is uses the below defined | ||
* {{{TypeTreeTraverser}}} in place of the standard {{{Traverser}}} to | ||
* traverse the Tree. | ||
*/ | ||
class TreeWrapper(tree: Tree) { | ||
private val adaptee = new TreeOps(tree) | ||
|
||
def isType: Boolean = adaptee.isType | ||
|
||
def foreach(f: Tree => Unit) { | ||
new ForeachTypeTreeTraverser(f).traverse(tree) | ||
} | ||
// TODO: Need to replace {{{filter}} with {{{withFilter}}} | ||
def filter(p: Tree => Boolean): List[Tree] = { | ||
val ft = new FilterTypeTreeTraverser(p) | ||
ft.traverse(tree) | ||
ft.hits.toList | ||
} | ||
} | ||
|
||
//Note [mirco]: The implementation was copied from {{{Trees.ForeachTreeTraverser}}}. Can this be avoided? | ||
private class ForeachTypeTreeTraverser(f: Tree => Unit) extends TypeTreeTraverser { | ||
override def traverse(t: Tree) { | ||
f(t) | ||
super.traverse(t) | ||
} | ||
} | ||
|
||
//Note [mirco]: The implementation was copied from {{{Trees.ForeachTreeTraverser}}}. Can this be avoided? | ||
private class FilterTypeTreeTraverser(p: Tree => Boolean) extends TypeTreeTraverser { | ||
val hits = new ListBuffer[Tree] | ||
override def traverse(t: Tree) { | ||
if (p(t)) hits += t | ||
super.traverse(t) | ||
} | ||
} | ||
|
||
/** | ||
* Traverse {{{TypeTree}} AST nodes if an {{{original}}} (underlying) Tree exists. | ||
* This let us decompose traverse type trees such as {{{ExistentialTypeTree}}} which | ||
* would otherwise be ignored by the standard {{{scala.tools.nsc.Trees.Traverser}}} | ||
* implementation | ||
*/ | ||
private trait TypeTreeTraverser extends Traverser { | ||
override def traverse(tree: Tree): Unit = tree match { | ||
case tpeTree: TypeTree => | ||
val original = tpeTree.original | ||
if (original == null || original == tpeTree) super.traverse(tpeTree) | ||
else traverse(original) | ||
|
||
case _ => super.traverse(tree) | ||
} | ||
} | ||
} |