KT-6407 Completing function with "tab" (replace) shouldn't insert parentheses when type arguments are present
#KT-6407 Fixed
This commit is contained in:
+29
-6
@@ -40,12 +40,13 @@ import org.jetbrains.jet.lang.psi.JetSimpleNameExpression
|
|||||||
import org.jetbrains.jet.lang.psi.JetPsiFactory
|
import org.jetbrains.jet.lang.psi.JetPsiFactory
|
||||||
import org.jetbrains.jet.lang.psi.JetParenthesizedExpression
|
import org.jetbrains.jet.lang.psi.JetParenthesizedExpression
|
||||||
import org.jetbrains.jet.lang.psi.JetBinaryExpressionWithTypeRHS
|
import org.jetbrains.jet.lang.psi.JetBinaryExpressionWithTypeRHS
|
||||||
import org.jetbrains.jet.lang.psi.JetExpression
|
|
||||||
import org.jetbrains.jet.plugin.codeInsight.ShortenReferences
|
import org.jetbrains.jet.plugin.codeInsight.ShortenReferences
|
||||||
import org.jetbrains.jet.lang.psi.JetCodeFragment
|
|
||||||
import org.jetbrains.jet.lang.psi.psiUtil.getStrictParentOfType
|
import org.jetbrains.jet.lang.psi.psiUtil.getStrictParentOfType
|
||||||
import com.intellij.psi.util.PsiTreeUtil
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
import org.jetbrains.jet.plugin.completion.qualifiedNameForSourceCode
|
import org.jetbrains.jet.plugin.completion.qualifiedNameForSourceCode
|
||||||
|
import org.jetbrains.jet.lexer.JetTokens
|
||||||
|
import org.jetbrains.jet.lang.psi.JetTypeArgumentList
|
||||||
|
import com.intellij.codeInsight.lookup.Lookup
|
||||||
|
|
||||||
public abstract class KotlinCallableInsertHandler : BaseDeclarationInsertHandler() {
|
public abstract class KotlinCallableInsertHandler : BaseDeclarationInsertHandler() {
|
||||||
public override fun handleInsert(context: InsertionContext, item: LookupElement) {
|
public override fun handleInsert(context: InsertionContext, item: LookupElement) {
|
||||||
@@ -139,15 +140,34 @@ public class KotlinFunctionInsertHandler(val caretPosition : CaretPosition, val
|
|||||||
context.setAddCompletionChar(false)
|
context.setAddCompletionChar(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
val offset = context.getTailOffset()
|
var offset = context.getTailOffset()
|
||||||
val document = context.getDocument()
|
val document = context.getDocument()
|
||||||
|
val chars = document.getCharsSequence()
|
||||||
|
|
||||||
val forceParenthesis = lambdaInfo != null && completionChar == '\t' && document.getCharsSequence().charAt(offset) == '('
|
val forceParenthesis = lambdaInfo != null && completionChar == '\t' && chars.charAt(offset) == '('
|
||||||
val braces = lambdaInfo != null && completionChar != '(' && !forceParenthesis
|
val braces = lambdaInfo != null && completionChar != '(' && !forceParenthesis
|
||||||
|
|
||||||
val openingBracket = if (braces) '{' else '('
|
val openingBracket = if (braces) '{' else '('
|
||||||
val closingBracket = if (braces) '}' else ')'
|
val closingBracket = if (braces) '}' else ')'
|
||||||
|
|
||||||
|
if (completionChar == Lookup.REPLACE_SELECT_CHAR) {
|
||||||
|
offset = skipSpaces(chars, offset)
|
||||||
|
if (offset < document.getTextLength()) {
|
||||||
|
val c = chars[offset]
|
||||||
|
if (c == '<') {
|
||||||
|
PsiDocumentManager.getInstance(context.getProject()).commitDocument(document)
|
||||||
|
val psiFile = context.getFile()
|
||||||
|
val token = psiFile.findElementAt(offset)
|
||||||
|
if (token.getNode().getElementType() == JetTokens.LT) {
|
||||||
|
val parent = token.getParent()
|
||||||
|
if (parent is JetTypeArgumentList && parent.getText().indexOf('\n') < 0/* if type argument list is on multiple lines this is more likely wrong parsing*/) {
|
||||||
|
offset = parent.getTextRange().getEndOffset()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var openingBracketOffset = indexOfSkippingSpace(document, openingBracket, offset)
|
var openingBracketOffset = indexOfSkippingSpace(document, openingBracket, offset)
|
||||||
var inBracketsShift = 0
|
var inBracketsShift = 0
|
||||||
if (openingBracketOffset == -1) {
|
if (openingBracketOffset == -1) {
|
||||||
@@ -208,13 +228,16 @@ public class KotlinFunctionInsertHandler(val caretPosition : CaretPosition, val
|
|||||||
private fun indexOfSkippingSpace(document: Document, ch : Char, startIndex : Int) : Int {
|
private fun indexOfSkippingSpace(document: Document, ch : Char, startIndex : Int) : Int {
|
||||||
val text = document.getCharsSequence()
|
val text = document.getCharsSequence()
|
||||||
for (i in startIndex..text.length() - 1) {
|
for (i in startIndex..text.length() - 1) {
|
||||||
val currentChar = text.charAt(i)
|
val currentChar = text[i]
|
||||||
if (ch == currentChar) return i
|
if (ch == currentChar) return i
|
||||||
if (!Character.isWhitespace(currentChar)) return -1
|
if (currentChar != ' ' && currentChar != '\t') return -1
|
||||||
}
|
}
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun skipSpaces(chars: CharSequence, index : Int) : Int
|
||||||
|
= (index..chars.length() - 1).firstOrNull { val c = chars[it]; c != ' ' && c != '\t' } ?: chars.length()
|
||||||
|
|
||||||
private fun isInsertSpacesInOneLineFunctionEnabled(project : Project)
|
private fun isInsertSpacesInOneLineFunctionEnabled(project : Project)
|
||||||
= CodeStyleSettingsManager.getSettings(project)
|
= CodeStyleSettingsManager.getSettings(project)
|
||||||
.getCustomSettings(javaClass<JetCodeStyleSettings>())!!.INSERT_WHITESPACES_IN_SIMPLE_ONE_LINE_METHOD
|
.getCustomSettings(javaClass<JetCodeStyleSettings>())!!.INSERT_WHITESPACES_IN_SIMPLE_ONE_LINE_METHOD
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
fun <T> foo() {}
|
||||||
|
|
||||||
|
fun use() = f<caret><String>()
|
||||||
|
|
||||||
|
// ELEMENT: foo
|
||||||
|
// CHAR: '\t'
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
fun <T> foo() {}
|
||||||
|
|
||||||
|
fun use() = foo<String>()<caret>
|
||||||
|
|
||||||
|
// ELEMENT: foo
|
||||||
|
// CHAR: '\t'
|
||||||
+6
@@ -48,6 +48,12 @@ public class BasicCompletionHandlerTestGenerated extends AbstractBasicCompletion
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("GenericFunctionWithTab.kt")
|
||||||
|
public void testGenericFunctionWithTab() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/basic/GenericFunctionWithTab.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("SecondTypeArg.kt")
|
@TestMetadata("SecondTypeArg.kt")
|
||||||
public void testSecondTypeArg() throws Exception {
|
public void testSecondTypeArg() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/basic/SecondTypeArg.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/basic/SecondTypeArg.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user