Skip to content

Commit

Permalink
Find references finds also references for base methods
Browse files Browse the repository at this point in the history
  • Loading branch information
kpbochenek committed Feb 11, 2020
1 parent ccc8f75 commit c44f65d
Show file tree
Hide file tree
Showing 11 changed files with 568 additions and 336 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package scala.meta.internal.implementation

import org.eclipse.lsp4j.Location
import org.eclipse.lsp4j.TextDocumentPositionParams
import scala.meta.internal.mtags.Semanticdbs
import scala.meta.internal.mtags.{Symbol => MSymbol}
import scala.meta.internal.metals.MetalsEnrichments._
Expand All @@ -12,14 +10,13 @@ import scala.meta.internal.semanticdb.ClassSignature
import scala.meta.internal.semanticdb.TypeRef
import scala.meta.internal.semanticdb.Signature
import scala.meta.internal.semanticdb.TextDocument
import java.util.concurrent.ConcurrentHashMap
import java.nio.file.Path
import scala.meta.internal.semanticdb.SymbolInformation
import scala.meta.internal.semanticdb.MethodSignature
import scala.meta.internal.mtags.GlobalSymbolIndex
import scala.meta.internal.metals.BuildTargets
import scala.meta.internal.metals.Buffers
import scala.meta.internal.metals.BuildTargets
import scala.meta.internal.metals.DefinitionProvider
import scala.meta.internal.metals.PositionInFile
import scala.meta.internal.metals.TokenEditDistance
import scala.meta.internal.semanticdb.Scala._
import scala.meta.internal.semanticdb.TypeSignature
Expand All @@ -28,6 +25,9 @@ import scala.meta.internal.symtab.GlobalSymbolTable
import scala.util.control.NonFatal
import scala.meta.internal.mtags.Mtags
import java.util.concurrent.ConcurrentLinkedQueue
import java.util.concurrent.ConcurrentHashMap
import java.nio.file.Path
import org.eclipse.lsp4j.Location

final class ImplementationProvider(
semanticdbs: Semanticdbs,
Expand Down Expand Up @@ -83,16 +83,12 @@ final class ImplementationProvider(
}

def implementations(
params: TextDocumentPositionParams
positionInFile: PositionInFile
): List[Location] = {
val source = params.getTextDocument.getUri.toAbsolutePath
lazy val global = globalTable.globalSymbolTableFor(source)
lazy val global = globalTable.globalSymbolTableFor(positionInFile.filePath)
val locations = for {
(symbolOccurrence, currentDocument) <- definitionProvider
.symbolOccurence(
source,
params
)
.symbolOccurrence(positionInFile)
.toIterable
} yield {
// 1. Search locally for symbol
Expand All @@ -118,7 +114,7 @@ final class ImplementationProvider(
// symbol is not in workspace, we only search classpath for it
case None =>
globalTable.globalContextFor(
source,
positionInFile.filePath,
implementationsInPath.asScala.toMap
)
// symbol is in workspace,
Expand All @@ -133,36 +129,37 @@ final class ImplementationProvider(
}
symbolLocationsFromContext(
dealiased,
source,
positionInFile.filePath,
inheritanceContext
)
}
locations.flatten.toList
}

def topMethodParents(
symbol: String,
textDocument: TextDocument
doc: TextDocument,
symbol: String
): Seq[Location] = {
// location in semanticDB for symbol might not be present when symbol is local then it must be in current document
val textDocument = findSemanticDbForSymbol(symbol).getOrElse(doc)

def findClassInfo(owner: String) = {
if (owner.nonEmpty) {
findSymbol(textDocument, owner)
} else {
textDocument.symbols.find {
case sym =>
sym.signature match {
case sig: ClassSignature =>
sig.declarations.exists(_.symlinks.contains(symbol))
case _ => false
}
textDocument.symbols.find { sym =>
sym.signature match {
case sig: ClassSignature =>
sig.declarations.exists(_.symlinks.contains(symbol))
case _ => false
}
}
}
}

val results = for {
currentInfo <- findSymbol(textDocument, symbol)
if (!isClassLike(currentInfo))
if !isClassLike(currentInfo)
classInfo <- findClassInfo(symbol.owner)
} yield {
classInfo.signature match {
Expand Down Expand Up @@ -244,7 +241,7 @@ final class ImplementationProvider(
buffer
)
revised <- distance.toRevised(range.toLSP)
} yield new Location(source.toNIO.toUri().toString(), revised)
} yield new Location(source.toNIO.toUri.toString, revised)
}

private def symbolLocationsFromContext(
Expand Down Expand Up @@ -328,10 +325,10 @@ final class ImplementationProvider(
loc =>
// we are not interested in local symbols from outside the workspace
(loc.symbol.isLocal && loc.file.isEmpty) ||
// local symbols ineheritance should only be picked up in the same file
// local symbols inheritance should only be picked up in the same file
(loc.symbol.isLocal && loc.file != currentPath)
}
directImplementations.toSet ++ directImplementations
directImplementations ++ directImplementations
.flatMap { loc =>
val allPossible = loop(loc.symbol, loc.file)
allPossible.map(_.translateAsSeenFrom(loc))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import scala.meta.io.AbsolutePath
import scala.concurrent.Future
import scala.concurrent.ExecutionContext
import scala.meta.internal.semanticdb.SymbolOccurrence
import org.eclipse.lsp4j.Position

/**
* Implements goto definition that works even in code that doesn't parse.
Expand Down Expand Up @@ -60,7 +59,7 @@ final class DefinitionProvider(
warnings.noSemanticdb(path)
DefinitionResult.empty
}
if (fromSemanticdb.locations.isEmpty()) {
if (fromSemanticdb.locations.isEmpty) {
compilers().definition(params, token)
} else {
Future.successful(fromSemanticdb)
Expand All @@ -84,47 +83,46 @@ final class DefinitionProvider(
.definition(Symbol(sym))
.map(symDef => symDef.path.toInputFromBuffers(buffers))

def symbolOccurence(
source: AbsolutePath,
dirtyPosition: TextDocumentPositionParams
def symbolOccurrence(
dirtyPositionInFile: PositionInFile
): Option[(SymbolOccurrence, TextDocument)] = {
for {
currentDocument <- semanticdbs
.textDocument(source)
.textDocument(dirtyPositionInFile.filePath)
.documentIncludingStale
posOcc = positionOccurrence(
source,
dirtyPosition,
dirtyPositionInFile,
currentDocument
)
symbolOccurrence <- {
def mtagsOccurrence =
fromMtags(source, dirtyPosition.getPosition())
posOcc.occurrence.orElse(mtagsOccurrence)
}
symbolOccurrence <- posOcc.occurrence.orElse(
fromMtags(dirtyPositionInFile)
)
} yield (symbolOccurrence, currentDocument)
}

def positionOccurrence(
source: AbsolutePath,
dirtyPosition: TextDocumentPositionParams,
dirtyPositionInFile: PositionInFile,
snapshot: TextDocument
): ResolvedSymbolOccurrence = {
// Convert dirty buffer position to snapshot position in "source"
val sourceDistance =
TokenEditDistance.fromBuffer(source, snapshot.text, buffers)
TokenEditDistance.fromBuffer(
dirtyPositionInFile.filePath,
snapshot.text,
buffers
)
val snapshotPosition = sourceDistance.toOriginal(
dirtyPosition.getPosition.getLine,
dirtyPosition.getPosition.getCharacter
dirtyPositionInFile.position.getLine,
dirtyPositionInFile.position.getCharacter
)

// Find matching symbol occurrence in SemanticDB snapshot
val occurrence = for {
queryPosition <- snapshotPosition.toPosition(dirtyPosition.getPosition)
queryPosition <- snapshotPosition.toPosition(dirtyPositionInFile.position)
occurrence <- snapshot.occurrences
.find(_.encloses(queryPosition, true))
.find(_.encloses(queryPosition, includeLastCharacter = true))
// In case of macros we might need to get the postion from the presentation compiler
.orElse(fromMtags(source, queryPosition))
.orElse(fromMtags(dirtyPositionInFile.copy(position = queryPosition)))
} yield occurrence

ResolvedSymbolOccurrence(sourceDistance, occurrence)
Expand All @@ -136,7 +134,10 @@ final class DefinitionProvider(
snapshot: TextDocument
): DefinitionResult = {
val ResolvedSymbolOccurrence(sourceDistance, occurrence) =
positionOccurrence(source, dirtyPosition, snapshot)
positionOccurrence(
PositionInFile(source, dirtyPosition.getPosition),
snapshot
)
// Find symbol definition location.
val result: Option[DefinitionResult] = occurrence.flatMap { occ =>
val isLocal = occ.symbol.isLocal || snapshot.definesSymbol(occ.symbol)
Expand All @@ -158,11 +159,13 @@ final class DefinitionProvider(
result.getOrElse(DefinitionResult.empty(occurrence.fold("")(_.symbol)))
}

private def fromMtags(source: AbsolutePath, dirtyPos: Position) = {
private def fromMtags(
dirtyPositionInFile: PositionInFile
): Option[SymbolOccurrence] = {
Mtags
.allToplevels(source.toInput)
.allToplevels(dirtyPositionInFile.filePath.toInput)
.occurrences
.find(_.encloses(dirtyPos))
.find(_.encloses(dirtyPositionInFile.position))
}

private case class DefinitionDestination(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package scala.meta.internal.metals

import org.eclipse.lsp4j.DocumentHighlight
import org.eclipse.lsp4j.DocumentHighlightKind
import org.eclipse.lsp4j.TextDocumentPositionParams
import scala.meta.internal.metals.MetalsEnrichments._
import scala.meta.internal.mtags.DefinitionAlternatives.GlobalSymbol
import scala.meta.internal.mtags.Semanticdbs
Expand All @@ -19,16 +18,14 @@ final class DocumentHighlightProvider(
) {

def documentHighlight(
params: TextDocumentPositionParams
positionInFile: PositionInFile
): java.util.List[DocumentHighlight] = {
val source = params.getTextDocument.getUri.toAbsolutePath
val result = semanticdbs.textDocument(source)
val result = semanticdbs.textDocument(positionInFile.filePath)

val highlights = for {
doc <- result.documentIncludingStale.toList
positionOccurrence = definitionProvider.positionOccurrence(
source,
params,
positionInFile,
doc
)
occ <- positionOccurrence.occurrence.toList
Expand Down
Loading

0 comments on commit c44f65d

Please sign in to comment.