Refactor hovering

This commit is contained in:
Patrick Förster 2019-01-20 13:10:41 +01:00
parent 4179272056
commit 0354e6dfb2
8 changed files with 104 additions and 61 deletions

View file

@ -28,17 +28,17 @@ import texlab.highlight.AggregateHighlightProvider
import texlab.highlight.HighlightProvider
import texlab.highlight.HighlightRequest
import texlab.highlight.LatexLabelHighlightProvider
import texlab.hover.*
import texlab.link.AggregateLinkProvider
import texlab.link.LatexIncludeLinkProvider
import texlab.link.LinkProvider
import texlab.link.LinkRequest
import texlab.metadata.BibtexEntryTypeMetadataProvider
import texlab.metadata.LatexPackageMetadataProvider
import texlab.metadata.LatexComponentMetadataProvider
import texlab.references.*
import texlab.rename.*
import texlab.symbol.*
import texlab.syntax.bibtex.BibtexDeclarationSyntax
import texlab.syntax.bibtex.BibtexEntrySyntax
import java.io.File
import java.net.URI
import java.nio.file.Path
@ -127,8 +127,10 @@ class TextDocumentServiceImpl(private val workspace: Workspace) : CustomTextDocu
private val highlightProvider: HighlightProvider =
AggregateHighlightProvider(LatexLabelHighlightProvider)
private val packageMetadataProvider = LatexPackageMetadataProvider()
private val bibtexEntryTypeMetadataProvider = BibtexEntryTypeMetadataProvider()
private val hoverProvider: HoverProvider =
AggregateHoverProvider(
LatexComponentHoverProvider,
BibtexEntryTypeHoverProvider)
private val referenceProvider: ReferenceProvider =
AggregateReferenceProvider(
@ -238,8 +240,8 @@ class TextDocumentServiceImpl(private val workspace: Workspace) : CustomTextDocu
override fun resolveCompletionItem(unresolved: CompletionItem): CompletableFuture<CompletionItem> {
return CompletableFuture.supplyAsync<CompletionItem> {
val provider = when (unresolved.kind) {
CompletionItemKind.Class -> packageMetadataProvider
CompletionItemKind.Interface -> bibtexEntryTypeMetadataProvider
CompletionItemKind.Class -> LatexComponentMetadataProvider
CompletionItemKind.Interface -> BibtexEntryTypeMetadataProvider
else -> null
}
@ -278,44 +280,9 @@ class TextDocumentServiceImpl(private val workspace: Workspace) : CustomTextDocu
override fun hover(params: TextDocumentPositionParams): CompletableFuture<Hover> {
val uri = URIHelper.parse(params.textDocument.uri)
val (name, provider) = synchronized(workspace) {
val document = workspace.documents
.firstOrNull { it.uri == uri }
?: return CompletableFuture.completedFuture(null)
val name = when (document) {
is LatexDocument -> {
document.tree.includes
.filter { it.isUnitImport }
.firstOrNull { it.command.range.contains(params.position) }?.path
?: return CompletableFuture.completedFuture(null)
}
is BibtexDocument -> {
document.tree.root.children
.filterIsInstance<BibtexEntrySyntax>()
.firstOrNull { it.type.range.contains(params.position) }?.type?.text?.substring(1)
?: return CompletableFuture.completedFuture(null)
}
}
val provider = when (document) {
is LatexDocument -> packageMetadataProvider
is BibtexDocument -> bibtexEntryTypeMetadataProvider
}
name to provider
}
return CompletableFuture.supplyAsync {
val metadata = provider.getMetadata(name)
val description = metadata?.documentation
if (description != null) {
Hover(description)
} else {
null
}
}
val relatedDocuments = synchronized(workspace) { workspace.relatedDocuments(uri) }
val request = HoverRequest(uri, relatedDocuments, params.position)
return CompletableFuture.completedFuture(hoverProvider.getHover(request))
}
override fun formatting(params: DocumentFormattingParams): CompletableFuture<MutableList<out TextEdit>> {

View file

@ -0,0 +1,15 @@
package texlab.hover
import org.eclipse.lsp4j.Hover
class AggregateHoverProvider(private vararg val providers: HoverProvider) : HoverProvider {
override fun getHover(request: HoverRequest): Hover? {
for (provider in providers) {
val hover = provider.getHover(request)
if (hover != null) {
return hover
}
}
return null
}
}

View file

@ -0,0 +1,24 @@
package texlab.hover
import org.eclipse.lsp4j.Hover
import texlab.BibtexDocument
import texlab.contains
import texlab.metadata.BibtexEntryTypeMetadataProvider
import texlab.syntax.bibtex.BibtexEntrySyntax
object BibtexEntryTypeHoverProvider : HoverProvider {
override fun getHover(request: HoverRequest): Hover? {
if (request.document !is BibtexDocument) {
return null
}
val name = request.document.tree.root.children
.filterIsInstance<BibtexEntrySyntax>()
.firstOrNull { it.type.range.contains(request.position) }?.type?.text?.substring(1)
?: return null
val metadata = BibtexEntryTypeMetadataProvider.getMetadata(name)
val documentation = metadata?.documentation ?: return null
return Hover(documentation)
}
}

View file

@ -0,0 +1,7 @@
package texlab.hover
import org.eclipse.lsp4j.Hover
interface HoverProvider {
fun getHover(request: HoverRequest): Hover?
}

View file

@ -0,0 +1,11 @@
package texlab.hover
import org.eclipse.lsp4j.Position
import texlab.Document
import java.net.URI
data class HoverRequest(val uri: URI,
val relatedDocuments: List<Document>,
val position: Position) {
val document: Document = relatedDocuments.first { it.uri == uri }
}

View file

@ -0,0 +1,22 @@
package texlab.hover
import org.eclipse.lsp4j.Hover
import texlab.LatexDocument
import texlab.contains
import texlab.metadata.LatexComponentMetadataProvider
object LatexComponentHoverProvider : HoverProvider {
override fun getHover(request: HoverRequest): Hover? {
if (request.document !is LatexDocument) {
return null
}
val name = request.document.tree.includes
.filter { it.isUnitImport }
.firstOrNull { it.command.range.contains(request.position) }?.path ?: return null
val metadata = LatexComponentMetadataProvider.getMetadata(name)
val documentation = metadata?.documentation ?: return null
return Hover(documentation)
}
}

View file

@ -3,22 +3,19 @@ package texlab.metadata
import org.eclipse.lsp4j.MarkupContent
import org.eclipse.lsp4j.MarkupKind
class BibtexEntryTypeMetadataProvider : MetadataProvider {
private val trimRegex = Regex("""^[ \t]+""", RegexOption.MULTILINE)
object BibtexEntryTypeMetadataProvider : MetadataProvider {
override fun getMetadata(name: String): Metadata? {
return if (documentationByName.containsKey(name)) {
val documentation = MarkupContent().apply {
kind = MarkupKind.MARKDOWN
value = documentationByName.getValue(name).replace(trimRegex, "")
}
Metadata(name, name, documentation)
} else {
null
val markdown = DOCUMENTATION_BY_NAME[name] ?: return null
val documentation = MarkupContent().apply {
kind = MarkupKind.MARKDOWN
value = markdown.replace(TRIM_REGEX, "")
}
return Metadata(name, name, documentation)
}
private val documentationByName = mapOf(
private val TRIM_REGEX = Regex("""^[ \t]+""", RegexOption.MULTILINE)
private val DOCUMENTATION_BY_NAME = mapOf(
"article" to
"""An article in a journal, magazine, newspaper, or other periodical which forms a
self-contained unit with its own title. The title of the periodical is given in the

View file

@ -9,13 +9,13 @@ import org.eclipse.lsp4j.MarkupKind
import java.io.IOException
import java.net.URL
class LatexPackageMetadataProvider : MetadataProvider {
object LatexComponentMetadataProvider : MetadataProvider {
override fun getMetadata(name: String): Metadata? {
return try {
val json = URL("https://ctan.org/json/2.0/pkg/$name").readText()
val mapper = jacksonObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
val result = mapper.readValue<Package>(json)
val result = mapper.readValue<Component>(json)
val description = result.descriptions.firstOrNull { it.language == null }?.text ?: return null
val documentation = MarkupContent().apply {
kind = MarkupKind.MARKDOWN
@ -27,9 +27,9 @@ class LatexPackageMetadataProvider : MetadataProvider {
}
}
private data class Package(val name: String,
val caption: String,
val descriptions: List<Description>)
private data class Component(val name: String,
val caption: String,
val descriptions: List<Description>)
private data class Description(val language: String?,
val text: String)