Workaround KT-14531, Partial fix for KT-13600, KT-11620 J2K: Invalid conversion context on plain text pasting
For detailed info see KT-14531
This commit is contained in:
+11
-10
@@ -86,7 +86,7 @@ class ConvertJavaCopyPasteProcessor : CopyPastePostProcessor<TextBlockTransferab
|
||||
|
||||
fun doConversion(): Result {
|
||||
val dataForConversion = DataForConversion.prepare(data, project)
|
||||
val result = convertCopiedCodeToKotlin(dataForConversion.elementsAndTexts, project)
|
||||
val result = dataForConversion.elementsAndTexts.convertCodeToKotlin(project)
|
||||
val referenceData = buildReferenceData(result.text, result.parseContext, dataForConversion.importsAndPackage, targetFile)
|
||||
val text = if (result.textChanged) result.text else null
|
||||
return Result(text, referenceData, result.importsToAdd)
|
||||
@@ -198,14 +198,14 @@ internal class ConversionResult(
|
||||
val textChanged: Boolean
|
||||
)
|
||||
|
||||
internal fun convertCopiedCodeToKotlin(elementsAndTexts: Collection<Any>, project: Project): ConversionResult {
|
||||
internal fun ElementAndTextList.convertCodeToKotlin(project: Project): ConversionResult {
|
||||
val converter = JavaToKotlinConverter(
|
||||
project,
|
||||
ConverterSettings.defaultSettings,
|
||||
IdeaJavaToKotlinServices
|
||||
)
|
||||
|
||||
val inputElements = elementsAndTexts.filterIsInstance<PsiElement>()
|
||||
val inputElements = this.toList().filterIsInstance<PsiElement>()
|
||||
val results = converter.elementsToKotlin(inputElements).results
|
||||
val importsToAdd = LinkedHashSet<FqName>()
|
||||
|
||||
@@ -213,9 +213,9 @@ internal fun convertCopiedCodeToKotlin(elementsAndTexts: Collection<Any>, projec
|
||||
val convertedCodeBuilder = StringBuilder()
|
||||
val originalCodeBuilder = StringBuilder()
|
||||
var parseContext: ParseContext? = null
|
||||
for (o in elementsAndTexts) {
|
||||
if (o is PsiElement) {
|
||||
val originalText = o.text
|
||||
this.process(object : ElementsAndTextsProcessor {
|
||||
override fun processElement(element: PsiElement) {
|
||||
val originalText = element.text
|
||||
originalCodeBuilder.append(originalText)
|
||||
|
||||
val result = results[resultIndex++]
|
||||
@@ -230,11 +230,12 @@ internal fun convertCopiedCodeToKotlin(elementsAndTexts: Collection<Any>, projec
|
||||
convertedCodeBuilder.append(originalText)
|
||||
}
|
||||
}
|
||||
else {
|
||||
originalCodeBuilder.append(o)
|
||||
convertedCodeBuilder.append(o as String)
|
||||
|
||||
override fun processText(string: String) {
|
||||
originalCodeBuilder.append(string)
|
||||
convertedCodeBuilder.append(string)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
val convertedCode = convertedCodeBuilder.toString()
|
||||
val originalCode = originalCodeBuilder.toString()
|
||||
|
||||
+30
-58
@@ -27,22 +27,23 @@ import com.intellij.openapi.project.DumbService
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Ref
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.psi.PsiErrorElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiFileFactory
|
||||
import com.intellij.util.LocalTimeCounter
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.kotlin.asJava.toLightClass
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.idea.codeInsight.referenceExpression
|
||||
import org.jetbrains.kotlin.idea.editor.KotlinEditorOptions
|
||||
import org.jetbrains.kotlin.idea.j2k.J2kPostProcessor
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.j2k.AfterConversionPass
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||
import org.jetbrains.kotlin.resolve.ImportPath
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
|
||||
import java.awt.datatransfer.DataFlavor
|
||||
@@ -103,10 +104,21 @@ class ConvertTextJavaCopyPasteProcessor : CopyPastePostProcessor<TextBlockTransf
|
||||
if (!confirmConvertJavaOnPaste(project, isPlainText = true)) return
|
||||
|
||||
val copiedJavaCode = prepareCopiedJavaCodeByContext(text, conversionContext, pasteTarget)
|
||||
val dataForConversion = DataForConversion.prepare(copiedJavaCode, project)
|
||||
|
||||
val convertedText = copiedJavaCode.convertCodeToKotlin(project).text
|
||||
val additionalImports = dataForConversion.tryResolveImports(targetFile)
|
||||
var convertedImportsText = additionalImports.convertCodeToKotlin(project).text
|
||||
|
||||
val convertedText = dataForConversion.convertCodeToKotlin(project).text
|
||||
|
||||
runWriteAction {
|
||||
|
||||
val importsInsertOffset = targetFile.importList?.endOffset ?: 0
|
||||
if (targetFile.importDirectives.isEmpty() && importsInsertOffset > 0)
|
||||
convertedImportsText = "\n" + convertedImportsText
|
||||
if (convertedImportsText.isNotBlank())
|
||||
editor.document.insertString(importsInsertOffset, convertedImportsText)
|
||||
|
||||
val startOffset = bounds.startOffset
|
||||
editor.document.replaceString(startOffset, bounds.endOffset, convertedText)
|
||||
|
||||
@@ -116,16 +128,15 @@ class ConvertTextJavaCopyPasteProcessor : CopyPastePostProcessor<TextBlockTransf
|
||||
val newBounds = TextRange(startOffset, startOffset + convertedText.length)
|
||||
|
||||
psiDocumentManager.commitAllDocuments()
|
||||
|
||||
AfterConversionPass(project, J2kPostProcessor(formatCode = true)).run(targetFile, newBounds)
|
||||
|
||||
conversionPerformed = true
|
||||
}
|
||||
}
|
||||
|
||||
private fun CopiedJavaCode.convertCodeToKotlin(project: Project): ConversionResult {
|
||||
val dataForConversion = DataForConversion.prepare(this, project)
|
||||
val conversionResult = convertCopiedCodeToKotlin(dataForConversion.elementsAndTexts, project)
|
||||
return conversionResult
|
||||
private fun DataForConversion.convertCodeToKotlin(project: Project): ConversionResult {
|
||||
return elementsAndTexts.convertCodeToKotlin(project)
|
||||
}
|
||||
|
||||
private val KtElement.pasteContext: KotlinContext
|
||||
@@ -211,7 +222,14 @@ class ConvertTextJavaCopyPasteProcessor : CopyPastePostProcessor<TextBlockTransf
|
||||
}
|
||||
|
||||
private fun parseAsFile(text: String, fileType: LanguageFileType, project: Project): PsiFile {
|
||||
return PsiFileFactory.getInstance(project).createFileFromText("Dummy", fileType, text, LocalTimeCounter.currentTime(), true)
|
||||
return PsiFileFactory.getInstance(project).createFileFromText("Dummy.java", fileType, text, LocalTimeCounter.currentTime(), true)
|
||||
}
|
||||
|
||||
private fun DataForConversion.tryResolveImports(targetFile: KtFile): ElementAndTextList {
|
||||
val importResolver = PlainTextPasteImportResolver(this, targetFile)
|
||||
importResolver.addImportsFromTargetFile()
|
||||
importResolver.tryResolveReferences()
|
||||
return ElementAndTextList(importResolver.addedImports.flatMap { listOf("\n", it) } + "\n\n") //TODO Non-manual formatting for import list
|
||||
}
|
||||
|
||||
private fun prepareCopiedJavaCodeByContext(text: String, context: JavaContext, target: KtElement): CopiedJavaCode {
|
||||
@@ -225,53 +243,6 @@ class ConvertTextJavaCopyPasteProcessor : CopyPastePostProcessor<TextBlockTransf
|
||||
append(";\n")
|
||||
}
|
||||
}
|
||||
|
||||
fun appendImport(importPath: ImportPath) {
|
||||
append("import ")
|
||||
append(importPath)
|
||||
append(";\n")
|
||||
}
|
||||
|
||||
fun appendStaticImport(importPath: ImportPath) {
|
||||
append("import static ")
|
||||
append(importPath)
|
||||
append(";\n")
|
||||
}
|
||||
|
||||
targetFile.importDirectives.forEach {
|
||||
val importPath = it.importPath
|
||||
val importedReference = it.importedReference
|
||||
if (importPath != null && !importPath.hasAlias() && importedReference is KtDotQualifiedExpression) {
|
||||
|
||||
val receiver = importedReference
|
||||
.receiverExpression
|
||||
.referenceExpression()
|
||||
?.mainReference
|
||||
?.resolve()
|
||||
val selector = importedReference
|
||||
.selectorExpression
|
||||
?.referenceExpression()
|
||||
?.mainReference
|
||||
?.resolve()
|
||||
|
||||
val isPackageReceiver = receiver is PsiPackage
|
||||
val isClassReceiver = receiver is PsiClass
|
||||
val isClassSelector = selector is PsiClass
|
||||
|
||||
if (importPath.isAllUnder) {
|
||||
if (isClassReceiver)
|
||||
appendStaticImport(importPath)
|
||||
else if (isPackageReceiver)
|
||||
appendImport(importPath)
|
||||
}
|
||||
else {
|
||||
if (isPackageReceiver && isClassSelector)
|
||||
appendImport(importPath)
|
||||
else if (isClassReceiver)
|
||||
appendStaticImport(importPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val classDef = when (context) {
|
||||
@@ -300,11 +271,12 @@ class ConvertTextJavaCopyPasteProcessor : CopyPastePostProcessor<TextBlockTransf
|
||||
|
||||
JavaContext.EXPRESSION -> createCopiedJavaCode(prefix, "$classDef {\nObject field = $\n}", text)
|
||||
}
|
||||
|
||||
return copiedJavaCode
|
||||
}
|
||||
|
||||
private fun createCopiedJavaCode(prefix: String, templateWithoutPrefix: String, text: String): CopiedJavaCode {
|
||||
val template = "$prefix\n$templateWithoutPrefix"
|
||||
val template = "$prefix$templateWithoutPrefix"
|
||||
val index = template.indexOf("$")
|
||||
assert(index >= 0)
|
||||
val fileText = template.substring(0, index) + text + template.substring(index + 1)
|
||||
|
||||
@@ -29,8 +29,9 @@ import org.jetbrains.kotlin.psi.psiUtil.siblings
|
||||
import java.util.*
|
||||
|
||||
data class DataForConversion private constructor(
|
||||
val elementsAndTexts: Collection<Any> /* list consisting of PsiElement's to convert and plain String's */,
|
||||
val importsAndPackage: String
|
||||
val elementsAndTexts: ElementAndTextList /* list consisting of PsiElement's to convert and plain String's */,
|
||||
val importsAndPackage: String,
|
||||
val file: PsiJavaFile
|
||||
) {
|
||||
companion object {
|
||||
fun prepare(copiedCode: CopiedJavaCode, project: Project): DataForConversion {
|
||||
@@ -49,12 +50,12 @@ data class DataForConversion private constructor(
|
||||
file = PsiFileFactory.getInstance(project).createFileFromText(JavaLanguage.INSTANCE, newFileText) as PsiJavaFile
|
||||
}
|
||||
|
||||
val elementsAndTexts = ArrayList<Any>()
|
||||
val elementsAndTexts = ElementAndTextList()
|
||||
for (i in startOffsets.indices) {
|
||||
elementsAndTexts.collectElementsToConvert(file, fileText, TextRange(startOffsets[i], endOffsets[i]))
|
||||
}
|
||||
|
||||
return DataForConversion(elementsAndTexts, importsAndPackage)
|
||||
return DataForConversion(elementsAndTexts, importsAndPackage, file)
|
||||
}
|
||||
|
||||
private fun clipTextIfNeeded(file: PsiJavaFile, fileText: String, startOffsets: IntArray, endOffsets: IntArray): String? {
|
||||
@@ -207,7 +208,7 @@ data class DataForConversion private constructor(
|
||||
return clipTo
|
||||
}
|
||||
|
||||
private fun MutableList<Any>.collectElementsToConvert(
|
||||
private fun ElementAndTextList.collectElementsToConvert(
|
||||
file: PsiJavaFile,
|
||||
fileText: String,
|
||||
range: TextRange
|
||||
@@ -218,8 +219,11 @@ data class DataForConversion private constructor(
|
||||
}
|
||||
else {
|
||||
add(fileText.substring(range.start, elements.first().range.start))
|
||||
elements.flatMapTo(this) {
|
||||
if (shouldExpandToChildren(it)) it.allChildren.toList() else listOf(it)
|
||||
elements.forEach {
|
||||
if (shouldExpandToChildren(it))
|
||||
this += it.allChildren.toList()
|
||||
else
|
||||
this += it
|
||||
}
|
||||
add(fileText.substring(elements.last().range.end, range.end))
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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.conversion.copy
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import java.util.*
|
||||
|
||||
|
||||
class ElementAndTextList() {
|
||||
private val elementsAndTexts = ArrayList<Any>()
|
||||
|
||||
constructor(elements: List<Any>) : this() {
|
||||
elementsAndTexts.addAll(elements.filter { it is PsiElement || it is String })
|
||||
}
|
||||
|
||||
fun add(a: String) = elementsAndTexts.add(a)
|
||||
|
||||
fun add(a: PsiElement) = elementsAndTexts.add(a)
|
||||
|
||||
operator fun plusAssign(other: String) = plusAssign(other as Any)
|
||||
|
||||
operator fun plusAssign(other: PsiElement) = plusAssign(other as Any)
|
||||
|
||||
private fun plusAssign(a: Any) {
|
||||
elementsAndTexts.add(a)
|
||||
}
|
||||
|
||||
operator fun plusAssign(other: Collection<PsiElement>): Unit {
|
||||
elementsAndTexts.addAll(other)
|
||||
}
|
||||
|
||||
operator fun plus(other: ElementAndTextList): ElementAndTextList {
|
||||
val newList = ElementAndTextList()
|
||||
newList.elementsAndTexts.addAll(this.elementsAndTexts)
|
||||
newList.elementsAndTexts.addAll(other.elementsAndTexts)
|
||||
return newList
|
||||
}
|
||||
|
||||
fun toList(): List<Any> = elementsAndTexts.toList()
|
||||
|
||||
fun process(processor: ElementsAndTextsProcessor) {
|
||||
elementsAndTexts.forEach {
|
||||
when (it) {
|
||||
is PsiElement -> processor.processElement(it)
|
||||
is String -> processor.processText(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface ElementsAndTextsProcessor {
|
||||
fun processElement(element: PsiElement)
|
||||
fun processText(string: String)
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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.conversion.copy
|
||||
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.search.PsiShortNamesCache
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFully
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getJavaMemberDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||
import org.jetbrains.kotlin.idea.codeInsight.referenceExpression
|
||||
import org.jetbrains.kotlin.idea.core.isVisible
|
||||
import org.jetbrains.kotlin.idea.imports.canBeReferencedViaImport
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
|
||||
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtImportDirective
|
||||
import java.util.*
|
||||
|
||||
|
||||
class PlainTextPasteImportResolver(dataForConversion: DataForConversion, val targetFile: KtFile) {
|
||||
|
||||
private val file = dataForConversion.file
|
||||
private val project = targetFile.project
|
||||
|
||||
private val importList = file.importList!!
|
||||
private val psiElementFactory = PsiElementFactory.SERVICE.getInstance(project)
|
||||
|
||||
private val bindingContext by lazy { targetFile.analyzeFully() }
|
||||
private val resolutionFacade = targetFile.getResolutionFacade()
|
||||
|
||||
private val shortNameCache = PsiShortNamesCache.getInstance(project)
|
||||
private val scope = file.resolveScope
|
||||
|
||||
val failedToResolveReferenceNames = HashSet<String>()
|
||||
var ambiguityInResolution = false
|
||||
var couldNotResolve = false
|
||||
|
||||
val addedImports = ArrayList<PsiImportStatementBase>()
|
||||
|
||||
private fun canBeImported(descriptor: DeclarationDescriptorWithVisibility?): Boolean {
|
||||
return descriptor != null
|
||||
&& descriptor.canBeReferencedViaImport()
|
||||
&& descriptor.isVisible(targetFile, null, bindingContext, resolutionFacade)
|
||||
}
|
||||
|
||||
private fun addImport(importStatement: PsiImportStatementBase, shouldAddToTarget: Boolean = false) {
|
||||
importList.add(importStatement)
|
||||
if (shouldAddToTarget)
|
||||
addedImports.add(importStatement)
|
||||
}
|
||||
|
||||
fun addImportsFromTargetFile() {
|
||||
|
||||
fun tryConvertKotlinImport(importDirective: KtImportDirective) {
|
||||
val importPath = importDirective.importPath
|
||||
val importedReference = importDirective.importedReference
|
||||
if (importPath != null && !importPath.hasAlias() && importedReference is KtDotQualifiedExpression) {
|
||||
val receiver = importedReference
|
||||
.receiverExpression
|
||||
.referenceExpression()
|
||||
?.mainReference
|
||||
?.resolve()
|
||||
val selector = importedReference
|
||||
.selectorExpression
|
||||
?.referenceExpression()
|
||||
?.mainReference
|
||||
?.resolve()
|
||||
|
||||
val isPackageReceiver = receiver is PsiPackage
|
||||
val isClassReceiver = receiver is PsiClass
|
||||
val isClassSelector = selector is PsiClass
|
||||
|
||||
if (importPath.isAllUnder) {
|
||||
if (isClassReceiver)
|
||||
psiElementFactory.createImportStaticStatement(receiver as PsiClass, "*")
|
||||
else if (isPackageReceiver)
|
||||
psiElementFactory.createImportStatementOnDemand((receiver as PsiPackage).qualifiedName)
|
||||
}
|
||||
else {
|
||||
if (isPackageReceiver && isClassSelector)
|
||||
psiElementFactory.createImportStatement(selector as PsiClass)
|
||||
else if (isClassReceiver)
|
||||
psiElementFactory.createImportStaticStatement(receiver as PsiClass, importPath.importedName!!.asString())
|
||||
}
|
||||
}
|
||||
}
|
||||
runWriteAction {
|
||||
targetFile.importDirectives.forEach(::tryConvertKotlinImport)
|
||||
}
|
||||
}
|
||||
|
||||
fun tryResolveReferences() {
|
||||
|
||||
val elementsWithUnresolvedRef = PsiTreeUtil.collectElements(file) {
|
||||
it.reference != null
|
||||
&& it.reference is PsiQualifiedReference
|
||||
&& it.reference?.resolve() == null
|
||||
}
|
||||
|
||||
fun tryResolveReference(reference: PsiQualifiedReference): Boolean {
|
||||
if (reference.resolve() != null) return true
|
||||
val referenceName = reference.referenceName!!
|
||||
if (referenceName in failedToResolveReferenceNames) return false
|
||||
val classes = shortNameCache.getClassesByName(referenceName, scope)
|
||||
.map { it to it.resolveToDescriptor(resolutionFacade) }
|
||||
.filter { canBeImported(it.second) }
|
||||
|
||||
classes.find { (psiClass, descriptor) -> JavaToKotlinClassMap.INSTANCE.mapPlatformClass(descriptor!!).isNotEmpty() }
|
||||
?.let { (psiClass, descriptor) -> addImport(psiElementFactory.createImportStatement(psiClass)) }
|
||||
if (reference.resolve() != null) return true
|
||||
|
||||
classes.singleOrNull()?.let { (psiClass, descriptor) ->
|
||||
addImport(psiElementFactory.createImportStatement(psiClass), true)
|
||||
}
|
||||
|
||||
if (reference.resolve() != null) return true
|
||||
else {
|
||||
if (classes.isNotEmpty()) {
|
||||
ambiguityInResolution = true
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
val members = (shortNameCache.getMethodsByName(referenceName, scope).asList() +
|
||||
shortNameCache.getFieldsByName(referenceName, scope).asList())
|
||||
.map { it as PsiMember }
|
||||
.map { it to it.getJavaMemberDescriptor(resolutionFacade) as? DeclarationDescriptorWithVisibility }
|
||||
.filter { canBeImported(it.second) }
|
||||
|
||||
members.singleOrNull()?.let { (psiMember, descriptor) ->
|
||||
addImport(psiElementFactory.createImportStaticStatement(psiMember.containingClass!!, psiMember.name!!), true)
|
||||
}
|
||||
|
||||
if (reference.resolve() != null) return false
|
||||
else {
|
||||
if (members.isNotEmpty()) {
|
||||
ambiguityInResolution = true
|
||||
}
|
||||
else {
|
||||
couldNotResolve = true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
runWriteAction {
|
||||
elementsWithUnresolvedRef.forEach {
|
||||
val reference = it.reference as PsiQualifiedReference
|
||||
if (!tryResolveReference(reference)) failedToResolveReferenceNames += reference.referenceName!!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
import java.util.ArrayList
|
||||
|
||||
fun foo() {
|
||||
bar(ArrayList<String>())
|
||||
}
|
||||
}
|
||||
@@ -1 +1,3 @@
|
||||
fun foo() = ArrayList<String>()
|
||||
import java.util.ArrayList
|
||||
|
||||
fun foo() = ArrayList<String>()
|
||||
@@ -0,0 +1,34 @@
|
||||
package test;
|
||||
|
||||
public class ToBeImportedJava {
|
||||
public static final String TO_BE_IMPORTED_CONST = "!!!";
|
||||
|
||||
public static void staticMethod() {
|
||||
}
|
||||
}
|
||||
|
||||
public interface IAmbiguousJava {
|
||||
|
||||
}
|
||||
|
||||
public interface AmbiguousJava {
|
||||
|
||||
}
|
||||
|
||||
public interface IAmbiguous {
|
||||
|
||||
}
|
||||
|
||||
public interface Ambiguous {
|
||||
|
||||
}
|
||||
|
||||
public class Z {
|
||||
public interface IAmbiguousJava {
|
||||
|
||||
}
|
||||
|
||||
public interface AmbiguousJava {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package test
|
||||
|
||||
class ToBeImportedKotlin {
|
||||
|
||||
}
|
||||
|
||||
interface IAmbiguous {
|
||||
|
||||
}
|
||||
|
||||
interface Ambiguous {
|
||||
|
||||
}
|
||||
|
||||
|
||||
interface IAmbiguousKotlin {
|
||||
|
||||
}
|
||||
|
||||
interface AmbiguousKotlin {
|
||||
|
||||
}
|
||||
|
||||
class Z {
|
||||
interface IAmbiguousKotlin {
|
||||
|
||||
}
|
||||
|
||||
interface AmbiguousKotlin {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import java.util.ArrayList
|
||||
import test.ToBeImportedJava
|
||||
import test.ToBeImportedKotlin
|
||||
import java.util.HashMap
|
||||
import test.ToBeImportedJava.TO_BE_IMPORTED_CONST
|
||||
import test.ToBeImportedJava.staticMethod
|
||||
|
||||
class Target {
|
||||
var listOfPlatformType: List<String> = ArrayList()
|
||||
|
||||
var unresolved: UnresolvedInterface<UnresolvedGeneric> = UnresolvedImplementation() // Should not add import
|
||||
|
||||
var hashMapOfNotImported: Map<ToBeImportedJava, ToBeImportedKotlin> = HashMap()
|
||||
|
||||
fun acceptKotlinClass(tbi: ToBeImportedKotlin) {
|
||||
|
||||
}
|
||||
|
||||
fun acceptJavaClass(tbi: ToBeImportedJava) {
|
||||
|
||||
}
|
||||
|
||||
var ambiguousKotlin: IAmbiguousKotlin = AmbiguousKotlin() // Should not add import in case of 2 declarations in Kotlin
|
||||
var ambiguous: IAmbiguous = Ambiguous() // Should not add import in case of ambiguous declarations in Kotlin and in Java
|
||||
var ambiguousJava: IAmbiguousJava = AmbiguousJava() // Should not add import in case of 2 declarations in Java
|
||||
|
||||
fun workWithStatics() {
|
||||
val a = TO_BE_IMPORTED_CONST
|
||||
staticMethod()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
class Target {
|
||||
<caret>
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
public List<String> listOfPlatformType = new ArrayList<String>();
|
||||
|
||||
UnresolvedInterface<UnresolvedGeneric> unresolved = new UnresolvedImplementation<>(); // Should not add import
|
||||
|
||||
Map<ToBeImportedJava, ToBeImportedKotlin> hashMapOfNotImported = new HashMap<>();
|
||||
|
||||
void acceptKotlinClass(ToBeImportedKotlin tbi) {
|
||||
|
||||
}
|
||||
|
||||
void acceptJavaClass(ToBeImportedJava tbi) {
|
||||
|
||||
}
|
||||
|
||||
IAmbiguousKotlin ambiguousKotlin = new AmbiguousKotlin(); // Should not add import in case of 2 declarations in Kotlin
|
||||
IAmbiguous ambiguous = new Ambiguous(); // Should not add import in case of ambiguous declarations in Kotlin and in Java
|
||||
IAmbiguousJava ambiguousJava = new AmbiguousJava(); // Should not add import in case of 2 declarations in Java
|
||||
|
||||
void workWithStatics() {
|
||||
String a = TO_BE_IMPORTED_CONST;
|
||||
staticMethod();
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
import java.util.ArrayList
|
||||
|
||||
fun foo() {
|
||||
bar(/*comment*/ArrayList<String>())
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
import java.util.ArrayList
|
||||
|
||||
class A {
|
||||
fun foo() {
|
||||
val list = ArrayList<String>()
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package to
|
||||
|
||||
import java.util.ArrayList
|
||||
|
||||
|
||||
fun foo() {
|
||||
val list = ArrayList<String>()
|
||||
list.add(1)
|
||||
|
||||
+2
@@ -1,3 +1,5 @@
|
||||
import java.util.ArrayList
|
||||
|
||||
fun foo() {
|
||||
val list = ArrayList<String>()
|
||||
list.add(1)
|
||||
|
||||
+6
@@ -47,6 +47,12 @@ public class TextJavaToKotlinCopyPasteConversionTestGenerated extends AbstractTe
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ImportResolve.txt")
|
||||
public void testImportResolve() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/copyPaste/plainTextConversion/ImportResolve.txt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("InsideIdentifier.txt")
|
||||
public void testInsideIdentifier() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/copyPaste/plainTextConversion/InsideIdentifier.txt");
|
||||
|
||||
Reference in New Issue
Block a user