Show Review Added Imports on paste action
Fixed multi-caret selection in kotlin-to-kotlin copy-paste processor Relates to #KT-33939
This commit is contained in:
@@ -14,6 +14,7 @@ class BasicKotlinReferenceTransferableData(
|
|||||||
val sourceFileUrl: String,
|
val sourceFileUrl: String,
|
||||||
val packageName: String,
|
val packageName: String,
|
||||||
val imports: List<String>,
|
val imports: List<String>,
|
||||||
|
val sourceTextOffset: Int,
|
||||||
val sourceText: String,
|
val sourceText: String,
|
||||||
val textRanges: List<TextRange>
|
val textRanges: List<TextRange>
|
||||||
) : TextBlockTransferableData, Cloneable, Serializable {
|
) : TextBlockTransferableData, Cloneable, Serializable {
|
||||||
|
|||||||
+74
-44
@@ -37,10 +37,13 @@ import com.intellij.psi.*
|
|||||||
import com.intellij.psi.util.PsiTreeUtil
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
import com.intellij.util.concurrency.AppExecutorUtil
|
import com.intellij.util.concurrency.AppExecutorUtil
|
||||||
import org.jetbrains.annotations.TestOnly
|
import org.jetbrains.annotations.TestOnly
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.allowResolveInDispatchThread
|
import org.jetbrains.kotlin.idea.caches.resolve.allowResolveInDispatchThread
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference
|
||||||
|
import org.jetbrains.kotlin.idea.codeInsight.ReviewAddedImports.reviewAddedImports
|
||||||
import org.jetbrains.kotlin.idea.codeInsight.shorten.performDelayedRefactoringRequests
|
import org.jetbrains.kotlin.idea.codeInsight.shorten.performDelayedRefactoringRequests
|
||||||
import org.jetbrains.kotlin.idea.core.util.end
|
import org.jetbrains.kotlin.idea.core.util.end
|
||||||
import org.jetbrains.kotlin.idea.core.util.range
|
import org.jetbrains.kotlin.idea.core.util.range
|
||||||
@@ -62,6 +65,7 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
|||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.getImportableDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||||
import org.jetbrains.kotlin.resolve.scopes.utils.findFunction
|
import org.jetbrains.kotlin.resolve.scopes.utils.findFunction
|
||||||
@@ -109,15 +113,14 @@ class KotlinCopyPasteReferenceProcessor : CopyPastePostProcessor<BasicKotlinRefe
|
|||||||
val endOfImportsOffset = file.importDirectives.map { it.endOffset }.max() ?: file.packageDirective?.endOffset ?: 0
|
val endOfImportsOffset = file.importDirectives.map { it.endOffset }.max() ?: file.packageDirective?.endOffset ?: 0
|
||||||
val offsetDelta = if (startOffsets.any { it <= endOfImportsOffset }) 0 else endOfImportsOffset
|
val offsetDelta = if (startOffsets.any { it <= endOfImportsOffset }) 0 else endOfImportsOffset
|
||||||
val text = file.text.substring(offsetDelta)
|
val text = file.text.substring(offsetDelta)
|
||||||
val ranges = startOffsets.indices.map {
|
val ranges = startOffsets.indices.map { TextRange(startOffsets[it], endOffsets[it]) }
|
||||||
TextRange(startOffsets[it] - offsetDelta, endOffsets[it] - offsetDelta)
|
|
||||||
}
|
|
||||||
|
|
||||||
return listOf(
|
return listOf(
|
||||||
BasicKotlinReferenceTransferableData(
|
BasicKotlinReferenceTransferableData(
|
||||||
sourceFileUrl = file.virtualFile.url,
|
sourceFileUrl = file.virtualFile.url,
|
||||||
packageName = packageName,
|
packageName = packageName,
|
||||||
imports = imports,
|
imports = imports,
|
||||||
|
sourceTextOffset = offsetDelta,
|
||||||
sourceText = text,
|
sourceText = text,
|
||||||
textRanges = ranges
|
textRanges = ranges
|
||||||
)
|
)
|
||||||
@@ -165,8 +168,8 @@ class KotlinCopyPasteReferenceProcessor : CopyPastePostProcessor<BasicKotlinRefe
|
|||||||
for ((range, elements) in elementsByRange) {
|
for ((range, elements) in elementsByRange) {
|
||||||
elements.forEachDescendant { ktElement ->
|
elements.forEachDescendant { ktElement ->
|
||||||
result.addReferenceDataInsideElement(
|
result.addReferenceDataInsideElement(
|
||||||
ktElement, file, range.start, ranges, bindingContext,
|
ktElement, file, ranges, bindingContext, fakePackageName = fakePackageName,
|
||||||
fakePackageName = fakePackageName, sourcePackageName = sourcePackageName, targetPackageName = targetPackageName
|
sourcePackageName = sourcePackageName, targetPackageName = targetPackageName
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,7 +193,6 @@ class KotlinCopyPasteReferenceProcessor : CopyPastePostProcessor<BasicKotlinRefe
|
|||||||
private fun MutableCollection<KotlinReferenceData>.addReferenceDataInsideElement(
|
private fun MutableCollection<KotlinReferenceData>.addReferenceDataInsideElement(
|
||||||
ktElement: KtElement,
|
ktElement: KtElement,
|
||||||
file: KtFile,
|
file: KtFile,
|
||||||
startOffset: Int,
|
|
||||||
textRanges: List<TextRange>,
|
textRanges: List<TextRange>,
|
||||||
bindingContext: BindingContext,
|
bindingContext: BindingContext,
|
||||||
fakePackageName: String? = null,
|
fakePackageName: String? = null,
|
||||||
@@ -230,14 +232,14 @@ class KotlinCopyPasteReferenceProcessor : CopyPastePostProcessor<BasicKotlinRefe
|
|||||||
|
|
||||||
val kind = KotlinReferenceData.Kind.fromDescriptor(descriptor) ?: continue
|
val kind = KotlinReferenceData.Kind.fromDescriptor(descriptor) ?: continue
|
||||||
val isQualifiable = KotlinReferenceData.isQualifiable(ktElement, descriptor)
|
val isQualifiable = KotlinReferenceData.isQualifiable(ktElement, descriptor)
|
||||||
val relativeStart = ktElement.range.start - startOffset
|
val relativeStart = ktElement.range.start
|
||||||
val relativeEnd = ktElement.range.end - startOffset
|
val relativeEnd = ktElement.range.end
|
||||||
add(KotlinReferenceData(relativeStart, relativeEnd, fqName, isQualifiable, kind))
|
add(KotlinReferenceData(relativeStart, relativeEnd, fqName, isQualifiable, kind))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private data class ReferenceToRestoreData(val reference: KtReference, val refData: KotlinReferenceData)
|
private data class ReferenceToRestoreData(val reference: KtReference, val refData: KotlinReferenceData)
|
||||||
private data class PsiElementByTextRange(val textRange: TextRange, val element: PsiElement)
|
private data class PsiElementByTextRange(val originalTextRange: TextRange, val element: PsiElement)
|
||||||
|
|
||||||
override fun processTransferableData(
|
override fun processTransferableData(
|
||||||
project: Project,
|
project: Project,
|
||||||
@@ -255,30 +257,42 @@ class KotlinCopyPasteReferenceProcessor : CopyPastePostProcessor<BasicKotlinRefe
|
|||||||
val file = PsiDocumentManager.getInstance(project).getPsiFile(document)
|
val file = PsiDocumentManager.getInstance(project).getPsiFile(document)
|
||||||
if (file !is KtFile) return
|
if (file !is KtFile) return
|
||||||
|
|
||||||
processReferenceData(project, file, bounds.startOffset, values.single())
|
processReferenceData(project, editor, file, bounds.startOffset, values.single())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processReferenceData(
|
private fun processReferenceData(
|
||||||
project: Project,
|
project: Project,
|
||||||
|
editor: Editor,
|
||||||
file: KtFile,
|
file: KtFile,
|
||||||
blockStart: Int,
|
blockStart: Int,
|
||||||
transferableData: BasicKotlinReferenceTransferableData
|
transferableData: BasicKotlinReferenceTransferableData
|
||||||
) {
|
) {
|
||||||
PsiDocumentManager.getInstance(project).commitAllDocuments()
|
PsiDocumentManager.getInstance(project).commitAllDocuments()
|
||||||
|
|
||||||
|
var startOffsetDelta = blockStart
|
||||||
|
|
||||||
// figure out candidate elements in UI thread in paste phase
|
// figure out candidate elements in UI thread in paste phase
|
||||||
// as psi elements could be changed later on - relative offsets are used for mapping purposes
|
// as psi elements could be changed later on - relative offsets are used for mapping purposes
|
||||||
val elementsByRange = transferableData.textRanges.flatMap { originalTextRange ->
|
val elementsByRange = transferableData.textRanges.flatMap { originalTextRange ->
|
||||||
val textRange = TextRange(blockStart, blockStart + originalTextRange.endOffset - originalTextRange.startOffset)
|
val textRange = TextRange(
|
||||||
|
startOffsetDelta,
|
||||||
|
startOffsetDelta + originalTextRange.endOffset - originalTextRange.startOffset
|
||||||
|
)
|
||||||
|
startOffsetDelta = startOffsetDelta + originalTextRange.endOffset - originalTextRange.startOffset + 1
|
||||||
file.elementsInRange(textRange)
|
file.elementsInRange(textRange)
|
||||||
.filter { it is KtElement || it is KDocElement }
|
.filter { it is KtElement || it is KDocElement }
|
||||||
.map { PsiElementByTextRange(it.textRange, it) }
|
.map {
|
||||||
|
val range = TextRange(
|
||||||
|
originalTextRange.startOffset + it.textRange.startOffset - textRange.startOffset,
|
||||||
|
originalTextRange.startOffset + it.textRange.endOffset - textRange.startOffset
|
||||||
|
)
|
||||||
|
PsiElementByTextRange(range, it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
processReferenceData(project, file) { indicator: ProgressIndicator ->
|
processReferenceData(project, editor, file) { indicator: ProgressIndicator ->
|
||||||
findReferenceDataToRestore(
|
findReferenceDataToRestore(
|
||||||
file,
|
file,
|
||||||
blockStart,
|
|
||||||
indicator,
|
indicator,
|
||||||
elementsByRange,
|
elementsByRange,
|
||||||
transferableData
|
transferableData
|
||||||
@@ -286,14 +300,15 @@ class KotlinCopyPasteReferenceProcessor : CopyPastePostProcessor<BasicKotlinRefe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun processReferenceData(project: Project, file: KtFile, blockStart: Int, referenceData: Array<KotlinReferenceData>) {
|
fun processReferenceData(project: Project, editor: Editor, file: KtFile, blockStart: Int, referenceData: Array<KotlinReferenceData>) {
|
||||||
processReferenceData(project, file) { indicator: ProgressIndicator ->
|
processReferenceData(project, editor, file) { indicator: ProgressIndicator ->
|
||||||
findReferencesToRestore(file, blockStart, referenceData)
|
findReferencesToRestore(file, blockStart, referenceData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processReferenceData(
|
private fun processReferenceData(
|
||||||
project: Project,
|
project: Project,
|
||||||
|
editor: Editor,
|
||||||
file: KtFile,
|
file: KtFile,
|
||||||
findReferenceProvider: (indicator: ProgressIndicator) -> List<ReferenceToRestoreData>
|
findReferenceProvider: (indicator: ProgressIndicator) -> List<ReferenceToRestoreData>
|
||||||
) {
|
) {
|
||||||
@@ -309,13 +324,7 @@ class KotlinCopyPasteReferenceProcessor : CopyPastePostProcessor<BasicKotlinRefe
|
|||||||
.finishOnUiThread(
|
.finishOnUiThread(
|
||||||
ModalityState.defaultModalityState(),
|
ModalityState.defaultModalityState(),
|
||||||
Consumer<List<ReferenceToRestoreData>> { referencesPossibleToRestore ->
|
Consumer<List<ReferenceToRestoreData>> { referencesPossibleToRestore ->
|
||||||
val selectedReferencesToRestore =
|
applyResolvedImports(project, referencesPossibleToRestore, file, editor)
|
||||||
showRestoreReferencesDialog(project, referencesPossibleToRestore)
|
|
||||||
if (selectedReferencesToRestore.isEmpty()) return@Consumer
|
|
||||||
|
|
||||||
project.executeWriteCommand("resolve pasted references") {
|
|
||||||
restoreReferences(selectedReferencesToRestore, file)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.withDocumentsCommitted(project)
|
.withDocumentsCommitted(project)
|
||||||
@@ -326,9 +335,26 @@ class KotlinCopyPasteReferenceProcessor : CopyPastePostProcessor<BasicKotlinRefe
|
|||||||
ProgressManager.getInstance().run(task)
|
ProgressManager.getInstance().run(task)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun applyResolvedImports(
|
||||||
|
project: Project,
|
||||||
|
referencesPossibleToRestore: List<ReferenceToRestoreData>,
|
||||||
|
file: KtFile,
|
||||||
|
editor: Editor
|
||||||
|
) {
|
||||||
|
val selectedReferencesToRestore =
|
||||||
|
showRestoreReferencesDialog(project, referencesPossibleToRestore)
|
||||||
|
if (selectedReferencesToRestore.isEmpty()) return
|
||||||
|
|
||||||
|
project.executeWriteCommand("resolve pasted references") {
|
||||||
|
val imported = TreeSet<String>()
|
||||||
|
restoreReferences(selectedReferencesToRestore, file, imported)
|
||||||
|
|
||||||
|
reviewAddedImports(project, editor, file, imported)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun findReferenceDataToRestore(
|
private fun findReferenceDataToRestore(
|
||||||
file: PsiFile,
|
file: PsiFile,
|
||||||
blockStart: Int,
|
|
||||||
indicator: ProgressIndicator,
|
indicator: ProgressIndicator,
|
||||||
elementsByRange: List<PsiElementByTextRange>,
|
elementsByRange: List<PsiElementByTextRange>,
|
||||||
transferableData: BasicKotlinReferenceTransferableData
|
transferableData: BasicKotlinReferenceTransferableData
|
||||||
@@ -339,7 +365,7 @@ class KotlinCopyPasteReferenceProcessor : CopyPastePostProcessor<BasicKotlinRefe
|
|||||||
val element = elementByTextRange.element
|
val element = elementByTextRange.element
|
||||||
if (!element.isValid) return@flatMap emptyList<Pair<TextRange, KtReference>>()
|
if (!element.isValid) return@flatMap emptyList<Pair<TextRange, KtReference>>()
|
||||||
val refElementsRanges = mutableListOf<Pair<TextRange, KtReference>>()
|
val refElementsRanges = mutableListOf<Pair<TextRange, KtReference>>()
|
||||||
val offsetDelta = element.startOffset - elementByTextRange.textRange.startOffset
|
val offsetDelta = elementByTextRange.originalTextRange.startOffset - element.textRange.startOffset
|
||||||
element.forEachDescendant { ktElement ->
|
element.forEachDescendant { ktElement ->
|
||||||
indicator.checkCanceled()
|
indicator.checkCanceled()
|
||||||
|
|
||||||
@@ -347,12 +373,7 @@ class KotlinCopyPasteReferenceProcessor : CopyPastePostProcessor<BasicKotlinRefe
|
|||||||
val textRange = ref.element.textRange
|
val textRange = ref.element.textRange
|
||||||
findReference(file, textRange)?.let {
|
findReference(file, textRange)?.let {
|
||||||
// remap reference to the original (as it was on paste phase) text range
|
// remap reference to the original (as it was on paste phase) text range
|
||||||
val range = if (offsetDelta == 0) textRange
|
val range = TextRange(textRange.startOffset + offsetDelta, textRange.endOffset + offsetDelta)
|
||||||
else
|
|
||||||
TextRange(
|
|
||||||
textRange.startOffset - offsetDelta,
|
|
||||||
textRange.endOffset - offsetDelta
|
|
||||||
)
|
|
||||||
refElementsRanges.add(range to it)
|
refElementsRanges.add(range to it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -384,7 +405,7 @@ class KotlinCopyPasteReferenceProcessor : CopyPastePostProcessor<BasicKotlinRefe
|
|||||||
ctxFile
|
ctxFile
|
||||||
)
|
)
|
||||||
|
|
||||||
val offsetDelta = dummyOrigFileProlog.length
|
val offsetDelta = dummyOrigFileProlog.length - transferableData.sourceTextOffset
|
||||||
|
|
||||||
val dummyOriginalFileTextRanges =
|
val dummyOriginalFileTextRanges =
|
||||||
// it is required as it is shifted by dummy prolog
|
// it is required as it is shifted by dummy prolog
|
||||||
@@ -392,12 +413,14 @@ class KotlinCopyPasteReferenceProcessor : CopyPastePostProcessor<BasicKotlinRefe
|
|||||||
|
|
||||||
// Step 1. Find references in copied blocks of (recreated) source file
|
// Step 1. Find references in copied blocks of (recreated) source file
|
||||||
val sourceFileBasedReferences =
|
val sourceFileBasedReferences =
|
||||||
collectReferenceData(dummyOriginalFileTextRanges, dummyOriginalFile, file, fakePackageName, sourcePackageName)
|
collectReferenceData(dummyOriginalFileTextRanges, dummyOriginalFile, file, fakePackageName, sourcePackageName).map {
|
||||||
|
it.copy(startOffset = it.startOffset - offsetDelta, endOffset = it.endOffset - offsetDelta)
|
||||||
|
}
|
||||||
|
|
||||||
indicator.checkCanceled()
|
indicator.checkCanceled()
|
||||||
|
|
||||||
// Step 2. Find references to restore in a target file
|
// Step 2. Find references to restore in a target file
|
||||||
return findReferencesToRestore(file, blockStart, sourceFileBasedReferences, referencesByRange)
|
return findReferencesToRestore(file, sourceFileBasedReferences, referencesByRange)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildDummySourceScope(
|
private fun buildDummySourceScope(
|
||||||
@@ -487,17 +510,15 @@ class KotlinCopyPasteReferenceProcessor : CopyPastePostProcessor<BasicKotlinRefe
|
|||||||
|
|
||||||
private fun findReferencesToRestore(
|
private fun findReferencesToRestore(
|
||||||
file: PsiFile,
|
file: PsiFile,
|
||||||
blockStart: Int,
|
|
||||||
referenceData: List<KotlinReferenceData>,
|
referenceData: List<KotlinReferenceData>,
|
||||||
referencesByPosition: Map<TextRange, KtReference>
|
referencesByPosition: Map<TextRange, KtReference>
|
||||||
): List<ReferenceToRestoreData> =
|
): List<ReferenceToRestoreData> =
|
||||||
// use already found reference candidates - so file could be changed
|
// use already found reference candidates - so file could be changed
|
||||||
findReferences(file, referenceData
|
findReferences(file, referenceData.map {
|
||||||
.map {
|
val textRange = TextRange(it.startOffset, it.endOffset)
|
||||||
val textRange = TextRange(it.startOffset + blockStart, it.endOffset + blockStart)
|
val reference = referencesByPosition[textRange]
|
||||||
val reference = referencesByPosition[textRange]
|
it to if (reference?.element?.isValid == true) reference else null
|
||||||
it to if (reference?.element?.isValid == true) reference else null
|
})
|
||||||
})
|
|
||||||
|
|
||||||
private fun findReferences(
|
private fun findReferences(
|
||||||
file: PsiFile,
|
file: PsiFile,
|
||||||
@@ -575,7 +596,11 @@ class KotlinCopyPasteReferenceProcessor : CopyPastePostProcessor<BasicKotlinRefe
|
|||||||
return reference.resolveToDescriptors(bindingContext).toList()
|
return reference.resolveToDescriptors(bindingContext).toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun restoreReferences(referencesToRestore: Collection<ReferenceToRestoreData>, file: KtFile) {
|
private fun restoreReferences(
|
||||||
|
referencesToRestore: Collection<ReferenceToRestoreData>,
|
||||||
|
file: KtFile,
|
||||||
|
imported: MutableSet<String>
|
||||||
|
) {
|
||||||
val importHelper = ImportInsertHelper.getInstance(file.project)
|
val importHelper = ImportInsertHelper.getInstance(file.project)
|
||||||
val smartPointerManager = SmartPointerManager.getInstance(file.project)
|
val smartPointerManager = SmartPointerManager.getInstance(file.project)
|
||||||
|
|
||||||
@@ -606,9 +631,14 @@ class KotlinCopyPasteReferenceProcessor : CopyPastePostProcessor<BasicKotlinRefe
|
|||||||
|
|
||||||
for (descriptor in descriptorsToImport) {
|
for (descriptor in descriptorsToImport) {
|
||||||
importHelper.importDescriptor(file, descriptor)
|
importHelper.importDescriptor(file, descriptor)
|
||||||
|
descriptor.getImportableDescriptor().importableFqName?.let { imported.add(it.asString()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
for ((pointer, fqName) in bindingRequests) {
|
for ((pointer, fqName) in bindingRequests) {
|
||||||
pointer.element?.mainReference?.bindToFqName(fqName, KtSimpleNameReference.ShorteningMode.DELAYED_SHORTENING)
|
pointer.element?.mainReference?.let {
|
||||||
|
it.bindToFqName(fqName, KtSimpleNameReference.ShorteningMode.DELAYED_SHORTENING)
|
||||||
|
imported.add(fqName.asString())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
performDelayedRefactoringRequests(file.project)
|
performDelayedRefactoringRequests(file.project)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.codeInsight
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.CodeInsightBundle
|
||||||
|
import com.intellij.codeInsight.CodeInsightSettings
|
||||||
|
import com.intellij.codeInsight.hint.HintManager
|
||||||
|
import com.intellij.codeInsight.hint.HintManagerImpl
|
||||||
|
import com.intellij.codeInsight.hint.HintUtil
|
||||||
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
|
import com.intellij.openapi.application.ModalityState
|
||||||
|
import com.intellij.openapi.command.WriteCommandAction
|
||||||
|
import com.intellij.openapi.editor.Editor
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.ui.LightweightHint
|
||||||
|
import com.intellij.util.ArrayUtil
|
||||||
|
import org.jetbrains.annotations.TestOnly
|
||||||
|
import org.jetbrains.kotlin.idea.imports.KotlinImportOptimizer
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
import org.jetbrains.kotlin.resolve.ImportPath
|
||||||
|
import java.util.*
|
||||||
|
import javax.swing.event.HyperlinkEvent
|
||||||
|
import javax.swing.event.HyperlinkListener
|
||||||
|
|
||||||
|
object ReviewAddedImports {
|
||||||
|
@get:TestOnly
|
||||||
|
var importsToBeReviewed: Collection<String> = emptyList()
|
||||||
|
|
||||||
|
@get:TestOnly
|
||||||
|
var importsToBeDeleted: Collection<String> = emptyList()
|
||||||
|
|
||||||
|
fun reviewAddedImports(
|
||||||
|
project: Project,
|
||||||
|
editor: Editor,
|
||||||
|
file: KtFile,
|
||||||
|
imported: TreeSet<String>
|
||||||
|
) {
|
||||||
|
if (CodeInsightSettings.getInstance().ADD_IMPORTS_ON_PASTE == CodeInsightSettings.YES &&
|
||||||
|
!imported.isEmpty()
|
||||||
|
) {
|
||||||
|
if (ApplicationManager.getApplication().isUnitTestMode) {
|
||||||
|
importsToBeReviewed = imported
|
||||||
|
removeImports(project, file, importsToBeDeleted)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val notificationText = CodeInsightBundle
|
||||||
|
.message("copy.paste.reference.notification", imported.size)
|
||||||
|
ApplicationManager.getApplication().invokeLater(
|
||||||
|
Runnable {
|
||||||
|
showHint(
|
||||||
|
editor,
|
||||||
|
notificationText,
|
||||||
|
HyperlinkListener { e: HyperlinkEvent ->
|
||||||
|
if (e.eventType == HyperlinkEvent.EventType.ACTIVATED) {
|
||||||
|
reviewImports(project, file, imported)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}, ModalityState.NON_MODAL
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showHint(
|
||||||
|
editor: Editor,
|
||||||
|
info: String,
|
||||||
|
hyperlinkListener: HyperlinkListener
|
||||||
|
) {
|
||||||
|
if (ApplicationManager.getApplication().isUnitTestMode) return
|
||||||
|
val hint = LightweightHint(HintUtil.createInformationLabel(info, hyperlinkListener, null, null))
|
||||||
|
val flags = HintManager.HIDE_BY_ANY_KEY or HintManager.HIDE_BY_TEXT_CHANGE
|
||||||
|
HintManagerImpl.getInstanceImpl().showEditorHint(hint, editor, HintManager.UNDER, flags, 0, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun reviewImports(
|
||||||
|
project: Project,
|
||||||
|
file: KtFile,
|
||||||
|
importedClasses: Set<String>
|
||||||
|
) {
|
||||||
|
val dialog = RestoreReferencesDialog(project, ArrayUtil.toObjectArray(importedClasses))
|
||||||
|
dialog.title = CodeInsightBundle.message("dialog.import.on.paste.title3")
|
||||||
|
if (dialog.showAndGet()) {
|
||||||
|
removeImports(project, file, dialog.selectedElements.map { it as String }.toSortedSet())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun removeImports(
|
||||||
|
project: Project,
|
||||||
|
file: KtFile,
|
||||||
|
importsToRemove: Collection<String>
|
||||||
|
) {
|
||||||
|
if (importsToRemove.isEmpty()) return
|
||||||
|
|
||||||
|
WriteCommandAction.runWriteCommandAction(project, "revert applied imports", null, Runnable {
|
||||||
|
val newImports = file.importDirectives.mapNotNull {
|
||||||
|
val importedFqName = it.importedFqName ?: return@mapNotNull null
|
||||||
|
if (importsToRemove.contains(importedFqName.asString())) return@mapNotNull null
|
||||||
|
ImportPath(importedFqName, it.isAllUnder, it.aliasName?.let { alias -> Name.identifier(alias) })
|
||||||
|
}
|
||||||
|
KotlinImportOptimizer.replaceImports(file, newImports)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.codeInsight
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.CodeInsightBundle
|
||||||
|
import com.intellij.codeInsight.CodeInsightSettings
|
||||||
|
import com.intellij.codeInsight.hint.HintManager
|
||||||
|
import com.intellij.codeInsight.hint.HintManagerImpl
|
||||||
|
import com.intellij.codeInsight.hint.HintUtil
|
||||||
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
|
import com.intellij.openapi.application.ModalityState
|
||||||
|
import com.intellij.openapi.command.WriteCommandAction
|
||||||
|
import com.intellij.openapi.editor.Editor
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.ui.LightweightHint
|
||||||
|
import com.intellij.util.ArrayUtil
|
||||||
|
import org.jetbrains.annotations.TestOnly
|
||||||
|
import org.jetbrains.kotlin.idea.imports.KotlinImportOptimizer
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
import org.jetbrains.kotlin.resolve.ImportPath
|
||||||
|
import java.util.*
|
||||||
|
import javax.swing.event.HyperlinkEvent
|
||||||
|
import javax.swing.event.HyperlinkListener
|
||||||
|
|
||||||
|
object ReviewAddedImports {
|
||||||
|
@get:TestOnly
|
||||||
|
var importsToBeReviewed: Collection<String> = emptyList()
|
||||||
|
|
||||||
|
@get:TestOnly
|
||||||
|
var importsToBeDeleted: Collection<String> = emptyList()
|
||||||
|
|
||||||
|
fun reviewAddedImports(
|
||||||
|
project: Project,
|
||||||
|
editor: Editor,
|
||||||
|
file: KtFile,
|
||||||
|
imported: TreeSet<String>
|
||||||
|
) {
|
||||||
|
if (CodeInsightSettings.getInstance().ADD_IMPORTS_ON_PASTE == CodeInsightSettings.YES &&
|
||||||
|
!imported.isEmpty()
|
||||||
|
) {
|
||||||
|
if (ApplicationManager.getApplication().isUnitTestMode) {
|
||||||
|
importsToBeReviewed = imported
|
||||||
|
removeImports(project, file, importsToBeDeleted)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// there is actual no such functionality in 191
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun removeImports(
|
||||||
|
project: Project,
|
||||||
|
file: KtFile,
|
||||||
|
importsToRemove: Collection<String>
|
||||||
|
) {
|
||||||
|
if (importsToRemove.isEmpty()) return
|
||||||
|
|
||||||
|
WriteCommandAction.runWriteCommandAction(project, "revert applied imports", null, Runnable {
|
||||||
|
val newImports = file.importDirectives.mapNotNull {
|
||||||
|
val importedFqName = it.importedFqName ?: return@mapNotNull null
|
||||||
|
if (importsToRemove.contains(importedFqName.asString())) return@mapNotNull null
|
||||||
|
ImportPath(importedFqName, it.isAllUnder, it.aliasName?.let { alias -> Name.identifier(alias) })
|
||||||
|
}
|
||||||
|
KotlinImportOptimizer.replaceImports(file, newImports)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.codeInsight
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.CodeInsightBundle
|
||||||
|
import com.intellij.codeInsight.CodeInsightSettings
|
||||||
|
import com.intellij.codeInsight.hint.HintManager
|
||||||
|
import com.intellij.codeInsight.hint.HintManagerImpl
|
||||||
|
import com.intellij.codeInsight.hint.HintUtil
|
||||||
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
|
import com.intellij.openapi.application.ModalityState
|
||||||
|
import com.intellij.openapi.command.WriteCommandAction
|
||||||
|
import com.intellij.openapi.editor.Editor
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.ui.LightweightHint
|
||||||
|
import com.intellij.util.ArrayUtil
|
||||||
|
import org.jetbrains.annotations.TestOnly
|
||||||
|
import org.jetbrains.kotlin.idea.imports.KotlinImportOptimizer
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
import org.jetbrains.kotlin.resolve.ImportPath
|
||||||
|
import java.util.*
|
||||||
|
import javax.swing.event.HyperlinkEvent
|
||||||
|
import javax.swing.event.HyperlinkListener
|
||||||
|
|
||||||
|
object ReviewAddedImports {
|
||||||
|
@get:TestOnly
|
||||||
|
var importsToBeReviewed: Collection<String> = emptyList()
|
||||||
|
|
||||||
|
@get:TestOnly
|
||||||
|
var importsToBeDeleted: Collection<String> = emptyList()
|
||||||
|
|
||||||
|
fun reviewAddedImports(
|
||||||
|
project: Project,
|
||||||
|
editor: Editor,
|
||||||
|
file: KtFile,
|
||||||
|
imported: TreeSet<String>
|
||||||
|
) {
|
||||||
|
if (CodeInsightSettings.getInstance().ADD_IMPORTS_ON_PASTE == CodeInsightSettings.YES &&
|
||||||
|
!imported.isEmpty()
|
||||||
|
) {
|
||||||
|
if (ApplicationManager.getApplication().isUnitTestMode) {
|
||||||
|
importsToBeReviewed = imported
|
||||||
|
removeImports(project, file, importsToBeDeleted)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// there is actual no such functionality in 192
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun removeImports(
|
||||||
|
project: Project,
|
||||||
|
file: KtFile,
|
||||||
|
importsToRemove: Collection<String>
|
||||||
|
) {
|
||||||
|
if (importsToRemove.isEmpty()) return
|
||||||
|
|
||||||
|
WriteCommandAction.runWriteCommandAction(project, "revert applied imports", null, Runnable {
|
||||||
|
val newImports = file.importDirectives.mapNotNull {
|
||||||
|
val importedFqName = it.importedFqName ?: return@mapNotNull null
|
||||||
|
if (importsToRemove.contains(importedFqName.asString())) return@mapNotNull null
|
||||||
|
ImportPath(importedFqName, it.isAllUnder, it.aliasName?.let { alias -> Name.identifier(alias) })
|
||||||
|
}
|
||||||
|
KotlinImportOptimizer.replaceImports(file, newImports)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -130,7 +130,7 @@ class ConvertJavaCopyPasteProcessor : CopyPastePostProcessor<TextBlockTransferab
|
|||||||
rangeMarker.isGreedyToLeft = true
|
rangeMarker.isGreedyToLeft = true
|
||||||
rangeMarker.isGreedyToRight = true
|
rangeMarker.isGreedyToRight = true
|
||||||
|
|
||||||
KotlinCopyPasteReferenceProcessor().processReferenceData(project, targetFile, bounds.start, referenceData.toTypedArray())
|
KotlinCopyPasteReferenceProcessor().processReferenceData(project, editor, targetFile, bounds.start, referenceData.toTypedArray())
|
||||||
|
|
||||||
runWriteAction {
|
runWriteAction {
|
||||||
explicitImports.forEach { fqName ->
|
explicitImports.forEach { fqName ->
|
||||||
@@ -224,7 +224,11 @@ class ConvertJavaCopyPasteProcessor : CopyPastePostProcessor<TextBlockTransferab
|
|||||||
}
|
}
|
||||||
|
|
||||||
val dummyFile = KtPsiFactory(targetFile.project).createAnalyzableFile("dummy.kt", fileText, targetFile)
|
val dummyFile = KtPsiFactory(targetFile.project).createAnalyzableFile("dummy.kt", fileText, targetFile)
|
||||||
return KotlinCopyPasteReferenceProcessor().collectReferenceData(dummyFile, intArrayOf(blockStart!!), intArrayOf(blockEnd!!))
|
val startOffset = blockStart!!
|
||||||
|
val endOffset = blockEnd!!
|
||||||
|
return KotlinCopyPasteReferenceProcessor().collectReferenceData(dummyFile, intArrayOf(startOffset), intArrayOf(endOffset)).map {
|
||||||
|
it.copy(startOffset = it.startOffset - startOffset, endOffset = it.endOffset - startOffset)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateDummyFunctionName(convertedCode: String): String {
|
private fun generateDummyFunctionName(convertedCode: String): String {
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
// ERROR: Unresolved reference: B
|
||||||
|
// ERROR: Unresolved reference: B
|
||||||
|
// ERROR: Unresolved reference: B
|
||||||
|
// ERROR: A 'return' expression required in a function with a block body ('{...}')
|
||||||
|
package to
|
||||||
|
|
||||||
|
import a.A
|
||||||
|
import a.T
|
||||||
|
import java.util.*
|
||||||
|
import java.util.concurrent.atomic.AtomicReference
|
||||||
|
import java.util.concurrent.atomic.AtomicLong as ALong
|
||||||
|
|
||||||
|
fun g(t: T): Int {
|
||||||
|
g(A)
|
||||||
|
B.f()
|
||||||
|
A
|
||||||
|
B
|
||||||
|
A.Companion
|
||||||
|
B.Companion
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
a.A
|
||||||
|
a.B
|
||||||
|
a.T
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
a.B
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package a
|
||||||
|
|
||||||
|
interface T
|
||||||
|
|
||||||
|
class A {
|
||||||
|
companion object: T {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class B {
|
||||||
|
companion object {
|
||||||
|
fun f(): Int
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<selection>fun g(t: T): Int {
|
||||||
|
g(A)
|
||||||
|
B.f()
|
||||||
|
A
|
||||||
|
B
|
||||||
|
A.Companion
|
||||||
|
B.Companion
|
||||||
|
}</selection>
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package to
|
||||||
|
|
||||||
|
import java.util.*
|
||||||
|
import java.util.concurrent.atomic.AtomicReference
|
||||||
|
import java.util.concurrent.atomic.AtomicLong as ALong
|
||||||
|
|
||||||
|
<caret>
|
||||||
+1
-1
@@ -14,7 +14,7 @@ package d
|
|||||||
import foo.Bar
|
import foo.Bar
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Some kdoc for class Foo
|
* Some kdoc [Bar] for class Foo
|
||||||
*/
|
*/
|
||||||
class Foo(val a: A) {
|
class Foo(val a: A) {
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -12,7 +12,7 @@ package d
|
|||||||
import foo.Bar
|
import foo.Bar
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Some kdoc for class Foo
|
* Some kdoc [Bar] for class Foo
|
||||||
*/
|
*/
|
||||||
class Foo(val a: A) {
|
class Foo(val a: A) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
class Bar(val v: Int){}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package to
|
||||||
|
|
||||||
|
import d.A
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
package d
|
||||||
|
|
||||||
|
import foo.Bar
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some kdoc [Bar] for class Foo
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Foo(val a: A) {
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
d.A
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
// WITH_LIBRARY: copyPaste/imports/KotlinLibrary
|
||||||
|
<selection>
|
||||||
|
<caret>/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
package d</selection>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some comment in front of imports
|
||||||
|
*/
|
||||||
|
<selection>
|
||||||
|
<caret>import foo.Bar</selection>
|
||||||
|
|
||||||
|
<selection>
|
||||||
|
<caret>/**
|
||||||
|
* Some kdoc [Bar] for class Foo
|
||||||
|
*/</selection>
|
||||||
|
<selection>
|
||||||
|
<caret>class Foo(val a: A) {
|
||||||
|
}
|
||||||
|
</selection>
|
||||||
@@ -47,6 +47,14 @@ abstract class AbstractInsertImportOnPasteTest : AbstractCopyPasteTest() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
KotlinCopyPasteReferenceProcessor.declarationsToImportSuggested = emptyList()
|
KotlinCopyPasteReferenceProcessor.declarationsToImportSuggested = emptyList()
|
||||||
|
ReviewAddedImports.importsToBeReviewed = emptyList()
|
||||||
|
|
||||||
|
val importsToBeDeletedFile = testDataFile(testFileName.replace(".kt", ".imports_to_delete"))
|
||||||
|
ReviewAddedImports.importsToBeDeleted = if (importsToBeDeletedFile.exists()) {
|
||||||
|
importsToBeDeletedFile.readLines()
|
||||||
|
} else {
|
||||||
|
emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
configureTargetFile(testFileName.replace(".kt", ".to.kt"))
|
configureTargetFile(testFileName.replace(".kt", ".to.kt"))
|
||||||
performNotWriteEditorAction(IdeActions.ACTION_PASTE)
|
performNotWriteEditorAction(IdeActions.ACTION_PASTE)
|
||||||
@@ -59,6 +67,7 @@ abstract class AbstractInsertImportOnPasteTest : AbstractCopyPasteTest() {
|
|||||||
|
|
||||||
val namesToImportDump = KotlinCopyPasteReferenceProcessor.declarationsToImportSuggested.joinToString("\n")
|
val namesToImportDump = KotlinCopyPasteReferenceProcessor.declarationsToImportSuggested.joinToString("\n")
|
||||||
KotlinTestUtils.assertEqualsToFile(testDataFile(testFileName.replace(".kt", ".expected.names")), namesToImportDump)
|
KotlinTestUtils.assertEqualsToFile(testDataFile(testFileName.replace(".kt", ".expected.names")), namesToImportDump)
|
||||||
|
assertEquals(namesToImportDump, ReviewAddedImports.importsToBeReviewed.joinToString("\n"))
|
||||||
|
|
||||||
val resultFile = myFixture.file as KtFile
|
val resultFile = myFixture.file as KtFile
|
||||||
val resultText = if (InTextDirectivesUtils.isDirectiveDefined(testFileText, NO_ERRORS_DUMP_DIRECTIVE))
|
val resultText = if (InTextDirectivesUtils.isDirectiveDefined(testFileText, NO_ERRORS_DUMP_DIRECTIVE))
|
||||||
|
|||||||
+20
@@ -55,6 +55,11 @@ public class InsertImportOnPasteTestGenerated extends AbstractInsertImportOnPast
|
|||||||
runTest("idea/testData/copyPaste/imports/ClassObject.kt");
|
runTest("idea/testData/copyPaste/imports/ClassObject.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ClassObjectAndDropImports.kt")
|
||||||
|
public void testClassObjectAndDropImports() throws Exception {
|
||||||
|
runTest("idea/testData/copyPaste/imports/ClassObjectAndDropImports.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("ClassObjectFunInsideClass.kt")
|
@TestMetadata("ClassObjectFunInsideClass.kt")
|
||||||
public void testClassObjectFunInsideClass() throws Exception {
|
public void testClassObjectFunInsideClass() throws Exception {
|
||||||
runTest("idea/testData/copyPaste/imports/ClassObjectFunInsideClass.kt");
|
runTest("idea/testData/copyPaste/imports/ClassObjectFunInsideClass.kt");
|
||||||
@@ -245,6 +250,11 @@ public class InsertImportOnPasteTestGenerated extends AbstractInsertImportOnPast
|
|||||||
runTest("idea/testData/copyPaste/imports/Local.kt");
|
runTest("idea/testData/copyPaste/imports/Local.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("MultiCaretSelectionEntireFile.kt")
|
||||||
|
public void testMultiCaretSelectionEntireFile() throws Exception {
|
||||||
|
runTest("idea/testData/copyPaste/imports/MultiCaretSelectionEntireFile.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("MultiDeclaration.kt")
|
@TestMetadata("MultiDeclaration.kt")
|
||||||
public void testMultiDeclaration() throws Exception {
|
public void testMultiDeclaration() throws Exception {
|
||||||
runTest("idea/testData/copyPaste/imports/MultiDeclaration.kt");
|
runTest("idea/testData/copyPaste/imports/MultiDeclaration.kt");
|
||||||
@@ -408,6 +418,11 @@ public class InsertImportOnPasteTestGenerated extends AbstractInsertImportOnPast
|
|||||||
runTest("idea/testData/copyPaste/imports/ClassObject.kt");
|
runTest("idea/testData/copyPaste/imports/ClassObject.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ClassObjectAndDropImports.kt")
|
||||||
|
public void testClassObjectAndDropImports() throws Exception {
|
||||||
|
runTest("idea/testData/copyPaste/imports/ClassObjectAndDropImports.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("ClassObjectFunInsideClass.kt")
|
@TestMetadata("ClassObjectFunInsideClass.kt")
|
||||||
public void testClassObjectFunInsideClass() throws Exception {
|
public void testClassObjectFunInsideClass() throws Exception {
|
||||||
runTest("idea/testData/copyPaste/imports/ClassObjectFunInsideClass.kt");
|
runTest("idea/testData/copyPaste/imports/ClassObjectFunInsideClass.kt");
|
||||||
@@ -598,6 +613,11 @@ public class InsertImportOnPasteTestGenerated extends AbstractInsertImportOnPast
|
|||||||
runTest("idea/testData/copyPaste/imports/Local.kt");
|
runTest("idea/testData/copyPaste/imports/Local.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("MultiCaretSelectionEntireFile.kt")
|
||||||
|
public void testMultiCaretSelectionEntireFile() throws Exception {
|
||||||
|
runTest("idea/testData/copyPaste/imports/MultiCaretSelectionEntireFile.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("MultiDeclaration.kt")
|
@TestMetadata("MultiDeclaration.kt")
|
||||||
public void testMultiDeclaration() throws Exception {
|
public void testMultiDeclaration() throws Exception {
|
||||||
runTest("idea/testData/copyPaste/imports/MultiDeclaration.kt");
|
runTest("idea/testData/copyPaste/imports/MultiDeclaration.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user