KT-7731 Completion: replacement of call with no parameters with property by Tab
#KT-7731 Fixed
This commit is contained in:
+4
-4
@@ -95,8 +95,8 @@ public class KotlinCompletionContributor : CompletionContributor() {
|
||||
// search expression to be replaced - go up while we are the first child of parent expression
|
||||
var expression = parent as JetExpression
|
||||
parent = expression.getParent()
|
||||
while (parent is JetExpression && parent!!.getFirstChild() == expression) {
|
||||
expression = parent as JetExpression
|
||||
while (parent is JetExpression && parent.getFirstChild() == expression) {
|
||||
expression = parent
|
||||
parent = expression.getParent()
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@ public class KotlinCompletionContributor : CompletionContributor() {
|
||||
val text = builder.toString()
|
||||
val file = JetPsiFactory(tokenBefore.getProject()).createFile(text)
|
||||
val declaration = file.getDeclarations().singleOrNull() ?: return null
|
||||
if (declaration.getTextLength() != text.length) return null
|
||||
if (declaration.getTextLength() != text.length()) return null
|
||||
val containsErrorElement = !PsiTreeUtil.processElements(file, PsiElementProcessor<PsiElement>{ it !is PsiErrorElement })
|
||||
return if (containsErrorElement) null else tail + "$"
|
||||
}
|
||||
@@ -384,7 +384,7 @@ public class KotlinCompletionContributor : CompletionContributor() {
|
||||
JetTokens.LPAR -> balance++
|
||||
JetTokens.RPAR -> balance--
|
||||
}
|
||||
current = current!!.prevLeaf()
|
||||
current = current.prevLeaf()
|
||||
}
|
||||
return balance
|
||||
}
|
||||
|
||||
+35
-33
@@ -20,7 +20,6 @@ import com.intellij.codeInsight.AutoPopupController
|
||||
import com.intellij.codeInsight.completion.InsertionContext
|
||||
import com.intellij.codeInsight.lookup.Lookup
|
||||
import com.intellij.codeInsight.lookup.LookupElement
|
||||
import com.intellij.openapi.editor.Document
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
@@ -52,11 +51,6 @@ public abstract class KotlinCallableInsertHandler : BaseDeclarationInsertHandler
|
||||
private fun addImport(context : InsertionContext, item : LookupElement) {
|
||||
PsiDocumentManager.getInstance(context.getProject()).commitAllDocuments()
|
||||
|
||||
val startOffset = context.getStartOffset()
|
||||
val element = context.getFile().findElementAt(startOffset)
|
||||
|
||||
if (element == null) return
|
||||
|
||||
val file = context.getFile()
|
||||
val o = item.getObject()
|
||||
if (file is JetFile && o is DeclarationDescriptorLookupObject) {
|
||||
@@ -77,7 +71,30 @@ public abstract class KotlinCallableInsertHandler : BaseDeclarationInsertHandler
|
||||
}
|
||||
}
|
||||
|
||||
public object KotlinPropertyInsertHandler : KotlinCallableInsertHandler()
|
||||
public object KotlinPropertyInsertHandler : KotlinCallableInsertHandler() {
|
||||
public override fun handleInsert(context: InsertionContext, item: LookupElement) {
|
||||
super.handleInsert(context, item)
|
||||
|
||||
if (context.getCompletionChar() == Lookup.REPLACE_SELECT_CHAR) {
|
||||
deleteEmptyParenthesis(context)
|
||||
}
|
||||
}
|
||||
|
||||
private fun deleteEmptyParenthesis(context: InsertionContext) {
|
||||
val psiDocumentManager = PsiDocumentManager.getInstance(context.getProject())
|
||||
psiDocumentManager.commitAllDocuments()
|
||||
psiDocumentManager.doPostponedOperationsAndUnblockDocument(context.getDocument())
|
||||
|
||||
val offset = context.getTailOffset()
|
||||
val document = context.getDocument()
|
||||
val chars = document.getCharsSequence()
|
||||
|
||||
val lParenOffset = chars.indexOfSkippingSpace('(', offset) ?: return
|
||||
val rParenOffset = chars.indexOfSkippingSpace(')', lParenOffset + 1) ?: return
|
||||
|
||||
document.deleteString(offset, rParenOffset + 1)
|
||||
}
|
||||
}
|
||||
|
||||
public enum class CaretPosition {
|
||||
IN_BRACKETS
|
||||
@@ -143,8 +160,8 @@ public class KotlinFunctionInsertHandler(val caretPosition : CaretPosition, val
|
||||
val closingBracket = if (braces) '}' else ')'
|
||||
|
||||
if (completionChar == Lookup.REPLACE_SELECT_CHAR) {
|
||||
val offset1 = skipSpaces(chars, offset)
|
||||
if (offset1 < document.getTextLength()) {
|
||||
val offset1 = chars.skipSpaces(offset)
|
||||
if (offset1 < chars.length()) {
|
||||
if (chars[offset1] == '<') {
|
||||
PsiDocumentManager.getInstance(context.getProject()).commitDocument(document)
|
||||
val token = context.getFile().findElementAt(offset1)!!
|
||||
@@ -158,9 +175,9 @@ public class KotlinFunctionInsertHandler(val caretPosition : CaretPosition, val
|
||||
}
|
||||
}
|
||||
|
||||
var openingBracketOffset = indexOfSkippingSpace(document, openingBracket, offset)
|
||||
var openingBracketOffset = chars.indexOfSkippingSpace(openingBracket, offset)
|
||||
var inBracketsShift = 0
|
||||
if (openingBracketOffset == -1) {
|
||||
if (openingBracketOffset == null) {
|
||||
if (braces) {
|
||||
if (completionChar == ' ' || completionChar == '{') {
|
||||
context.setAddCompletionChar(false)
|
||||
@@ -180,13 +197,12 @@ public class KotlinFunctionInsertHandler(val caretPosition : CaretPosition, val
|
||||
PsiDocumentManager.getInstance(context.getProject()).commitDocument(document)
|
||||
}
|
||||
|
||||
openingBracketOffset = indexOfSkippingSpace(document, openingBracket, offset)
|
||||
assert(openingBracketOffset != -1, "If there wasn't open bracket it should already have been inserted")
|
||||
openingBracketOffset = chars.indexOfSkippingSpace(openingBracket, offset)!!
|
||||
|
||||
val closeBracketOffset = chars.indexOfSkippingSpace(closingBracket, openingBracketOffset + 1)
|
||||
|
||||
val closeBracketOffset = indexOfSkippingSpace(document, closingBracket, openingBracketOffset + 1)
|
||||
val editor = context.getEditor()
|
||||
|
||||
if (shouldPlaceCaretInBrackets(completionChar) || closeBracketOffset == -1) {
|
||||
if (shouldPlaceCaretInBrackets(completionChar) || closeBracketOffset == null) {
|
||||
editor.getCaretModel().moveToOffset(openingBracketOffset + 1 + inBracketsShift)
|
||||
AutoPopupController.getInstance(context.getProject())?.autoPopupParameterInfo(editor, offsetElement)
|
||||
}
|
||||
@@ -197,7 +213,7 @@ public class KotlinFunctionInsertHandler(val caretPosition : CaretPosition, val
|
||||
PsiDocumentManager.getInstance(context.getProject()).commitDocument(document)
|
||||
|
||||
if (lambdaInfo != null && lambdaInfo.explicitParameters) {
|
||||
insertLambdaTemplate(context, TextRange(openingBracketOffset, closeBracketOffset + 1), lambdaInfo.lambdaType)
|
||||
insertLambdaTemplate(context, TextRange(openingBracketOffset, closeBracketOffset!! + 1), lambdaInfo.lambdaType)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,22 +227,8 @@ public class KotlinFunctionInsertHandler(val caretPosition : CaretPosition, val
|
||||
public val NO_PARAMETERS_HANDLER: KotlinFunctionInsertHandler = KotlinFunctionInsertHandler(CaretPosition.AFTER_BRACKETS, null)
|
||||
public val WITH_PARAMETERS_HANDLER: KotlinFunctionInsertHandler = KotlinFunctionInsertHandler(CaretPosition.IN_BRACKETS, null)
|
||||
|
||||
private fun indexOfSkippingSpace(document: Document, ch : Char, startIndex : Int) : Int {
|
||||
val text = document.getCharsSequence()
|
||||
for (i in startIndex..text.length() - 1) {
|
||||
val currentChar = text[i]
|
||||
if (ch == currentChar) return i
|
||||
if (currentChar != ' ' && currentChar != '\t') 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)
|
||||
= CodeStyleSettingsManager.getSettings(project)
|
||||
.getCustomSettings(javaClass<JetCodeStyleSettings>())!!.INSERT_WHITESPACES_IN_SIMPLE_ONE_LINE_METHOD
|
||||
private fun isInsertSpacesInOneLineFunctionEnabled(project: Project)
|
||||
= CodeStyleSettingsManager.getSettings(project).getCustomSettings(javaClass<JetCodeStyleSettings>())!!.INSERT_WHITESPACES_IN_SIMPLE_ONE_LINE_METHOD
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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.completion.handlers
|
||||
|
||||
fun CharSequence.indexOfSkippingSpace(c: Char, startIndex: Int): Int? {
|
||||
for (i in startIndex..this.length() - 1) {
|
||||
val currentChar = this[i]
|
||||
if (c == currentChar) return i
|
||||
if (currentChar != ' ' && currentChar != '\t') return null
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun CharSequence.skipSpaces(index: Int): Int
|
||||
= (index..length() - 1).firstOrNull { val c = this[it]; c != ' ' && c != '\t' } ?: this.length()
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
class C {
|
||||
val bar: Int
|
||||
}
|
||||
|
||||
fun foo(c: C) {
|
||||
val v = c.<caret>getBar()
|
||||
}
|
||||
|
||||
// ELEMENT: bar
|
||||
// CHAR: '\t'
|
||||
@@ -0,0 +1,10 @@
|
||||
class C {
|
||||
val bar: Int
|
||||
}
|
||||
|
||||
fun foo(c: C) {
|
||||
val v = c.bar<caret>
|
||||
}
|
||||
|
||||
// ELEMENT: bar
|
||||
// CHAR: '\t'
|
||||
@@ -0,0 +1,10 @@
|
||||
class C {
|
||||
val bar: Int
|
||||
}
|
||||
|
||||
fun foo(c: C) {
|
||||
val v = c.<caret>getBar(0)
|
||||
}
|
||||
|
||||
// ELEMENT: bar
|
||||
// CHAR: '\t'
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
class C {
|
||||
val bar: Int
|
||||
}
|
||||
|
||||
fun foo(c: C) {
|
||||
val v = c.bar<caret>(0)
|
||||
}
|
||||
|
||||
// ELEMENT: bar
|
||||
// CHAR: '\t'
|
||||
+12
@@ -101,6 +101,18 @@ public class BasicCompletionHandlerTestGenerated extends AbstractBasicCompletion
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ReplaceFunctionCallByProperty.kt")
|
||||
public void testReplaceFunctionCallByProperty() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/ReplaceFunctionCallByProperty.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ReplaceFunctionCallByPropertyArgs.kt")
|
||||
public void testReplaceFunctionCallByPropertyArgs() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/ReplaceFunctionCallByPropertyArgs.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("SecondTypeArg.kt")
|
||||
public void testSecondTypeArg() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/SecondTypeArg.kt");
|
||||
|
||||
Reference in New Issue
Block a user