From b1cf98d82a02a549dd04cd9fc698558350f42551 Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Thu, 15 Nov 2018 13:06:47 +0300 Subject: [PATCH] Reformat completion.handlers --- .../handlers/CastReceiverInsertHandler.kt | 8 +- .../handlers/KotlinCallableInsertHandler.kt | 13 +-- .../handlers/KotlinClassifierInsertHandler.kt | 12 ++- .../handlers/KotlinFunctionInsertHandler.kt | 55 +++++++------ .../handlers/WithTailInsertHandler.kt | 12 +-- .../idea/completion/handlers/handlerUtils.kt | 80 ++++++++++--------- 6 files changed, 99 insertions(+), 81 deletions(-) diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/CastReceiverInsertHandler.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/CastReceiverInsertHandler.kt index 37ee3c3fc5a..7c024d5d2b1 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/CastReceiverInsertHandler.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/CastReceiverInsertHandler.kt @@ -21,14 +21,15 @@ import com.intellij.codeInsight.lookup.LookupElement import com.intellij.psi.PsiDocumentManager import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.idea.core.ShortenReferences import org.jetbrains.kotlin.idea.core.completion.DeclarationLookupObject import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers -import org.jetbrains.kotlin.idea.core.ShortenReferences import org.jetbrains.kotlin.psi.* object CastReceiverInsertHandler { fun postHandleInsert(context: InsertionContext, item: LookupElement) { - val expression = PsiTreeUtil.findElementOfClassAtOffset(context.file, context.startOffset, KtSimpleNameExpression::class.java, false) + val expression = + PsiTreeUtil.findElementOfClassAtOffset(context.file, context.startOffset, KtSimpleNameExpression::class.java, false) val qualifiedExpression = PsiTreeUtil.getParentOfType(expression, KtQualifiedExpression::class.java, true) if (qualifiedExpression != null) { val receiver = qualifiedExpression.receiverExpression @@ -36,7 +37,8 @@ object CastReceiverInsertHandler { val descriptor = (item.`object` as? DeclarationLookupObject)?.descriptor as CallableDescriptor val project = context.project - val thisObj = if (descriptor.extensionReceiverParameter != null) descriptor.extensionReceiverParameter else descriptor.dispatchReceiverParameter + val thisObj = + if (descriptor.extensionReceiverParameter != null) descriptor.extensionReceiverParameter else descriptor.dispatchReceiverParameter val fqName = IdeDescriptorRenderers.SOURCE_CODE.renderClassifierName(thisObj!!.type.constructor.declarationDescriptor!!) val parentCast = KtPsiFactory(project).createExpression("(expr as $fqName)") as KtParenthesizedExpression diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinCallableInsertHandler.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinCallableInsertHandler.kt index 5349d28d6e6..182194898dc 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinCallableInsertHandler.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinCallableInsertHandler.kt @@ -32,7 +32,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils abstract class KotlinCallableInsertHandler(val callType: CallType<*>) : BaseDeclarationInsertHandler() { companion object { - private val shortenReferences = ShortenReferences({ ShortenReferences.Options.DEFAULT.copy(dropBracesInStringTemplates = false)}) + private val shortenReferences = ShortenReferences({ ShortenReferences.Options.DEFAULT.copy(dropBracesInStringTemplates = false) }) } override fun handleInsert(context: InsertionContext, item: LookupElement) { @@ -41,7 +41,7 @@ abstract class KotlinCallableInsertHandler(val callType: CallType<*>) : BaseDecl addImport(context, item) } - private fun addImport(context : InsertionContext, item : LookupElement) { + private fun addImport(context: InsertionContext, item: LookupElement) { val psiDocumentManager = PsiDocumentManager.getInstance(context.project) psiDocumentManager.commitAllDocuments() @@ -53,11 +53,14 @@ abstract class KotlinCallableInsertHandler(val callType: CallType<*>) : BaseDecl if (DescriptorUtils.isTopLevelDeclaration(descriptor) && !descriptor.isArtificialImportAliasedDescriptor) { ImportInsertHelper.getInstance(context.project).importDescriptor(file, descriptor) } - } - else if (callType == CallType.DEFAULT) { + } else if (callType == CallType.DEFAULT) { if (descriptor.isArtificialImportAliasedDescriptor) return val fqName = descriptor.importableFqName ?: return - context.document.replaceString(context.startOffset, context.tailOffset, fqName.render() + " ") // insert space after for correct parsing + context.document.replaceString( + context.startOffset, + context.tailOffset, + fqName.render() + " " + ) // insert space after for correct parsing psiDocumentManager.commitAllDocuments() diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinClassifierInsertHandler.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinClassifierInsertHandler.kt index a78bd25d90a..c14ba4af9cc 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinClassifierInsertHandler.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinClassifierInsertHandler.kt @@ -25,10 +25,10 @@ import org.jetbrains.kotlin.descriptors.ClassifierDescriptor import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.completion.isAfterDot import org.jetbrains.kotlin.idea.completion.isArtificialImportAliasedDescriptor +import org.jetbrains.kotlin.idea.core.ShortenReferences import org.jetbrains.kotlin.idea.core.completion.DeclarationLookupObject import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers -import org.jetbrains.kotlin.idea.core.ShortenReferences import org.jetbrains.kotlin.name.FqNameUnsafe import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtNameReferenceExpression @@ -53,7 +53,7 @@ object KotlinClassifierInsertHandler : BaseDeclarationInsertHandler() { val lookupObject = item.`object` as DeclarationLookupObject if (lookupObject.descriptor?.isArtificialImportAliasedDescriptor == true) return // never need to insert import or use qualified name for import-aliased class - + val qualifiedName = qualifiedName(lookupObject) // first try to resolve short name for faster handling @@ -62,7 +62,7 @@ object KotlinClassifierInsertHandler : BaseDeclarationInsertHandler() { if (nameRef != null) { val bindingContext = nameRef.analyze(BodyResolveMode.PARTIAL) val target = bindingContext[BindingContext.SHORT_REFERENCE_TO_COMPANION_OBJECT, nameRef] - ?: bindingContext[BindingContext.REFERENCE_TARGET, nameRef] as? ClassDescriptor + ?: bindingContext[BindingContext.REFERENCE_TARGET, nameRef] as? ClassDescriptor if (target != null && IdeDescriptorRenderers.SOURCE_CODE.renderClassifierName(target) == qualifiedName) return } @@ -71,8 +71,7 @@ object KotlinClassifierInsertHandler : BaseDeclarationInsertHandler() { // we insert space so that any preceding spaces inserted by formatter on reference shortening are deleted // (but not for annotations where spaces are not allowed after @) if (isAnnotation) "" else " " - } - else { + } else { "$;val v:" // if we have no reference in the current context we have a more complicated prefix to get one } val tempSuffix = ".xxx" // we add "xxx" after dot because of KT-9606 @@ -99,8 +98,7 @@ object KotlinClassifierInsertHandler : BaseDeclarationInsertHandler() { private fun qualifiedName(lookupObject: DeclarationLookupObject): String { return if (lookupObject.descriptor != null) { IdeDescriptorRenderers.SOURCE_CODE.renderClassifierName(lookupObject.descriptor as ClassifierDescriptor) - } - else { + } else { val qualifiedName = (lookupObject.psiElement as PsiClass).qualifiedName!! if (FqNameUnsafe.isValid(qualifiedName)) FqNameUnsafe(qualifiedName).render() else qualifiedName } diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinFunctionInsertHandler.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinFunctionInsertHandler.kt index 825fdeac35f..b42da892fda 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinFunctionInsertHandler.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinFunctionInsertHandler.kt @@ -39,12 +39,12 @@ class GenerateLambdaInfo(val lambdaType: KotlinType, val explicitParameters: Boo sealed class KotlinFunctionInsertHandler(callType: CallType<*>) : KotlinCallableInsertHandler(callType) { class Normal( - callType: CallType<*>, - val inputTypeArguments: Boolean, - val inputValueArguments: Boolean, - val argumentText: String = "", - val lambdaInfo: GenerateLambdaInfo? = null, - val argumentsOnly: Boolean = false + callType: CallType<*>, + val inputTypeArguments: Boolean, + val inputValueArguments: Boolean, + val argumentText: String = "", + val lambdaInfo: GenerateLambdaInfo? = null, + val argumentsOnly: Boolean = false ) : KotlinFunctionInsertHandler(callType) { init { if (lambdaInfo != null) { @@ -54,12 +54,12 @@ sealed class KotlinFunctionInsertHandler(callType: CallType<*>) : KotlinCallable //TODO: add 'data' or special annotation when supported fun copy( - callType: CallType<*> = this.callType, - inputTypeArguments: Boolean = this.inputTypeArguments, - inputValueArguments: Boolean = this.inputValueArguments, - argumentText: String = this.argumentText, - lambdaInfo: GenerateLambdaInfo? = this.lambdaInfo, - argumentsOnly: Boolean = this.argumentsOnly + callType: CallType<*> = this.callType, + inputTypeArguments: Boolean = this.inputTypeArguments, + inputValueArguments: Boolean = this.inputValueArguments, + argumentText: String = this.argumentText, + lambdaInfo: GenerateLambdaInfo? = this.lambdaInfo, + argumentsOnly: Boolean = this.argumentsOnly ) = Normal(callType, inputTypeArguments, inputValueArguments, argumentText, lambdaInfo, argumentsOnly) override fun handleInsert(context: InsertionContext, item: LookupElement) { @@ -81,7 +81,7 @@ sealed class KotlinFunctionInsertHandler(callType: CallType<*>) : KotlinCallable addArguments(context, element) } - private fun addArguments(context : InsertionContext, offsetElement : PsiElement) { + private fun addArguments(context: InsertionContext, offsetElement: PsiElement) { val completionChar = context.completionChar if (completionChar == '(') { //TODO: more correct behavior related to braces type context.setAddCompletionChar(false) @@ -98,7 +98,8 @@ sealed class KotlinFunctionInsertHandler(callType: CallType<*>) : KotlinCallable val openingBracket = if (insertLambda) '{' else '(' val closingBracket = if (insertLambda) '}' else ')' - var insertTypeArguments = inputTypeArguments && (completionChar == '\n' || completionChar == '\r' || completionChar == Lookup.REPLACE_SELECT_CHAR) + var insertTypeArguments = + inputTypeArguments && (completionChar == '\n' || completionChar == '\r' || completionChar == Lookup.REPLACE_SELECT_CHAR) if (completionChar == Lookup.REPLACE_SELECT_CHAR) { val offset1 = chars.skipSpaces(offset) @@ -144,12 +145,10 @@ sealed class KotlinFunctionInsertHandler(callType: CallType<*>) : KotlinCallable if (isInsertSpacesInOneLineFunctionEnabled(project)) { document.insertString(offset, " { }") inBracketsShift = 1 - } - else { + } else { document.insertString(offset, " {}") } - } - else { + } else { document.insertString(offset, "()") } PsiDocumentManager.getInstance(project).commitDocument(document) @@ -160,8 +159,15 @@ sealed class KotlinFunctionInsertHandler(callType: CallType<*>) : KotlinCallable if (insertLambda && lambdaInfo!!.explicitParameters) { val placeholderRange = TextRange(openingBracketOffset, closeBracketOffset!! + 1) - val explicitParameterTypes = LambdaSignatureTemplates.explicitParameterTypesRequired(context.file as KtFile, placeholderRange, lambdaInfo.lambdaType) - LambdaSignatureTemplates.insertTemplate(context, placeholderRange, lambdaInfo.lambdaType, explicitParameterTypes, signatureOnly = false) + val explicitParameterTypes = + LambdaSignatureTemplates.explicitParameterTypesRequired(context.file as KtFile, placeholderRange, lambdaInfo.lambdaType) + LambdaSignatureTemplates.insertTemplate( + context, + placeholderRange, + lambdaInfo.lambdaType, + explicitParameterTypes, + signatureOnly = false + ) return } @@ -176,8 +182,7 @@ sealed class KotlinFunctionInsertHandler(callType: CallType<*>) : KotlinCallable if (!insertLambda) { AutoPopupController.getInstance(project)?.autoPopupParameterInfo(editor, offsetElement) } - } - else { + } else { editor.caretModel.moveToOffset(closeBracketOffset + 1) } } @@ -189,8 +194,8 @@ sealed class KotlinFunctionInsertHandler(callType: CallType<*>) : KotlinCallable return inputValueArguments || lambdaInfo != null } - private fun isInsertSpacesInOneLineFunctionEnabled(project: Project) - = CodeStyleSettingsManager.getSettings(project).getCustomSettings(KotlinCodeStyleSettings::class.java)!!.INSERT_WHITESPACES_IN_SIMPLE_ONE_LINE_METHOD + private fun isInsertSpacesInOneLineFunctionEnabled(project: Project) = + CodeStyleSettingsManager.getSettings(project).getCustomSettings(KotlinCodeStyleSettings::class.java)!!.INSERT_WHITESPACES_IN_SIMPLE_ONE_LINE_METHOD } object Infix : KotlinFunctionInsertHandler(CallType.INFIX) { @@ -205,7 +210,7 @@ sealed class KotlinFunctionInsertHandler(callType: CallType<*>) : KotlinCallable context.document.insertString(tailOffset, " ") context.editor.caretModel.moveToOffset(tailOffset + 1) } - } + } class OnlyName(callType: CallType<*>) : KotlinFunctionInsertHandler(callType) diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/WithTailInsertHandler.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/WithTailInsertHandler.kt index f890e63bf76..ad9bfc2a8a1 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/WithTailInsertHandler.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/WithTailInsertHandler.kt @@ -27,10 +27,12 @@ import org.jetbrains.kotlin.idea.completion.KEEP_OLD_ARGUMENT_LIST_ON_TAB_KEY import org.jetbrains.kotlin.idea.completion.smart.SmartCompletion import org.jetbrains.kotlin.idea.completion.tryGetOffset -class WithTailInsertHandler(val tailText: String, - val spaceBefore: Boolean, - val spaceAfter: Boolean, - val overwriteText: Boolean = true) : InsertHandler { +class WithTailInsertHandler( + val tailText: String, + val spaceBefore: Boolean, + val spaceAfter: Boolean, + val overwriteText: Boolean = true +) : InsertHandler { override fun handleInsert(context: InsertionContext, item: LookupElement) { item.handleInsert(context) postHandleInsert(context, item) @@ -49,7 +51,7 @@ class WithTailInsertHandler(val tailText: String, var tailOffset = context.tailOffset if (completionChar == Lookup.REPLACE_SELECT_CHAR && item.getUserData(KEEP_OLD_ARGUMENT_LIST_ON_TAB_KEY) != null) { context.offsetMap.tryGetOffset(SmartCompletion.OLD_ARGUMENTS_REPLACEMENT_OFFSET) - ?.let { tailOffset = it } + ?.let { tailOffset = it } } val moveCaret = context.editor.caretModel.offset == tailOffset diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/handlerUtils.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/handlerUtils.kt index 769e4871827..e552ee252ed 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/handlerUtils.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/handlerUtils.kt @@ -90,21 +90,21 @@ fun CharSequence.indexOfSkippingSpace(c: Char, startIndex: Int): Int? { return null } -fun CharSequence.skipSpaces(index: Int): Int - = (index..length - 1).firstOrNull { val c = this[it]; c != ' ' && c != '\t' } ?: this.length +fun CharSequence.skipSpaces(index: Int): Int = (index..length - 1).firstOrNull { val c = this[it]; c != ' ' && c != '\t' } ?: this.length -fun CharSequence.skipSpacesAndLineBreaks(index: Int): Int - = (index..length - 1).firstOrNull { val c = this[it]; c != ' ' && c != '\t' && c != '\n' && c != '\r' } ?: this.length +fun CharSequence.skipSpacesAndLineBreaks(index: Int): Int = + (index..length - 1).firstOrNull { val c = this[it]; c != ' ' && c != '\t' && c != '\n' && c != '\r' } ?: this.length fun CharSequence.isCharAt(offset: Int, c: Char) = offset < length && this[offset] == c -fun Document.isTextAt(offset: Int, text: String) = offset + text.length <= textLength && getText(TextRange(offset, offset + text.length)) == text +fun Document.isTextAt(offset: Int, text: String) = + offset + text.length <= textLength && getText(TextRange(offset, offset + text.length)) == text fun createKeywordConstructLookupElement( - project: Project, - keyword: String, - fileTextToReformat: String, - trimSpacesAroundCaret: Boolean = false + project: Project, + keyword: String, + fileTextToReformat: String, + trimSpacesAroundCaret: Boolean = false ): LookupElement { val file = KtPsiFactory(project).createFile(fileTextToReformat) CodeStyleManager.getInstance(project).reformat(file) @@ -133,46 +133,54 @@ fun createKeywordConstructLookupElement( tailAfterCaret = tailAfterCaret.unindent(indent) val tailText = (if (tailBeforeCaret.contains('\n')) tailBeforeCaret.replace("\n", "").trimEnd() else tailBeforeCaret) + - "..." + - (if (tailAfterCaret.contains('\n')) tailAfterCaret.replace("\n", "").trimStart() else tailAfterCaret) + "..." + + (if (tailAfterCaret.contains('\n')) tailAfterCaret.replace("\n", "").trimStart() else tailAfterCaret) return LookupElementBuilder.create(KeywordLookupObject(), keyword) - .bold() - .withTailText(tailText) - .withInsertHandler { insertionContext, _ -> - if (insertionContext.completionChar == Lookup.NORMAL_SELECT_CHAR || - insertionContext.completionChar == Lookup.REPLACE_SELECT_CHAR || - insertionContext.completionChar == Lookup.AUTO_INSERT_SELECT_CHAR) { + .bold() + .withTailText(tailText) + .withInsertHandler { insertionContext, _ -> + if (insertionContext.completionChar == Lookup.NORMAL_SELECT_CHAR || + insertionContext.completionChar == Lookup.REPLACE_SELECT_CHAR || + insertionContext.completionChar == Lookup.AUTO_INSERT_SELECT_CHAR + ) { - val offset = insertionContext.tailOffset - val newIndent = detectIndent(insertionContext.document.charsSequence, offset - keyword.length) + val offset = insertionContext.tailOffset + val newIndent = detectIndent(insertionContext.document.charsSequence, offset - keyword.length) - val beforeCaret = tailBeforeCaret.indentLinesAfterFirst(newIndent) - val afterCaret = tailAfterCaret.indentLinesAfterFirst(newIndent) + val beforeCaret = tailBeforeCaret.indentLinesAfterFirst(newIndent) + val afterCaret = tailAfterCaret.indentLinesAfterFirst(newIndent) - val element = insertionContext.file.findElementAt(offset) + val element = insertionContext.file.findElementAt(offset) - val sibling = when { - element !is PsiWhiteSpace -> element - element.textContains('\n') -> null - else -> element.getNextSiblingIgnoringWhitespace(true) - } + val sibling = when { + element !is PsiWhiteSpace -> element + element.textContains('\n') -> null + else -> element.getNextSiblingIgnoringWhitespace(true) + } - if (sibling != null && beforeCaret.trimStart().startsWith(insertionContext.document.getText(TextRange.from(sibling.startOffset, 1)))) { - insertionContext.editor.moveCaret(sibling.startOffset + 1) - } - else { - insertionContext.document.insertString(offset, beforeCaret + afterCaret) - insertionContext.editor.moveCaret(offset + beforeCaret.length) - } + if (sibling != null && beforeCaret.trimStart().startsWith( + insertionContext.document.getText( + TextRange.from( + sibling.startOffset, + 1 + ) + ) + ) + ) { + insertionContext.editor.moveCaret(sibling.startOffset + 1) + } else { + insertionContext.document.insertString(offset, beforeCaret + afterCaret) + insertionContext.editor.moveCaret(offset + beforeCaret.length) } } + } } private fun detectIndent(text: CharSequence, offset: Int): String { return text.substring(0, offset) - .substringAfterLast('\n') - .takeWhile(Char::isWhitespace) + .substringAfterLast('\n') + .takeWhile(Char::isWhitespace) } private fun String.indentLinesAfterFirst(indent: String): String {