Skip to content

Commit

Permalink
Cleanup locate() and friends.
Browse files Browse the repository at this point in the history
  • Loading branch information
vigdorchik authored and huitseeker committed Jun 24, 2013
1 parent 9477285 commit fdcf2fa
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 85 deletions.
66 changes: 29 additions & 37 deletions org.scala-ide.sdt.core/src/scala/tools/eclipse/LocateSymbol.scala
Expand Up @@ -23,24 +23,17 @@ import scala.tools.eclipse.sourcefileprovider.SourceFileProviderRegistry

trait LocateSymbol { self : ScalaPresentationCompiler =>

def locate(sym : Symbol, scu : InteractiveCompilationUnit): Option[(InteractiveCompilationUnit, Int)] = {
def find[T, V](arr : Array[T])(f : T => Option[V]) : Option[V] = {
for(e <- arr) {
f(e) match {
case v@Some(_) => return v
case None =>
}
}
None
}
def findClassFile(): Option[ScalaClassFile] = {
def findCompilationUnit(sym: Symbol) = {
def findClassFile: Option[InteractiveCompilationUnit] = {
logger.debug("Looking for a classfile for " + sym.fullName)
val packName = sym.enclosingPackage.fullName
val project = scu.scalaProject.javaProject.asInstanceOf[JavaProject]
val pfs = new SearchableEnvironment(project, null: WorkingCopyOwner).nameLookup.findPackageFragments(packName, false)
if (pfs eq null) None else find(pfs) { pf =>
val top = sym.enclosingTopLevelClass
val name = if (sym.owner.isPackageObjectClass) "package$.class" else top.name + (if (top.isModuleClass) "$" else "") + ".class"
val packName = sym.enclosingPackageClass.fullName
val javaProject = project.javaProject.asInstanceOf[JavaProject]
val pfs = new SearchableEnvironment(javaProject, null: WorkingCopyOwner).nameLookup.findPackageFragments(packName, false)
if (pfs eq null) None else pfs.toStream flatMap { pf =>
val name = ask { () =>
val top = sym.enclosingTopLevelClass
if (sym.owner.isPackageObjectClass) "package$.class" else top.name + (if (top.isModuleClass) "$" else "") + ".class"
}
logger.debug("Trying out to get " + name)
val cf = pf.getClassFile(name)
cf match {
Expand All @@ -49,39 +42,39 @@ trait LocateSymbol { self : ScalaPresentationCompiler =>
Some(classFile)
case _ => None
}
}
} headOption
}

def findCompilationUnit(): Option[IPath] = {
def findPath: Option[IPath] = {
logger.info("Looking for a compilation unit for " + sym.fullName)
val project = scu.scalaProject.javaProject.asInstanceOf[JavaProject]
val nameLookup = new SearchableEnvironment(project, null: WorkingCopyOwner).nameLookup
val javaProject = project.javaProject.asInstanceOf[JavaProject]
val nameLookup = new SearchableEnvironment(javaProject, null: WorkingCopyOwner).nameLookup

val name = if (sym.owner.isPackageObject) sym.owner.owner.fullName + ".package" else sym.enclosingTopLevelClass.fullName
val name = ask { () =>
if (sym.owner.isPackageObject) sym.owner.owner.fullName + ".package" else sym.enclosingTopLevelClass.fullName
}
logger.debug("Looking for compilation unit " + name)
Option(nameLookup.findCompilationUnit(name)) map (_.getResource().getFullPath())
}

def findSourceFile(): Option[IPath] =
def findSourceFile: Option[IPath] =
if (sym.sourceFile ne null) {
val path = new Path(sym.sourceFile.path)
val root = ResourcesPlugin.getWorkspace().getRoot()
root.findFilesForLocation(path) match {
case arr: Array[_] if arr.length == 1 => Some(arr(0).getFullPath)
case _ => findCompilationUnit()
root.findFilesForLocationURI(path.toFile.toURI) match {
case Array(f) => Some(f.getFullPath)
case _ => findPath
}
} else
findCompilationUnit()

val sourceFile = findSourceFile()

val target =
if(sourceFile.isDefined)
SourceFileProviderRegistry.getProvider(sourceFile.get).createFrom(sourceFile.get)
else
findClassFile()
findPath

findSourceFile.fold(findClassFile) { f =>
SourceFileProviderRegistry.getProvider(f) flatMap (_.createFrom(f))
}
}

target flatMap { file =>
def locate(sym : Symbol): Option[(InteractiveCompilationUnit, Int)] =
findCompilationUnit(sym) flatMap { file =>
val pos = if (sym.pos eq NoPosition) {
file.withSourceFile { (f, _) =>
val pos = new Response[Position]
Expand All @@ -96,5 +89,4 @@ trait LocateSymbol { self : ScalaPresentationCompiler =>
else Some(file, p.point)
}
}
}
}
Expand Up @@ -33,7 +33,7 @@ import scala.tools.nsc.io.VirtualFile
import scala.tools.nsc.interactive.MissingResponse


class ScalaPresentationCompiler(project: ScalaProject, settings: Settings) extends {
class ScalaPresentationCompiler(val project: ScalaProject, settings: Settings) extends {
/**
* Lock object for protecting compiler names. Names are cached in a global `Array[Char]`
* and concurrent access may lead to overwritten names.
Expand Down
Expand Up @@ -32,13 +32,11 @@ import scala.tools.eclipse.InteractiveCompilationUnit
abstract class HyperlinkFactory {
protected val global: ScalaPresentationCompiler

def create(createHyperlink: Hyperlink.Factory, scu: InteractiveCompilationUnit, sym: global.Symbol, region: IRegion): Option[IHyperlink] = {
global.askOption { () =>
global.locate(sym, scu) map {
case (f, pos) =>
val text = sym.kindString + " " + sym.fullName
createHyperlink(f, pos, sym.name.length, text, region)
}
}.getOrElse(None)
def create(createHyperlink: Hyperlink.Factory, sym: global.Symbol, region: IRegion): Option[IHyperlink] = {
global.locate(sym) map {
case (f, pos) =>
val text = sym.kindString + " " + sym.fullName
createHyperlink(f, pos, sym.name.length, text, region)
}
}
}
Expand Up @@ -17,6 +17,8 @@ class ScalaDeclarationHyperlinkComputer extends HasLogger {
}

def findHyperlinks(icu: InteractiveCompilationUnit, wordRegion: IRegion, mappedRegion: IRegion): Option[List[IHyperlink]] = {
logger.info("detectHyperlinks: wordRegion = " + mappedRegion)

/** In 2.9 ClazzTag was called ClassTag. Source-compatibility hack */
implicit def compatClazzTag(com: ScalaPresentationCompiler) = new {
def ClazzTag = 12 // we really, really hope this constant won't change in 2.9.x
Expand All @@ -40,45 +42,41 @@ class ScalaDeclarationHyperlinkComputer extends HasLogger {

val response = new Response[compiler.Tree]
askTypeAt(pos, response)
val typed = response.get
val symsOpt = response.get.left.toOption.map { tree =>
compiler.askOption { () =>
tree match {
case Import(expr, sels) =>
if (expr.pos.includes(pos)) {
@annotation.tailrec
def locate(p: Position, inExpr: Tree): Symbol = inExpr match {
case Select(qualifier, name) =>
if (qualifier.pos.includes(p)) locate(p, qualifier)
else inExpr.symbol
case tree => tree.symbol
}

logger.info("detectHyperlinks: wordRegion = " + mappedRegion)
compiler.askOption { () =>
typed.left.toOption map {
case Import(expr, sels) =>
if (expr.pos.includes(pos)) {
@annotation.tailrec
def locate(p: Position, inExpr: Tree): Symbol = inExpr match {
case Select(qualifier, name) =>
if (qualifier.pos.includes(p)) locate(p, qualifier)
else inExpr.symbol
case tree => tree.symbol
List(locate(pos, expr))
} else {
sels find (selPos => selPos.namePos >= pos.start && selPos.namePos <= pos.end) map { sel =>
val tpe = stabilizedType(expr)
List(tpe.member(sel.name), tpe.member(sel.name.toTypeName))
} getOrElse Nil
}

List(locate(pos, expr))
} else {
sels find (selPos => selPos.namePos >= pos.start && selPos.namePos <= pos.end) map { sel =>
val tpe = stabilizedType(expr)
List(tpe.member(sel.name), tpe.member(sel.name.toTypeName))
} getOrElse Nil
}
case Annotated(atp, _) => List(atp.symbol)
case Literal(const) if const.tag == compiler.ClazzTag => List(const.typeValue.typeSymbol)
case ap @ Select(qual, nme.apply) => List(qual.symbol, ap.symbol)
case st if st.symbol ne null => List(st.symbol)
case _ => List()
} flatMap { list =>
val filteredSyms = list filterNot { sym => sym.isPackage || sym == NoSymbol }
if (filteredSyms.isEmpty) None else Some(
filteredSyms.foldLeft(List[IHyperlink]()) { (links, sym) =>
if (sym.isJavaDefined) links
else
DeclarationHyperlinkFactory.create(Hyperlink.withText("Open Declaration (%s)".format(sym.toString)), icu, sym, wordRegion).toList ::: links
})
case Annotated(atp, _) => List(atp.symbol)
case Literal(const) if const.tag == compiler.ClazzTag => List(const.typeValue.typeSymbol)
case ap @ Select(qual, nme.apply) => List(ap.symbol, qual.symbol)
case st if st.symbol ne null => List(st.symbol)
case _ => List()
}
}
}.flatten
symsOpt map { syms =>
syms filterNot { sym => sym == NoSymbol || sym.isPackage || sym.isJavaDefined } flatMap { sym =>
DeclarationHyperlinkFactory.create(Hyperlink.withText("Open Declaration (%s)".format(sym.toString)), sym, wordRegion)
}
}.flatten.headOption
}
}
})(None)
}

}
}
Expand Up @@ -46,7 +46,7 @@ trait ScalaOverrideIndicatorBuilder { self : ScalaPresentationCompiler =>
case class ScalaIndicator(scu: ScalaCompilationUnit, text: String, base: Symbol, val isOverwrite: Boolean)
extends source.Annotation(OVERRIDE_ANNOTATION_TYPE, false, text) with IScalaOverrideIndicator {
def open = {
ask { () => locate(base, scu) } map {
locate(base) map {
case (file, pos) =>
EditorUtility.openInEditor(file, true) match {
case editor: ITextEditor => editor.selectAndReveal(pos, 0)
Expand Down
Expand Up @@ -164,7 +164,7 @@ object ImplicitHighlightingPresenter {
val txt = new String(sourceFile.content, t.pos.startOrPoint, math.max(0, t.pos.endOrPoint - t.pos.startOrPoint)).trim()
val pos = mkPosition(t.pos, txt)
val region = new Region(pos.offset, pos.getLength)
val annotation = new ImplicitConversionAnnotation(() => ImplicitHyperlinkFactory.create(Hyperlink.withText("Open Implicit"), scu, t.symbol, region),
val annotation = new ImplicitConversionAnnotation(() => ImplicitHyperlinkFactory.create(Hyperlink.withText("Open Implicit"), t.symbol, region),
"Implicit conversions found: " + txt + DisplayStringSeparator + t.fun.symbol.name + "(" + txt + ")")

(annotation, pos)
Expand Down
Expand Up @@ -23,9 +23,9 @@ object SourceFileProviderRegistry extends HasLogger {

registerProviders()

def getProvider(path: IPath): SourceFileProvider = getProvider(FileExtension(path))
def getProvider(path: IPath): Option[SourceFileProvider] = getProvider(FileExtension(path))

private def getProvider(extension: FileExtension): SourceFileProvider = registry get extension
private def getProvider(extension: FileExtension): Option[SourceFileProvider] = Option(registry get extension)

private def registerProviders() {
val extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(EXTENSION_POINT)
Expand Down

0 comments on commit fdcf2fa

Please sign in to comment.