Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import javax.tools.JavaFileObject.Kind
import javax.tools.SimpleJavaFileObject

import scala.meta.internal.metals.MetalsEnrichments._
import scala.meta.internal.mtags.Symbol
import scala.meta.internal.{semanticdb => s}
import scala.meta.pc
import scala.meta.pc.SemanticdbCompilationUnit
Expand All @@ -32,7 +33,7 @@ final case class VirtualTextDocument(
case None =>
pkg.replace('/', '.')
case Some(sym) =>
sym.stripSuffix("#").stripSuffix(".").replace('/', '.')
Symbol(sym).toplevelClassName
}
}
override def getName(): String = uri.toString
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,7 @@ class ClasspathDefinitionIndex(mtags: () => Mtags, dialect: Dialect) {
symbol: Symbol
): Option[String] = {
val jar = new JarFile(module.jar.toFile)
val classfileName =
s"${symbol.toplevel.value.stripSuffix("#").stripSuffix(".")}.class"
val classfileName = s"${symbol.toplevelBinaryName}.class"
try {
val entry = jar.getEntry(classfileName)
if (entry != null) {
Expand Down
25 changes: 25 additions & 0 deletions mtags/src/main/scala/scala/meta/internal/mtags/Symbol.scala
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,22 @@ final class Symbol private (val value: String) {
!value.isPackage &&
value.owner.isPackage
}

/**
* The JVMS 4.2.1 binary name of the toplevel class this symbol belongs to,
* for example `scala/Option#get().` becomes `scala/Option`. Toplevel, because
* a nested class is `Outer$Inner` in a binary name but `Outer#Inner#` here.
*/
def toplevelBinaryName: String =
toplevel.value.stripSuffix("#").stripSuffix(".")

/**
* [[toplevelBinaryName]] with `.` between package parts, the form
* `Class.forName` expects: `scala/Option#get().` becomes `scala.Option`.
*/
def toplevelClassName: String =
toplevelBinaryName.replace('/', '.')

def asNonEmpty: Option[Symbol] =
if (isNone) None
else Some(this)
Expand Down Expand Up @@ -86,6 +102,15 @@ object Symbol {
else new Symbol(sym)
}

/**
* The symbol of a toplevel class named the way `Class.forName` names it, the
* inverse of [[Symbol.toplevelClassName]]: `scala.Option` becomes
* `scala/Option#`. Toplevel, since a nested class is `Outer.Inner` there but
* `Outer#Inner#` here.
*/
def fromToplevelClassName(className: String): Symbol =
Symbol(className.replace('.', '/') + "#")

def validated(sym: String): Either[String, Symbol] = {
// NOTE(olafur): this validation method is hacky, we should write a proper
// parser that reports positioned error messages with actionable feedback
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ class SymbolIndexBucket(
// Output: scala/collection/immutable/List.scala
// scala/collection/immutable/List.java
private def trivialPaths(toplevel: Symbol): List[String] = {
val noExtension = toplevel.value.stripSuffix(".").stripSuffix("#")
val noExtension = toplevel.toplevelBinaryName
List(
noExtension + ".scala",
noExtension + ".java"
Expand All @@ -382,8 +382,8 @@ class SymbolIndexBucket(

private def modulePaths(toplevel: Symbol): List[String] = {
if (Properties.isJavaAtLeast("9")) {
val noExtension = toplevel.value.stripSuffix(".").stripSuffix("#")
val javaSymbol = noExtension.replace("/", ".")
val noExtension = toplevel.toplevelBinaryName
val javaSymbol = toplevel.toplevelClassName
for {
cls <- sourceJars.loadClassSafe(javaSymbol).toList
// note(@tgodzik) Modules are only available in Java 9+, so we need to invoke this reflectively
Expand Down
Loading