Reformat completion.handlers
This commit is contained in:
+5
-3
@@ -21,14 +21,15 @@ import com.intellij.codeInsight.lookup.LookupElement
|
|||||||
import com.intellij.psi.PsiDocumentManager
|
import com.intellij.psi.PsiDocumentManager
|
||||||
import com.intellij.psi.util.PsiTreeUtil
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
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.core.completion.DeclarationLookupObject
|
||||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||||
import org.jetbrains.kotlin.idea.core.ShortenReferences
|
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
|
||||||
object CastReceiverInsertHandler {
|
object CastReceiverInsertHandler {
|
||||||
fun postHandleInsert(context: InsertionContext, item: LookupElement) {
|
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)
|
val qualifiedExpression = PsiTreeUtil.getParentOfType(expression, KtQualifiedExpression::class.java, true)
|
||||||
if (qualifiedExpression != null) {
|
if (qualifiedExpression != null) {
|
||||||
val receiver = qualifiedExpression.receiverExpression
|
val receiver = qualifiedExpression.receiverExpression
|
||||||
@@ -36,7 +37,8 @@ object CastReceiverInsertHandler {
|
|||||||
val descriptor = (item.`object` as? DeclarationLookupObject)?.descriptor as CallableDescriptor
|
val descriptor = (item.`object` as? DeclarationLookupObject)?.descriptor as CallableDescriptor
|
||||||
val project = context.project
|
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 fqName = IdeDescriptorRenderers.SOURCE_CODE.renderClassifierName(thisObj!!.type.constructor.declarationDescriptor!!)
|
||||||
|
|
||||||
val parentCast = KtPsiFactory(project).createExpression("(expr as $fqName)") as KtParenthesizedExpression
|
val parentCast = KtPsiFactory(project).createExpression("(expr as $fqName)") as KtParenthesizedExpression
|
||||||
|
|||||||
+8
-5
@@ -32,7 +32,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
|
|||||||
|
|
||||||
abstract class KotlinCallableInsertHandler(val callType: CallType<*>) : BaseDeclarationInsertHandler() {
|
abstract class KotlinCallableInsertHandler(val callType: CallType<*>) : BaseDeclarationInsertHandler() {
|
||||||
companion object {
|
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) {
|
override fun handleInsert(context: InsertionContext, item: LookupElement) {
|
||||||
@@ -41,7 +41,7 @@ abstract class KotlinCallableInsertHandler(val callType: CallType<*>) : BaseDecl
|
|||||||
addImport(context, item)
|
addImport(context, item)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addImport(context : InsertionContext, item : LookupElement) {
|
private fun addImport(context: InsertionContext, item: LookupElement) {
|
||||||
val psiDocumentManager = PsiDocumentManager.getInstance(context.project)
|
val psiDocumentManager = PsiDocumentManager.getInstance(context.project)
|
||||||
psiDocumentManager.commitAllDocuments()
|
psiDocumentManager.commitAllDocuments()
|
||||||
|
|
||||||
@@ -53,11 +53,14 @@ abstract class KotlinCallableInsertHandler(val callType: CallType<*>) : BaseDecl
|
|||||||
if (DescriptorUtils.isTopLevelDeclaration(descriptor) && !descriptor.isArtificialImportAliasedDescriptor) {
|
if (DescriptorUtils.isTopLevelDeclaration(descriptor) && !descriptor.isArtificialImportAliasedDescriptor) {
|
||||||
ImportInsertHelper.getInstance(context.project).importDescriptor(file, descriptor)
|
ImportInsertHelper.getInstance(context.project).importDescriptor(file, descriptor)
|
||||||
}
|
}
|
||||||
}
|
} else if (callType == CallType.DEFAULT) {
|
||||||
else if (callType == CallType.DEFAULT) {
|
|
||||||
if (descriptor.isArtificialImportAliasedDescriptor) return
|
if (descriptor.isArtificialImportAliasedDescriptor) return
|
||||||
val fqName = descriptor.importableFqName ?: 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()
|
psiDocumentManager.commitAllDocuments()
|
||||||
|
|
||||||
|
|||||||
+4
-6
@@ -25,10 +25,10 @@ import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
|||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
import org.jetbrains.kotlin.idea.completion.isAfterDot
|
import org.jetbrains.kotlin.idea.completion.isAfterDot
|
||||||
import org.jetbrains.kotlin.idea.completion.isArtificialImportAliasedDescriptor
|
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.core.completion.DeclarationLookupObject
|
||||||
import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver
|
import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver
|
||||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||||
import org.jetbrains.kotlin.idea.core.ShortenReferences
|
|
||||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||||
@@ -62,7 +62,7 @@ object KotlinClassifierInsertHandler : BaseDeclarationInsertHandler() {
|
|||||||
if (nameRef != null) {
|
if (nameRef != null) {
|
||||||
val bindingContext = nameRef.analyze(BodyResolveMode.PARTIAL)
|
val bindingContext = nameRef.analyze(BodyResolveMode.PARTIAL)
|
||||||
val target = bindingContext[BindingContext.SHORT_REFERENCE_TO_COMPANION_OBJECT, nameRef]
|
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
|
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
|
// 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 @)
|
// (but not for annotations where spaces are not allowed after @)
|
||||||
if (isAnnotation) "" else " "
|
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 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
|
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 {
|
private fun qualifiedName(lookupObject: DeclarationLookupObject): String {
|
||||||
return if (lookupObject.descriptor != null) {
|
return if (lookupObject.descriptor != null) {
|
||||||
IdeDescriptorRenderers.SOURCE_CODE.renderClassifierName(lookupObject.descriptor as ClassifierDescriptor)
|
IdeDescriptorRenderers.SOURCE_CODE.renderClassifierName(lookupObject.descriptor as ClassifierDescriptor)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
val qualifiedName = (lookupObject.psiElement as PsiClass).qualifiedName!!
|
val qualifiedName = (lookupObject.psiElement as PsiClass).qualifiedName!!
|
||||||
if (FqNameUnsafe.isValid(qualifiedName)) FqNameUnsafe(qualifiedName).render() else qualifiedName
|
if (FqNameUnsafe.isValid(qualifiedName)) FqNameUnsafe(qualifiedName).render() else qualifiedName
|
||||||
}
|
}
|
||||||
|
|||||||
+30
-25
@@ -39,12 +39,12 @@ class GenerateLambdaInfo(val lambdaType: KotlinType, val explicitParameters: Boo
|
|||||||
sealed class KotlinFunctionInsertHandler(callType: CallType<*>) : KotlinCallableInsertHandler(callType) {
|
sealed class KotlinFunctionInsertHandler(callType: CallType<*>) : KotlinCallableInsertHandler(callType) {
|
||||||
|
|
||||||
class Normal(
|
class Normal(
|
||||||
callType: CallType<*>,
|
callType: CallType<*>,
|
||||||
val inputTypeArguments: Boolean,
|
val inputTypeArguments: Boolean,
|
||||||
val inputValueArguments: Boolean,
|
val inputValueArguments: Boolean,
|
||||||
val argumentText: String = "",
|
val argumentText: String = "",
|
||||||
val lambdaInfo: GenerateLambdaInfo? = null,
|
val lambdaInfo: GenerateLambdaInfo? = null,
|
||||||
val argumentsOnly: Boolean = false
|
val argumentsOnly: Boolean = false
|
||||||
) : KotlinFunctionInsertHandler(callType) {
|
) : KotlinFunctionInsertHandler(callType) {
|
||||||
init {
|
init {
|
||||||
if (lambdaInfo != null) {
|
if (lambdaInfo != null) {
|
||||||
@@ -54,12 +54,12 @@ sealed class KotlinFunctionInsertHandler(callType: CallType<*>) : KotlinCallable
|
|||||||
|
|
||||||
//TODO: add 'data' or special annotation when supported
|
//TODO: add 'data' or special annotation when supported
|
||||||
fun copy(
|
fun copy(
|
||||||
callType: CallType<*> = this.callType,
|
callType: CallType<*> = this.callType,
|
||||||
inputTypeArguments: Boolean = this.inputTypeArguments,
|
inputTypeArguments: Boolean = this.inputTypeArguments,
|
||||||
inputValueArguments: Boolean = this.inputValueArguments,
|
inputValueArguments: Boolean = this.inputValueArguments,
|
||||||
argumentText: String = this.argumentText,
|
argumentText: String = this.argumentText,
|
||||||
lambdaInfo: GenerateLambdaInfo? = this.lambdaInfo,
|
lambdaInfo: GenerateLambdaInfo? = this.lambdaInfo,
|
||||||
argumentsOnly: Boolean = this.argumentsOnly
|
argumentsOnly: Boolean = this.argumentsOnly
|
||||||
) = Normal(callType, inputTypeArguments, inputValueArguments, argumentText, lambdaInfo, argumentsOnly)
|
) = Normal(callType, inputTypeArguments, inputValueArguments, argumentText, lambdaInfo, argumentsOnly)
|
||||||
|
|
||||||
override fun handleInsert(context: InsertionContext, item: LookupElement) {
|
override fun handleInsert(context: InsertionContext, item: LookupElement) {
|
||||||
@@ -81,7 +81,7 @@ sealed class KotlinFunctionInsertHandler(callType: CallType<*>) : KotlinCallable
|
|||||||
addArguments(context, element)
|
addArguments(context, element)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addArguments(context : InsertionContext, offsetElement : PsiElement) {
|
private fun addArguments(context: InsertionContext, offsetElement: PsiElement) {
|
||||||
val completionChar = context.completionChar
|
val completionChar = context.completionChar
|
||||||
if (completionChar == '(') { //TODO: more correct behavior related to braces type
|
if (completionChar == '(') { //TODO: more correct behavior related to braces type
|
||||||
context.setAddCompletionChar(false)
|
context.setAddCompletionChar(false)
|
||||||
@@ -98,7 +98,8 @@ sealed class KotlinFunctionInsertHandler(callType: CallType<*>) : KotlinCallable
|
|||||||
val openingBracket = if (insertLambda) '{' else '('
|
val openingBracket = if (insertLambda) '{' else '('
|
||||||
val closingBracket = 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) {
|
if (completionChar == Lookup.REPLACE_SELECT_CHAR) {
|
||||||
val offset1 = chars.skipSpaces(offset)
|
val offset1 = chars.skipSpaces(offset)
|
||||||
@@ -144,12 +145,10 @@ sealed class KotlinFunctionInsertHandler(callType: CallType<*>) : KotlinCallable
|
|||||||
if (isInsertSpacesInOneLineFunctionEnabled(project)) {
|
if (isInsertSpacesInOneLineFunctionEnabled(project)) {
|
||||||
document.insertString(offset, " { }")
|
document.insertString(offset, " { }")
|
||||||
inBracketsShift = 1
|
inBracketsShift = 1
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
document.insertString(offset, " {}")
|
document.insertString(offset, " {}")
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
document.insertString(offset, "()")
|
document.insertString(offset, "()")
|
||||||
}
|
}
|
||||||
PsiDocumentManager.getInstance(project).commitDocument(document)
|
PsiDocumentManager.getInstance(project).commitDocument(document)
|
||||||
@@ -160,8 +159,15 @@ sealed class KotlinFunctionInsertHandler(callType: CallType<*>) : KotlinCallable
|
|||||||
|
|
||||||
if (insertLambda && lambdaInfo!!.explicitParameters) {
|
if (insertLambda && lambdaInfo!!.explicitParameters) {
|
||||||
val placeholderRange = TextRange(openingBracketOffset, closeBracketOffset!! + 1)
|
val placeholderRange = TextRange(openingBracketOffset, closeBracketOffset!! + 1)
|
||||||
val explicitParameterTypes = LambdaSignatureTemplates.explicitParameterTypesRequired(context.file as KtFile, placeholderRange, lambdaInfo.lambdaType)
|
val explicitParameterTypes =
|
||||||
LambdaSignatureTemplates.insertTemplate(context, placeholderRange, lambdaInfo.lambdaType, explicitParameterTypes, signatureOnly = false)
|
LambdaSignatureTemplates.explicitParameterTypesRequired(context.file as KtFile, placeholderRange, lambdaInfo.lambdaType)
|
||||||
|
LambdaSignatureTemplates.insertTemplate(
|
||||||
|
context,
|
||||||
|
placeholderRange,
|
||||||
|
lambdaInfo.lambdaType,
|
||||||
|
explicitParameterTypes,
|
||||||
|
signatureOnly = false
|
||||||
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,8 +182,7 @@ sealed class KotlinFunctionInsertHandler(callType: CallType<*>) : KotlinCallable
|
|||||||
if (!insertLambda) {
|
if (!insertLambda) {
|
||||||
AutoPopupController.getInstance(project)?.autoPopupParameterInfo(editor, offsetElement)
|
AutoPopupController.getInstance(project)?.autoPopupParameterInfo(editor, offsetElement)
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
editor.caretModel.moveToOffset(closeBracketOffset + 1)
|
editor.caretModel.moveToOffset(closeBracketOffset + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -189,8 +194,8 @@ sealed class KotlinFunctionInsertHandler(callType: CallType<*>) : KotlinCallable
|
|||||||
return inputValueArguments || lambdaInfo != null
|
return inputValueArguments || lambdaInfo != null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isInsertSpacesInOneLineFunctionEnabled(project: Project)
|
private fun isInsertSpacesInOneLineFunctionEnabled(project: Project) =
|
||||||
= CodeStyleSettingsManager.getSettings(project).getCustomSettings(KotlinCodeStyleSettings::class.java)!!.INSERT_WHITESPACES_IN_SIMPLE_ONE_LINE_METHOD
|
CodeStyleSettingsManager.getSettings(project).getCustomSettings(KotlinCodeStyleSettings::class.java)!!.INSERT_WHITESPACES_IN_SIMPLE_ONE_LINE_METHOD
|
||||||
}
|
}
|
||||||
|
|
||||||
object Infix : KotlinFunctionInsertHandler(CallType.INFIX) {
|
object Infix : KotlinFunctionInsertHandler(CallType.INFIX) {
|
||||||
@@ -205,7 +210,7 @@ sealed class KotlinFunctionInsertHandler(callType: CallType<*>) : KotlinCallable
|
|||||||
context.document.insertString(tailOffset, " ")
|
context.document.insertString(tailOffset, " ")
|
||||||
context.editor.caretModel.moveToOffset(tailOffset + 1)
|
context.editor.caretModel.moveToOffset(tailOffset + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class OnlyName(callType: CallType<*>) : KotlinFunctionInsertHandler(callType)
|
class OnlyName(callType: CallType<*>) : KotlinFunctionInsertHandler(callType)
|
||||||
|
|
||||||
|
|||||||
+7
-5
@@ -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.smart.SmartCompletion
|
||||||
import org.jetbrains.kotlin.idea.completion.tryGetOffset
|
import org.jetbrains.kotlin.idea.completion.tryGetOffset
|
||||||
|
|
||||||
class WithTailInsertHandler(val tailText: String,
|
class WithTailInsertHandler(
|
||||||
val spaceBefore: Boolean,
|
val tailText: String,
|
||||||
val spaceAfter: Boolean,
|
val spaceBefore: Boolean,
|
||||||
val overwriteText: Boolean = true) : InsertHandler<LookupElement> {
|
val spaceAfter: Boolean,
|
||||||
|
val overwriteText: Boolean = true
|
||||||
|
) : InsertHandler<LookupElement> {
|
||||||
override fun handleInsert(context: InsertionContext, item: LookupElement) {
|
override fun handleInsert(context: InsertionContext, item: LookupElement) {
|
||||||
item.handleInsert(context)
|
item.handleInsert(context)
|
||||||
postHandleInsert(context, item)
|
postHandleInsert(context, item)
|
||||||
@@ -49,7 +51,7 @@ class WithTailInsertHandler(val tailText: String,
|
|||||||
var tailOffset = context.tailOffset
|
var tailOffset = context.tailOffset
|
||||||
if (completionChar == Lookup.REPLACE_SELECT_CHAR && item.getUserData(KEEP_OLD_ARGUMENT_LIST_ON_TAB_KEY) != null) {
|
if (completionChar == Lookup.REPLACE_SELECT_CHAR && item.getUserData(KEEP_OLD_ARGUMENT_LIST_ON_TAB_KEY) != null) {
|
||||||
context.offsetMap.tryGetOffset(SmartCompletion.OLD_ARGUMENTS_REPLACEMENT_OFFSET)
|
context.offsetMap.tryGetOffset(SmartCompletion.OLD_ARGUMENTS_REPLACEMENT_OFFSET)
|
||||||
?.let { tailOffset = it }
|
?.let { tailOffset = it }
|
||||||
}
|
}
|
||||||
|
|
||||||
val moveCaret = context.editor.caretModel.offset == tailOffset
|
val moveCaret = context.editor.caretModel.offset == tailOffset
|
||||||
|
|||||||
+44
-36
@@ -90,21 +90,21 @@ fun CharSequence.indexOfSkippingSpace(c: Char, startIndex: Int): Int? {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun CharSequence.skipSpaces(index: Int): Int
|
fun CharSequence.skipSpaces(index: Int): Int = (index..length - 1).firstOrNull { val c = this[it]; c != ' ' && c != '\t' } ?: this.length
|
||||||
= (index..length - 1).firstOrNull { val c = this[it]; c != ' ' && c != '\t' } ?: this.length
|
|
||||||
|
|
||||||
fun CharSequence.skipSpacesAndLineBreaks(index: Int): Int
|
fun CharSequence.skipSpacesAndLineBreaks(index: Int): Int =
|
||||||
= (index..length - 1).firstOrNull { val c = this[it]; c != ' ' && c != '\t' && c != '\n' && c != '\r' } ?: this.length
|
(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 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(
|
fun createKeywordConstructLookupElement(
|
||||||
project: Project,
|
project: Project,
|
||||||
keyword: String,
|
keyword: String,
|
||||||
fileTextToReformat: String,
|
fileTextToReformat: String,
|
||||||
trimSpacesAroundCaret: Boolean = false
|
trimSpacesAroundCaret: Boolean = false
|
||||||
): LookupElement {
|
): LookupElement {
|
||||||
val file = KtPsiFactory(project).createFile(fileTextToReformat)
|
val file = KtPsiFactory(project).createFile(fileTextToReformat)
|
||||||
CodeStyleManager.getInstance(project).reformat(file)
|
CodeStyleManager.getInstance(project).reformat(file)
|
||||||
@@ -133,46 +133,54 @@ fun createKeywordConstructLookupElement(
|
|||||||
tailAfterCaret = tailAfterCaret.unindent(indent)
|
tailAfterCaret = tailAfterCaret.unindent(indent)
|
||||||
|
|
||||||
val tailText = (if (tailBeforeCaret.contains('\n')) tailBeforeCaret.replace("\n", "").trimEnd() else tailBeforeCaret) +
|
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)
|
return LookupElementBuilder.create(KeywordLookupObject(), keyword)
|
||||||
.bold()
|
.bold()
|
||||||
.withTailText(tailText)
|
.withTailText(tailText)
|
||||||
.withInsertHandler { insertionContext, _ ->
|
.withInsertHandler { insertionContext, _ ->
|
||||||
if (insertionContext.completionChar == Lookup.NORMAL_SELECT_CHAR ||
|
if (insertionContext.completionChar == Lookup.NORMAL_SELECT_CHAR ||
|
||||||
insertionContext.completionChar == Lookup.REPLACE_SELECT_CHAR ||
|
insertionContext.completionChar == Lookup.REPLACE_SELECT_CHAR ||
|
||||||
insertionContext.completionChar == Lookup.AUTO_INSERT_SELECT_CHAR) {
|
insertionContext.completionChar == Lookup.AUTO_INSERT_SELECT_CHAR
|
||||||
|
) {
|
||||||
|
|
||||||
val offset = insertionContext.tailOffset
|
val offset = insertionContext.tailOffset
|
||||||
val newIndent = detectIndent(insertionContext.document.charsSequence, offset - keyword.length)
|
val newIndent = detectIndent(insertionContext.document.charsSequence, offset - keyword.length)
|
||||||
|
|
||||||
val beforeCaret = tailBeforeCaret.indentLinesAfterFirst(newIndent)
|
val beforeCaret = tailBeforeCaret.indentLinesAfterFirst(newIndent)
|
||||||
val afterCaret = tailAfterCaret.indentLinesAfterFirst(newIndent)
|
val afterCaret = tailAfterCaret.indentLinesAfterFirst(newIndent)
|
||||||
|
|
||||||
val element = insertionContext.file.findElementAt(offset)
|
val element = insertionContext.file.findElementAt(offset)
|
||||||
|
|
||||||
val sibling = when {
|
val sibling = when {
|
||||||
element !is PsiWhiteSpace -> element
|
element !is PsiWhiteSpace -> element
|
||||||
element.textContains('\n') -> null
|
element.textContains('\n') -> null
|
||||||
else -> element.getNextSiblingIgnoringWhitespace(true)
|
else -> element.getNextSiblingIgnoringWhitespace(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sibling != null && beforeCaret.trimStart().startsWith(insertionContext.document.getText(TextRange.from(sibling.startOffset, 1)))) {
|
if (sibling != null && beforeCaret.trimStart().startsWith(
|
||||||
insertionContext.editor.moveCaret(sibling.startOffset + 1)
|
insertionContext.document.getText(
|
||||||
}
|
TextRange.from(
|
||||||
else {
|
sibling.startOffset,
|
||||||
insertionContext.document.insertString(offset, beforeCaret + afterCaret)
|
1
|
||||||
insertionContext.editor.moveCaret(offset + beforeCaret.length)
|
)
|
||||||
}
|
)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
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 {
|
private fun detectIndent(text: CharSequence, offset: Int): String {
|
||||||
return text.substring(0, offset)
|
return text.substring(0, offset)
|
||||||
.substringAfterLast('\n')
|
.substringAfterLast('\n')
|
||||||
.takeWhile(Char::isWhitespace)
|
.takeWhile(Char::isWhitespace)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun String.indentLinesAfterFirst(indent: String): String {
|
private fun String.indentLinesAfterFirst(indent: String): String {
|
||||||
|
|||||||
Reference in New Issue
Block a user