From b778bc7230c588316a70258aee10fe1e7d828bd8 Mon Sep 17 00:00:00 2001 From: Katarzyna Marek Date: Thu, 5 Oct 2023 08:01:06 +0200 Subject: [PATCH] include the build target in the report name --- .../meta/internal/metals/Compilers.scala | 24 +++++----- .../internal/metals/MetalsLspService.scala | 10 +++++ .../meta/internal/metals/doctor/Doctor.scala | 17 ++----- .../meta/metals/MetalsLanguageServer.scala | 2 +- .../scala/meta/pc/PresentationCompiler.java | 11 ++++- .../meta/internal/metals/ReportContext.scala | 44 +++++++++++++------ .../pc/ScalaPresentationCompiler.scala | 8 +++- .../pc/ScalaPresentationCompiler.scala | 8 +++- .../src/main/scala/tests/TestingServer.scala | 3 +- .../unit/src/main/scala/tests/TreeUtils.scala | 3 +- .../src/test/scala/tests/ReportsSuite.scala | 6 ++- 11 files changed, 87 insertions(+), 49 deletions(-) diff --git a/metals/src/main/scala/scala/meta/internal/metals/Compilers.scala b/metals/src/main/scala/scala/meta/internal/metals/Compilers.scala index ca061b457cd..768fa021402 100644 --- a/metals/src/main/scala/scala/meta/internal/metals/Compilers.scala +++ b/metals/src/main/scala/scala/meta/internal/metals/Compilers.scala @@ -924,11 +924,12 @@ class Compilers( ): Option[PresentationCompiler] = { val pc = JavaPresentationCompiler() Some( - configure(pc, search).newInstance( - targetUri, - classpath.toAbsoluteClasspath.map(_.toNIO).toSeq.asJava, - log.asJava, - ) + configure(pc, search) + .newInstance( + targetUri, + classpath.toAbsoluteClasspath.map(_.toNIO).toSeq.asJava, + log.asJava, + ) ) } @@ -1097,7 +1098,7 @@ class Compilers( classpath, search, target.scalac.getTarget.getUri, - ) + ).withBuildTargetName(target.displayName) } def newCompiler( @@ -1116,11 +1117,12 @@ class Compilers( } val filteredOptions = plugins.filterSupportedOptions(options) - configure(pc, search).newInstance( - name, - classpath.asJava, - (log ++ filteredOptions).asJava, - ) + configure(pc, search) + .newInstance( + name, + classpath.asJava, + (log ++ filteredOptions).asJava, + ) } private def toDebugCompletionType( 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 8f1e5ccdbd8..eaf3c135f86 100644 --- a/metals/src/main/scala/scala/meta/internal/metals/MetalsLspService.scala +++ b/metals/src/main/scala/scala/meta/internal/metals/MetalsLspService.scala @@ -173,6 +173,16 @@ class MetalsLspService( implicit val reports: StdReportContext = new StdReportContext( folder.toNIO, + _.flatMap { uri => + for { + filePath <- uri.toAbsolutePathSafe + buildTargetId <- buildTargets.inverseSources(filePath) + name <- buildTargets + .scalaTarget(buildTargetId) + .map(_.displayName) + .orElse(buildTargets.javaTarget(buildTargetId).map(_.displayName)) + } yield name + }, ReportLevel.fromString(MetalsServerConfig.default.loglevel), ) diff --git a/metals/src/main/scala/scala/meta/internal/metals/doctor/Doctor.scala b/metals/src/main/scala/scala/meta/internal/metals/doctor/Doctor.scala index 3d2c192df38..8809670fb2d 100644 --- a/metals/src/main/scala/scala/meta/internal/metals/doctor/Doctor.scala +++ b/metals/src/main/scala/scala/meta/internal/metals/doctor/Doctor.scala @@ -242,18 +242,6 @@ final class Doctor( private def getErrorReports(): List[ErrorReportInfo] = { def decode(text: String) = text.replace(StdReportContext.WORKSPACE_STR, workspace.toString()) - def getBuildTarget(lines: List[String]) = - for { - filePath <- lines.collectFirst { - case line if line.startsWith("file:") => - decode(line.trim()).toAbsolutePath - } - buildTargetId <- buildTargets.inverseSources(filePath) - name <- buildTargets - .scalaTarget(buildTargetId) - .map(_.displayName) - .orElse(buildTargets.javaTarget(buildTargetId).map(_.displayName)) - } yield name def getSummary(lines: List[String]) = { val reversed = lines.reverse val index = reversed.indexWhere(_.startsWith(Report.summaryTitle)) @@ -269,11 +257,12 @@ final class Doctor( rc.getReports().map { case TimestampedFile(file, timestamp) => val optLines = Try(Files.readAllLines(file.toPath).asScala.toList).toOption + val (name, buildTarget) = ReportFileName.getReportNameAndBuildTarget(file) ErrorReportInfo( - ReportFileName.getReportName(file), + name, timestamp, file.toPath.toUri().toString(), - optLines.flatMap(getBuildTarget(_)), + buildTarget, optLines.map(getSummary(_)).getOrElse(""), ) } diff --git a/metals/src/main/scala/scala/meta/metals/MetalsLanguageServer.scala b/metals/src/main/scala/scala/meta/metals/MetalsLanguageServer.scala index a74ce31ce5d..9cef353b2fb 100644 --- a/metals/src/main/scala/scala/meta/metals/MetalsLanguageServer.scala +++ b/metals/src/main/scala/scala/meta/metals/MetalsLanguageServer.scala @@ -202,7 +202,7 @@ class MetalsLanguageServer( metalsService.underlying = service folderPathsWithScala.foreach(folder => - new StdReportContext(folder.toNIO).cleanUpOldReports() + new StdReportContext(folder.toNIO, _ => None).cleanUpOldReports() ) service.initialize() diff --git a/mtags-interfaces/src/main/java/scala/meta/pc/PresentationCompiler.java b/mtags-interfaces/src/main/java/scala/meta/pc/PresentationCompiler.java index 1427e3f2cbc..1d60f573ea0 100644 --- a/mtags-interfaces/src/main/java/scala/meta/pc/PresentationCompiler.java +++ b/mtags-interfaces/src/main/java/scala/meta/pc/PresentationCompiler.java @@ -43,7 +43,7 @@ public abstract class PresentationCompiler { * */ public CompletableFuture> semanticTokens(VirtualFileParams params) { - + return CompletableFuture.completedFuture(Collections.emptyList()); } @@ -208,6 +208,13 @@ public PresentationCompiler withReportsLoggerLevel(String level) { return this; }; + /** + * Set build target name. + */ + public PresentationCompiler withBuildTargetName(String buildTargetName) { + return this; + }; + /** * Provide a SymbolSearch to extract docstrings, java parameter names and Scala * default parameter values. @@ -252,7 +259,7 @@ public abstract PresentationCompiler withScheduledExecutorService( * better-monadic-for. */ public abstract PresentationCompiler newInstance(String buildTargetIdentifier, List classpath, - List options); + List options); // ============================= // Intentionally missing methods diff --git a/mtags-shared/src/main/scala/scala/meta/internal/metals/ReportContext.scala b/mtags-shared/src/main/scala/scala/meta/internal/metals/ReportContext.scala index e898513595e..1ae04cf151c 100644 --- a/mtags-shared/src/main/scala/scala/meta/internal/metals/ReportContext.scala +++ b/mtags-shared/src/main/scala/scala/meta/internal/metals/ReportContext.scala @@ -33,26 +33,32 @@ trait Reporter { def deleteAll(): Unit } -class StdReportContext(workspace: Path, level: ReportLevel = ReportLevel.Info) - extends ReportContext { +class StdReportContext( + workspace: Path, + resolveBuildTarget: Option[String] => Option[String], + level: ReportLevel = ReportLevel.Info +) extends ReportContext { val reportsDir: Path = workspace.resolve(StdReportContext.reportsDir) val unsanitized = new StdReporter( workspace, StdReportContext.reportsDir.resolve("metals-full"), + resolveBuildTarget, level ) val incognito = new StdReporter( workspace, StdReportContext.reportsDir.resolve("metals"), + resolveBuildTarget, level ) val bloop = new StdReporter( workspace, StdReportContext.reportsDir.resolve("bloop"), + resolveBuildTarget, level ) @@ -71,8 +77,12 @@ class StdReportContext(workspace: Path, level: ReportLevel = ReportLevel.Info) } } -class StdReporter(workspace: Path, pathToReports: Path, level: ReportLevel) - extends Reporter { +class StdReporter( + workspace: Path, + pathToReports: Path, + resolveBuildTarget: Option[String] => Option[String], + level: ReportLevel +) extends Reporter { private lazy val maybeReportsDir: Path = workspace.resolve(pathToReports) private lazy val reportsDir = maybeReportsDir.createDirectories() private val limitedFilesManager = @@ -114,7 +124,7 @@ class StdReporter(workspace: Path, pathToReports: Path, level: ReportLevel) val sanitizedId = report.id.map(sanitize) if (sanitizedId.isDefined && reported.contains(sanitizedId.get)) None else { - val path = reportPath(report.name) + val path = reportPath(report) path.getParent.createDirectories() sanitizedId.foreach(reported += _) path.writeText(sanitize(report.fullText(withIdAndSummary = true))) @@ -130,10 +140,12 @@ class StdReporter(workspace: Path, pathToReports: Path, level: ReportLevel) .getOrElse(textAfterWokspaceReplace) } - private def reportPath(name: String): Path = { + private def reportPath(report: Report): Path = { val date = TimeFormatter.getDate() val time = TimeFormatter.getTime() - val filename = s"r_${name}_${time}.md" + val buildTargetPart = + resolveBuildTarget(report.path).map(":" ++ _).getOrElse("") + val filename = s"r_${report.name}${buildTargetPart}_${time}.md" reportsDir.resolve(date).resolve(filename) } @@ -278,11 +290,15 @@ object ReportLevel { } object ReportFileName { - val pattern: Regex = "r_(.*)_".r - - def getReportName(file: File): String = - pattern - .findPrefixMatchOf(file.getName()) - .map(_.group(1)) - .getOrElse(file.getName()) + val pattern: Regex = "r_([^:]*)(:.*)?_".r + + def getReportNameAndBuildTarget(file: File): (String, Option[String]) = + pattern.findPrefixMatchOf(file.getName()) match { + case None => (file.getName(), None) + case Some(foundMatch) => + ( + foundMatch.group(1), + Option(foundMatch.group(2)).map(_.stripPrefix(":")) + ) + } } diff --git a/mtags/src/main/scala-2/scala/meta/internal/pc/ScalaPresentationCompiler.scala b/mtags/src/main/scala-2/scala/meta/internal/pc/ScalaPresentationCompiler.scala index 5747b120294..70bf681a9cb 100644 --- a/mtags/src/main/scala-2/scala/meta/internal/pc/ScalaPresentationCompiler.scala +++ b/mtags/src/main/scala-2/scala/meta/internal/pc/ScalaPresentationCompiler.scala @@ -50,6 +50,7 @@ import org.eclipse.lsp4j.TextEdit case class ScalaPresentationCompiler( buildTargetIdentifier: String = "", + buildTargetName: Option[String] = None, classpath: Seq[Path] = Nil, options: List[String] = Nil, search: SymbolSearch = EmptySymbolSearch, @@ -69,9 +70,14 @@ case class ScalaPresentationCompiler( implicit val reportContex: ReportContext = folderPath - .map(new StdReportContext(_, reportsLevel)) + .map(new StdReportContext(_, _ => buildTargetName, reportsLevel)) .getOrElse(EmptyReportContext) + override def withBuildTargetName( + buildTargetName: String + ): ScalaPresentationCompiler = + copy(buildTargetName = Some(buildTargetName)) + override def withReportsLoggerLevel(level: String): PresentationCompiler = copy(reportsLevel = ReportLevel.fromString(level)) diff --git a/mtags/src/main/scala-3/scala/meta/internal/pc/ScalaPresentationCompiler.scala b/mtags/src/main/scala-3/scala/meta/internal/pc/ScalaPresentationCompiler.scala index b92ca56db8b..393a212aa28 100644 --- a/mtags/src/main/scala-3/scala/meta/internal/pc/ScalaPresentationCompiler.scala +++ b/mtags/src/main/scala-3/scala/meta/internal/pc/ScalaPresentationCompiler.scala @@ -31,6 +31,7 @@ import org.eclipse.{lsp4j as l} case class ScalaPresentationCompiler( buildTargetIdentifier: String = "", + buildTargetName: Option[String] = None, classpath: Seq[Path] = Nil, options: List[String] = Nil, search: SymbolSearch = EmptySymbolSearch, @@ -41,7 +42,7 @@ case class ScalaPresentationCompiler( reportsLevel: ReportLevel = ReportLevel.Info, ) extends PresentationCompiler: - def this() = this("", Nil, Nil) + def this() = this("", None, Nil, Nil) val scalaVersion = BuildInfo.scalaCompilerVersion @@ -49,9 +50,12 @@ case class ScalaPresentationCompiler( private val forbiddenDoubleOptions = Set("-release") given ReportContext = folderPath - .map(StdReportContext(_, reportsLevel)) + .map(StdReportContext(_, _ => buildTargetName, reportsLevel)) .getOrElse(EmptyReportContext) + override def withBuildTargetName(buildTargetName: String) = + copy(buildTargetName = Some(buildTargetName)) + override def withReportsLoggerLevel(level: String): PresentationCompiler = copy(reportsLevel = ReportLevel.fromString(level)) diff --git a/tests/unit/src/main/scala/tests/TestingServer.scala b/tests/unit/src/main/scala/tests/TestingServer.scala index 71549fb440c..718ddbe8794 100644 --- a/tests/unit/src/main/scala/tests/TestingServer.scala +++ b/tests/unit/src/main/scala/tests/TestingServer.scala @@ -165,7 +165,8 @@ final case class TestingServer( lazy val fullServer = languageServer.getOldMetalsLanguageServer def server = fullServer.folderServices.head - implicit val reports: ReportContext = new StdReportContext(workspace.toNIO) + implicit val reports: ReportContext = + new StdReportContext(workspace.toNIO, _ => None) private lazy val trees = new Trees( buffers, diff --git a/tests/unit/src/main/scala/tests/TreeUtils.scala b/tests/unit/src/main/scala/tests/TreeUtils.scala index fede2762b09..91e3947e639 100644 --- a/tests/unit/src/main/scala/tests/TreeUtils.scala +++ b/tests/unit/src/main/scala/tests/TreeUtils.scala @@ -21,7 +21,8 @@ object TreeUtils { () => UserConfiguration(fallbackScalaVersion = scalaVersion), buildTargets, ) - implicit val reports = new StdReportContext(Paths.get(".").toAbsolutePath) + implicit val reports = + new StdReportContext(Paths.get(".").toAbsolutePath, _ => None) val trees = new Trees(buffers, selector) (buffers, trees) diff --git a/tests/unit/src/test/scala/tests/ReportsSuite.scala b/tests/unit/src/test/scala/tests/ReportsSuite.scala index 4296b4548b4..cb099b4e6ca 100644 --- a/tests/unit/src/test/scala/tests/ReportsSuite.scala +++ b/tests/unit/src/test/scala/tests/ReportsSuite.scala @@ -14,7 +14,8 @@ import scala.meta.io.AbsolutePath class ReportsSuite extends BaseSuite { val workspace: AbsolutePath = AbsolutePath(Paths.get(".")) - val reportsProvider = new StdReportContext(workspace.toNIO) + val reportsProvider = + new StdReportContext(workspace.toNIO, _ => Some("buildTarget")) val folderReportsZippper: FolderReportsZippper = FolderReportsZippper(exampleBuildTargetsInfo, reportsProvider) @@ -107,7 +108,8 @@ class ReportsSuite extends BaseSuite { Report("test_error_again", None, exampleText(), "Test error", testId) ) assert(none1.isEmpty) - val newReportsProvider = new StdReportContext(workspace.toNIO) + val newReportsProvider = + new StdReportContext(workspace.toNIO, _ => Some("buildTarget")) val none2 = newReportsProvider.incognito.create( Report("test_error_again", None, exampleText(), "Test error", testId) )