J2K: correct mutable/non-mutable types for overrides of Kotlin methods

This commit is contained in:
Valentin Kipyatkov
2014-10-29 16:07:07 +03:00
committed by valentin
parent 0092c952ef
commit 17622f8259
14 changed files with 92 additions and 15 deletions
@@ -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) })
@@ -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" }
+6 -3
View File
@@ -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()
}
}
@@ -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) }
@@ -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]
}
@@ -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");
@@ -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");
+2
View File
@@ -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)
}
}