Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Implemented find references in constructor's super call

This commit is the direct consequence of the following observation:
"expressions can only live inside methods".  And
``ScalaMatchLocator$MatchLocatorTraverser.enclosingMethod`` is the realization
of this fact. Indeed, ``enclosingMethod`` retrieves the method's symbol
enclosing the currently traversed expression.

* Fixed implementation of ``ScalaMatchLocator $FieldLocator.report``.
  • Loading branch information...
commit e57c21964d336e8126ecb3f2ec52f1035dc5639f 1 parent 013e5eb
@dotta dotta authored
View
26 ...scala-ide.sdt.core.tests/src/scala/tools/eclipse/findreferences/FindReferencesTests.scala
@@ -9,15 +9,19 @@ import scala.tools.eclipse.javaelements.ScalaModuleElement
import scala.tools.eclipse.javaelements.ScalaTypeElement
import scala.tools.eclipse.javaelements.ScalaValElement
import scala.tools.eclipse.javaelements.ScalaVarElement
+import scala.tools.eclipse.logging.HasLogger
import scala.tools.eclipse.testsetup.FileUtils
import scala.tools.eclipse.testsetup.SDTTestUtils
import scala.tools.eclipse.testsetup.SearchOps
import scala.tools.eclipse.testsetup.TestProjectSetup
-import org.eclipse.core.resources.IProject
+
+import org.eclipse.core.resources.IResource
import org.eclipse.core.runtime.IPath
import org.eclipse.core.runtime.NullProgressMonitor
import org.eclipse.core.runtime.Path
import org.eclipse.jdt.core.IJavaElement
+import org.eclipse.jdt.core.IType
+import org.eclipse.jdt.internal.core.JavaElement
import org.eclipse.jdt.internal.core.SourceType
import org.junit.After
import org.junit.Assert.assertEquals
@@ -26,9 +30,6 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
-import scala.tools.eclipse.logging.HasLogger
-import org.eclipse.jdt.internal.core.JavaElement
-import org.eclipse.core.resources.IResource
@RunWith(classOf[JUnit4])
class FindReferencesTests extends FindReferencesTester with HasLogger {
@@ -118,7 +119,16 @@ class FindReferencesTests extends FindReferencesTester with HasLogger {
val msg = "Don't know how to convert element `%s` of type `%s`".format(e.getElementName, e.getClass)
throw new IllegalArgumentException(msg)
}
- testElement(e.readableName)
+ testElement(fullyQualifiedName(e))
+ }
+
+ private def fullyQualifiedName(e: JavaElement): String = {
+ // Ugly hack for extracting the fully-qualified name of a JavaElement. If anyone has a better idea, please say something.
+ val pkg =
+ if (e.getElementType == IJavaElement.METHOD) e.getParent.asInstanceOf[IType].getPackageFragment.getElementName
+ else ""
+
+ (if (pkg.nonEmpty) pkg + "." else "") + e.readableName
}
@Test
@@ -162,4 +172,10 @@ class FindReferencesTests extends FindReferencesTester with HasLogger {
val expected = fieldVal("Foo$.ss") isReferencedBy moduleConstructor("Foo")
runTest("ex1", "Ex1.scala", expected)
}
+
+ @Test
+ def findReferencesInConstructorSuperCall() {
+ val expected = fieldVal("Bar$.v") isReferencedBy clazzConstructor("foo.Foo")
+ runTest("super", "foo/Bar.scala", expected)
+ }
}
View
5 org.scala-ide.sdt.core.tests/test-workspace/find-references/super/src/foo/Bar.scala
@@ -0,0 +1,5 @@
+package foo
+
+object Bar {
+ val v/*ref*/ = 2
+}
View
3  org.scala-ide.sdt.core.tests/test-workspace/find-references/super/src/foo/Foo.scala
@@ -0,0 +1,3 @@
+package foo
+
+class Foo extends Top(Bar.v)
View
3  org.scala-ide.sdt.core.tests/test-workspace/find-references/super/src/foo/Top.scala
@@ -0,0 +1,3 @@
+package foo
+
+class Top(val v: Int)
View
8 org.scala-ide.sdt.core/src/scala/tools/eclipse/javaelements/ScalaJavaMapper.scala
@@ -29,9 +29,11 @@ trait ScalaJavaMapper extends ScalaAnnotationHelper with SymbolNameUtil with Has
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)))
+ lazy val methName = meth.getElementName
+ lazy val symName = (if(sym.isConstructor) sym.owner.simpleName.toString + (if (sym.owner.isModuleClass) "$" else "") else sym.name.toString)
+ lazy val sameName = methName == symName
+ lazy val sameParams = meth.getParameterTypes.map(tp => getTypeErasure(getElementType(tp))).sameElements(sym.tpe.paramTypes.map(mapParamTypeSignature))
+ sameName && sameParams
}.getOrElse(false)
}
View
56 org.scala-ide.sdt.core/src/scala/tools/eclipse/javaelements/ScalaMatchLocator.scala
@@ -72,7 +72,20 @@ trait ScalaMatchLocator { self: ScalaPresentationCompiler =>
}
def posToLong(pos: Position): Long = pos.startOrPoint << 32 | pos.endOrPoint
-
+
+ /** Returns the class/method/field symbol enclosing the tree node that is currently traversed.*/
+ protected def enclosingDeclaration(): Symbol = {
+ if(currentOwner.isLocalDummy) {
+ // expressions in an entity's body are flagged as "local dummy", which is basically a synthetic owner of
+ // the expression. Since these expression are effectively evaluated in the entity's primary constructor,
+ // it makes sense to return the constructor symbol as the enclosing declaration owning the expression.
+ // TODO: I now wonder how this will work with traits and nested method declarations. Need to test this!
+ val constructor = currentOwner.enclClass.info.member(self.nme.CONSTRUCTOR)
+ constructor
+ }
+ else currentOwner
+ }
+
/* simplified from org.eclipse.jdt.internal.core.search.matching.PatternLocator */
/*def qualifiedPattern(simpleNamePattern: Array[Char], qualificationPattern: Array[Char]): Array[Char] =
// NOTE: if case insensitive search then simpleNamePattern & qualificationPattern are assumed to be lowercase
@@ -214,34 +227,31 @@ trait ScalaMatchLocator { self: ScalaPresentationCompiler =>
def report(tree: Tree) = tree match {
case s @ Select(qualifier, _) =>
report(qualifier)
- s.symbol match {
- case sym : MethodSymbol => reportVariableReference(s, pattern)
- case _ =>
- }
+ if(s.symbol.isValue || s.symbol.isVariable)
+ reportVariableReference(s, pattern)
case _ =>
}
def reportVariableReference(s: Select, pat: FieldPattern) {
val searchedVar = pat.getIndexKey
-
- if (!s.pos.isDefined ||
- (!pat.matchesName(searchedVar, s.name.toChars) &&
- !pat.matchesName(CharOp.concat(searchedVar, "_$eq".toCharArray), s.name.toChars)) ||
- !checkQualifier(s, declaringSimpleName(pat), pat))
- return
-
- val enclosingElement = scu match {
- case ssf: ScalaSourceFile => ssf.getElementAt(s.pos.start)
- case _ => null
- }
- val accuracy = SearchMatch.A_INACCURATE
- val offset = s.pos.start
- val length = s.pos.end - offset
- val insideDocComment = false
- val participant = possibleMatch.document.getParticipant
- val resource = possibleMatch.resource
- report(new FieldReferenceMatch(enclosingElement, accuracy, offset, length, true, false, insideDocComment, participant, resource))
+ lazy val noPosition = !s.pos.isDefined
+ lazy val nameNoMatch = !pat.matchesName(searchedVar, s.name.toChars)
+ lazy val varNoMatch = !pat.matchesName(CharOp.concat(searchedVar, "_$eq".toCharArray), s.name.toChars)
+ lazy val qualifierNoMatch = !checkQualifier(s, declaringSimpleName(pat), pat)
+
+ if (noPosition || (nameNoMatch && varNoMatch) || qualifierNoMatch) return
+
+ getJavaElement(enclosingDeclaration, scu.project.javaProject).foreach { enclosingElement =>
+ val accuracy = SearchMatch.A_ACCURATE
+ val offset = s.pos.start
+ val length = s.pos.end - offset
+ val insideDocComment = false
+ val participant = possibleMatch.document.getParticipant
+ val resource = possibleMatch.resource
+
+ report(new FieldReferenceMatch(enclosingElement, accuracy, offset, length, /*isReadAccess*/true, /*isWriteAccess*/false, insideDocComment, participant, resource))
+ }
}
}
Please sign in to comment.
Something went wrong with that request. Please try again.