mirror of
https://github.com/latex-lsp/texlab.git
synced 2025-12-23 09:19:21 +00:00
Replace List with Map in Workspace
This commit is contained in:
parent
0321795052
commit
8a955460ad
5 changed files with 59 additions and 54 deletions
|
|
@ -216,7 +216,8 @@ class LatexLanguageServer : LanguageServer, LatexTextDocumentService, WorkspaceS
|
|||
launch {
|
||||
while (true) {
|
||||
workspaceActor.withWorkspace { workspace ->
|
||||
workspace.documents.map { workspace.relatedDocuments(it.uri) }
|
||||
workspace.documentsByUri.values
|
||||
.map { workspace.relatedDocuments(it.uri) }
|
||||
.forEach { componentDatabase.await().getRelatedComponents(it) }
|
||||
}
|
||||
|
||||
|
|
@ -273,7 +274,7 @@ class LatexLanguageServer : LanguageServer, LatexTextDocumentService, WorkspaceS
|
|||
val texUri = texPath.toUri()
|
||||
|
||||
workspaceActor.withWorkspace { workspace ->
|
||||
val document = workspace.documents.firstOrNull { it.uri == texUri }
|
||||
val document = workspace.documentsByUri[texUri]
|
||||
if (document != null) {
|
||||
try {
|
||||
val log = withContext(Dispatchers.IO) {
|
||||
|
|
@ -285,7 +286,7 @@ class LatexLanguageServer : LanguageServer, LatexTextDocumentService, WorkspaceS
|
|||
.groupBy { it.uri }
|
||||
.mapValues { errors -> errors.value.map { it.toDiagnostic() } }
|
||||
|
||||
workspace.documents.forEach { publishDiagnostics(it.uri) }
|
||||
workspace.documentsByUri.values.forEach { publishDiagnostics(it.uri) }
|
||||
} catch (e: IOException) {
|
||||
// File is still locked
|
||||
}
|
||||
|
|
@ -316,7 +317,7 @@ class LatexLanguageServer : LanguageServer, LatexTextDocumentService, WorkspaceS
|
|||
assert(params.contentChanges.size == 1)
|
||||
val uri = URIHelper.parse(params.textDocument.uri)
|
||||
workspaceActor.put { workspace ->
|
||||
val oldDocument = workspace.documents.first { it.uri == uri }
|
||||
val oldDocument = workspace.documentsByUri.getValue(uri)
|
||||
val text = params.contentChanges[0].text
|
||||
val tree = when (oldDocument) {
|
||||
is LatexDocument -> LatexSyntaxTree(text)
|
||||
|
|
@ -433,21 +434,17 @@ class LatexLanguageServer : LanguageServer, LatexTextDocumentService, WorkspaceS
|
|||
}
|
||||
|
||||
override fun formatting(params: DocumentFormattingParams)
|
||||
: CompletableFuture<MutableList<out TextEdit>?> = future {
|
||||
: CompletableFuture<List<TextEdit>?> = future {
|
||||
val uri = URIHelper.parse(params.textDocument.uri)
|
||||
val config = client.configuration<BibtexFormatterConfig>("bibtex.formatting", uri)
|
||||
workspaceActor.withWorkspace { workspace ->
|
||||
val document = workspace.documents
|
||||
.filterIsInstance<BibtexDocument>()
|
||||
.firstOrNull { it.uri == uri }
|
||||
val document = workspace.documentsByUri[uri] as? BibtexDocument
|
||||
?: return@withWorkspace null
|
||||
val formatter =
|
||||
BibtexFormatter(params.options.isInsertSpaces, params.options.tabSize, config.lineLength)
|
||||
val edits = mutableListOf<TextEdit>()
|
||||
for (entry in document.tree.root.children.filterIsInstance<BibtexDeclarationSyntax>()) {
|
||||
edits.add(TextEdit(entry.range, formatter.format(entry)))
|
||||
}
|
||||
edits
|
||||
document.tree.root.children
|
||||
.filterIsInstance<BibtexDeclarationSyntax>()
|
||||
.map { TextEdit(it.range, formatter.format(it)) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -498,7 +495,7 @@ class LatexLanguageServer : LanguageServer, LatexTextDocumentService, WorkspaceS
|
|||
|
||||
private suspend fun resolveIncludes() {
|
||||
workspaceActor.withWorkspace { workspace ->
|
||||
for (parent in workspace.documents.filterIsInstance<LatexDocument>()) {
|
||||
for (parent in workspace.documentsByUri.values.filterIsInstance<LatexDocument>()) {
|
||||
for (include in parent.tree.includes) {
|
||||
if (workspace.resolveDocument(parent.uri, include.path) != null) {
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -11,15 +11,16 @@ import java.nio.file.Path
|
|||
import java.nio.file.Paths
|
||||
import java.util.*
|
||||
|
||||
data class Workspace(val documents: List<Document> = listOf()) {
|
||||
class Workspace(val documentsByUri: Map<URI, Document> = emptyMap()) {
|
||||
fun resolveDocument(uri: URI, relativePath: String): Document? {
|
||||
for (target in resolveLinkTargets(uri, relativePath)) {
|
||||
val child = File(target).toURI()
|
||||
val document = documents.filter { it.isFile }.firstOrNull { it.uri == child }
|
||||
if (document != null) {
|
||||
val document = documentsByUri[child]
|
||||
if (document != null && document.isFile) {
|
||||
return document
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
|
|
@ -47,7 +48,8 @@ data class Workspace(val documents: List<Document> = listOf()) {
|
|||
|
||||
fun relatedDocuments(uri: URI): List<Document> {
|
||||
val edges = mutableSetOf<Pair<Document, Document>>()
|
||||
documents.filterIsInstance<LatexDocument>()
|
||||
documentsByUri.values
|
||||
.filterIsInstance<LatexDocument>()
|
||||
.filter { it.isFile }
|
||||
.forEach { parent ->
|
||||
parent.tree.includes
|
||||
|
|
@ -59,7 +61,7 @@ data class Workspace(val documents: List<Document> = listOf()) {
|
|||
}
|
||||
|
||||
val results = mutableListOf<Document>()
|
||||
val start = documents.firstOrNull { it.uri == uri } ?: return results
|
||||
val start = documentsByUri[uri] ?: return results
|
||||
val visited = mutableSetOf<Document>()
|
||||
val stack = Stack<Document>()
|
||||
stack.push(start)
|
||||
|
|
@ -70,8 +72,8 @@ data class Workspace(val documents: List<Document> = listOf()) {
|
|||
}
|
||||
|
||||
results.add(current)
|
||||
documents.filter { edges.contains(Pair(current, it)) }
|
||||
.forEach { stack.push(it) }
|
||||
documentsByUri.filterValues { edges.contains(Pair(current, it)) }
|
||||
.forEach { stack.push(it.value) }
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
|
@ -80,7 +82,7 @@ data class Workspace(val documents: List<Document> = listOf()) {
|
|||
return relatedDocuments(childUri)
|
||||
.filterIsInstance<LatexDocument>()
|
||||
.firstOrNull { it.tree.isStandalone }
|
||||
?: documents.first { it.uri == childUri }
|
||||
?: documentsByUri.getValue(childUri)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package texlab
|
|||
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.actor
|
||||
import java.net.URI
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
@ObsoleteCoroutinesApi
|
||||
|
|
@ -9,17 +10,16 @@ class WorkspaceActor : CoroutineScope {
|
|||
override val coroutineContext: CoroutineContext = Dispatchers.Default + Job()
|
||||
|
||||
private val actor = actor<Action> {
|
||||
var documents = listOf<Document>()
|
||||
val documentsByUri = mutableMapOf<URI, Document>()
|
||||
for (message in channel) {
|
||||
val workspace = Workspace(documents)
|
||||
val workspace = Workspace(documentsByUri)
|
||||
when (message) {
|
||||
is Action.Get -> {
|
||||
message.response.complete(workspace)
|
||||
}
|
||||
is Action.Put -> {
|
||||
val document = message.updater(workspace)
|
||||
documents = documents.filterNot { it.uri == document.uri }
|
||||
.plus(document)
|
||||
documentsByUri[document.uri] = document
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,14 +18,18 @@ class WorkspaceBuilder {
|
|||
return URIHelper.parse(file.toURI().toString())
|
||||
}
|
||||
|
||||
fun document(path: String, text: String): WorkspaceBuilder {
|
||||
val file = File(path)
|
||||
fun document(uri: URI, text: String): WorkspaceBuilder {
|
||||
val file = File(uri)
|
||||
val language = getLanguageByExtension(file.extension)!!
|
||||
val document = Document.create(uri(path), text, language)
|
||||
workspace = Workspace(workspace.documents.plus(document))
|
||||
val document = Document.create(uri, text, language)
|
||||
workspace = Workspace(workspace.documentsByUri.plus(Pair(document.uri, document)))
|
||||
return this
|
||||
}
|
||||
|
||||
fun document(path: String, text: String): WorkspaceBuilder {
|
||||
return document(uri(path), text)
|
||||
}
|
||||
|
||||
fun <T> request(path: String, paramsFactory: (TextDocumentIdentifier) -> T): FeatureRequest<T> {
|
||||
val uri = uri(path)
|
||||
val identifier = TextDocumentIdentifier(uri.toString())
|
||||
|
|
|
|||
|
|
@ -14,51 +14,55 @@ class WorkspaceTests {
|
|||
|
||||
@Test
|
||||
fun `it should append extensions when analyzing includes`() {
|
||||
val workspace = WorkspaceBuilder()
|
||||
.document("foo.tex", "\\include{bar/baz}")
|
||||
val builder = WorkspaceBuilder()
|
||||
val uri = builder.uri("foo.tex")
|
||||
val workspace = builder
|
||||
.document(uri, "\\include{bar/baz}")
|
||||
.document("bar/baz.tex", "")
|
||||
.workspace
|
||||
|
||||
val expected = workspace.documents
|
||||
.map { it.uri }
|
||||
.toTypedArray()
|
||||
val actual = relatedDocuments(workspace, workspace.documents[0].uri)
|
||||
val expected = workspace.documentsByUri.keys.toTypedArray()
|
||||
val actual = relatedDocuments(workspace, uri)
|
||||
assertArrayEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `it should ignore invalid includes`() {
|
||||
val workspace = WorkspaceBuilder()
|
||||
.document("foo.tex", "\\include{<foo>?|bar|:}\n\\include{}")
|
||||
val builder = WorkspaceBuilder()
|
||||
val uri = builder.uri("foo.tex")
|
||||
val workspace = builder
|
||||
.document(uri, "\\include{<foo>?|bar|:}\n\\include{}")
|
||||
.workspace
|
||||
|
||||
val expected = arrayOf(workspace.documents[0].uri)
|
||||
val actual = relatedDocuments(workspace, workspace.documents[0].uri)
|
||||
val expected = arrayOf(uri)
|
||||
val actual = relatedDocuments(workspace, uri)
|
||||
assertArrayEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `it should find related bibliographies`() {
|
||||
val workspace = WorkspaceBuilder()
|
||||
.document("foo.tex", "\\addbibresource{bar.bib}")
|
||||
val builder = WorkspaceBuilder()
|
||||
val uri = builder.uri("foo.tex")
|
||||
val workspace = builder
|
||||
.document(uri, "\\addbibresource{bar.bib}")
|
||||
.document("bar.bib", "")
|
||||
.workspace
|
||||
|
||||
val expected = workspace.documents
|
||||
.map { it.uri }
|
||||
.toTypedArray()
|
||||
val actual = relatedDocuments(workspace, workspace.documents[0].uri)
|
||||
val expected = workspace.documentsByUri.keys.toTypedArray()
|
||||
val actual = relatedDocuments(workspace, uri)
|
||||
assertArrayEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `it should ignore includes that cannot be resolved`() {
|
||||
val workspace = WorkspaceBuilder()
|
||||
.document("foo.tex", "\\include{bar.tex}")
|
||||
val builder = WorkspaceBuilder()
|
||||
val uri = builder.uri("foo.tex")
|
||||
val workspace = builder
|
||||
.document(uri, "\\include{bar.tex}")
|
||||
.workspace
|
||||
|
||||
val expected = arrayOf(workspace.documents[0].uri)
|
||||
val actual = relatedDocuments(workspace, workspace.documents[0].uri)
|
||||
val expected = arrayOf(uri)
|
||||
val actual = relatedDocuments(workspace, uri)
|
||||
assertArrayEquals(expected, actual)
|
||||
}
|
||||
|
||||
|
|
@ -69,10 +73,8 @@ class WorkspaceTests {
|
|||
.document("bar.tex", "\\input{foo.tex}")
|
||||
.workspace
|
||||
|
||||
val expected = workspace.documents
|
||||
.map { it.uri }
|
||||
.toTypedArray()
|
||||
val actual = relatedDocuments(workspace, workspace.documents[0].uri)
|
||||
val expected = workspace.documentsByUri.keys.toTypedArray()
|
||||
val actual = relatedDocuments(workspace, workspace.documentsByUri.keys.first())
|
||||
assertArrayEquals(expected, actual)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue