Skip to content

Commit

Permalink
connection completion
Browse files Browse the repository at this point in the history
  • Loading branch information
develar committed Dec 27, 2023
1 parent 1da9084 commit daee738
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 102 deletions.
19 changes: 10 additions & 9 deletions src/main/kotlin/com/dvd/intellij/d2/ide/utils/constants.kt
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
package com.dvd.intellij.d2.ide.utils

internal const val D2_TOOLWINDOW_ID = "D2ToolWindow"
internal const val D2_EDITOR_NAME = "D2FileEditor"
internal const val D2_EDITOR_ID = "D2Editor"

internal const val D2_GROUP_TOOLBAR = "D2.EditorToolbar"
internal const val D2_GROUP_POPUP = "D2.EditorPopupMenu"
internal const val D2_ACTION_PLACE = "D2.Editor"

internal const val NOTIFICATION_GROUP = "D2_INFO"

// https://github.com/terrastruct/d2/blob/eb55a49559fe933b3846094d8af01496ed55d037/d2graph/d2graph.go#L1040-L1050
internal val RESERVED_KEYWORDS = arrayOf(
val SIMPLE_RESERVED_KEYWORDS: Array<String> = arrayOf(
"label",
"desc",
"shape",
Expand All @@ -22,6 +14,15 @@ internal val RESERVED_KEYWORDS = arrayOf(
"near",
"width",
"height",
"direction",
"top",
"left",
"grid-rows",
"grid-columns",
"grid-gap",
"vertical-gap",
"horizontal-gap",
"class",
)

// https://github.com/terrastruct/d2/blob/eb55a49559fe933b3846094d8af01496ed55d037/d2graph/d2graph.go#L1054-L1057
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package org.jetbrains.plugins.d2.completion

import com.dvd.intellij.d2.ide.utils.D2Icons
import com.dvd.intellij.d2.ide.utils.KEYWORD_HOLDERS
import com.dvd.intellij.d2.ide.utils.SIMPLE_RESERVED_KEYWORDS
import com.intellij.codeInsight.completion.*
import com.intellij.codeInsight.lookup.LookupElement
import com.intellij.codeInsight.lookup.LookupElementBuilder
import com.intellij.psi.PsiWhiteSpace
import org.jetbrains.annotations.VisibleForTesting
import org.jetbrains.plugins.d2.lang.psi.D2BlockDefinition
import org.jetbrains.plugins.d2.lang.psi.D2ShapeDefinition

private val keywords = (SIMPLE_RESERVED_KEYWORDS + KEYWORD_HOLDERS).map {
val builder = LookupElementBuilder.create(it)
.withIcon(D2Icons.ATTRIBUTE)
if (it != "style") {
builder.withInsertHandler(ColonLookupElementInsertHandler)
}
builder
}

private object ColonLookupElementInsertHandler : InsertHandler<LookupElement> {
override fun handleInsert(context: InsertionContext, item: LookupElement) {
val caretOffset = context.editor.caretModel.offset
val colon = ": "
context.document.insertString(context.selectionEndOffset, colon)
context.editor.caretModel.moveToOffset(caretOffset + colon.length)
}
}

@VisibleForTesting
internal val varsAndClasses: List<LookupElementBuilder> = sequenceOf("vars", "classes")
.map {
LookupElementBuilder.create(it)
.withIcon(D2Icons.ATTRIBUTE)
.withInsertHandler(ColonLookupElementInsertHandler)
}
.toList()

private val connections = sequenceOf("--", "->", "<-", "<->")
.map {
LookupElementBuilder.create(it)
.withIcon(D2Icons.CONNECTION)
}
.toList()


private class D2BasicCompletionContributor : CompletionContributor() {
override fun fillCompletionVariants(parameters: CompletionParameters, result: CompletionResultSet) {
if (parameters.completionType != CompletionType.BASIC) {
return
}

val position = parameters.position
val parent = position.context
if (parent !is D2ShapeDefinition) {
return
}

// see D2CompletionTest.connection
if (position.prevSibling is PsiWhiteSpace) {
result.addAllElements(connections)
} else {
// todo check next sibling - reserved keywords are prohibited in edges
val inMap = parent.context is D2BlockDefinition
result.addAllElements(keywords)
if (!inMap) {
// classes and vars only in a file context
result.addAllElements(varsAndClasses)
}
}
}
}

This file was deleted.

This file was deleted.

4 changes: 1 addition & 3 deletions src/main/kotlin/org/jetbrains/plugins/d2/lang/grammar.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,5 @@ class D2LexerAdapter : FlexAdapter(_D2Lexer(null))

interface D2CompositeElement : PsiElement

open class D2CompositeElementImpl(node: ASTNode) : ASTWrapperPsiElement(node), D2CompositeElement {

}
open class D2CompositeElementImpl(node: ASTNode) : ASTWrapperPsiElement(node), D2CompositeElement

11 changes: 3 additions & 8 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,9 @@

<formattingService implementation="org.jetbrains.plugins.d2.editor.D2FormatterService"/>

<completion.contributor language="d2"
implementationClass="org.jetbrains.plugins.d2.completion.D2ShapesTypesCompletionContributor"/>
<completion.contributor language="d2"
implementationClass="org.jetbrains.plugins.d2.completion.D2StyleCompletionContributor"/>
<completion.contributor language="d2"
implementationClass="org.jetbrains.plugins.d2.completion.D2BlockCompletionContributor"/>
<completion.contributor language="d2"
implementationClass="org.jetbrains.plugins.d2.completion.D2ConnectorCompletionContributor"/>
<!--<completion.contributor language="d2" implementationClass="org.jetbrains.plugins.d2.completion.D2ShapesTypesCompletionContributor"/>-->
<!--<completion.contributor language="d2" implementationClass="org.jetbrains.plugins.d2.completion.D2StyleCompletionContributor"/>-->
<completion.contributor language="d2" implementationClass="org.jetbrains.plugins.d2.completion.D2BasicCompletionContributor"/>

<spellchecker.support language="d2" implementationClass="org.jetbrains.plugins.d2.editor.D2SpellCheckerStrategy"/>

Expand Down
47 changes: 32 additions & 15 deletions src/test/kotlin/org/jetbrains/plugins/d2/D2CompletionTest.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package org.jetbrains.plugins.d2

import com.dvd.intellij.d2.ide.utils.KEYWORD_HOLDERS
import com.dvd.intellij.d2.ide.utils.SIMPLE_RESERVED_KEYWORDS
import com.intellij.codeInsight.completion.CompletionType
import com.intellij.testFramework.fixtures.BasePlatformTestCase
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
import org.assertj.core.api.Assertions.assertThat
import org.jetbrains.plugins.d2.completion.varsAndClasses
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.AfterEachCallback
import org.junit.jupiter.api.extension.BeforeEachCallback
Expand All @@ -12,7 +15,7 @@ import org.junit.jupiter.api.extension.RegisterExtension

class D2CompletionTest : D2LightCodeInsightFixtureTestCase() {
@Test
fun `block completion`() {
fun block() {
fixture.configureByText(
"test.d2",
"""
Expand All @@ -24,21 +27,35 @@ class D2CompletionTest : D2LightCodeInsightFixtureTestCase() {
fixture.complete(CompletionType.BASIC)
val lookupElementStrings = fixture.lookupElementStrings
assertThat(lookupElementStrings).isNotNull()
assertThat(lookupElementStrings).containsExactlyInAnyOrder(
"constraint",
"desc",
"height",
"icon",
"label",
"link",
"near",
"shape",
"source-arrowhead",
"style",
"target-arrowhead",
"tooltip",
"width"
assertThat(lookupElementStrings).containsOnlyElementsOf((SIMPLE_RESERVED_KEYWORDS + KEYWORD_HOLDERS).toList())
}

@Test
fun file() {
fixture.configureByText(
"test.d2",
"""
<caret>
"""
)
fixture.complete(CompletionType.BASIC)
val lookupElementStrings = fixture.lookupElementStrings
assertThat(lookupElementStrings).isNotNull()
assertThat(lookupElementStrings).containsOnlyElementsOf((SIMPLE_RESERVED_KEYWORDS + KEYWORD_HOLDERS).toList() + varsAndClasses.map { it.lookupString })
}

@Test
fun connection() {
fixture.configureByText(
"test.d2",
"""
s <caret>
"""
)
fixture.complete(CompletionType.BASIC)
val lookupElementStrings = fixture.lookupElementStrings
assertThat(lookupElementStrings).isNotNull()
assertThat(lookupElementStrings).containsOnlyElementsOf(listOf("--", "->", "<-", "<->"))
}
}

Expand Down

0 comments on commit daee738

Please sign in to comment.