Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial support for remote reporters #5884

Open
wants to merge 23 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
b41fb23
Initial support for remote reporting based on Smithy4s
WojciechMazur Nov 27, 2023
01f6dcc
Rewrite telemetry-interfaces to Java, use Gson for serialization and …
WojciechMazur Nov 28, 2023
092970a
Fix formating, revert spurious change sin tests
WojciechMazur Nov 28, 2023
6dd35ed
Add Source Code sanitizer to obfuscate to anonimize the source code c…
WojciechMazur Nov 30, 2023
c4ecdc9
Allow to configure telemetry level in the user configuration
WojciechMazur Dec 1, 2023
4fed0d1
Collect crash reports
WojciechMazur Dec 2, 2023
1ee55ed
Fixes to build.sbt, scalafix and cleanup
WojciechMazur Dec 4, 2023
182c5cb
After rebase fixes
WojciechMazur Jan 17, 2024
3b42d73
Fix typos based on review
WojciechMazur Jan 17, 2024
4c9cdfa
Remove cusotm OptionConventers use CommonMtagsEnrichments instead
WojciechMazur Jan 17, 2024
ee3a3bc
Change default telemetry level to Off
WojciechMazur Jan 17, 2024
ec60a70
Remove UnknownProducerContext
WojciechMazur Jan 17, 2024
86c390e
Better detection of well known package names in source code transformer
WojciechMazur Jan 17, 2024
a0676a0
Define Language enum for better handling of source language hints
WojciechMazur Jan 17, 2024
202adf2
Don't store offset markers in sanitised sources
WojciechMazur Jan 17, 2024
b434093
Explcitly set scalaCliLauncher to None in UserConfiguration
WojciechMazur Jan 17, 2024
7ceaff1
Add ClientInfo to MetalsLspContext
WojciechMazur Jan 17, 2024
73b5787
Refactor Report Context to java interface, extend PresentationCompile…
rochala Jan 26, 2024
d05dd83
Move to scala classes from java interfaces, push for better overview …
rochala Mar 19, 2024
a9d3d2d
Reformat
rochala Mar 19, 2024
ebd43f7
Add tests, disable telemetry in reporter
rochala Mar 26, 2024
cca5308
Remove source code sanitizer, switch to tapir, use sttp as client, ad…
rochala Mar 29, 2024
2fea0b6
Finalize initial telemetry
rochala Apr 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 34 additions & 4 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ commands ++= Seq(
runMtagsPublishLocal(st, v, localSnapshotVersion)
}
"interfaces/publishLocal" ::
"+telemetryInterfaces/publishLocal" ::
s"++${V.scala213} metals/publishLocal" ::
"mtags-java/publishLocal" ::
publishMtags
Expand Down Expand Up @@ -181,6 +182,7 @@ def lintingOptions(scalaVersion: String) = {
"-Wconf:src=*.TreeViewProvider.scala&msg=parameter params in method (children|parent) is never used:silent",
// silence "The outer reference in this type test cannot be checked at run time."
"-Wconf:src=.*(CompletionProvider|ArgCompletions|Completions|Keywords|IndentOnPaste).scala&msg=The outer reference:silent",
"-Wconf:src=.*(SourceCodeSanitizer).scala&msg=Unused import:silent",
)
crossSetting(
scalaVersion,
Expand Down Expand Up @@ -208,7 +210,7 @@ val sharedScalacOptions = List(
isScala212(partialVersion) && V.scala212 != scalaVersion.value =>
List("-target:jvm-1.8", "-Yrangepos", "-Xexperimental")
case partialVersion if isScala3(partialVersion) =>
List("-Xtarget:8", "-language:implicitConversions", "-Xsemanticdb")
List("-Xtarget:8", "-language:implicitConversions")
case _ =>
List("-target:jvm-1.8", "-Yrangepos")
}
Expand Down Expand Up @@ -251,6 +253,26 @@ lazy val interfaces = project
),
)

lazy val telemetryInterfaces = project
.in(file("telemetry-interfaces"))
.settings(sharedSettings)
.settings(
moduleName := "telemetry-interfaces",
crossScalaVersions := List(V.scala213, V.scala3),
crossVersion := CrossVersion.binary,
Compile / scalacOptions ++= {
if (scalaVersion.value == V.scala3)
List("-Xmax-inlines", "64")
else Nil
},
libraryDependencies := List(
"com.softwaremill.sttp.tapir" %% "tapir-core" % "1.10.0",
"com.softwaremill.sttp.tapir" %% "tapir-jsoniter-scala" % "1.10.0",
"com.github.plokhotnyuk.jsoniter-scala" %% "jsoniter-scala-core" % "2.27.7",
"com.github.plokhotnyuk.jsoniter-scala" %% "jsoniter-scala-macros" % "2.27.7" % "compile-internal",
),
)

lazy val mtagsShared = project
.in(file("mtags-shared"))
.settings(sharedSettings)
Expand All @@ -265,7 +287,12 @@ lazy val mtagsShared = project
Compile / packageSrc / publishArtifact := true,
Compile / scalacOptions ++= {
if (scalaVersion.value == V.scala3)
List("-Yexplicit-nulls", "-language:unsafeNulls")
List(
"-Yexplicit-nulls",
"-language:unsafeNulls",
"-Xfatal-warnings",
"-deprecation",
)
else Nil
},
libraryDependencies ++= List(
Expand Down Expand Up @@ -502,7 +529,9 @@ lazy val metals = project
// for JSON formatted doctor
"com.lihaoyi" %% "ujson" % "3.1.5",
// For fetching projects' templates
"com.lihaoyi" %% "requests" % "0.8.0",
// telemetry client
"com.softwaremill.sttp.client3" %% "core" % "3.9.5",
"com.softwaremill.sttp.tapir" %% "tapir-sttp-client" % "1.10.0",
// for producing SemanticDB from Scala source files, to be sure we want the same version of scalameta
"org.scalameta" %% "scalameta" % V.semanticdb(scalaVersion.value),
"org.scalameta" % "semanticdb-scalac-core" % V.semanticdb(
Expand Down Expand Up @@ -557,7 +586,7 @@ lazy val metals = project
"lastSupportedSemanticdb" -> SemanticDbSupport.last,
),
)
.dependsOn(mtags, `mtags-java`)
.dependsOn(mtags, `mtags-java`, telemetryInterfaces)
.enablePlugins(BuildInfoPlugin)

lazy val `sbt-metals` = project
Expand Down Expand Up @@ -805,6 +834,7 @@ lazy val unit = project
"io.get-coursier" %% "coursier" % V.coursier, // for jars
"ch.epfl.scala" %% "bloop-config" % V.bloopConfig,
"org.scalameta" %% "munit" % V.munit,
"com.softwaremill.sttp.tapir" %% "tapir-sttp-stub-server" % "1.10.0",
),
buildInfoPackage := "tests",
Compile / resourceGenerators += InputProperties
Expand Down
2 changes: 1 addition & 1 deletion metals-bench/src/main/scala/bench/MetalsBench.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import scala.meta.dialects
import scala.meta.interactive.InteractiveSemanticdb
import scala.meta.internal.metals.EmptyReportContext
import scala.meta.internal.metals.JdkSources
import scala.meta.internal.metals.ReportContext
import scala.meta.internal.metals.logging.MetalsLogger
import scala.meta.internal.mtags.JavaMtags
import scala.meta.internal.mtags.Mtags
Expand All @@ -22,6 +21,7 @@ import scala.meta.internal.tokenizers.LegacyScanner
import scala.meta.internal.tokenizers.LegacyToken
import scala.meta.io.AbsolutePath
import scala.meta.io.Classpath
import scala.meta.pc.ReportContext

import org.openjdk.jmh.annotations.Benchmark
import org.openjdk.jmh.annotations.BenchmarkMode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import scala.meta.internal.metals.BspStatus
import scala.meta.internal.metals.ClientCommands
import scala.meta.internal.metals.Icons
import scala.meta.internal.metals.MetalsEnrichments._
import scala.meta.internal.metals.ReportContext
import scala.meta.internal.metals.clients.language.MetalsStatusParams
import scala.meta.internal.metals.clients.language.StatusType
import scala.meta.io.AbsolutePath
import scala.meta.pc.ReportContext

class ConnectionBspStatus(
bspStatus: BspStatus,
Expand Down Expand Up @@ -102,7 +102,7 @@ class ConnectionBspStatus(
*/
private def syncWithReportContext(errorReports: Set[String]) =
errorReports.intersect(
rc.bloop.getReports().map(_.toPath.toUri().toString()).toSet
rc.bloop.getReports().map(_.toPath.toUri().toString()).asScala.toSet
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import java.security.MessageDigest
import scala.meta.internal.bsp.BspSession
import scala.meta.internal.bsp.ConnectionBspStatus
import scala.meta.internal.metals.MetalsEnrichments._
import scala.meta.internal.metals.Report
import scala.meta.internal.metals.ReportContext
import scala.meta.internal.metals.Tables
import scala.meta.internal.pc.StandardReport
import scala.meta.pc.ReportContext

import com.google.common.io.BaseEncoding

Expand All @@ -19,7 +19,7 @@ class BspErrorHandler(
def onError(message: String): Unit = {
if (shouldShowBspError) {
for {
report <- createReport(message)
report <- createReport(message).asScala
if !tables.dismissedNotifications.BspErrors.isDismissed
} bspStatus.showError(message, report)
} else logError(message)
Expand All @@ -36,7 +36,7 @@ class BspErrorHandler(
val id = BaseEncoding.base64().encode(digest)
val sanitized = reportContext.bloop.sanitize(message)
reportContext.bloop.create(
Report(
StandardReport(
sanitized.trimTo(20),
s"""|### Bloop error:
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import scala.meta.internal.process.ExitCodes
import scala.meta.io.AbsolutePath

import coursierapi._
import sttp.client3._

class NewProjectProvider(
client: MetalsLanguageClient,
Expand All @@ -34,13 +35,15 @@ class NewProjectProvider(
)(implicit context: ExecutionContext) {

private val templatesUrl =
"https://github.com/foundweekends/giter8/wiki/giter8-templates.md"
uri"https://github.com/foundweekends/giter8/wiki/giter8-templates.md"
private val giterDependency = Dependency
.of("org.foundweekends.giter8", "giter8_2.12", BuildInfo.gitter8Version)
// equal to cmd's: g8 playframework/play-scala-seed.g8 --name=../<<name>>
private val giterMain = "giter8.Giter8"

val backend: SttpBackend[Identity, Any] = HttpClientSyncBackend()
private var allTemplates = Seq.empty[MetalsQuickPickItem]

def allTemplatesFromWeb: Seq[MetalsQuickPickItem] =
synchronized {
if (allTemplates.nonEmpty) {
Expand All @@ -53,14 +56,17 @@ class NewProjectProvider(
// - [jimschubert/finatra.g8](https://github.com/jimschubert/finatra.g8)
// (A simple Finatra 2.5 template with sbt-revolver and sbt-native-packager)
val all = for {
result <- Try(requests.get(templatesUrl)).toOption.toIterable
_ = if (result.statusCode != 200)
result <- Try(
basicRequest.get(templatesUrl).send(backend)
).toOption.toIterable
_ = if (!result.is200)
client.showMessage(
NewScalaProject.templateDownloadFailed(result.statusMessage)
NewScalaProject.templateDownloadFailed(result.statusText)
)
if result.statusCode == 200
if result.is200
text <- result.body.toOption
} yield {
NewProjectProvider.templatesFromText(result.text(), icons.github)
NewProjectProvider.templatesFromText(text, icons.github)
}
allTemplates = all.flatten.toSeq
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ import scala.meta.internal.metals.BuildTargets
import scala.meta.internal.metals.Compilers
import scala.meta.internal.metals.DefinitionProvider
import scala.meta.internal.metals.MetalsEnrichments._
import scala.meta.internal.metals.Report
import scala.meta.internal.metals.ReportContext
import scala.meta.internal.metals.ScalaVersionSelector
import scala.meta.internal.metals.ScalaVersions
import scala.meta.internal.metals.SemanticdbFeatureProvider
Expand All @@ -29,6 +27,7 @@ import scala.meta.internal.mtags.Semanticdbs
import scala.meta.internal.mtags.UnresolvedOverriddenSymbol
import scala.meta.internal.parsing.Trees
import scala.meta.internal.pc.PcSymbolInformation
import scala.meta.internal.pc.StandardReport
import scala.meta.internal.search.SymbolHierarchyOps._
import scala.meta.internal.semanticdb.ClassSignature
import scala.meta.internal.semanticdb.Scala.Descriptor.Method
Expand All @@ -42,6 +41,7 @@ import scala.meta.internal.semanticdb.TypeSignature
import scala.meta.io.AbsolutePath
import scala.meta.pc.PcSymbolKind
import scala.meta.pc.PcSymbolProperty
import scala.meta.pc.ReportContext

import ch.epfl.scala.bsp4j.BuildTargetIdentifier
import org.eclipse.lsp4j.Location
Expand Down Expand Up @@ -176,7 +176,7 @@ final class ImplementationProvider(

if (sourceFiles.isEmpty) {
rc.unsanitized.create(
Report(
StandardReport(
"missing-definition",
s"""|Missing definition symbol for:
|$dealisedSymbol
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import scala.meta.internal.implementation.Supermethods.formatMethodSymbolForQuic
import scala.meta.internal.metals.ClientCommands
import scala.meta.internal.metals.DefinitionProvider
import scala.meta.internal.metals.MetalsEnrichments._
import scala.meta.internal.metals.ReportContext
import scala.meta.internal.metals.clients.language.MetalsLanguageClient
import scala.meta.internal.metals.clients.language.MetalsQuickPickItem
import scala.meta.internal.metals.clients.language.MetalsQuickPickParams
import scala.meta.internal.search.SymbolHierarchyOps
import scala.meta.internal.semanticdb.SymbolInformation
import scala.meta.io.AbsolutePath
import scala.meta.pc.ReportContext

import org.eclipse.lsp4j.ExecuteCommandParams
import org.eclipse.lsp4j.Location
Expand Down
72 changes: 55 additions & 17 deletions metals/src/main/scala/scala/meta/internal/metals/Compilers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ import scala.meta.internal.pc.JavaPresentationCompiler
import scala.meta.internal.pc.LogMessages
import scala.meta.internal.pc.PcSymbolInformation
import scala.meta.internal.pc.ScalaPresentationCompiler
import scala.meta.internal.telemetry
import scala.meta.internal.telemetry.ReporterContext
import scala.meta.internal.telemetry.ScalaPresentationCompilerContext
import scala.meta.internal.telemetry.TelemetryReportContext
import scala.meta.internal.worksheets.WorksheetPcData
import scala.meta.internal.worksheets.WorksheetProvider
import scala.meta.io.AbsolutePath
Expand All @@ -34,6 +38,8 @@ import scala.meta.pc.CancelToken
import scala.meta.pc.HoverSignature
import scala.meta.pc.OffsetParams
import scala.meta.pc.PresentationCompiler
import scala.meta.pc.PresentationCompilerConfig
import scala.meta.pc.ReportContext
import scala.meta.pc.SymbolSearch
import scala.meta.pc.SyntheticDecorationsParams

Expand Down Expand Up @@ -1046,7 +1052,7 @@ class Compilers(
): Option[PresentationCompiler] = {
val pc = JavaPresentationCompiler()
Some(
configure(pc, search)
configure(pc, search, log)
.newInstance(
targetUri,
classpath.toAbsoluteClasspath.map(_.toNIO).toSeq.asJava,
Expand Down Expand Up @@ -1203,28 +1209,58 @@ class Compilers(
sourceMapper.pcMapping(path, scalaVersion)
}

private def createPresentationCompilerContext(
scalaVersion: String,
config: PresentationCompilerConfig,
options: List[String],
): ReporterContext =
ScalaPresentationCompilerContext(
scalaVersion = scalaVersion,
options = options,
config = telemetry.conversion.PresentationCompilerConfig(config),
)

private def getPcConfiguration(): PresentationCompilerConfig = {
val options =
InitializationOptions.from(initializeParams).compilerOptions
config.initialConfig.compilers
.update(options)
.copy(
_symbolPrefixes = userConfig().symbolPrefixes,
isCompletionSnippetsEnabled =
initializeParams.supportsCompletionSnippets,
_isStripMarginOnTypeFormattingEnabled =
() => userConfig().enableStripMarginOnTypeFormatting,
)
}

private def configure(
pc: PresentationCompiler,
search: SymbolSearch,
): PresentationCompiler =
options: List[String],
): PresentationCompiler = {
val pcConfig = getPcConfiguration()
val config = userConfig()

val remoteReportContext: ReportContext =
new TelemetryReportContext(
telemetryConfiguration = () => config.telemetryConfiguration,
reporterContext = () =>
createPresentationCompilerContext(pc.scalaVersion, pcConfig, options),
workspaceSanitizer = new WorkspaceSanitizer(Some(workspace.toNIO)),
telemetryClient = new telemetry.TelemetryClientImpl(
config.telemetryConfiguration.telemetryLevel
),
)

pc.withSearch(search)
.withExecutorService(ec)
.withWorkspace(workspace.toNIO)
.withScheduledExecutorService(sh)
.withReportsLoggerLevel(MetalsServerConfig.default.loglevel)
.withConfiguration {
val options =
InitializationOptions.from(initializeParams).compilerOptions
config.initialConfig.compilers
.update(options)
.copy(
_symbolPrefixes = userConfig().symbolPrefixes,
isCompletionSnippetsEnabled =
initializeParams.supportsCompletionSnippets,
_isStripMarginOnTypeFormattingEnabled =
() => userConfig().enableStripMarginOnTypeFormatting,
)
}
.withConfiguration(pcConfig)
.withAdditionalReportContexts(List(remoteReportContext).asJava)
}

def newCompiler(
target: ScalaTarget,
Expand Down Expand Up @@ -1266,11 +1302,13 @@ class Compilers(
}

val filteredOptions = plugins.filterSupportedOptions(options)
configure(pc, search)
val allOptions = log ++ filteredOptions

configure(pc, search, allOptions)
.newInstance(
name,
classpath.asJava,
(log ++ filteredOptions).asJava,
(allOptions).asJava,
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import scala.meta.internal.semanticdb.Synthetic
import scala.meta.internal.semanticdb.TextDocument
import scala.meta.io.AbsolutePath
import scala.meta.pc.CancelToken
import scala.meta.pc.ReportContext
import scala.meta.tokens.Token

import ch.epfl.scala.bsp4j.BuildTargetIdentifier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import scala.meta.internal.semanticdb.Scala._
import scala.meta.internal.tvp.FolderTreeViewProvider
import scala.meta.internal.worksheets.WorksheetProvider
import scala.meta.io.AbsolutePath
import scala.meta.pc.ReportContext

import ch.epfl.scala.{bsp4j => b}
import org.eclipse.lsp4j.Position
Expand Down
Loading