summaryrefslogtreecommitdiff
path: root/src/interactive/scala/tools
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2015-09-08 23:32:56 +1000
committerJason Zaugg <jzaugg@gmail.com>2015-09-08 23:32:56 +1000
commit0a8c4b263e979a7ed9fc9172ebc5f51e8093f3d5 (patch)
tree24e76f91257145c5ba34b4f4317ce03bb1cb81e1 /src/interactive/scala/tools
parent3f1352f3ff16b0588b0f6e05bdb0a76b4702e431 (diff)
downloadscala-0a8c4b263e979a7ed9fc9172ebc5f51e8093f3d5.tar.gz
scala-0a8c4b263e979a7ed9fc9172ebc5f51e8093f3d5.tar.bz2
scala-0a8c4b263e979a7ed9fc9172ebc5f51e8093f3d5.zip
Camel Case and JavaBean completion
This is just too useful to leave on the cutting room floor. ``` scala> classOf[String].enclo<TAB> scala> classOf[String].getEnclosing getEnclosingClass getEnclosingConstructor getEnclosingMethod scala> classOf[String].simpl<TAB> scala> classOf[String].getSimpleName type X = global.TTWD<TAB> scala> type X = global.TypeTreeWithDeferredRefCheck ``` I revised the API of `matchingResults` as it was clunky to reuse the filtering on accessibility and term/type-ness while providing a custom name matcher.
Diffstat (limited to 'src/interactive/scala/tools')
-rw-r--r--src/interactive/scala/tools/nsc/interactive/Global.scala34
1 files changed, 26 insertions, 8 deletions
diff --git a/src/interactive/scala/tools/nsc/interactive/Global.scala b/src/interactive/scala/tools/nsc/interactive/Global.scala
index b9d06b3633..703da0b947 100644
--- a/src/interactive/scala/tools/nsc/interactive/Global.scala
+++ b/src/interactive/scala/tools/nsc/interactive/Global.scala
@@ -1159,8 +1159,14 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
/** The (possibly partial) detected that precedes the cursor */
def name: Name
def positionDelta: Int
- def matchingResults(matcher: (M, Name) => Boolean = CompletionResult.prefixMatcher): List[M] = {
- results filter (r => matcher(r, name))
+ def matchingResults(nameMatcher: (Name) => Name => Boolean = entered => candidate => candidate.startsWith(entered)): List[M] = {
+ val enteredName = if (name == nme.ERROR) nme.EMPTY else name
+ val matcher = nameMatcher(enteredName)
+ results filter { (member: Member) =>
+ val symbol = member.sym
+ def isStable = member.tpe.isStable || member.sym.isStable || member.sym.getterIn(member.sym.owner).isStable
+ member.accessible && !symbol.isConstructor && (name.isEmpty || matcher(member.sym.name) && (symbol.name.isTermName == name.isTermName || name.isTypeName && isStable))
+ }
}
}
object CompletionResult {
@@ -1176,12 +1182,24 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
override def positionDelta = 0
}
- val prefixMatcher = (member: Member, name: Name) => {
- val symbol = member.sym
- val prefix = if (name == nme.ERROR) nme.EMPTY else name
- def isStable = member.tpe.isStable || member.sym.isStable || member.sym.getterIn(member.sym.owner).isStable
- val nameMatches = !symbol.isConstructor && (prefix.isEmpty || symbol.name.startsWith(prefix) && (symbol.name.isTermName == prefix.isTermName || prefix.isTypeName && isStable))
- nameMatches && member.accessible
+ private val CamelRegex = "([A-Z][^A-Z]*)".r
+ private def camelComponents(s: String): List[String] = {
+ CamelRegex.findAllIn("X" + s).toList match { case head :: tail => head.drop(1) :: tail; case Nil => Nil }
+ }
+ def camelMatch(entered: Name): Name => Boolean = {
+ val chunks: List[String] = camelComponents(entered.toString)
+
+ (candidate: Name) => {
+ val candidateChunks = camelComponents(candidate.toString)
+ val exactCamelMatch =
+ (chunks corresponds candidateChunks.take(chunks.length))((x, y) => y.startsWith(x))
+ def beanCamelMatch = candidateChunks match {
+ case ("get" | "is") :: tail =>
+ (chunks corresponds tail.take(chunks.length))((x, y) => y.toLowerCase.startsWith(x.toLowerCase))
+ case _ => false
+ }
+ exactCamelMatch || beanCamelMatch
+ }
}
}