forked from scalameta/metals
-
Notifications
You must be signed in to change notification settings - Fork 2
/
MetalsSymbolSearch.scala
115 lines (104 loc) Β· 3.29 KB
/
MetalsSymbolSearch.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package scala.meta.internal.metals
import java.net.URI
import java.util.Optional
import java.{util => ju}
import scala.collection.concurrent.TrieMap
import scala.meta.internal.metals.MetalsEnrichments._
import scala.meta.internal.mtags.Mtags
import scala.meta.io.AbsolutePath
import scala.meta.pc.ParentSymbols
import scala.meta.pc.SymbolDocumentation
import scala.meta.pc.SymbolSearch
import scala.meta.pc.SymbolSearchVisitor
import ch.epfl.scala.bsp4j.BuildTargetIdentifier
import org.eclipse.lsp4j.Location
/**
* Implementation of SymbolSearch that delegates to WorkspaceSymbolProvider and SymbolDocumentationIndexer.
*/
class MetalsSymbolSearch(
docs: Docstrings,
wsp: WorkspaceSymbolProvider,
defn: DefinitionProvider,
)(implicit rc: ReportContext)
extends SymbolSearch {
// A cache for definitionSourceToplevels.
// The key is an absolute path to the dependency source file, and
// the value is the list of symbols that the file contains.
private val dependencySourceCache =
new TrieMap[AbsolutePath, ju.List[String]]()
def reset(): Unit = {
dependencySourceCache.clear()
}
override def documentation(
symbol: String,
parents: ParentSymbols,
): Optional[SymbolDocumentation] =
docs.documentation(symbol, parents)
def definition(symbol: String, source: URI): ju.List[Location] = {
val sourcePath = Option(source).map(AbsolutePath.fromAbsoluteUri)
defn.fromSymbol(symbol, sourcePath)
}
/**
* Returns a list of semanticdb symbols in a source file that contains the
* definition of the given symbol.
*/
override def definitionSourceToplevels(
symbol: String,
source: URI,
): ju.List[String] = {
val sourcePath = Option(source).map(AbsolutePath.fromAbsoluteUri)
defn
.definitionPathInputFromSymbol(symbol, sourcePath)
.map(input => {
val path = AbsolutePath(input.path)
if (path.isWorkspaceSource(wsp.workspace)) {
// If the source file is a workspace source, retrieve its symbols from
// WorkspaceSymbolProvider so that metals server can reuse its cache.
wsp.inWorkspace
.get(path.toNIO)
.map(symInfo => {
symInfo.symbols
.sortBy(sym =>
(
sym.range.getStart().getLine(),
sym.range.getStart().getCharacter(),
)
)
.map(_.symbol)
.asJava
})
.getOrElse(
ju.Collections.emptyList[String]()
)
} else {
dependencySourceCache.getOrElseUpdate(
path,
Mtags.toplevels(input).asJava,
)
}
})
.getOrElse(ju.Collections.emptyList())
}
override def search(
query: String,
buildTargetIdentifier: String,
visitor: SymbolSearchVisitor,
): SymbolSearch.Result = {
wsp.search(
WorkspaceSymbolQuery.exact(query),
visitor,
Some(new BuildTargetIdentifier(buildTargetIdentifier)),
)
}
override def searchMethods(
query: String,
buildTargetIdentifier: String,
visitor: SymbolSearchVisitor,
): SymbolSearch.Result = {
wsp.searchMethods(
query,
visitor,
Some(new BuildTargetIdentifier(buildTargetIdentifier)),
)
}
}