Minor: Move around some functions
This commit is contained in:
@@ -18,14 +18,16 @@ package org.jetbrains.kotlin.idea.quickfix
|
|||||||
|
|
||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.intellij.openapi.editor.ScrollType
|
import com.intellij.openapi.editor.ScrollType
|
||||||
|
import com.intellij.openapi.util.text.StringUtil
|
||||||
import com.intellij.psi.PsiDocumentManager
|
import com.intellij.psi.PsiDocumentManager
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiWhiteSpace
|
import com.intellij.psi.PsiWhiteSpace
|
||||||
import com.intellij.psi.SmartPointerManager
|
import com.intellij.psi.SmartPointerManager
|
||||||
import org.jetbrains.kotlin.psi.JetBlockExpression
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
import org.jetbrains.kotlin.psi.JetDeclarationWithBody
|
import com.intellij.util.SmartList
|
||||||
import org.jetbrains.kotlin.psi.JetProperty
|
import org.jetbrains.kotlin.idea.util.ShortenReferences
|
||||||
import org.jetbrains.kotlin.psi.JetWithExpressionInitializer
|
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.siblings
|
import org.jetbrains.kotlin.psi.psiUtil.siblings
|
||||||
|
|
||||||
public fun moveCaretIntoGeneratedElement(editor: Editor, element: PsiElement) {
|
public fun moveCaretIntoGeneratedElement(editor: Editor, element: PsiElement) {
|
||||||
@@ -96,3 +98,85 @@ public fun Editor.moveCaret(offset: Int, scrollType: ScrollType = ScrollType.REL
|
|||||||
getCaretModel().moveToOffset(offset)
|
getCaretModel().moveToOffset(offset)
|
||||||
getScrollingModel().scrollToCaret(scrollType)
|
getScrollingModel().scrollToCaret(scrollType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun findInsertAfterAnchor(editor: Editor, body: JetClassBody): PsiElement? {
|
||||||
|
val afterAnchor = body.lBrace ?: return null
|
||||||
|
|
||||||
|
val offset = editor.caretModel.offset
|
||||||
|
val offsetCursorElement = PsiTreeUtil.findFirstParent(body.containingFile.findElementAt(offset)) {
|
||||||
|
it.parent == body
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offsetCursorElement is PsiWhiteSpace) {
|
||||||
|
return removeAfterOffset(offset, offsetCursorElement)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offsetCursorElement != null && offsetCursorElement != body.rBrace) {
|
||||||
|
return offsetCursorElement
|
||||||
|
}
|
||||||
|
|
||||||
|
return afterAnchor
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun removeAfterOffset(offset: Int, whiteSpace: PsiWhiteSpace): PsiElement {
|
||||||
|
val spaceNode = whiteSpace.node
|
||||||
|
if (spaceNode.textRange.contains(offset)) {
|
||||||
|
var beforeWhiteSpaceText = spaceNode.text.substring(0, offset - spaceNode.startOffset)
|
||||||
|
if (!StringUtil.containsLineBreak(beforeWhiteSpaceText)) {
|
||||||
|
// Prevent insertion on same line
|
||||||
|
beforeWhiteSpaceText += "\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
val factory = JetPsiFactory(whiteSpace.project)
|
||||||
|
|
||||||
|
val insertAfter = whiteSpace.prevSibling
|
||||||
|
whiteSpace.delete()
|
||||||
|
|
||||||
|
val beforeSpace = factory.createWhiteSpace(beforeWhiteSpaceText)
|
||||||
|
insertAfter.parent.addAfter(beforeSpace, insertAfter)
|
||||||
|
|
||||||
|
return insertAfter.nextSibling
|
||||||
|
}
|
||||||
|
|
||||||
|
return whiteSpace
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun <T : JetDeclaration> generateMembers(
|
||||||
|
editor: Editor,
|
||||||
|
classOrObject: JetClassOrObject,
|
||||||
|
generators: Collection<() -> T>
|
||||||
|
): List<T> {
|
||||||
|
val insertedMembers = SmartList<T>()
|
||||||
|
return runWriteAction<List<T>> {
|
||||||
|
if (generators.isEmpty()) return@runWriteAction emptyList()
|
||||||
|
|
||||||
|
val body = classOrObject.getOrCreateBody()
|
||||||
|
|
||||||
|
var afterAnchor = findInsertAfterAnchor(editor, body) ?: return@runWriteAction emptyList()
|
||||||
|
|
||||||
|
var firstGenerated: PsiElement? = null
|
||||||
|
|
||||||
|
for (generator in generators) {
|
||||||
|
val member = generator()
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
val added = body.addAfter(member, afterAnchor) as T
|
||||||
|
|
||||||
|
if (firstGenerated == null) {
|
||||||
|
firstGenerated = added
|
||||||
|
}
|
||||||
|
|
||||||
|
afterAnchor = added
|
||||||
|
insertedMembers.add(added)
|
||||||
|
}
|
||||||
|
|
||||||
|
ShortenReferences.DEFAULT.process(insertedMembers)
|
||||||
|
|
||||||
|
moveCaretIntoGeneratedElement(editor, firstGenerated!!)
|
||||||
|
|
||||||
|
insertedMembers
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun <T : JetDeclaration> generateMember(editor: Editor, classOrObject: JetClassOrObject, declaration: T): T {
|
||||||
|
return generateMembers(editor, classOrObject, listOf({ declaration })).single()
|
||||||
|
}
|
||||||
+5
-78
@@ -22,20 +22,14 @@ import com.intellij.lang.LanguageCodeInsightActionHandler
|
|||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.ui.DialogWrapper
|
import com.intellij.openapi.ui.DialogWrapper
|
||||||
import com.intellij.openapi.util.text.StringUtil
|
|
||||||
import com.intellij.psi.PsiDocumentManager
|
import com.intellij.psi.PsiDocumentManager
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
import com.intellij.psi.PsiWhiteSpace
|
|
||||||
import com.intellij.psi.util.PsiTreeUtil
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||||
import org.jetbrains.kotlin.idea.quickfix.moveCaretIntoGeneratedElement
|
import org.jetbrains.kotlin.idea.quickfix.generateMembers
|
||||||
import org.jetbrains.kotlin.idea.util.ShortenReferences
|
import org.jetbrains.kotlin.psi.JetClassOrObject
|
||||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
import org.jetbrains.kotlin.psi.JetFile
|
||||||
import org.jetbrains.kotlin.psi.*
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
public abstract class OverrideImplementMembersHandler : LanguageCodeInsightActionHandler {
|
public abstract class OverrideImplementMembersHandler : LanguageCodeInsightActionHandler {
|
||||||
|
|
||||||
@@ -95,75 +89,8 @@ public abstract class OverrideImplementMembersHandler : LanguageCodeInsightActio
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
public fun generateMembers(editor: Editor, classOrObject: JetClassOrObject, selectedElements: Collection<OverrideMemberChooserObject>) {
|
public fun generateMembers(editor: Editor, classOrObject: JetClassOrObject, selectedElements: Collection<OverrideMemberChooserObject>) {
|
||||||
runWriteAction {
|
val project = classOrObject.project
|
||||||
if (selectedElements.isEmpty()) return@runWriteAction
|
generateMembers(editor, classOrObject, selectedElements.map { chooser -> { chooser.generateMember(project) } })
|
||||||
|
|
||||||
val body = classOrObject.getOrCreateBody()
|
|
||||||
|
|
||||||
var afterAnchor = findInsertAfterAnchor(editor, body) ?: return@runWriteAction
|
|
||||||
|
|
||||||
var firstGenerated: PsiElement? = null
|
|
||||||
|
|
||||||
val project = classOrObject.project
|
|
||||||
val insertedMembers = ArrayList<JetCallableDeclaration>()
|
|
||||||
for (memberObject in selectedElements) {
|
|
||||||
val member = memberObject.generateMember(project)
|
|
||||||
val added = body.addAfter(member, afterAnchor) as JetCallableDeclaration
|
|
||||||
|
|
||||||
if (firstGenerated == null) {
|
|
||||||
firstGenerated = added
|
|
||||||
}
|
|
||||||
|
|
||||||
afterAnchor = added
|
|
||||||
insertedMembers.add(added)
|
|
||||||
}
|
|
||||||
|
|
||||||
ShortenReferences.DEFAULT.process(insertedMembers)
|
|
||||||
|
|
||||||
moveCaretIntoGeneratedElement(editor, firstGenerated!!)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun findInsertAfterAnchor(editor: Editor, body: JetClassBody): PsiElement? {
|
|
||||||
val afterAnchor = body.lBrace ?: return null
|
|
||||||
|
|
||||||
val offset = editor.caretModel.offset
|
|
||||||
val offsetCursorElement = PsiTreeUtil.findFirstParent(body.containingFile.findElementAt(offset)) {
|
|
||||||
it.parent == body
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offsetCursorElement is PsiWhiteSpace) {
|
|
||||||
return removeAfterOffset(offset, offsetCursorElement)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offsetCursorElement != null && offsetCursorElement != body.rBrace) {
|
|
||||||
return offsetCursorElement
|
|
||||||
}
|
|
||||||
|
|
||||||
return afterAnchor
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun removeAfterOffset(offset: Int, whiteSpace: PsiWhiteSpace): PsiElement {
|
|
||||||
val spaceNode = whiteSpace.node
|
|
||||||
if (spaceNode.textRange.contains(offset)) {
|
|
||||||
var beforeWhiteSpaceText = spaceNode.text.substring(0, offset - spaceNode.startOffset)
|
|
||||||
if (!StringUtil.containsLineBreak(beforeWhiteSpaceText)) {
|
|
||||||
// Prevent insertion on same line
|
|
||||||
beforeWhiteSpaceText += "\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
val factory = JetPsiFactory(whiteSpace.project)
|
|
||||||
|
|
||||||
val insertAfter = whiteSpace.prevSibling
|
|
||||||
whiteSpace.delete()
|
|
||||||
|
|
||||||
val beforeSpace = factory.createWhiteSpace(beforeWhiteSpaceText)
|
|
||||||
insertAfter.parent.addAfter(beforeSpace, insertAfter)
|
|
||||||
|
|
||||||
return insertAfter.nextSibling
|
|
||||||
}
|
|
||||||
|
|
||||||
return whiteSpace
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-39
@@ -927,46 +927,15 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun setupEditor(declaration: JetNamedDeclaration) {
|
private fun setupEditor(declaration: JetNamedDeclaration) {
|
||||||
val caretModel = containingFileEditor.getCaretModel()
|
if (declaration is JetProperty && !declaration.hasInitializer() && containingElement is JetBlockExpression) {
|
||||||
val selectionModel = containingFileEditor.getSelectionModel()
|
val defaultValueType = typeCandidates[callableInfo.returnTypeInfo]!!.firstOrNull()?.theType
|
||||||
|
val defaultValue = defaultValueType?.let { CodeInsightUtils.defaultInitializer(it) } ?: "null"
|
||||||
if (declaration is JetSecondaryConstructor) {
|
val initializer = declaration.setInitializer(JetPsiFactory(declaration).createExpression(defaultValue))!!
|
||||||
caretModel.moveToOffset(declaration.getConstructorKeyword().endOffset)
|
val range = initializer.getTextRange()
|
||||||
|
containingFileEditor.getSelectionModel().setSelection(range.getStartOffset(), range.getEndOffset())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
else {
|
setupEditorSelection(containingFileEditor, declaration)
|
||||||
caretModel.moveToOffset(declaration.getNameIdentifier()!!.endOffset)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun positionBetween(left: PsiElement, right: PsiElement) {
|
|
||||||
val from = left.siblings(withItself = false, forward = true).firstOrNull { it !is PsiWhiteSpace } ?: return
|
|
||||||
val to = right.siblings(withItself = false, forward = false).firstOrNull { it !is PsiWhiteSpace } ?: return
|
|
||||||
val startOffset = from.startOffset
|
|
||||||
val endOffset = to.endOffset
|
|
||||||
caretModel.moveToOffset(endOffset)
|
|
||||||
selectionModel.setSelection(startOffset, endOffset)
|
|
||||||
}
|
|
||||||
|
|
||||||
when (declaration) {
|
|
||||||
is JetNamedFunction, is JetSecondaryConstructor -> {
|
|
||||||
((declaration as JetFunction).getBodyExpression() as? JetBlockExpression)?.let {
|
|
||||||
positionBetween(it.getLBrace()!!, it.getRBrace()!!)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
is JetClassOrObject -> {
|
|
||||||
caretModel.moveToOffset(declaration.startOffset)
|
|
||||||
}
|
|
||||||
is JetProperty -> {
|
|
||||||
if (!declaration.hasInitializer() && containingElement is JetBlockExpression) {
|
|
||||||
val defaultValueType = typeCandidates[callableInfo.returnTypeInfo]!!.firstOrNull()?.theType
|
|
||||||
val defaultValue = defaultValueType?.let {CodeInsightUtils.defaultInitializer(it) } ?: "null"
|
|
||||||
val initializer = declaration.setInitializer(JetPsiFactory(declaration).createExpression(defaultValue))!!
|
|
||||||
val range = initializer.getTextRange()
|
|
||||||
selectionModel.setSelection(range.getStartOffset(), range.getEndOffset())
|
|
||||||
}
|
|
||||||
caretModel.moveToOffset(declaration.endOffset)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
containingFileEditor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// build templates
|
// build templates
|
||||||
|
|||||||
+62
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* 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.quickfix.createFromUsage.callableBuilder
|
||||||
|
|
||||||
|
import com.intellij.openapi.editor.Editor
|
||||||
|
import com.intellij.openapi.editor.ScrollType
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.PsiWhiteSpace
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.siblings
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||||
|
|
||||||
|
public fun setupEditorSelection(editor: Editor, declaration: JetNamedDeclaration) {
|
||||||
|
val caretModel = editor.caretModel
|
||||||
|
val selectionModel = editor.selectionModel
|
||||||
|
|
||||||
|
if (declaration is JetSecondaryConstructor) {
|
||||||
|
caretModel.moveToOffset(declaration.getConstructorKeyword().endOffset)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
caretModel.moveToOffset(declaration.nameIdentifier!!.endOffset)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun positionBetween(left: PsiElement, right: PsiElement) {
|
||||||
|
val from = left.siblings(withItself = false, forward = true).firstOrNull { it !is PsiWhiteSpace } ?: return
|
||||||
|
val to = right.siblings(withItself = false, forward = false).firstOrNull { it !is PsiWhiteSpace } ?: return
|
||||||
|
val startOffset = from.startOffset
|
||||||
|
val endOffset = to.endOffset
|
||||||
|
caretModel.moveToOffset(endOffset)
|
||||||
|
selectionModel.setSelection(startOffset, endOffset)
|
||||||
|
}
|
||||||
|
|
||||||
|
when (declaration) {
|
||||||
|
is JetNamedFunction, is JetSecondaryConstructor -> {
|
||||||
|
((declaration as JetFunction).bodyExpression as? JetBlockExpression)?.let {
|
||||||
|
positionBetween(it.lBrace!!, it.rBrace!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is JetClassOrObject -> {
|
||||||
|
caretModel.moveToOffset(declaration.startOffset)
|
||||||
|
}
|
||||||
|
is JetProperty -> {
|
||||||
|
caretModel.moveToOffset(declaration.endOffset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
editor.scrollingModel.scrollToCaret(ScrollType.RELATIVE)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user