Skip to content

Commit

Permalink
Review changes update
Browse files Browse the repository at this point in the history
  • Loading branch information
kpbochenek committed Feb 21, 2020
1 parent 9c3ebc2 commit 81da8a9
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 119 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -85,71 +85,93 @@ final class ImplementationProvider(

def implementations(position: TextDocumentPositionParams): List[Location] = {
implementations(
FilePosition(
position.getTextDocument.getUri.toAbsolutePath,
position.getPosition
)
Left(
FilePosition(
position.getTextDocument.getUri.toAbsolutePath,
position.getPosition
)
),
position.getTextDocument.getUri.toAbsolutePath
)
}

def implementations(
filePosition: FilePosition
positionOrSymbol: Either[FilePosition, SymbolInformation],
source: AbsolutePath
): List[Location] = {
lazy val global = globalTable.globalSymbolTableFor(filePosition.filePath)
val locations = for {
(symbolOccurrence, currentDocument) <- definitionProvider
.symbolOccurrence(filePosition)
.toIterable
} yield {
// 1. Search locally for symbol
// 2. Search inside workspace
// 3. Search classpath via GlobalSymbolTable
def symbolSearch(symbol: String): Option[SymbolInformation] = {
findSymbol(currentDocument, symbol)
.orElse(findSymbolDef(symbol))
.orElse(global.flatMap(_.safeInfo(symbol)))
}
val sym = symbolOccurrence.symbol
val dealiased =
if (sym.desc.isType) dealiasClass(sym, symbolSearch _) else sym

val definitionDocument =
if (currentDocument.definesSymbol(dealiased)) {
Some(currentDocument)
} else {
findSemanticDbForSymbol(dealiased)
}
lazy val global = globalTable.globalSymbolTableFor(source)

positionOrSymbol match {
case Left(filePosition) =>
val locations = for {
(symbolOccurrence, currentDocument) <- definitionProvider
.symbolOccurrence(filePosition)
.toIterable
} yield {
// 1. Search locally for symbol
// 2. Search inside workspace
// 3. Search classpath via GlobalSymbolTable
def symbolSearch(symbol: String): Option[SymbolInformation] = {
findSymbol(currentDocument, symbol)
.orElse(findSymbolDef(symbol))
.orElse(global.flatMap(_.safeInfo(symbol)))
}

val inheritanceContext = definitionDocument match {
// symbol is not in workspace, we only search classpath for it
case None =>
globalTable.globalContextFor(
val sym = symbolOccurrence.symbol
val dealiased =
if (sym.desc.isType) dealiasClass(sym, symbolSearch _) else sym

val definitionDocument =
if (currentDocument.definesSymbol(dealiased)) {
Some(currentDocument)
} else {
findSemanticDbForSymbol(dealiased)
}

val inheritanceContext = definitionDocument match {
// symbol is not in workspace, we only search classpath for it
case None =>
globalTable.globalContextFor(
filePosition.filePath,
implementationsInPath.asScala.toMap
)
// symbol is in workspace,
// we might need to search different places for related symbols
case Some(textDocument) =>
Some(
InheritanceContext.fromDefinitions(
symbolSearch,
implementationsInPath.asScala.toMap
)
)
}
symbolLocationsFromContext(
dealiased,
filePosition.filePath,
implementationsInPath.asScala.toMap
inheritanceContext
)
// symbol is in workspace,
// we might need to search different places for related symbols
case Some(textDocument) =>
Some(
InheritanceContext.fromDefinitions(
symbolSearch,
implementationsInPath.asScala.toMap
)
)
}
symbolLocationsFromContext(
dealiased,
filePosition.filePath,
inheritanceContext
)
}
locations.flatten.toList

case Right(symbolInformation) =>
// symbol is not in workspace, we only search classpath for it
val inheritanceContext = globalTable.globalContextFor(
source,
implementationsInPath.asScala.toMap
)

symbolLocationsFromContext(
symbolInformation.symbol,
source,
inheritanceContext
).toList
}
locations.flatten.toList
}

def topMethodParents(
doc: TextDocument,
symbol: String
): Seq[Location] = {
): Seq[Either[Location, SymbolInformation]] = {
// 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)

Expand All @@ -173,9 +195,15 @@ final class ImplementationProvider(
classInfo <- findClassInfo(symbol.owner)
} yield {
classInfo.signature match {
case sig: ClassSignature =>
methodInParentSignature(sig, currentInfo)
case _ => Nil
case classSignature: ClassSignature =>
methodInParentSignature(
classSignature,
currentInfo,
globalTable.globalSymbolTableFor(
workspace.resolve(textDocument.uri)
)
)
case _ => Seq.empty
}
}
results.getOrElse(Seq.empty)
Expand All @@ -184,13 +212,18 @@ final class ImplementationProvider(
private def methodInParentSignature(
sig: ClassSignature,
childInfo: SymbolInformation,
globalSymbolTable: Option[GlobalSymbolTable],
childASF: Map[String, String] = Map.empty
): Seq[Location] = {
): Seq[Either[Location, SymbolInformation]] = {
sig.parents.flatMap {
case parentSym: TypeRef =>
case parentSym: TypeRef if parentSym.symbol != "scala/AnyRef#" =>
val parentTextDocument = findSemanticDbForSymbol(parentSym.symbol)
def search(symbol: String) =
parentTextDocument.flatMap(findSymbol(_, symbol))

def search(symbol: String): Option[SymbolInformation] =
parentTextDocument
.flatMap(findSymbol(_, symbol))
.orElse(globalSymbolTable.flatMap(_.safeInfo(symbol)))

val parentASF =
AsSeenFrom.calculateAsSeenFrom(parentSym, sig.typeParameters)
val asSeenFrom = AsSeenFrom.translateAsSeenFrom(childASF, parentASF)
Expand All @@ -199,6 +232,7 @@ final class ImplementationProvider(
val fromParent = methodInParentSignature(
parenClassSig,
childInfo,
globalSymbolTable,
asSeenFrom
)
if (fromParent.isEmpty) {
Expand All @@ -213,10 +247,10 @@ final class ImplementationProvider(
} else {
fromParent
}
case _ => Nil
case _ => Seq.empty
}

case _ => Nil
case _ => Seq.empty
}
}

Expand All @@ -227,31 +261,34 @@ final class ImplementationProvider(
asSeenFrom: Map[String, String],
search: String => Option[SymbolInformation],
parentTextDocument: Option[TextDocument]
): Option[Location] = {
): Option[Either[Location, SymbolInformation]] = {
val matchingSymbol = MethodImplementation.findParentSymbol(
childInfo,
sig,
parenClassSig,
asSeenFrom,
search
)
for {
symbol <- matchingSymbol
parentDoc <- parentTextDocument
source = workspace.resolve(parentDoc.uri)
implOccurrence <- findDefOccurrence(
parentDoc,
symbol,
source
)
range <- implOccurrence.range
distance = TokenEditDistance.fromBuffer(
source,
parentDoc.text,
buffer
)
revised <- distance.toRevised(range.toLSP)
} yield new Location(source.toNIO.toUri.toString, revised)
if (matchingSymbol.isDefined && parentTextDocument.isEmpty) {
Some(Right(matchingSymbol.get))
} else {
for {
symbol <- matchingSymbol
parentDoc <- parentTextDocument
source = workspace.resolve(parentDoc.uri)
implOccurrence <- findDefOccurrence(
parentDoc,
symbol.symbol,
source
)
range <- implOccurrence.range
distance = TokenEditDistance.fromBuffer(
source,
parentDoc.text,
buffer
)
revised <- distance.toRevised(range.toLSP)
} yield Left(new Location(source.toNIO.toUri.toString, revised))
}
}

private def symbolLocationsFromContext(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,10 @@ object MethodImplementation {

def findParentSymbol(
childSymbol: SymbolInformation,
childClassSig: ClassSignature,
parentClassSig: ClassSignature,
asSeenFromMap: Map[String, String],
findSymbol: String => Option[SymbolInformation]
): Option[String] = {
): Option[SymbolInformation] = {
val validMethods = for {
declarations <- parentClassSig.declarations.toIterable
methodSymbol <- declarations.symlinks
Expand All @@ -52,7 +51,7 @@ object MethodImplementation {
if isOverridenMethod(methodSymbolInfo, childSymbol, findParent = true)(
context
)
} yield methodSymbol
} yield methodSymbolInfo
validMethods.headOption
}

Expand Down
Loading

0 comments on commit 81da8a9

Please sign in to comment.