Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Implement code select. #76

Closed
wants to merge 1 commit into from

2 participants

@dragos
Owner

This allows the Javadoc view to track the cursor, and searching for references of the current method under the cursor.

It's part of my clean-up effort of branches that hang around my checkout. I think this one is generally useful and adds some convenience when working with Java APIs, plus it cleans up something that never worked.

@dragos dragos Implement code select.
This allows the Javadoc view to track the cursor, and searching for references of the current method under the cursor.
1d78669
@dotta dotta commented on the diff
...cala/tools/eclipse/javaelements/ScalaJavaMapper.scala
((21 lines not shown))
+ askOption { () =>
+ ((meth.getElementName == sym.name.toString)
+ && meth.getParameterTypes.map(tp => getTypeErasure(getElementType(tp)))
+ .sameElements(sym.tpe.paramTypes.map(mapParamTypeSignature)))
+ }.getOrElse(false)
+ }
+
+ if (sym.isPackage) {
+ val fullName = sym.fullName
+ val results = projects.map(p => Option(p.findPackageFragment(new Path(fullName))))
+ results.flatten.headOption
+ } else if (sym.isClass || sym.isModule) {
+ val fullClassName = mapType(sym)
+ val results = projects.map(p => Option(p.findType(fullClassName)))
+ results.find(_.isDefined).flatten.headOption
+ } else getJavaElement(sym.owner) match {
@dotta Owner
dotta added a note

isn't sym.owner risky? (I mean executing it outside of the PC)

@dragos Owner
dragos added a note

It shouldn't be. The scala compiler uses laziness only in types, not in symbols... Every symbol has an owner, since they are always created through factory methods, like owner.newValue or owner.newClass. That being said, to my great surprise TypeTree.symbol is delegating to its type to retrieve the symbol. However, that looks like a bug or an exception and I'm willing to take a risk here for the owner. As soon as we get the API (yeah, I know, it sounds like empty promisses), this can be switched to the 'safe' API.

@dotta Owner
dotta added a note

In the compiler I remember seeing phases changing the owner in some cases, that's what made me thinking. But I guess that owners don't change if only phases up to typer are run.

Looking forward to the API, we will finally be able to fix quite a bit of code. We really have way too many places were we can suffer visibility issues because we access compiler's data structures that are not thread safe...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@dragos dragos closed this
@misto misto referenced this pull request from a commit
@misto misto Create fatal errors when a refactoring's initial check yields an error.
Until now, we created normal errors, which were shown in a wizard page,
and because they were non-fatal, the refactoring still tried to execute,
resulting in exceptions in the log file. Now we use fatal errors, which
immediately abort a refactoring and show the error message in a window.

Fixes scala-refactoring #76
0ae24d2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Feb 29, 2012
  1. @dragos

    Implement code select.

    dragos authored
    This allows the Javadoc view to track the cursor, and searching for references of the current method under the cursor.
This page is out of date. Refresh to see the latest.
View
25 org.scala-ide.sdt.core/src/scala/tools/eclipse/javaelements/ScalaCompilationUnit.scala
@@ -27,10 +27,7 @@ import scala.tools.nsc.util.{ BatchSourceFile, SourceFile }
import scala.tools.eclipse.contribution.weaving.jdt.{ IScalaCompilationUnit, IScalaWordFinder }
import scala.tools.eclipse.{ ScalaImages, ScalaPlugin, ScalaPresentationCompiler, ScalaSourceIndexer, ScalaWordFinder }
import scala.tools.eclipse.util.ReflectionUtils
-import org.eclipse.jdt.core.IField
-import org.eclipse.jdt.core.IMethod
-import org.eclipse.jdt.core.ISourceReference
-import org.eclipse.jdt.core.IParent
+import org.eclipse.jdt.core._
import org.eclipse.jdt.internal.core.JavaElement
import org.eclipse.jdt.internal.core.SourceRefElement
import scala.tools.eclipse.logging.HasLogger
@@ -187,9 +184,23 @@ trait ScalaCompilationUnit extends Openable with env.ICompilationUnit with Scala
case elem => elem
}
}
-
- override def codeSelect(cu : env.ICompilationUnit, offset : Int, length : Int, workingCopyOwner : WorkingCopyOwner) : Array[IJavaElement] = {
- Array.empty
+
+ override def codeSelect(cu: env.ICompilationUnit, offset: Int, length: Int, workingCopyOwner: WorkingCopyOwner): Array[IJavaElement] = {
+ withSourceFile { (srcFile, compiler) =>
+ val pos = compiler.rangePos(srcFile, offset, offset, offset)
+
+ val typed = new compiler.Response[compiler.Tree]
+ compiler.askTypeAt(pos, typed)
+ val typedRes = typed.get
+ val element = for {
+ t <- typedRes.left.toOption
+ if t.hasSymbol
+ element <- compiler.getJavaElement(t.symbol)
+ } yield Array(element: IJavaElement)
+
+ val res = element.getOrElse(Array.empty[IJavaElement])
+ res
+ }(Array.empty[IJavaElement])
}
def codeComplete
View
47 org.scala-ide.sdt.core/src/scala/tools/eclipse/javaelements/ScalaJavaMapper.scala
@@ -11,9 +11,56 @@ import scala.tools.nsc.symtab.Flags
import scala.tools.eclipse.ScalaPresentationCompiler
import ch.epfl.lamp.fjbg.{ JObjectType, JType }
import scala.tools.eclipse.logging.HasLogger
+import org.eclipse.jdt.core._
+import org.eclipse.jdt.internal.core.JavaModelManager
+import org.eclipse.core.runtime.Path
trait ScalaJavaMapper extends ScalaAnnotationHelper with HasLogger { self : ScalaPresentationCompiler =>
+ /** Return the Java Element corresponding to the given Scala Symbol, looking in the
+ * given project list
+ *
+ * If the symbol exists in several projects, it returns one of them.
+ */
+ def getJavaElement(sym: Symbol, projects: IJavaProject*): Option[IJavaElement] = {
+ assert(sym ne null)
+ if (sym == NoSymbol) return None
+
+ def matchesMethod(meth: IMethod): Boolean = {
+ import Signature._
+ askOption { () =>
+ ((meth.getElementName == sym.name.toString)
+ && meth.getParameterTypes.map(tp => getTypeErasure(getElementType(tp)))
+ .sameElements(sym.tpe.paramTypes.map(mapParamTypeSignature)))
+ }.getOrElse(false)
+ }
+
+ if (sym.isPackage) {
+ val fullName = sym.fullName
+ val results = projects.map(p => Option(p.findPackageFragment(new Path(fullName))))
+ results.flatten.headOption
+ } else if (sym.isClass || sym.isModule) {
+ val fullClassName = mapType(sym)
+ val results = projects.map(p => Option(p.findType(fullClassName)))
+ results.find(_.isDefined).flatten.headOption
+ } else getJavaElement(sym.owner) match {
@dotta Owner
dotta added a note

isn't sym.owner risky? (I mean executing it outside of the PC)

@dragos Owner
dragos added a note

It shouldn't be. The scala compiler uses laziness only in types, not in symbols... Every symbol has an owner, since they are always created through factory methods, like owner.newValue or owner.newClass. That being said, to my great surprise TypeTree.symbol is delegating to its type to retrieve the symbol. However, that looks like a bug or an exception and I'm willing to take a risk here for the owner. As soon as we get the API (yeah, I know, it sounds like empty promisses), this can be switched to the 'safe' API.

@dotta Owner
dotta added a note

In the compiler I remember seeing phases changing the owner in some cases, that's what made me thinking. But I guess that owners don't change if only phases up to typer are run.

Looking forward to the API, we will finally be able to fix quite a bit of code. We really have way too many places were we can suffer visibility issues because we access compiler's data structures that are not thread safe...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ case Some(ownerClass: IType) =>
+ if (sym.isMethod) ownerClass.getMethods.find(matchesMethod)
+ else ownerClass.getFields.find(_.getElementName == sym.name.toString)
+ case _ => None
+ }
+ }
+
+ /** Return the Java Element corresponding to the given Scala Symbol, looking in the
+ * all existing Java projects.
+ *
+ * If the symbol exists in several projects, it returns one of them.
+ */
+ def getJavaElement(sym: Symbol): Option[IJavaElement] = {
+ val javaModel = JavaModelManager.getJavaModelManager.getJavaModel
+ getJavaElement(sym, javaModel.getJavaProjects(): _*)
+ }
+
def mapType(t : Tree) : String = {
(t match {
case tt : TypeTree => {
Something went wrong with that request. Please try again.