Skip to content

Commit

Permalink
Remove map combinator from FeatureProvider
Browse files Browse the repository at this point in the history
  • Loading branch information
efoerster committed Mar 6, 2019
1 parent b755779 commit 364295b
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 84 deletions.
20 changes: 13 additions & 7 deletions src/main/kotlin/texlab/TextDocumentServiceImpl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import texlab.build.BuildConfig
import texlab.build.BuildEngine
import texlab.build.BuildParams
import texlab.build.BuildResult
import texlab.completion.OrderByQualityProvider
import texlab.completion.MatchQualityComparator
import texlab.completion.bibtex.BibtexCitationActor
import texlab.completion.bibtex.BibtexEntryTypeProvider
import texlab.completion.bibtex.BibtexFieldNameProvider
Expand Down Expand Up @@ -153,9 +153,6 @@ class TextDocumentServiceImpl(val workspaceActor: WorkspaceActor) : CustomTextDo
BibtexEntryTypeProvider,
BibtexFieldNameProvider,
BibtexKernelCommandProvider)
.map { items -> items.distinctBy { it.label } }
.let { OrderByQualityProvider(it) }
.map { it.take(completionLimit) }

private val symbolProvider: FeatureProvider<DocumentSymbolParams, List<DocumentSymbol>> =
FeatureProvider.concat(
Expand Down Expand Up @@ -300,10 +297,19 @@ class TextDocumentServiceImpl(val workspaceActor: WorkspaceActor) : CustomTextDo

override fun completion(params: CompletionParams)
: CompletableFuture<Either<List<CompletionItem>, CompletionList>> = future {
val items = runFeature(completionProvider, params.textDocument, params)
val items = workspaceActor.withWorkspace { workspace ->
val uri = URIHelper.parse(params.textDocument.uri)
val request = FeatureRequest(uri, workspace, params, logger)
val comparator = MatchQualityComparator(request.document, params.position)

completionProvider.get(request)
.distinctBy { it.label }
.sortedWith(comparator)
.take(completionLimit)
}

val allIncludes = items.all {
it.kind == CompletionItemKind.Folder ||
it.kind == CompletionItemKind.File
it.kind == CompletionItemKind.Folder || it.kind == CompletionItemKind.File
}
val isIncomplete = !allIncludes || items.size > completionLimit
val list = CompletionList(isIncomplete, items)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,39 +1,62 @@
package texlab.completion

import org.eclipse.lsp4j.CompletionItem
import org.eclipse.lsp4j.CompletionParams
import org.eclipse.lsp4j.Position
import texlab.BibtexDocument
import texlab.Document
import texlab.LatexDocument
import texlab.contains
import texlab.provider.FeatureProvider
import texlab.provider.FeatureRequest
import texlab.syntax.bibtex.*
import texlab.syntax.latex.LatexCommandSyntax
import texlab.syntax.latex.LatexDocumentSyntax
import texlab.syntax.latex.LatexGroupSyntax
import texlab.syntax.latex.LatexTextSyntax

class OrderByQualityProvider(private val provider: FeatureProvider<CompletionParams, List<CompletionItem>>)
: FeatureProvider<CompletionParams, List<CompletionItem>> {
class MatchQualityComparator(private val document: Document,
private val position: Position) : Comparator<CompletionItem> {
override fun compare(left: CompletionItem, right: CompletionItem): Int {
val leftQuality = getQuality(left.label)
val rightQuality = getQuality(right.label)
return rightQuality.compareTo(leftQuality)
}

private fun getQuality(label: String): Int {
val query = getName(document, position) ?: return -1
if (label == query) {
return 7
}

if (label.equals(query, ignoreCase = true)) {
return 6
}

if (label.startsWith(query)) {
return 5
}

override suspend fun get(request: FeatureRequest<CompletionParams>): List<CompletionItem> {
val name = getName(request)
return if (name == null) {
emptyList()
} else {
provider.get(request)
.sortedByDescending { getQuality(it.label, name) }
if (label.toLowerCase().startsWith(query.toLowerCase())) {
return 4
}

if (label.contains(query)) {
return 3
}

if (label.toLowerCase().contains(query.toLowerCase())) {
return 2
}

return 1
}

private fun getName(request: FeatureRequest<CompletionParams>): String? {
return when (request.document) {
private fun getName(document: Document, position: Position): String? {
return when (document) {
is LatexDocument -> {
val descendants = request.document.tree.root.descendants()
val descendants = document.tree.root.descendants()
val node = descendants
.filterIsInstance<LatexCommandSyntax>()
.lastOrNull { it.name.range.contains(request.params.position) }
?: descendants.lastOrNull { it.range.contains(request.params.position) }
.lastOrNull { it.name.range.contains(position) }
?: descendants.lastOrNull { it.range.contains(position) }

when (node) {
is LatexGroupSyntax -> ""
Expand All @@ -44,14 +67,14 @@ class OrderByQualityProvider(private val provider: FeatureProvider<CompletionPar
}
}
is BibtexDocument -> {
val node = request.document.tree.root
val node = document.tree.root
.descendants()
.lastOrNull { it.range.contains(request.params.position) }
.lastOrNull { it.range.contains(position) }

when (node) {
is BibtexDocumentSyntax -> ""
is BibtexDeclarationSyntax -> {
if (node.type.range.contains(request.params.position)) {
if (node.type.range.contains(position)) {
node.type.text.substring(1)
} else {
""
Expand All @@ -61,7 +84,7 @@ class OrderByQualityProvider(private val provider: FeatureProvider<CompletionPar
node.token.text
}
is BibtexFieldSyntax -> {
if (node.name.range.contains(request.params.position)) {
if (node.name.range.contains(position)) {
node.name.text
} else {
""
Expand All @@ -81,32 +104,4 @@ class OrderByQualityProvider(private val provider: FeatureProvider<CompletionPar
}
}
}

private fun getQuality(label: String, query: String): Int {
if (label == query) {
return 7
}

if (label.equals(query, ignoreCase = true)) {
return 6
}

if (label.startsWith(query)) {
return 5
}

if (label.toLowerCase().startsWith(query.toLowerCase())) {
return 4
}

if (label.contains(query)) {
return 3
}

if (label.toLowerCase().contains(query.toLowerCase())) {
return 2
}

return 1
}
}
6 changes: 0 additions & 6 deletions src/main/kotlin/texlab/provider/FeatureProvider.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,6 @@ package texlab.provider
interface FeatureProvider<T, R> {
suspend fun get(request: FeatureRequest<T>): R

fun <C> map(transform: (R) -> C): FeatureProvider<T, C> {
return create { request ->
transform(get(request))
}
}

companion object {
fun <T, R> create(get: suspend (FeatureRequest<T>) -> R): FeatureProvider<T, R> {
return object : FeatureProvider<T, R> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@ import org.junit.jupiter.api.Test
import texlab.WorkspaceBuilder
import texlab.completion.latex.LatexKernelCommandProvider

class OrderByQualityProviderTests {
class MatchQualityComparatorTests {
@Test
fun `it should prioritize items that begin with the query`() = runBlocking {
val provider = OrderByQualityProvider(LatexKernelCommandProvider)
val request = WorkspaceBuilder()
.document("foo.tex", "\\usep")
.completion("foo.tex", 0, 5)
val items = provider.get(request)
val comparator = MatchQualityComparator(request.document, request.params.position)
val items = LatexKernelCommandProvider
.get(request)
.sortedWith(comparator)

assertEquals("usepackage", items[0].label)
}
}
21 changes: 2 additions & 19 deletions src/test/kotlin/texlab/provider/FeatureProviderTests.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package texlab.provider

import kotlinx.coroutines.runBlocking
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertNull
import org.junit.jupiter.api.Test
import texlab.WorkspaceBuilder

Expand All @@ -18,24 +19,6 @@ class FeatureProviderTests {
}
}

@Test
fun `it should create a new provider that maps the result`() = runBlocking {
val request = WorkspaceBuilder()
.document("foo.tex", "")
.request("foo.tex") {}

val provider = NumberProvider(1)
val firstResult = provider.get(request)

val transform = { x: Int? -> x?.plus(1) }
val result = provider
.map { transform(it) }
.get(request)

assertNotNull(result)
assertEquals(transform(firstResult), result)
}

@Test
fun `it should concatenate the results of the given providers`() = runBlocking {
val request = WorkspaceBuilder()
Expand Down

0 comments on commit 364295b

Please sign in to comment.