J2K: correct mutable/non-mutable types for overrides of Kotlin methods
This commit is contained in:
committed by
valentin
parent
0092c952ef
commit
17622f8259
@@ -407,7 +407,15 @@ public class ResolveSession implements KotlinCodeAnalyzer {
|
||||
return getBindingContext().get(BindingContext.VALUE_PARAMETER, parameter);
|
||||
}
|
||||
}
|
||||
return super.visitParameter(parameter, data);
|
||||
else if (grandFather instanceof JetNamedFunction) {
|
||||
FunctionDescriptor function = (FunctionDescriptor) visitNamedFunction((JetNamedFunction) grandFather, data);
|
||||
function.getValueParameters();
|
||||
return getBindingContext().get(BindingContext.VALUE_PARAMETER, parameter);
|
||||
}
|
||||
else {
|
||||
//TODO: support parameters in accessors and other places(?)
|
||||
return super.visitParameter(parameter, data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -38,6 +38,7 @@ import org.jetbrains.jet.plugin.j2k.J2kPostProcessor
|
||||
import com.intellij.openapi.vfs.CharsetToolkit
|
||||
import org.jetbrains.jet.lang.psi.JetFile
|
||||
import org.jetbrains.jet.utils.addIfNotNull
|
||||
import org.jetbrains.jet.plugin.caches.resolve.getLazyResolveSession
|
||||
|
||||
public class JavaToKotlinAction : AnAction() {
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
@@ -110,7 +111,7 @@ public class JavaToKotlinAction : AnAction() {
|
||||
}
|
||||
|
||||
private fun convertFiles(javaFiles: List<PsiJavaFile>, project: Project): List<VirtualFile> {
|
||||
val converter = JavaToKotlinConverter(project, ConverterSettings.defaultSettings, FilesConversionScope(javaFiles), IdeaReferenceSearcher)
|
||||
val converter = JavaToKotlinConverter(project, ConverterSettings.defaultSettings, FilesConversionScope(javaFiles), IdeaReferenceSearcher, { it.getLazyResolveSession() })
|
||||
|
||||
val convertedTexts = converter.elementsToKotlin(javaFiles.map { it to J2kPostProcessor(it) })
|
||||
|
||||
|
||||
+3
-1
@@ -34,6 +34,7 @@ import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager
|
||||
import com.intellij.lang.java.JavaLanguage
|
||||
import org.jetbrains.jet.plugin.j2k.J2kPostProcessor
|
||||
import org.jetbrains.jet.plugin.caches.resolve.getLazyResolveSession
|
||||
|
||||
public class ConvertJavaCopyPastePostProcessor() : CopyPastePostProcessor<TextBlockTransferableData>() {
|
||||
|
||||
@@ -89,7 +90,8 @@ public class ConvertJavaCopyPastePostProcessor() : CopyPastePostProcessor<TextBl
|
||||
val converter = JavaToKotlinConverter(fileCopiedFrom.getProject(),
|
||||
ConverterSettings.defaultSettings,
|
||||
FilesConversionScope(listOf(fileCopiedFrom)),
|
||||
IdeaReferenceSearcher)
|
||||
IdeaReferenceSearcher,
|
||||
{ it.getLazyResolveSession() })
|
||||
val startOffsets = code.startOffsets
|
||||
val endOffsets = code.endOffsets
|
||||
assert(startOffsets.size == endOffsets.size) { "Must have the same size" }
|
||||
|
||||
@@ -27,11 +27,14 @@ import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.jet.j2k.usageProcessing.UsageProcessing
|
||||
import org.jetbrains.jet.j2k.usageProcessing.FieldToPropertyProcessing
|
||||
import org.jetbrains.jet.j2k.usageProcessing.UsageProcessingExpressionConverter
|
||||
import org.jetbrains.jet.lang.psi.JetElement
|
||||
import org.jetbrains.jet.lang.resolve.lazy.KotlinCodeAnalyzer
|
||||
|
||||
class Converter private(private val elementToConvert: PsiElement,
|
||||
val settings: ConverterSettings,
|
||||
val conversionScope: ConversionScope,
|
||||
val referenceSearcher: ReferenceSearcher,
|
||||
val lazyResolveSessionGetter: ((JetElement) -> KotlinCodeAnalyzer)?,
|
||||
private val postProcessor: PostProcessor?,
|
||||
private val commonState: Converter.CommonState,
|
||||
private val personalState: Converter.PersonalState) {
|
||||
@@ -59,15 +62,15 @@ class Converter private(private val elementToConvert: PsiElement,
|
||||
|
||||
class object {
|
||||
public fun create(elementToConvert: PsiElement, settings: ConverterSettings, conversionScope: ConversionScope,
|
||||
referenceSearcher: ReferenceSearcher, postProcessor: PostProcessor?): Converter {
|
||||
return Converter(elementToConvert, settings, conversionScope, referenceSearcher, postProcessor, CommonState(), PersonalState(null))
|
||||
referenceSearcher: ReferenceSearcher, lazyResolveSessionGetter: ((JetElement) -> KotlinCodeAnalyzer)?, postProcessor: PostProcessor?): Converter {
|
||||
return Converter(elementToConvert, settings, conversionScope, referenceSearcher, lazyResolveSessionGetter, postProcessor, CommonState(), PersonalState(null))
|
||||
}
|
||||
}
|
||||
|
||||
public fun withSpecialContext(context: PsiElement): Converter = withState(PersonalState(context))
|
||||
|
||||
private fun withState(state: PersonalState): Converter
|
||||
= Converter(elementToConvert, settings, conversionScope, referenceSearcher, postProcessor, commonState, state)
|
||||
= Converter(elementToConvert, settings, conversionScope, referenceSearcher, lazyResolveSessionGetter, postProcessor, commonState, state)
|
||||
|
||||
private fun createDefaultCodeConverter() = CodeConverter(this, DefaultExpressionConverter(), DefaultStatementConverter(), null)
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@ import org.jetbrains.jet.lang.resolve.BindingContext
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import java.util.ArrayList
|
||||
import org.jetbrains.jet.j2k.usageProcessing.UsageProcessing
|
||||
import org.jetbrains.jet.lang.psi.JetElement
|
||||
import org.jetbrains.jet.lang.resolve.lazy.KotlinCodeAnalyzer
|
||||
|
||||
public trait ConversionScope {
|
||||
public fun contains(element: PsiElement): Boolean
|
||||
@@ -44,7 +46,8 @@ public trait PostProcessor {
|
||||
public class JavaToKotlinConverter(private val project: Project,
|
||||
private val settings: ConverterSettings,
|
||||
private val conversionScope: ConversionScope /*TODO: drop this parameter*/,
|
||||
private val referenceSearcher: ReferenceSearcher) {
|
||||
private val referenceSearcher: ReferenceSearcher,
|
||||
private val lazyResolveSessionGetter: ((JetElement) -> KotlinCodeAnalyzer)?) {
|
||||
private val LOG = Logger.getInstance("#org.jetbrains.jet.j2k.JavaToKotlinConverter")
|
||||
|
||||
public fun elementsToKotlin(psiElementsAndProcessors: List<Pair<PsiElement, PostProcessor?>>): List<String> {
|
||||
@@ -52,7 +55,7 @@ public class JavaToKotlinConverter(private val project: Project,
|
||||
val intermediateResults = ArrayList<Converter.IntermediateResult?>(psiElementsAndProcessors.size)
|
||||
val usageProcessings = ArrayList<UsageProcessing>()
|
||||
for ((psiElement, postProcessor) in psiElementsAndProcessors) {
|
||||
val converter = Converter.create(psiElement, settings, conversionScope, referenceSearcher, postProcessor)
|
||||
val converter = Converter.create(psiElement, settings, conversionScope, referenceSearcher, lazyResolveSessionGetter, postProcessor)
|
||||
val result = converter.convert()
|
||||
intermediateResults.add(result)
|
||||
result?.usageProcessings?.let { usageProcessings.addAll(it) }
|
||||
|
||||
@@ -90,7 +90,7 @@ public object JavaToKotlinTranslator {
|
||||
fun generateKotlinCode(javaCode: String): String {
|
||||
val file = createFile(javaCode)
|
||||
if (file is PsiJavaFile) {
|
||||
val converter = JavaToKotlinConverter(file.getProject(), ConverterSettings.defaultSettings, FilesConversionScope(listOf(file)), EmptyReferenceSearcher)
|
||||
val converter = JavaToKotlinConverter(file.getProject(), ConverterSettings.defaultSettings, FilesConversionScope(listOf(file)), EmptyReferenceSearcher, null)
|
||||
return prettify(converter.elementsToKotlin(listOf(file to null))[0])
|
||||
}
|
||||
return ""
|
||||
|
||||
@@ -31,6 +31,11 @@ import org.jetbrains.jet.j2k.ast.Identifier
|
||||
import java.util.HashMap
|
||||
import org.jetbrains.jet.j2k.ast.Mutability
|
||||
import java.util.HashSet
|
||||
import org.jetbrains.jet.asJava.KotlinLightElement
|
||||
import org.jetbrains.jet.lang.psi.JetCallableDeclaration
|
||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor
|
||||
import org.jetbrains.jet.lang.types.TypeUtils
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils
|
||||
|
||||
class TypeConverter(val converter: Converter) {
|
||||
public fun convertType(type: PsiType?, nullability: Nullability = Nullability.Default, mutability: Mutability = Mutability.Default): Type {
|
||||
@@ -363,6 +368,20 @@ class TypeConverter(val converter: Converter) {
|
||||
}
|
||||
|
||||
override fun fromAnnotations(owner: PsiModifierListOwner): Mutability {
|
||||
if (owner is KotlinLightElement<*, *>) {
|
||||
val jetDeclaration = owner.origin as? JetCallableDeclaration ?: return Mutability.Default
|
||||
val codeAnalyzer = converter.lazyResolveSessionGetter?.invoke(jetDeclaration)
|
||||
val descriptor = codeAnalyzer?.resolveToDescriptor(jetDeclaration)
|
||||
as? CallableDescriptor ?: return Mutability.Default
|
||||
val type = descriptor.getReturnType() ?: return Mutability.Default
|
||||
val classDescriptor = TypeUtils.getClassDescriptor(type) ?: return Mutability.Default
|
||||
return if (DescriptorUtils.getFqName(classDescriptor).asString() in mutableKotlinClasses)
|
||||
Mutability.Mutable
|
||||
else
|
||||
Mutability.NonMutable
|
||||
}
|
||||
//TODO: Kotlin compiled elements
|
||||
|
||||
return super<TypeFlavor>.fromAnnotations(owner) //TODO: ReadOnly annotation
|
||||
}
|
||||
|
||||
@@ -408,5 +427,7 @@ class TypeConverter(val converter: Converter) {
|
||||
private val modificationMethodNames = setOf(
|
||||
"add", "remove", "set", "addAll", "removeAll", "retainAll", "clear", "put", "putAll"
|
||||
)
|
||||
|
||||
private val mutableKotlinClasses = TypeVisitor.toKotlinMutableTypesMap.values().toSet()
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -32,6 +32,7 @@ import com.intellij.psi.PsiManager
|
||||
import java.util.ArrayList
|
||||
import org.jetbrains.jet.j2k.ConverterSettings
|
||||
import org.jetbrains.jet.lang.psi.JetFile
|
||||
import org.jetbrains.jet.plugin.caches.resolve.getLazyResolveSession
|
||||
|
||||
public abstract class AbstractJavaToKotlinConverterMultiFileTest() : AbstractJavaToKotlinConverterTest() {
|
||||
public fun doTest(dirPath: String) {
|
||||
@@ -46,7 +47,7 @@ public abstract class AbstractJavaToKotlinConverterMultiFileTest() : AbstractJav
|
||||
psiFiles.add(psiFile)
|
||||
}
|
||||
|
||||
val converter = JavaToKotlinConverter(project, ConverterSettings.defaultSettings, FilesConversionScope(psiFiles), IdeaReferenceSearcher)
|
||||
val converter = JavaToKotlinConverter(project, ConverterSettings.defaultSettings, FilesConversionScope(psiFiles), IdeaReferenceSearcher, { it.getLazyResolveSession() })
|
||||
val results: List<String> = converter.elementsToKotlin(psiFiles.map { it to J2kPostProcessor(it) })
|
||||
.map { reformat(it, project) }
|
||||
|
||||
|
||||
+3
-5
@@ -33,9 +33,7 @@ import com.intellij.psi.PsiJavaFile
|
||||
import org.jetbrains.jet.j2k.IdeaReferenceSearcher
|
||||
import org.jetbrains.jet.j2k.JavaToKotlinConverter
|
||||
import org.jetbrains.jet.lang.psi.JetFile
|
||||
import org.jetbrains.jet.plugin.caches.resolve.getAnalysisResults
|
||||
import org.jetbrains.jet.lang.diagnostics.Severity
|
||||
import org.jetbrains.jet.lang.diagnostics.rendering.DefaultErrorMessages
|
||||
import org.jetbrains.jet.plugin.caches.resolve.getLazyResolveSession
|
||||
|
||||
public abstract class AbstractJavaToKotlinConverterSingleFileTest() : AbstractJavaToKotlinConverterTest() {
|
||||
val testHeaderPattern = Pattern.compile("//(element|expression|statement|method|class|file|comp)\n")
|
||||
@@ -113,14 +111,14 @@ public abstract class AbstractJavaToKotlinConverterSingleFileTest() : AbstractJa
|
||||
|
||||
private fun elementToKotlin(text: String, settings: ConverterSettings, project: Project): String {
|
||||
val fileWithText = createJavaFile(text)
|
||||
val converter = JavaToKotlinConverter(project, settings, FilesConversionScope(listOf(fileWithText)), IdeaReferenceSearcher)
|
||||
val converter = JavaToKotlinConverter(project, settings, FilesConversionScope(listOf(fileWithText)), IdeaReferenceSearcher, { it.getLazyResolveSession() })
|
||||
val element = fileWithText.getFirstChild()!!
|
||||
return converter.elementsToKotlin(listOf(element to J2kPostProcessor(fileWithText)))[0]
|
||||
}
|
||||
|
||||
private fun fileToKotlin(text: String, settings: ConverterSettings, project: Project): String {
|
||||
val file = createJavaFile(text)
|
||||
val converter = JavaToKotlinConverter(project, settings, FilesConversionScope(listOf(file)), IdeaReferenceSearcher)
|
||||
val converter = JavaToKotlinConverter(project, settings, FilesConversionScope(listOf(file)), IdeaReferenceSearcher, { it.getLazyResolveSession() })
|
||||
return converter.elementsToKotlin(listOf(file to J2kPostProcessor(file)))[0]
|
||||
}
|
||||
|
||||
|
||||
+6
@@ -2799,6 +2799,12 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("Overrides.java")
|
||||
public void testOverrides() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("j2k/tests/testData/fileOrElement/mutableCollections/Overrides.java");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("Recursion.java")
|
||||
public void testRecursion() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("j2k/tests/testData/fileOrElement/mutableCollections/Recursion.java");
|
||||
|
||||
+6
@@ -2799,6 +2799,12 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("Overrides.java")
|
||||
public void testOverrides() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("j2k/tests/testData/fileOrElement/mutableCollections/Overrides.java");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("Recursion.java")
|
||||
public void testRecursion() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("j2k/tests/testData/fileOrElement/mutableCollections/Recursion.java");
|
||||
|
||||
@@ -4,6 +4,8 @@ public open class KotlinClass(public var field: Int) {
|
||||
public var property: String = ""
|
||||
public var nullableProperty: String? = ""
|
||||
|
||||
public open fun foo(mutableCollection: MutableCollection<String>, nullableCollection: Collection<Int>?): MutableList<Any> = arrayListOf()
|
||||
|
||||
class object {
|
||||
public fun staticFun(p: Int): Int = p
|
||||
public var staticVar: Int = 1
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package javaApi;
|
||||
|
||||
import kotlinApi.KotlinClass;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class C extends KotlinClass {
|
||||
public C(int field) {
|
||||
super(field);
|
||||
}
|
||||
|
||||
public List<Object> foo(Collection<String> mutableCollection, Collection<? extends Integer> nullableCollection) {
|
||||
return super.foo(mutableCollection, nullableCollection);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package javaApi
|
||||
|
||||
import kotlinApi.KotlinClass
|
||||
|
||||
public abstract class C(field: Int) : KotlinClass(field) {
|
||||
|
||||
override fun foo(mutableCollection: MutableCollection<String>, nullableCollection: Collection<out Int>?): MutableList<Any> {
|
||||
return super.foo(mutableCollection, nullableCollection)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user