KDoc typed handler: autoinsert pair brackets and parentheses

#KT-7347 fixed
This commit is contained in:
Dmitry Jemerov
2015-04-08 18:07:58 +02:00
parent 5bbbadeb37
commit 7f5b1d489e
21 changed files with 323 additions and 0 deletions
@@ -74,6 +74,7 @@ import org.jetbrains.kotlin.idea.imports.AbstractOptimizeImportsTest
import org.jetbrains.kotlin.idea.intentions.AbstractIntentionTest
import org.jetbrains.kotlin.idea.intentions.declarations.AbstractJoinLinesTest
import org.jetbrains.kotlin.idea.kdoc.AbstractKDocHighlightingTest
import org.jetbrains.kotlin.idea.kdoc.AbstractKDocTypingTest
import org.jetbrains.kotlin.idea.navigation.AbstractGotoSuperTest
import org.jetbrains.kotlin.idea.navigation.AbstractKotlinGotoImplementationTest
import org.jetbrains.kotlin.idea.navigation.AbstractKotlinGotoTest
@@ -628,6 +629,10 @@ fun main(args: Array<String>) {
testClass(javaClass<AbstractKDocHighlightingTest>()) {
model("kdoc/highlighting")
}
testClass<AbstractKDocTypingTest>() {
model("kdoc/typing")
}
}
testGroup("idea/tests", "compiler/testData") {
+1
View File
@@ -340,6 +340,7 @@
<basicWordSelectionFilter implementation="org.jetbrains.kotlin.idea.editor.wordSelection.KotlinWordSelectionFilter"/>
<typedHandler implementation="org.jetbrains.kotlin.idea.editor.KotlinTypedHandler"/>
<typedHandler implementation="org.jetbrains.kotlin.idea.kdoc.KDocTypedHandler"/>
<enterHandlerDelegate implementation="org.jetbrains.kotlin.idea.editor.KotlinEnterHandler"
id="KotlinEnterHandler" order="before EnterBetweenBracesHandler"/>
<lang.smartEnterProcessor language="jet" implementationClass="org.jetbrains.kotlin.idea.editor.KotlinSmartEnterHandler"/>
@@ -0,0 +1,98 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.kdoc
import com.intellij.codeInsight.CodeInsightSettings
import com.intellij.codeInsight.editorActions.TypedHandlerDelegate
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.EditorModificationUtil
import com.intellij.openapi.fileTypes.FileType
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.kdoc.lexer.KDocTokens
import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.psi.JetFile
public class KDocTypedHandler(): TypedHandlerDelegate() {
override fun beforeCharTyped(c: Char, project: Project, editor: Editor, file: PsiFile, fileType: FileType): TypedHandlerDelegate.Result =
if (handleBeforeBracketTyped(c, editor, file)) TypedHandlerDelegate.Result.STOP else TypedHandlerDelegate.Result.CONTINUE
override fun charTyped(c: Char, project: Project, editor: Editor, file: PsiFile): TypedHandlerDelegate.Result =
if (handleBracketTyped(c, project, editor, file)) TypedHandlerDelegate.Result.STOP else TypedHandlerDelegate.Result.CONTINUE
private fun handleBeforeBracketTyped(c: Char, editor: Editor, file: PsiFile): Boolean {
if (file !is JetFile) {
return false
}
if (!CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET) {
return false
}
val offset = editor.getCaretModel().getOffset()
val document = editor.getDocument()
if ((c == ']' || c == ')') && offset < document.getTextLength() && document.getCharsSequence().charAt(offset) == c) {
PsiDocumentManager.getInstance(file.getProject()).commitDocument(document)
val element = file.findElementAt(offset)
// if the bracket is not part of a link, it will be part of KDOC_TEXT, not a separate RBRACKET element
if (c == ']' &&
element?.getNode()?.getElementType() == JetTokens.RBRACKET ||
(offset > 0 && document.getCharsSequence().charAt(offset - 1) == '[')) {
EditorModificationUtil.moveCaretRelatively(editor, 1)
return true
}
if (c == ')' && element?.getNode()?.getElementType() == KDocTokens.MARKDOWN_INLINE_LINK) {
EditorModificationUtil.moveCaretRelatively(editor, 1)
return true
}
}
return false
}
private fun handleBracketTyped(c: Char, project: Project, editor: Editor, file: PsiFile): Boolean {
if (file !is JetFile) {
return false
}
if (!CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET) {
return false
}
val offset = editor.getCaretModel().getOffset()
if (offset == 0) {
return false
}
if (c == '[' || c == '(') {
val document = editor.getDocument()
PsiDocumentManager.getInstance(project).commitDocument(document)
val element = file.findElementAt(offset - 1)
if (element == null ||
element.getNode().getElementType() != KDocTokens.TEXT) {
return false
}
if (c == '[')
{
document.insertString(offset, "]")
return true
}
if (c == '(' && offset > 1 && document.getCharsSequence().charAt(offset - 2) == ']') {
document.insertString(offset, ")")
return true
}
}
return false
}
}
@@ -0,0 +1,6 @@
/**
* Just some brackets: <caret>]
*/
fun foo()
// TYPE: ]
@@ -0,0 +1,6 @@
/**
* Just some brackets: ]<caret>]
*/
fun foo()
// TYPE: ]
@@ -0,0 +1,6 @@
/**
* [foo<caret>]
*/
fun foo()
// TYPE: ]
@@ -0,0 +1,6 @@
/**
* [foo]<caret>
*/
fun foo()
// TYPE: ]
@@ -0,0 +1,6 @@
/**
* [<caret>]
*/
fun foo()
// TYPE: ]
@@ -0,0 +1,6 @@
/**
* []<caret>
*/
fun foo()
// TYPE: ]
@@ -0,0 +1,6 @@
/**
* [foo][bar<caret>]
*/
fun foo()
// TYPE: ]
@@ -0,0 +1,6 @@
/**
* [foo][bar]<caret>
*/
fun foo()
// TYPE: ]
@@ -0,0 +1,6 @@
/**
* [foo](bar<caret>)
*/
fun foo()
// TYPE: )
@@ -0,0 +1,6 @@
/**
* [foo](bar)<caret>
*/
fun foo()
// TYPE: )
@@ -0,0 +1,6 @@
/**
* <caret>
*/
fun foo()
// TYPE: [
@@ -0,0 +1,6 @@
/**
* [<caret>]
*/
fun foo()
// TYPE: [
@@ -0,0 +1,6 @@
/**
* [foo]<caret>
*/
fun foo()
// TYPE: [
@@ -0,0 +1,6 @@
/**
* [foo][<caret>]
*/
fun foo()
// TYPE: [
@@ -0,0 +1,6 @@
/**
* [foo]<caret>
*/
fun foo()
// TYPE: (
@@ -0,0 +1,6 @@
/**
* [foo](<caret>)
*/
fun foo()
// TYPE: (
@@ -0,0 +1,37 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.kdoc
import org.jetbrains.kotlin.idea.test.JetLightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.idea.test.JetLightProjectDescriptor
import org.jetbrains.kotlin.test.InTextDirectivesUtils
import org.jetbrains.kotlin.test.JetTestUtils
public abstract class AbstractKDocTypingTest : JetLightCodeInsightFixtureTestCase() {
override fun getTestDataPath(): String = JetTestUtils.getHomeDirectory()
override fun getProjectDescriptor() = JetLightProjectDescriptor.INSTANCE
protected fun doTest(fileName: String) {
myFixture.configureByFile(fileName)
val textToType = InTextDirectivesUtils.findStringWithPrefixes(myFixture.getFile().getText(), "// TYPE:")
if (textToType == null) {
throw IllegalArgumentException("Cannot find directive TYPE in input file")
}
myFixture.type(textToType)
myFixture.checkResultByFile(fileName + ".after")
}
}
@@ -0,0 +1,86 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.kdoc;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.InnerTestClasses;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.JetTestUtils;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("idea/testData/kdoc/typing")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class KDocTypingTestGenerated extends AbstractKDocTypingTest {
public void testAllFilesPresentInTyping() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/kdoc/typing"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("closingBracketNotInLink.kt")
public void testClosingBracketNotInLink() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/kdoc/typing/closingBracketNotInLink.kt");
doTest(fileName);
}
@TestMetadata("closingBracketOvertype.kt")
public void testClosingBracketOvertype() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/kdoc/typing/closingBracketOvertype.kt");
doTest(fileName);
}
@TestMetadata("closingBracketOvertypeEmpty.kt")
public void testClosingBracketOvertypeEmpty() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/kdoc/typing/closingBracketOvertypeEmpty.kt");
doTest(fileName);
}
@TestMetadata("closingBracketRefLinkOvertype.kt")
public void testClosingBracketRefLinkOvertype() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/kdoc/typing/closingBracketRefLinkOvertype.kt");
doTest(fileName);
}
@TestMetadata("closingParenOvertype.kt")
public void testClosingParenOvertype() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/kdoc/typing/closingParenOvertype.kt");
doTest(fileName);
}
@TestMetadata("openingBracket.kt")
public void testOpeningBracket() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/kdoc/typing/openingBracket.kt");
doTest(fileName);
}
@TestMetadata("openingBracketRefLink.kt")
public void testOpeningBracketRefLink() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/kdoc/typing/openingBracketRefLink.kt");
doTest(fileName);
}
@TestMetadata("openingParen.kt")
public void testOpeningParen() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/kdoc/typing/openingParen.kt");
doTest(fileName);
}
}