Skip to content

Commit

Permalink
use pc for references as fallback when missing semanticdb
Browse files Browse the repository at this point in the history
  • Loading branch information
kasiaMarek committed Dec 21, 2023
1 parent 61a8dbd commit ec87650
Show file tree
Hide file tree
Showing 14 changed files with 269 additions and 145 deletions.
14 changes: 9 additions & 5 deletions metals/src/main/scala/scala/meta/internal/metals/Compilers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ import org.eclipse.lsp4j.CompletionParams
import org.eclipse.lsp4j.Diagnostic
import org.eclipse.lsp4j.DocumentHighlight
import org.eclipse.lsp4j.InitializeParams
import org.eclipse.lsp4j.Location
import org.eclipse.lsp4j.ReferenceParams
import org.eclipse.lsp4j.RenameParams
import org.eclipse.lsp4j.SelectionRange
Expand Down Expand Up @@ -690,7 +689,7 @@ class Compilers(
params: ReferenceParams,
targetFiles: List[AbsolutePath],
token: CancelToken,
): Future[List[Location]] = {
): Future[List[ReferencesResult]] = {
withPCAndAdjustLsp(params) { (pc, pos, adjust) =>
val targets = targetFiles.map { target =>
target.toURI.toString -> {
Expand All @@ -712,9 +711,14 @@ class Compilers(
params.getContext().isIncludeDeclaration(),
).asScala
.map(
_.asScala.toList.map(loc =>
targets(loc.getUri())._2.adjustLocation(loc)
)
_.asScala.toList.map { defRes =>
val locations = defRes
.locations()
.asScala
.toList
.map(loc => targets(loc.getUri())._2.adjustLocation(loc))
ReferencesResult(defRes.symbol(), locations)
}
)
}
}.getOrElse(Future.successful(Nil))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,7 @@ final case class Indexer(
val input = sourceToIndex0.toInput
val symbols = ArrayBuffer.empty[WorkspaceSymbolInformation]
val methodSymbols = ArrayBuffer.empty[WorkspaceSymbolInformation]
referencesProvider().indexTokens(source, input, dialect)
SemanticdbDefinition.foreach(input, dialect, includeMembers = true) {
case SemanticdbDefinition(info, occ, owner) =>
if (info.isExtension) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ import scala.meta.internal.parsing.ClassFinder
import scala.meta.internal.parsing.ClassFinderGranularity
import scala.meta.internal.parsing.DocumentSymbolProvider
import scala.meta.internal.parsing.FoldingRangeProvider
import scala.meta.internal.parsing.TokenEditDistance
import scala.meta.internal.parsing.Trees
import scala.meta.internal.remotels.RemoteLanguageServer
import scala.meta.internal.rename.RenameProvider
Expand Down Expand Up @@ -607,10 +606,10 @@ class MetalsLspService(
semanticdbs,
buffers,
definitionProvider,
remote,
trees,
buildTargets,
compilers,
scalaVersionSelector,
)

private val syntheticHoverProvider: SyntheticHoverProvider =
Expand Down Expand Up @@ -1209,10 +1208,12 @@ class MetalsLspService(
val path = params.getTextDocument.getUri.toAbsolutePath
savedFiles.add(path)
// read file from disk, we only remove files from buffers on didClose.
buffers.put(path, path.toInput.text)
val text = path.toInput.text
buffers.put(path, text)
Future
.sequence(
List(
referencesProvider.indexTokens(path, text),
renameProvider.runSave(),
parseTrees(path),
onChange(List(path)),
Expand Down Expand Up @@ -1524,65 +1525,6 @@ class MetalsLspService(
referencesResult(params).map(_.flatMap(_.locations).asJava)
}

// Triggers a cascade compilation and tries to find new references to a given symbol.
// It's not possible to stream reference results so if we find new symbols we notify the
// user to run references again to see updated results.
private def compileAndLookForNewReferences(
params: ReferenceParams,
result: List[ReferencesResult],
): Future[Unit] = {
val path = params.getTextDocument.getUri.toAbsolutePath
val old = path.toInputFromBuffers(buffers)
compilations.cascadeCompileFiles(Seq(path)).flatMap { _ =>
val newBuffer = path.toInputFromBuffers(buffers)
val newParams: Option[ReferenceParams] =
if (newBuffer.text == old.text) Some(params)
else {
val edit = TokenEditDistance(old, newBuffer, trees)
edit
.getOrElse(TokenEditDistance.NoMatch)
.toRevised(
params.getPosition.getLine,
params.getPosition.getCharacter,
)
.foldResult(
pos => {
params.getPosition.setLine(pos.startLine)
params.getPosition.setCharacter(pos.startColumn)
Some(params)
},
() => Some(params),
() => None,
)
}
newParams match {
case None => Future.unit
case Some(p) =>
for {
newResult <- referencesProvider.references(p)
} yield {
val diff = newResult
.flatMap(_.locations)
.length - result.flatMap(_.locations).length
val diffSyms: Set[String] =
newResult.map(_.symbol).toSet -- result.map(_.symbol).toSet
if (diffSyms.nonEmpty && diff > 0) {
import scala.meta.internal.semanticdb.Scala._
val names =
diffSyms
.map(sym => s"'${sym.desc.name.value}'")
.mkString(" and ")
val message =
s"Found new symbol references for $names, try running again."
scribe.info(message)
statusBar
.addMessage(clientConfig.icons.info + message)
}
}
}
}
}

def referencesResult(
params: ReferenceParams
): Future[List[ReferencesResult]] = {
Expand All @@ -1600,7 +1542,8 @@ class MetalsLspService(
}
}
if (results.nonEmpty) {
compileAndLookForNewReferences(params, results)
val path = params.getTextDocument.getUri.toAbsolutePath
compilations.cascadeCompileFiles(Seq(path))
}
results
}
Expand Down
Loading

0 comments on commit ec87650

Please sign in to comment.