From ca681744e920681b0f251037c25aaa85c5187985 Mon Sep 17 00:00:00 2001 From: Katarzyna Marek Date: Tue, 2 Jan 2024 17:31:34 +0100 Subject: [PATCH] add back `compileAndLookForNewReferences` --- .../internal/metals/MetalsLspService.scala | 61 ++++++++++++++++++- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/metals/src/main/scala/scala/meta/internal/metals/MetalsLspService.scala b/metals/src/main/scala/scala/meta/internal/metals/MetalsLspService.scala index 468011bd119..4ab534ea06c 100644 --- a/metals/src/main/scala/scala/meta/internal/metals/MetalsLspService.scala +++ b/metals/src/main/scala/scala/meta/internal/metals/MetalsLspService.scala @@ -76,6 +76,7 @@ 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.rename.RenameProvider import scala.meta.internal.semver.SemVer @@ -1527,6 +1528,63 @@ 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], + ): Unit = { + val path = params.getTextDocument.getUri.toAbsolutePath + val old = path.toInputFromBuffers(buffers) + compilations.cascadeCompileFiles(Seq(path)).foreach { _ => + 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 => + case Some(p) => + referencesProvider.references(p).foreach { newResult => + 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]] = { @@ -1544,8 +1602,7 @@ class MetalsLspService( } } if (results.nonEmpty) { - val path = params.getTextDocument.getUri.toAbsolutePath - compilations.cascadeCompileFiles(Seq(path)) + compileAndLookForNewReferences(params, results) } results }