Skip to content

Commit

Permalink
feature: index overridden symbols in top level
Browse files Browse the repository at this point in the history
  • Loading branch information
kasiaMarek committed Aug 31, 2023
1 parent 3070213 commit f4eb439
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 17 deletions.
17 changes: 11 additions & 6 deletions mtags/src/main/scala/scala/meta/internal/mtags/MtagsIndexer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ trait MtagsIndexer {
)
}
}
def term(name: String, pos: m.Position, kind: Kind, properties: Int): String =
addSignature(Descriptor.Term(name), pos, kind, properties)
def term(name: String, pos: m.Position, kind: Kind, properties: Int, overriddenSymbols: List[(String, m.Position)] = List.empty): String =
addSignature(Descriptor.Term(name), pos, kind, properties, overriddenSymbols)
def term(name: Term.Name, kind: Kind, properties: Int): String =
addSignature(Descriptor.Term(name.value), name.pos, kind, properties)
def tparam(name: Name, kind: Kind, properties: Int): String =
Expand Down Expand Up @@ -122,8 +122,8 @@ trait MtagsIndexer {
properties
)
}
def tpe(name: String, pos: m.Position, kind: Kind, properties: Int): String =
addSignature(Descriptor.Type(name), pos, kind, properties)
def tpe(name: String, pos: m.Position, kind: Kind, properties: Int, overriddenSymbols: List[(String, m.Position)] = List.empty): String =
addSignature(Descriptor.Type(name), pos, kind, properties, overriddenSymbols)
def tpe(name: Name, kind: Kind, properties: Int): String =
addSignature(Descriptor.Type(name.value), name.pos, kind, properties)
def pkg(name: String, pos: m.Position): String = {
Expand All @@ -141,7 +141,8 @@ trait MtagsIndexer {
signature: Descriptor,
definition: m.Position,
kind: s.SymbolInformation.Kind,
properties: Int
properties: Int,
overriddenSymbols: List[(String, m.Position)] = List.empty
): String = {
val previousOwner = currentOwner
currentOwner = symbol(signature)
Expand All @@ -155,12 +156,16 @@ trait MtagsIndexer {
syntax,
role
)
val encodedOverriddenSymbols = overriddenSymbols.map{
case (simpleName, pos) => UnresolvedOverriddenSymbol(simpleName, pos.start)
}
val info = s.SymbolInformation(
symbol = syntax,
language = language,
kind = kind,
properties = properties,
displayName = signature.name.value
displayName = signature.name.value,
overriddenSymbols = encodedOverriddenSymbols
)
visitOccurrence(occ, info, previousOwner)
syntax
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,13 +177,13 @@ class ScalaToplevelMtags(
newExpectExtensionTemplate(nextOwner)
)
case CLASS | TRAIT | OBJECT | ENUM if needEmitMember(currRegion) =>
emitMember(false, currRegion.owner)
val maybeNewIdent = emitMember(false, currRegion.owner)
val template = expectTemplate match {
case Some(expect) if expect.isCaseClassConstructor =>
newExpectCaseClassTemplate
case _ => newExpectClassTemplate
}
loop(indent, isAfterNewline = false, currRegion, template)
loop(maybeNewIdent.getOrElse(indent), isAfterNewline = maybeNewIdent.isDefined, currRegion, template)
// also covers extension methods because of `def` inside
case DEF
// extension group
Expand Down Expand Up @@ -485,30 +485,59 @@ class ScalaToplevelMtags(
buf.result()
}

@tailrec
private def acceptAllAfterOverriddenIdentifier(): Unit = {
scanner.curr.token match {
case LPAREN =>
acceptBalancedDelimeters(LPAREN, RPAREN)
acceptAllAfterOverriddenIdentifier()
case LBRACKET =>
acceptBalancedDelimeters(LBRACKET, RBRACKET)
acceptAllAfterOverriddenIdentifier()
case _ =>
}

}

@tailrec
private def findOverridden(acc : List[Identifier]): (List[Identifier], Option[Int]) = {
val maybeNewIdent = acceptTrivia()
scanner.curr.token match {
case EXTENDS | WITH =>
acceptTrivia()
val curr = newIdentifier.toList
acceptAllAfterOverriddenIdentifier()
findOverridden(curr ++ acc)
case _ => (acc, maybeNewIdent)
}
}

/**
* Enters a toplevel symbol such as class, trait or object
*/
def emitMember(isPackageObject: Boolean, owner: String): Unit = {
def emitMember(isPackageObject: Boolean, owner: String): Option[Int] = {
val kind = scanner.curr.token
acceptTrivia()
val maybeName = newIdentifier
currentOwner = owner
val (overridden0, maybeNewIdent) = findOverridden(List.empty)
val overridden = overridden0.map(id => (id.name, id.pos))
maybeName.foreach { name =>
kind match {
case CLASS | ENUM =>
tpe(name.name, name.pos, Kind.CLASS, 0)
tpe(name.name, name.pos, Kind.CLASS, 0, overridden)
case TRAIT =>
tpe(name.name, name.pos, Kind.TRAIT, 0)
tpe(name.name, name.pos, Kind.TRAIT, 0, overridden)
case OBJECT =>
if (isPackageObject) {
currentOwner = symbol(Scala.Descriptor.Package(name.name))
term("package", name.pos, Kind.OBJECT, 0)
} else {
term(name.name, name.pos, Kind.OBJECT, 0)
term(name.name, name.pos, Kind.OBJECT, 0, overridden)
}
}
}
scanner.nextToken()
maybeNewIdent
}

/**
Expand Down Expand Up @@ -668,7 +697,9 @@ class ScalaToplevelMtags(
}
}

private def acceptTrivia(): Unit = {
private def acceptTrivia(): Option[Int] = {
var includedNewline = false
var ident = 0
scanner.nextToken()
while (
!isDone &&
Expand All @@ -677,8 +708,15 @@ class ScalaToplevelMtags(
case _ => false
})
) {
if(isNewline){
includedNewline = true
ident = 0
} else if(scanner.curr.token == WHITESPACE) {
ident += 1
}
scanner.nextToken()
}
if(includedNewline) Some(ident) else None
}

private def nextIsNL(): Boolean = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package scala.meta.internal.mtags

object UnresolvedOverriddenSymbol {
def apply(name: String, pos: Int): String =
s"unresolved::$name::$pos"

def unapply(unresolved: String): Option[(String, Int)] =
unresolved match {
case s"unresolved::$name::$pos" => pos.toIntOption.map((name, _))
case _ => None
}
}
17 changes: 14 additions & 3 deletions tests/unit/src/test/scala/tests/ScalaToplevelSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import scala.meta.Dialect
import scala.meta.dialects
import scala.meta.inputs.Input
import scala.meta.internal.mtags.Mtags
import scala.meta.internal.mtags.UnresolvedOverriddenSymbol

import munit.TestOptions

Expand Down Expand Up @@ -530,7 +531,7 @@ class ScalaToplevelSuite extends BaseSuite {
| }
|}
|""".stripMargin,
List("a/", "a/TypeProxy#"),
List("a/", "a/TypeProxy# -> Type"),
dialect = dialects.Scala3,
mode = ToplevelWithInner,
)
Expand Down Expand Up @@ -603,6 +604,7 @@ class ScalaToplevelSuite extends BaseSuite {
expected: List[String],
mode: Mode = Toplevel,
dialect: Dialect = dialects.Scala3,
includeOverridden: Boolean = true
)(implicit location: munit.Location): Unit = {
test(options) {
val input = Input.VirtualFile("Test.scala", code)
Expand All @@ -612,8 +614,17 @@ class ScalaToplevelSuite extends BaseSuite {
val includeMembers = mode == All
Mtags
.allToplevels(input, dialect, includeMembers)
.occurrences
.map(_.symbol)
.symbols
.map{ si =>
if(!includeOverridden || si.overriddenSymbols.isEmpty) si.symbol
else {
val overridden =
si.overriddenSymbols.collect{
case UnresolvedOverriddenSymbol(name, _) => name
}.mkString(", ")
s"${si.symbol} -> $overridden"
}
}
.toList
case Toplevel => Mtags.toplevels(input, dialect)
}
Expand Down

0 comments on commit f4eb439

Please sign in to comment.