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

Add semantic db info display on jar files #3843

Merged
merged 1 commit into from Apr 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -23,11 +23,13 @@ import scala.meta.internal.metals.MetalsEnrichments._
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.metap.DocumentPrinter
import scala.meta.internal.metap.Main
import scala.meta.internal.mtags.SemanticdbClasspath
import scala.meta.internal.mtags.URIEncoderDecoder
import scala.meta.internal.parsing.ClassFinder
import scala.meta.internal.parsing.ClassWithPos
import scala.meta.internal.semanticdb.TextDocument
import scala.meta.io.AbsolutePath
import scala.meta.metap.Format
import scala.meta.metap.Settings
Expand Down Expand Up @@ -84,6 +86,7 @@ final class FileDecoderProvider(
userConfig: () => UserConfiguration,
shellRunner: ShellRunner,
fileSystemSemanticdbs: FileSystemSemanticdbs,
interactiveSemanticdbs: InteractiveSemanticdbs,
languageClient: MetalsLanguageClient,
clientConfig: ClientConfiguration,
classFinder: ClassFinder
Expand Down Expand Up @@ -149,7 +152,12 @@ final class FileDecoderProvider(
Try(URI.create(URIEncoderDecoder.encode(uriAsStr))) match {
case Success(uri) =>
uri.getScheme() match {
case "jar" => Future { decodeJar(uriAsStr) }
case "jar" =>
val jarURI = convertJarStrToURI(uriAsStr)
if (semanticdbExtensions.exists(uriAsStr.endsWith))
decodeMetalsFile(jarURI)
else
Future { decodeJar(jarURI) }
case "file" => decodeMetalsFile(uri)
case "metalsDecode" =>
decodedFileContents(uri.getSchemeSpecificPart())
Expand All @@ -168,13 +176,16 @@ final class FileDecoderProvider(
}
}

private def decodeJar(uriAsStr: String): DecoderResponse = {
private def convertJarStrToURI(uriAsStr: String): URI = {

/**
* URI.create will decode the string, which means ZipFileSystemProvider will not work
* Related stack question: https://stackoverflow.com/questions/9873845/java-7-zip-file-system-provider-doesnt-seem-to-accept-spaces-in-uri
*/
val uri = new URI("jar", uriAsStr.stripPrefix("jar:"), null)
new URI("jar", uriAsStr.stripPrefix("jar:"), null)
}

private def decodeJar(uri: URI): DecoderResponse = {
Try {
val path = uri.toAbsolutePath
FileIO.slurp(path, StandardCharsets.UTF_8)
Expand All @@ -184,11 +195,21 @@ final class FileDecoderProvider(
}
}

private val semanticdbExtensions = Set(
"semanticdb-compact",
"semanticdb-detailed",
"semanticdb-proto"
)

private def decodeMetalsFile(
uri: URI
): Future[DecoderResponse] = {
val supportedExtensions = Set("javap", "javap-verbose", "tasty-decoded",
"semanticdb-compact", "semanticdb-detailed", "semanticdb-proto", "cfr")
val supportedExtensions = Set(
"javap",
"javap-verbose",
"tasty-decoded",
"cfr"
) ++ semanticdbExtensions
val additionalExtension = uri.toString().split('.').toList.last
if (supportedExtensions(additionalExtension)) {
val stripped = toFile(uri, s".$additionalExtension")
Expand Down Expand Up @@ -283,10 +304,16 @@ final class FileDecoderProvider(
format: Format
): DecoderResponse = {
if (path.isScalaOrJava)
findSemanticDbPathInfo(path)
.mapLeft(s => DecoderResponse.failed(path.toURI, s))
.map(decodeFromSemanticDBFile(_, format))
.fold(identity, identity)
interactiveSemanticdbs
.textDocument(path)
.documentIncludingStale
.map(decodeFromSemanticDBTextDocument(path, _, format))
.getOrElse(
findSemanticDbPathInfo(path)
.mapLeft(s => DecoderResponse.failed(path.toURI, s))
.map(decodeFromSemanticDBFile(_, format))
.fold(identity, identity)
)
else if (path.isSemanticdb) decodeFromSemanticDBFile(path, format)
else DecoderResponse.failed(path.toURI, "Unsupported extension")
}
Expand Down Expand Up @@ -560,9 +587,9 @@ final class FileDecoderProvider(
}
}

private def decodeFromSemanticDBFile(
private def decodeFromSemanticDB(
path: AbsolutePath,
format: Format
decode: Reporter => Unit
): DecoderResponse =
Try {
val out = new ByteArrayOutputStream()
Expand All @@ -572,12 +599,7 @@ final class FileDecoderProvider(
try {
val reporter =
Reporter().withOut(psOut).withErr(psErr)
val settings =
Settings()
.withPaths(List(path.toNIO))
.withFormat(format)
val main = new Main(settings, reporter)
main.process()
decode(reporter)
val output = new String(out.toByteArray)
val error = new String(err.toByteArray)
if (error.isEmpty)
Expand All @@ -589,11 +611,40 @@ final class FileDecoderProvider(
psErr.close()
}
} match {
case Failure(exception) =>
DecoderResponse.failed(path.toString(), exception)
case Failure(exception) => DecoderResponse.failed(path.toURI, exception)
case Success(value) => DecoderResponse.success(path.toURI, value)
}

private def decodeFromSemanticDBTextDocument(
path: AbsolutePath,
document: TextDocument,
format: Format
): DecoderResponse =
decodeFromSemanticDB(
path,
reporter => {
val settings = Settings().withFormat(format)
val printer = new DocumentPrinter(settings, reporter, document)
printer.print()
}
)

private def decodeFromSemanticDBFile(
path: AbsolutePath,
format: Format
): DecoderResponse =
decodeFromSemanticDB(
path,
reporter => {
val settings =
Settings()
.withPaths(List(path.toNIO))
.withFormat(format)
val main = new Main(settings, reporter)
main.process()
}
)

private def decodeFromTastyFile(
pathInfo: PathInfo
): Future[DecoderResponse] =
Expand Down
Expand Up @@ -730,6 +730,7 @@ class MetalsLanguageServer(
() => userConfig,
shellRunner,
fileSystemSemanticdbs,
interactiveSemanticdbs,
languageClient,
clientConfig,
classFinder
Expand Down