Skip to content

Commit

Permalink
bugfix: make symbol search prefer results with scala version of docum…
Browse files Browse the repository at this point in the history
…ent in focus
  • Loading branch information
kasiaMarek committed Mar 6, 2024
1 parent c95ba51 commit f2e80b9
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,13 @@ final class BuildTargets private (
} yield target.scalaVersion
}

def possibleScalaVersions(source: AbsolutePath): List[String] = {
for {
id <- inverseSourcesAll(source)
target <- scalaTarget(id).toList
} yield target.scalaVersion
}

/**
* Resolves sbt auto imports if a file belongs to a Sbt build target.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,8 @@ final class DefinitionProvider(
else true
}

val dialect = scalaVersionSelector.dialectFromBuildTarget(path)
val locs = workspaceSearch
.searchExactFrom(ident.value, path, token, dialect)
.searchExactFrom(ident.value, path, token, Some(path))

val reducedGuesses =
if (locs.size > 1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1689,7 +1689,9 @@ class MetalsLspService(
indexingPromise.future.map { _ =>
val timer = new Timer(time)
val result =
workspaceSymbols.search(params.getQuery, token, currentDialect).toList
workspaceSymbols
.search(params.getQuery, token, focusedDocument())
.toList
if (clientConfig.initialConfig.statistics.isWorkspaceSymbol) {
scribe.info(
s"time: found ${result.length} results for query '${params.getQuery}' in $timer"
Expand All @@ -1699,12 +1701,9 @@ class MetalsLspService(
}

def workspaceSymbol(query: String): Seq[SymbolInformation] = {
workspaceSymbols.search(query, currentDialect)
workspaceSymbols.search(query, focusedDocument())
}

private def currentDialect =
focusedDocument().flatMap(scalaVersionSelector.dialectFromBuildTarget)

def indexSources(): Future[Unit] = Future {
indexer.indexWorkspaceSources(buildTargets.allWritableData)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import java.{util => ju}

import scala.collection.mutable

import scala.meta.Dialect
import scala.meta.dialects
import scala.meta.internal.metals.MetalsEnrichments._
import scala.meta.internal.mtags.GlobalSymbolIndex
import scala.meta.internal.mtags.Symbol
Expand Down Expand Up @@ -34,7 +32,7 @@ class WorkspaceSearchVisitor(
token: CancelChecker,
index: GlobalSymbolIndex,
saveClassFileToDisk: Boolean,
preferredDialect: Option[Dialect],
resultOrdering: Ordering[SymbolDefinition] = DefaultSymbolDefinitionOrdering,
)(implicit rc: ReportContext)
extends SymbolSearchVisitor {
private val fromWorkspace = new ju.ArrayList[l.SymbolInformation]()
Expand Down Expand Up @@ -91,21 +89,12 @@ class WorkspaceSearchVisitor(
): Option[SymbolDefinition] = {
val nme = Classfile.name(filename)
val tpe = Symbol(Symbols.Global(pkg, Descriptor.Type(nme)))
val preferredDialects = preferredDialect match {
case Some(dialects.Scala213) =>
Set(dialects.Scala213, dialects.Scala213Source3)
case Some(dialects.Scala212) =>
Set(dialects.Scala212, dialects.Scala212Source3)
case opt => opt.toSet
}
val forTpe = index.definitions(tpe)
val defs = if (forTpe.isEmpty) {
val term = Symbol(Symbols.Global(pkg, Descriptor.Term(nme)))
index.definitions(term)
} else forTpe
defs.sortBy { defn =>
(!preferredDialects(defn.dialect), defn.path.toURI.toString)
}.headOption
defs.sorted(resultOrdering).headOption
}
override def shouldVisitPackage(pkg: String): Boolean = true
override def visitWorkspaceSymbol(
Expand Down Expand Up @@ -160,3 +149,10 @@ class WorkspaceSearchVisitor(
if (isHit) 1 else 0
}
}

object DefaultSymbolDefinitionOrdering extends Ordering[SymbolDefinition] {

override def compare(x: SymbolDefinition, y: SymbolDefinition): Int =
x.path.toURI.toString().length() - y.path.toURI.toString().length()

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import scala.annotation.tailrec
import scala.collection.concurrent.TrieMap
import scala.util.control.NonFatal

import scala.meta.Dialect
import scala.meta.internal.mtags.GlobalSymbolIndex
import scala.meta.internal.mtags.SymbolDefinition
import scala.meta.internal.pc.InterruptException
import scala.meta.io.AbsolutePath
import scala.meta.pc.CancelToken
Expand Down Expand Up @@ -44,19 +44,19 @@ final class WorkspaceSymbolProvider(

def search(
query: String,
preferredDialect: Option[Dialect],
fileInFocus: Option[AbsolutePath],
): Seq[l.SymbolInformation] = {
search(query, () => (), preferredDialect)
search(query, () => (), fileInFocus)
}

def search(
query: String,
token: CancelChecker,
preferredDialect: Option[Dialect],
fileInFocus: Option[AbsolutePath],
): Seq[l.SymbolInformation] = {
if (query.isEmpty) return Nil
try {
searchUnsafe(query, token, preferredDialect)
searchUnsafe(query, token, fileInFocus)
} catch {
case InterruptException() =>
Nil
Expand All @@ -67,7 +67,7 @@ final class WorkspaceSymbolProvider(
queryString: String,
path: AbsolutePath,
token: CancelToken,
preferredDialect: Option[Dialect],
fileInFocus: Option[AbsolutePath],
): Seq[l.SymbolInformation] = {
val query = WorkspaceSymbolQuery.exact(queryString)
val visitor =
Expand All @@ -77,7 +77,7 @@ final class WorkspaceSymbolProvider(
token,
index,
saveClassFileToDisk,
preferredDialect,
SymbolDefinitionOrdering.fromOptPath(fileInFocus),
)
val targetId = buildTargets.inverseSources(path)
search(query, visitor, targetId)
Expand Down Expand Up @@ -229,7 +229,7 @@ final class WorkspaceSymbolProvider(
private def searchUnsafe(
textQuery: String,
token: CancelChecker,
preferredDialect: Option[Dialect],
fileInFocus: Option[AbsolutePath],
): Seq[l.SymbolInformation] = {
val query = WorkspaceSymbolQuery.fromTextQuery(textQuery)
val visitor =
Expand All @@ -239,9 +239,39 @@ final class WorkspaceSymbolProvider(
token,
index,
saveClassFileToDisk,
preferredDialect,
SymbolDefinitionOrdering.fromOptPath(fileInFocus),
)
search(query, visitor, None)
visitor.allResults()
}

class PreferredScalaVersionOrdering(preferredScalaVersions: Set[String])
extends Ordering[SymbolDefinition] {
private def pathMatchesPreferred(path: AbsolutePath) =
buildTargets
.possibleScalaVersions(path)
.exists(preferredScalaVersions(_))

private def pathLength(symbolDef: SymbolDefinition) =
symbolDef.path.toURI.toString().length()

override def compare(x: SymbolDefinition, y: SymbolDefinition): Int = {
val xVersionMatches = pathMatchesPreferred(x.path)
val yVersionMatches = pathMatchesPreferred(y.path)

if (xVersionMatches && !yVersionMatches) -1
else if (yVersionMatches && !xVersionMatches) 1
else pathLength(x) - pathLength(y)
}
}

object SymbolDefinitionOrdering {
def fromOptPath(path: Option[AbsolutePath]): Ordering[SymbolDefinition] = {
path.toList.flatMap(buildTargets.possibleScalaVersions(_)) match {
case Nil => DefaultSymbolDefinitionOrdering
case preferredScalaVersions =>
new PreferredScalaVersionOrdering(preferredScalaVersions.toSet)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,9 @@ final class StepNavigator(
throw new Exception(s"${expected.file} does not exist")
}
} else {
// workaround for https://github.com/scalameta/metals/issues/6155
val regex = raw"2\.\d+\.\d+"
val expectWithoutVersion =
expected.file.replaceAll(regex, "").stripPrefix("file://")
val obtainedWithoutVersion = actualPath.replaceAll(regex, "")
if (expectWithoutVersion == obtainedWithoutVersion) {
nextStep
} else {
val error =
s"Obtained [$actualPath, $actualLine], expected [${expected.file}, ${expected.line}]"
throw new Exception(error)
}
val error =
s"Obtained [$actualPath, $actualLine], expected [${expected.file}, ${expected.line}]"
throw new Exception(error)
}
}
}
Expand Down

0 comments on commit f2e80b9

Please sign in to comment.