KT-7135 Java to Kotlin converter should update usages in Java and Koltin code in the rest of the project
#KT-7135 Fixed
This commit is contained in:
@@ -714,7 +714,7 @@ fun main(args: Array<String>) {
|
||||
}
|
||||
testGroup("j2k/tests", "j2k/testData") {
|
||||
testClass(javaClass<AbstractJavaToKotlinConverterMultiFileTest>()) {
|
||||
model("multiFile", extension = null)
|
||||
model("multiFile", extension = null, recursive = false)
|
||||
}
|
||||
}
|
||||
testGroup("j2k/tests", "j2k/testData") {
|
||||
|
||||
+2
-1
@@ -126,7 +126,8 @@ public class JetSimpleNameReference(
|
||||
)
|
||||
}
|
||||
|
||||
return nameElement.replace(element)
|
||||
nameElement.replace(element)
|
||||
return expression
|
||||
}
|
||||
|
||||
public enum class ShorteningMode {
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.actions
|
||||
|
||||
import com.intellij.codeInsight.actions.ReformatCodeProcessor
|
||||
import com.intellij.openapi.actionSystem.AnAction
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys
|
||||
@@ -25,6 +24,7 @@ import com.intellij.openapi.command.CommandProcessor
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager
|
||||
import com.intellij.openapi.progress.ProgressManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.Messages
|
||||
import com.intellij.openapi.ui.ex.MessagesEx
|
||||
import com.intellij.openapi.vfs.CharsetToolkit
|
||||
import com.intellij.openapi.vfs.VfsUtilCore
|
||||
@@ -32,14 +32,14 @@ import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.openapi.vfs.VirtualFileVisitor
|
||||
import com.intellij.psi.PsiJavaFile
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager
|
||||
import org.jetbrains.kotlin.idea.j2k.IdeaResolverForConverter
|
||||
import org.jetbrains.kotlin.idea.j2k.J2kPostProcessor
|
||||
import org.jetbrains.kotlin.idea.util.application.executeCommand
|
||||
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.j2k.ConverterSettings
|
||||
import org.jetbrains.kotlin.j2k.IdeaReferenceSearcher
|
||||
import org.jetbrains.kotlin.j2k.JavaToKotlinConverter
|
||||
import org.jetbrains.kotlin.psi.JetFile
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import java.io.IOException
|
||||
import java.util.ArrayList
|
||||
@@ -49,36 +49,53 @@ public class JavaToKotlinAction : AnAction() {
|
||||
val javaFiles = selectedJavaFiles(e).toList()
|
||||
val project = CommonDataKeys.PROJECT.getData(e.getDataContext())!!
|
||||
|
||||
var convertedTexts: List<String>? = null
|
||||
var converterResult: JavaToKotlinConverter.Result? = null
|
||||
fun convert() {
|
||||
val converter = JavaToKotlinConverter(project, ConverterSettings.defaultSettings,
|
||||
IdeaReferenceSearcher, IdeaResolverForConverter, J2kPostProcessor(formatCode = true))
|
||||
val inputElements = javaFiles.map { JavaToKotlinConverter.InputElement(it, it) }
|
||||
convertedTexts = converter.elementsToKotlin(inputElements, ProgressManager.getInstance().getProgressIndicator())
|
||||
.map { it!!.text /*conversion of a file always succeeds*/ }
|
||||
converterResult = converter.elementsToKotlin(inputElements, ProgressManager.getInstance().getProgressIndicator())
|
||||
}
|
||||
|
||||
val title = "Convert Java to Kotlin"
|
||||
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(
|
||||
{
|
||||
runReadAction(::convert)
|
||||
},
|
||||
"Converting Java to Kotlin",
|
||||
title,
|
||||
true,
|
||||
project)) return
|
||||
|
||||
|
||||
CommandProcessor.getInstance().executeCommand(project, object : Runnable {
|
||||
override fun run() {
|
||||
CommandProcessor.getInstance().markCurrentCommandAsGlobal(project)
|
||||
var externalCodeUpdate: (() -> Unit)? = null
|
||||
|
||||
val newFiles = saveResults(javaFiles, convertedTexts!!)
|
||||
deleteFiles(javaFiles)
|
||||
|
||||
newFiles.singleOrNull()?.let {
|
||||
FileEditorManager.getInstance(project).openFile(it, true)
|
||||
}
|
||||
if (converterResult!!.externalCodeProcessing != null) {
|
||||
val question = "Some code in the rest of your project may require corrections after performing this conversion. Do you want to find such code and correct it too?"
|
||||
if (Messages.showOkCancelDialog(project, question, title, Messages.getQuestionIcon()) == Messages.OK) {
|
||||
ProgressManager.getInstance().runProcessWithProgressSynchronously(
|
||||
{
|
||||
runReadAction {
|
||||
externalCodeUpdate = converterResult!!.externalCodeProcessing(ProgressManager.getInstance().getProgressIndicator())
|
||||
}
|
||||
},
|
||||
title,
|
||||
true,
|
||||
project)
|
||||
}
|
||||
}, "Convert files from Java to Kotlin", null)
|
||||
}
|
||||
|
||||
project.executeWriteCommand("Convert files from Java to Kotlin") {
|
||||
CommandProcessor.getInstance().markCurrentCommandAsGlobal(project)
|
||||
|
||||
val newFiles = saveResults(javaFiles, converterResult!!.results.map { it!!.text /*conversion of a file always succeeds*/ })
|
||||
deleteFiles(javaFiles)
|
||||
|
||||
externalCodeUpdate?.invoke()
|
||||
|
||||
newFiles.singleOrNull()?.let {
|
||||
FileEditorManager.getInstance(project).openFile(it, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun update(e: AnActionEvent) {
|
||||
@@ -116,9 +133,7 @@ public class JavaToKotlinAction : AnAction() {
|
||||
private fun saveResults(javaFiles: List<PsiJavaFile>, convertedTexts: List<String>): List<VirtualFile> {
|
||||
val result = ArrayList<VirtualFile>()
|
||||
for ((psiFile, text) in javaFiles.zip(convertedTexts)) {
|
||||
ApplicationManager.getApplication().runWriteAction {
|
||||
result.addIfNotNull(saveConversionResult(psiFile.getVirtualFile(), text, psiFile.getProject()))
|
||||
}
|
||||
result.addIfNotNull(saveConversionResult(psiFile.getVirtualFile(), text, psiFile.getProject()))
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -137,13 +152,11 @@ public class JavaToKotlinAction : AnAction() {
|
||||
|
||||
private fun deleteFiles(javaFiles: List<PsiJavaFile>) {
|
||||
for (psiFile in javaFiles) {
|
||||
ApplicationManager.getApplication().runWriteAction {
|
||||
try {
|
||||
psiFile.getVirtualFile()?.delete(this)
|
||||
}
|
||||
catch (e: IOException) {
|
||||
MessagesEx.error(psiFile.getProject(), e.getMessage()).showLater()
|
||||
}
|
||||
try {
|
||||
psiFile.getVirtualFile()?.delete(this)
|
||||
}
|
||||
catch (e: IOException) {
|
||||
MessagesEx.error(psiFile.getProject(), e.getMessage()).showLater()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -161,7 +161,7 @@ public class ConvertJavaCopyPastePostProcessor : CopyPastePostProcessor<TextBloc
|
||||
)
|
||||
|
||||
val inputElements = list.filterIsInstance<PsiElement>().map { JavaToKotlinConverter.InputElement(it, null) }
|
||||
val results = converter.elementsToKotlin(inputElements)
|
||||
val results = converter.elementsToKotlin(inputElements).results
|
||||
|
||||
var resultIndex = 0
|
||||
val convertedCodeBuilder = StringBuilder()
|
||||
|
||||
@@ -21,6 +21,10 @@ import com.intellij.psi.*
|
||||
import org.jetbrains.kotlin.j2k.ast.*
|
||||
import org.jetbrains.kotlin.j2k.ast.Class
|
||||
import org.jetbrains.kotlin.j2k.usageProcessing.AccessorToPropertyProcessing
|
||||
import org.jetbrains.kotlin.j2k.usageProcessing.MethodIntoObjectProcessing
|
||||
import org.jetbrains.kotlin.j2k.usageProcessing.ToObjectWithOnlyMethodsProcessing
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import java.util.ArrayList
|
||||
import java.util.HashMap
|
||||
import java.util.HashSet
|
||||
@@ -71,6 +75,19 @@ class ClassBodyConverter(private val psiClass: PsiClass,
|
||||
val rBrace = RBrace().assignPrototype(psiClass.getRBrace())
|
||||
|
||||
if (isObject) {
|
||||
val psiMembers = convertedMembers.keySet()
|
||||
if (psiMembers.all { it is PsiMethod }) { // for object with no fields we can use faster external usage processing
|
||||
converter.addUsageProcessing(ToObjectWithOnlyMethodsProcessing(psiClass))
|
||||
}
|
||||
else {
|
||||
for (psiMember in psiMembers) {
|
||||
if (psiMember is PsiMethod /* fields in object can be accessed as fields from java */
|
||||
&& !psiMember.hasModifierProperty(PsiModifier.PRIVATE)) {
|
||||
converter.addUsageProcessing(MethodIntoObjectProcessing(psiMember, JvmAbi.INSTANCE_FIELD))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ClassBody(null, null, convertedMembers.values().toList(), emptyList(), lBrace, rBrace)
|
||||
}
|
||||
|
||||
@@ -87,6 +104,10 @@ class ClassBodyConverter(private val psiClass: PsiClass,
|
||||
}
|
||||
else if (useCompanionObject && member !is Class && psiMember !is PsiEnumConstant && psiMember.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
companionObjectMembers.add(member)
|
||||
if (psiMember is PsiMethod /* fields in companion object can be accessed as fields from java */
|
||||
&& !psiMember.hasModifierProperty(PsiModifier.PRIVATE)) {
|
||||
converter.addUsageProcessing(MethodIntoObjectProcessing(psiMember, SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT.getIdentifier()))
|
||||
}
|
||||
}
|
||||
else {
|
||||
members.add(member)
|
||||
@@ -179,10 +200,11 @@ class ClassBodyConverter(private val psiClass: PsiClass,
|
||||
|
||||
private fun getAccessorInfo(method: PsiMethod): AccessorInfo? {
|
||||
val name = method.getName()
|
||||
val static = method.hasModifierProperty(PsiModifier.STATIC)
|
||||
if (name.startsWith("get") && method.getParameterList().getParametersCount() == 0) {
|
||||
val body = method.getBody() ?: return null
|
||||
val returnStatement = (body.getStatements().singleOrNull() as? PsiReturnStatement) ?: return null
|
||||
val field = fieldByExpression(returnStatement.getReturnValue()) ?: return null
|
||||
val field = fieldByExpression(returnStatement.getReturnValue(), static) ?: return null
|
||||
if (field.getType() != method.getReturnType()) return null
|
||||
if (converter.typeConverter.variableMutability(field) != converter.typeConverter.methodMutability(method)) return null
|
||||
val propertyName = StringUtil.decapitalize(name.substring("get".length()))
|
||||
@@ -193,7 +215,7 @@ class ClassBodyConverter(private val psiClass: PsiClass,
|
||||
val statement = (body.getStatements().singleOrNull() as? PsiExpressionStatement) ?: return null
|
||||
val assignment = statement.getExpression() as? PsiAssignmentExpression ?: return null
|
||||
if (assignment.getOperationTokenType() != JavaTokenType.EQ) return null
|
||||
val field = fieldByExpression(assignment.getLExpression()) ?: return null
|
||||
val field = fieldByExpression(assignment.getLExpression(), static) ?: return null
|
||||
val parameter = method.getParameterList().getParameters().single()
|
||||
if ((assignment.getRExpression() as? PsiReferenceExpression)?.resolve() != parameter) return null
|
||||
if (field.getType() != parameter.getType()) return null
|
||||
@@ -205,11 +227,16 @@ class ClassBodyConverter(private val psiClass: PsiClass,
|
||||
}
|
||||
}
|
||||
|
||||
private fun fieldByExpression(expression: PsiExpression?): PsiField? {
|
||||
private fun fieldByExpression(expression: PsiExpression?, static: Boolean): PsiField? {
|
||||
val refExpr = expression as? PsiReferenceExpression ?: return null
|
||||
if (!refExpr.isQualifierEmptyOrThis()) return null
|
||||
if (static) {
|
||||
if (!refExpr.isQualifierEmptyOrClass(psiClass)) return null
|
||||
}
|
||||
else {
|
||||
if (!refExpr.isQualifierEmptyOrThis()) return null
|
||||
}
|
||||
val field = refExpr.resolve() as? PsiField ?: return null
|
||||
if (field.getContainingClass() != psiClass || field.hasModifierProperty(PsiModifier.STATIC)) return null
|
||||
if (field.getContainingClass() != psiClass || field.hasModifierProperty(PsiModifier.STATIC) != static) return null
|
||||
return field
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.j2k
|
||||
|
||||
import com.google.common.collect.Multimap
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.CommonClassNames.*
|
||||
@@ -73,7 +74,7 @@ class Converter private(
|
||||
private fun createDefaultCodeConverter() = CodeConverter(this, DefaultExpressionConverter(), DefaultStatementConverter(), null)
|
||||
|
||||
public data class IntermediateResult(
|
||||
val codeGenerator: (Map<PsiElement, UsageProcessing>) -> String,
|
||||
val codeGenerator: (Map<PsiElement, Collection<UsageProcessing>>) -> String,
|
||||
val parseContext: ParseContext
|
||||
)
|
||||
|
||||
@@ -108,7 +109,7 @@ class Converter private(
|
||||
else -> null
|
||||
}
|
||||
|
||||
private fun unfoldDeferredElements(usageProcessings: Map<PsiElement, UsageProcessing>) {
|
||||
private fun unfoldDeferredElements(usageProcessings: Map<PsiElement, Collection<UsageProcessing>>) {
|
||||
val codeConverter = createDefaultCodeConverter().withSpecialExpressionConverter(UsageProcessingExpressionConverter(usageProcessings))
|
||||
|
||||
// we use loop with index because new deferred elements can be added during unfolding
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.j2k
|
||||
|
||||
import com.intellij.ide.util.DelegatingProgressIndicator
|
||||
import com.intellij.lang.java.JavaLanguage
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.editor.RangeMarker
|
||||
import com.intellij.openapi.progress.EmptyProgressIndicator
|
||||
@@ -26,15 +28,19 @@ import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiNamedElement
|
||||
import com.intellij.psi.PsiReference
|
||||
import com.intellij.psi.impl.source.DummyHolder
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.idea.JetLanguage
|
||||
import org.jetbrains.kotlin.j2k.ast.Element
|
||||
import org.jetbrains.kotlin.j2k.usageProcessing.UsageProcessing
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import java.util.ArrayList
|
||||
import java.util.HashMap
|
||||
import java.util.*
|
||||
|
||||
public trait PostProcessor {
|
||||
public fun analyzeFile(file: JetFile, range: TextRange?): BindingContext
|
||||
@@ -80,22 +86,26 @@ public class JavaToKotlinConverter(private val project: Project,
|
||||
val postProcessingContext: PsiElement?
|
||||
)
|
||||
|
||||
public data class Result(val text: String, val parseContext: ParseContext)
|
||||
public data class ElementResult(val text: String, val parseContext: ParseContext)
|
||||
|
||||
public data class Result(val results: List<ElementResult?>, val externalCodeProcessing: ((ProgressIndicator) -> (() -> Unit)?)?) //TODO: change interface to not perform write-actions under progress
|
||||
|
||||
public fun elementsToKotlin(
|
||||
inputElements: List<InputElement>,
|
||||
progress: ProgressIndicator = EmptyProgressIndicator()
|
||||
): List<Result?> {
|
||||
): Result {
|
||||
try {
|
||||
val elementCount = inputElements.size()
|
||||
val intermediateResults = ArrayList<(Converter.IntermediateResult)?>(elementCount)
|
||||
val usageProcessings = HashMap<PsiElement, UsageProcessing>()
|
||||
val usageProcessingCollector: (UsageProcessing) -> Unit = { usageProcessing ->
|
||||
assert(!usageProcessings.containsKey(usageProcessing.targetElement))
|
||||
{ "Duplicated UsageProcessing for target element ${usageProcessing.targetElement}" }
|
||||
usageProcessings.put(usageProcessing.targetElement, usageProcessing)
|
||||
|
||||
val usageProcessings = LinkedHashMap<PsiElement, MutableCollection<UsageProcessing>>()
|
||||
val usageProcessingCollector: (UsageProcessing) -> Unit = {
|
||||
usageProcessings.getOrPut(it.targetElement, { ArrayList() }).add(it)
|
||||
}
|
||||
|
||||
fun inConversionScope(element: PsiElement)
|
||||
= inputElements.any { it.element.isAncestor(element, strict = false) }
|
||||
|
||||
val progressText = "Converting Java to Kotlin"
|
||||
val fileCountText = elementCount.toString() + " " + if (elementCount > 1) "files" else "file"
|
||||
var fraction = 0.0
|
||||
@@ -128,31 +138,29 @@ public class JavaToKotlinConverter(private val project: Project,
|
||||
|
||||
processFilesWithProgress(0.25) { i ->
|
||||
val psiElement = inputElements[i].element
|
||||
|
||||
fun inConversionScope(element: PsiElement)
|
||||
= inputElements.any { it.element.isAncestor(element, strict = false) }
|
||||
|
||||
val converter = Converter.create(psiElement, settings, ::inConversionScope, referenceSearcher, resolverForConverter, usageProcessingCollector)
|
||||
val result = converter.convert()
|
||||
intermediateResults.add(result)
|
||||
}
|
||||
|
||||
val results = ArrayList<Result?>(elementCount)
|
||||
val results = ArrayList<ElementResult?>(elementCount)
|
||||
processFilesWithProgress(0.25) { i ->
|
||||
val result = intermediateResults[i]
|
||||
results.add(if (result != null)
|
||||
Result(result.codeGenerator(usageProcessings), result.parseContext)
|
||||
ElementResult(result.codeGenerator(usageProcessings), result.parseContext)
|
||||
else
|
||||
null)
|
||||
intermediateResults[i] = null // to not hold unused objects in the heap
|
||||
}
|
||||
|
||||
val externalCodeProcessing = buildExternalCodeProcessing(usageProcessings, ::inConversionScope)
|
||||
|
||||
if (postProcessor == null) {
|
||||
assert(progress is EmptyProgressIndicator, "Progress indicator not supported for postProcessor == null")
|
||||
return results
|
||||
return Result(results, externalCodeProcessing)
|
||||
}
|
||||
|
||||
val finalResults = ArrayList<Result?>(elementCount)
|
||||
val finalResults = ArrayList<ElementResult?>(elementCount)
|
||||
processFilesWithProgress(0.5) { i ->
|
||||
val result = results[i]
|
||||
if (result != null) {
|
||||
@@ -160,7 +168,7 @@ public class JavaToKotlinConverter(private val project: Project,
|
||||
//TODO: post processing does not work correctly for ParseContext different from TOP_LEVEL
|
||||
val kotlinFile = JetPsiFactory(project).createAnalyzableFile("dummy.kt", result.text, inputElements[i].postProcessingContext!!)
|
||||
AfterConversionPass(project, postProcessor).run(kotlinFile, range = null)
|
||||
finalResults.add(Result(kotlinFile.getText(), result.parseContext))
|
||||
finalResults.add(ElementResult(kotlinFile.getText(), result.parseContext))
|
||||
}
|
||||
catch(e: ProcessCanceledException) {
|
||||
throw e
|
||||
@@ -175,7 +183,7 @@ public class JavaToKotlinConverter(private val project: Project,
|
||||
}
|
||||
}
|
||||
|
||||
return finalResults
|
||||
return Result(finalResults, externalCodeProcessing)
|
||||
}
|
||||
catch(e: ElementCreationStackTraceRequiredException) {
|
||||
// if we got this exception then we need to turn element creation stack traces on to get better diagnostic
|
||||
@@ -188,4 +196,130 @@ public class JavaToKotlinConverter(private val project: Project,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class ReferenceInfo(
|
||||
val reference: PsiReference,
|
||||
val target: PsiElement,
|
||||
val file: PsiFile,
|
||||
val processings: Collection<UsageProcessing>
|
||||
)
|
||||
|
||||
private fun buildExternalCodeProcessing(
|
||||
usageProcessings: Map<PsiElement, Collection<UsageProcessing>>,
|
||||
inConversionScope: (PsiElement) -> Boolean
|
||||
): ((ProgressIndicator) -> (() -> Unit)?)? {
|
||||
if (usageProcessings.isEmpty()) return null
|
||||
|
||||
|
||||
val map: Map<PsiElement, Collection<UsageProcessing>> = usageProcessings.values()
|
||||
.flatMap { it }
|
||||
.filter { it.javaCodeProcessor != null || it.kotlinCodeProcessor != null }
|
||||
.groupBy { it.targetElement }
|
||||
if (map.isEmpty()) return null
|
||||
|
||||
return fun(progress: ProgressIndicator): (() -> Unit)? {
|
||||
val refs = ArrayList<ReferenceInfo>()
|
||||
|
||||
progress.setText("Searching usages to update...")
|
||||
|
||||
for ((i, entry) in map.entrySet().withIndex()) {
|
||||
val psiElement = entry.key
|
||||
val processings = entry.value
|
||||
|
||||
progress.setText2((psiElement as? PsiNamedElement)?.getName() ?: "")
|
||||
progress.checkCanceled()
|
||||
|
||||
ProgressManager.getInstance().runProcess(
|
||||
{
|
||||
val searchJava = processings.any { it.javaCodeProcessor != null }
|
||||
val searchKotlin = processings.any { it.kotlinCodeProcessor != null }
|
||||
referenceSearcher.findExternalCodeProcessingUsages(psiElement, searchJava, searchKotlin)
|
||||
.filterNot { inConversionScope(it.getElement()) }
|
||||
.mapTo(refs) { ReferenceInfo(it, psiElement, it.getElement().getContainingFile(), processings) }
|
||||
},
|
||||
ProgressPortionReporter(progress, i / map.size().toDouble(), 1.0 / map.size()))
|
||||
|
||||
}
|
||||
|
||||
if (refs.isEmpty()) return null
|
||||
|
||||
return { processUsages(refs) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun processUsages(refs: Collection<ReferenceInfo>) {
|
||||
@ReferenceLoop
|
||||
for ((reference, target, file, processings) in refs.sortBy(ReferenceComparator)) {
|
||||
val processors = when (reference.getElement().getLanguage()) {
|
||||
JavaLanguage.INSTANCE -> processings.map { it.javaCodeProcessor }.filterNotNull()
|
||||
JetLanguage.INSTANCE -> processings.map { it.kotlinCodeProcessor }.filterNotNull()
|
||||
else -> continue@ReferenceLoop
|
||||
}
|
||||
|
||||
checkReferenceValid(reference)
|
||||
|
||||
var references = listOf(reference)
|
||||
for (processor in processors) {
|
||||
references = references.flatMap { processor.processUsage(it) ?: listOf(it) }
|
||||
references.forEach { checkReferenceValid(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkReferenceValid(reference: PsiReference) {
|
||||
val element = reference.getElement()
|
||||
assert(element.isValid() && element.getContainingFile() !is DummyHolder) { "Reference $reference got invalidated" }
|
||||
}
|
||||
|
||||
private object ReferenceComparator : Comparator<ReferenceInfo> {
|
||||
override fun compare(info1: ReferenceInfo, info2: ReferenceInfo): Int {
|
||||
val element1 = info1.reference.getElement()
|
||||
val element2 = info2.reference.getElement()
|
||||
|
||||
val deepness1 = element1.deepnessInTree()
|
||||
val deepness2 = element2.deepnessInTree()
|
||||
if (deepness1 != deepness2) { // put deeper elements first to not invalidate them when processing ancestors
|
||||
return -deepness1.compareTo(deepness2)
|
||||
}
|
||||
|
||||
// process elements of the same deepness from right to left so that right-side of assignments is not invalidated by processing of the left one
|
||||
return -element1.getStartOffsetInParent().compareTo(element2.getStartOffsetInParent())
|
||||
}
|
||||
|
||||
private fun PsiElement.deepnessInTree() = parents(withItself = true).takeWhile { it !is PsiFile }.count()
|
||||
|
||||
}
|
||||
|
||||
private class ProgressPortionReporter(
|
||||
indicator: ProgressIndicator,
|
||||
private val start: Double,
|
||||
private val portion: Double
|
||||
) : DelegatingProgressIndicator(indicator) {
|
||||
|
||||
init {
|
||||
setFraction(0.0)
|
||||
}
|
||||
|
||||
override fun start() {
|
||||
setFraction(0.0)
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
setFraction(portion)
|
||||
}
|
||||
|
||||
override fun setFraction(fraction: Double) {
|
||||
super.setFraction(start + (fraction * portion))
|
||||
}
|
||||
|
||||
override fun getFraction(): Double {
|
||||
return (super.getFraction() - start) / portion
|
||||
}
|
||||
|
||||
override fun setText(text: String?) {
|
||||
}
|
||||
|
||||
override fun setText2(text: String?) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ public object JavaToKotlinTranslator {
|
||||
val file = createFile(javaCode)
|
||||
if (file is PsiJavaFile) {
|
||||
val converter = JavaToKotlinConverter(file.getProject(), ConverterSettings.defaultSettings, EmptyReferenceSearcher, EmptyResolverForConverter, null)
|
||||
return prettify(converter.elementsToKotlin(listOf(JavaToKotlinConverter.InputElement(file, null))).single()!!.text)
|
||||
return prettify(converter.elementsToKotlin(listOf(JavaToKotlinConverter.InputElement(file, null))).results.single()!!.text)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -16,49 +16,67 @@
|
||||
|
||||
package org.jetbrains.kotlin.j2k
|
||||
|
||||
import com.intellij.psi.PsiVariable
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiReferenceExpression
|
||||
import com.intellij.psi.search.searches.ReferencesSearch
|
||||
import com.intellij.lang.java.JavaLanguage
|
||||
import com.intellij.openapi.fileTypes.FileTypeManager
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.search.DelegatingGlobalSearchScope
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.search.LocalSearchScope
|
||||
import com.intellij.psi.PsiMethod
|
||||
import com.intellij.psi.PsiMethodCallExpression
|
||||
import com.intellij.psi.PsiClass
|
||||
import com.intellij.psi.search.searches.ClassInheritorsSearch
|
||||
import com.intellij.psi.search.searches.OverridingMethodsSearch
|
||||
import com.intellij.psi.search.searches.ReferencesSearch
|
||||
import org.jetbrains.kotlin.idea.JetLanguage
|
||||
|
||||
public trait ReferenceSearcher {
|
||||
fun findVariableUsages(variable: PsiVariable, scope: PsiElement): Collection<PsiReferenceExpression>
|
||||
fun findMethodCalls(method: PsiMethod, scope: PsiElement): Collection<PsiMethodCallExpression>
|
||||
fun findLocalUsages(element: PsiElement, scope: PsiElement): Collection<PsiReference>
|
||||
fun hasInheritors(`class`: PsiClass): Boolean
|
||||
fun hasOverrides(method: PsiMethod): Boolean
|
||||
|
||||
fun findExternalCodeProcessingUsages(element: PsiElement, searchJava: Boolean, searchKotlin: Boolean): Collection<PsiReference>
|
||||
}
|
||||
|
||||
public fun ReferenceSearcher.findVariableUsages(variable: PsiVariable, scope: PsiElement): Collection<PsiReferenceExpression>
|
||||
= findLocalUsages(variable, scope).filterIsInstance<PsiReferenceExpression>()
|
||||
|
||||
public fun ReferenceSearcher.findMethodCalls(method: PsiMethod, scope: PsiElement): Collection<PsiMethodCallExpression> {
|
||||
return findLocalUsages(method, scope).map {
|
||||
if (it is PsiReferenceExpression) {
|
||||
val methodCall = it.getParent() as? PsiMethodCallExpression
|
||||
if (methodCall?.getMethodExpression() == it) methodCall else null
|
||||
}
|
||||
else {
|
||||
null
|
||||
}
|
||||
}.filterNotNull()
|
||||
}
|
||||
|
||||
public object EmptyReferenceSearcher: ReferenceSearcher {
|
||||
override fun findVariableUsages(variable: PsiVariable, scope: PsiElement) = listOf<PsiReferenceExpression>()
|
||||
override fun findMethodCalls(method: PsiMethod, scope: PsiElement) = listOf<PsiMethodCallExpression>()
|
||||
override fun findLocalUsages(element: PsiElement, scope: PsiElement): Collection<PsiReference> = emptyList()
|
||||
override fun hasInheritors(`class`: PsiClass) = false
|
||||
override fun hasOverrides(method: PsiMethod) = false
|
||||
override fun findExternalCodeProcessingUsages(element: PsiElement, searchJava: Boolean, searchKotlin: Boolean): Collection<PsiReference>
|
||||
= throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
public object IdeaReferenceSearcher : ReferenceSearcher {
|
||||
override fun findVariableUsages(variable: PsiVariable, scope: PsiElement): Collection<PsiReferenceExpression> {
|
||||
return ReferencesSearch.search(variable, LocalSearchScope(scope)).findAll().filterIsInstance<PsiReferenceExpression>()
|
||||
}
|
||||
|
||||
override fun findMethodCalls(method: PsiMethod, scope: PsiElement): Collection<PsiMethodCallExpression> {
|
||||
return ReferencesSearch.search(method, LocalSearchScope(scope)).findAll().map {
|
||||
if (it is PsiReferenceExpression) {
|
||||
val methodCall = it.getParent() as? PsiMethodCallExpression
|
||||
if (methodCall?.getMethodExpression() == it) methodCall else null
|
||||
}
|
||||
else {
|
||||
null
|
||||
}
|
||||
}.filterNotNull()
|
||||
}
|
||||
public object IdeaReferenceSearcher: ReferenceSearcher {
|
||||
override fun findLocalUsages(element: PsiElement, scope: PsiElement) = ReferencesSearch.search(element, LocalSearchScope(scope)).findAll()
|
||||
|
||||
override fun hasInheritors(`class`: PsiClass) = ClassInheritorsSearch.search(`class`, false).any()
|
||||
|
||||
override fun hasOverrides(method: PsiMethod) = OverridingMethodsSearch.search(method, false).any()
|
||||
|
||||
override fun findExternalCodeProcessingUsages(element: PsiElement, searchJava: Boolean, searchKotlin: Boolean): Collection<PsiReference> {
|
||||
val searchScope = object : DelegatingGlobalSearchScope(GlobalSearchScope.projectScope(element.getProject())) {
|
||||
override fun contains(file: VirtualFile): Boolean {
|
||||
if (!super.contains(file)) return false
|
||||
return when (FileTypeManager.getInstance().getFileTypeByFile(file)) {
|
||||
JavaLanguage.INSTANCE.getAssociatedFileType() -> searchJava
|
||||
JetLanguage.INSTANCE.getAssociatedFileType() -> searchKotlin
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
return ReferencesSearch.search(element, searchScope).findAll()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +79,11 @@ fun PsiReferenceExpression.isQualifierEmptyOrThis(): Boolean {
|
||||
return qualifier == null || (qualifier is PsiThisExpression && qualifier.getQualifier() == null)
|
||||
}
|
||||
|
||||
fun PsiReferenceExpression.isQualifierEmptyOrClass(psiClass: PsiClass): Boolean {
|
||||
val qualifier = getQualifierExpression()
|
||||
return qualifier == null || (qualifier is PsiReferenceExpression && qualifier.isReferenceTo(psiClass))
|
||||
}
|
||||
|
||||
fun PsiElement.isInSingleLine(): Boolean {
|
||||
if (this is PsiWhiteSpace) {
|
||||
val text = getText()!!
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
package org.jetbrains.kotlin.j2k.usageProcessing
|
||||
|
||||
import com.intellij.psi.*
|
||||
import org.jetbrains.kotlin.j2k.*
|
||||
import org.jetbrains.kotlin.j2k.AccessorKind
|
||||
import org.jetbrains.kotlin.j2k.CodeConverter
|
||||
import org.jetbrains.kotlin.j2k.ast.*
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
class AccessorToPropertyProcessing(val accessorMethod: PsiMethod, val accessorKind: AccessorKind, val propertyName: String) : UsageProcessing {
|
||||
override val targetElement: PsiElement get() = accessorMethod
|
||||
@@ -34,11 +36,11 @@ class AccessorToPropertyProcessing(val accessorMethod: PsiMethod, val accessorKi
|
||||
val propertyAccess = QualifiedExpression(codeConverter.convertExpression(methodExpr.getQualifierExpression()), propertyName).assignNoPrototype()
|
||||
|
||||
if (accessorKind == AccessorKind.GETTER) {
|
||||
if (arguments.size != 0) return null // incorrect call
|
||||
if (arguments.size() != 0) return null // incorrect call
|
||||
return propertyAccess
|
||||
}
|
||||
else {
|
||||
if (arguments.size != 1) return null // incorrect call
|
||||
if (arguments.size() != 1) return null // incorrect call
|
||||
val argument = codeConverter.convertExpression(arguments[0])
|
||||
return AssignmentExpression(propertyAccess, argument, "=")
|
||||
}
|
||||
@@ -47,10 +49,42 @@ class AccessorToPropertyProcessing(val accessorMethod: PsiMethod, val accessorKi
|
||||
|
||||
override val javaCodeProcessor: ExternalCodeProcessor? = null
|
||||
|
||||
override val kotlinCodeProcessor: ExternalCodeProcessor? = object: ExternalCodeProcessor {
|
||||
override fun processUsage(reference: PsiReference) {
|
||||
//TODO
|
||||
//reference.getElement() as JetSimpleNameExpression
|
||||
override val kotlinCodeProcessor: ExternalCodeProcessor? = if (accessorMethod.hasModifierProperty(PsiModifier.PRIVATE))
|
||||
null
|
||||
else
|
||||
object : ExternalCodeProcessor {
|
||||
override fun processUsage(reference: PsiReference): Collection<PsiReference>? {
|
||||
val nameExpr = reference.getElement() as? JetSimpleNameExpression ?: return null
|
||||
val callExpr = nameExpr.getParent() as? JetCallExpression ?: return null
|
||||
|
||||
val arguments = callExpr.getValueArguments()
|
||||
|
||||
val factory = JetPsiFactory(nameExpr.getProject())
|
||||
var propertyNameExpr = factory.createSimpleName(propertyName)
|
||||
if (accessorKind == AccessorKind.GETTER) {
|
||||
if (arguments.size() != 0) return null // incorrect call
|
||||
propertyNameExpr = callExpr.replace(propertyNameExpr) as JetSimpleNameExpression
|
||||
return listOf(propertyNameExpr.getReference())
|
||||
}
|
||||
else {
|
||||
val value = arguments.singleOrNull()?.getArgumentExpression() ?: return null
|
||||
var assignment = factory.createExpression("a = b") as JetBinaryExpression
|
||||
assignment.getRight()!!.replace(value)
|
||||
|
||||
val qualifiedExpression = callExpr.getParent() as? JetQualifiedExpression
|
||||
if (qualifiedExpression != null && qualifiedExpression.getSelectorExpression() == callExpr) {
|
||||
callExpr.replace(propertyNameExpr)
|
||||
assignment.getLeft()!!.replace(qualifiedExpression)
|
||||
assignment = qualifiedExpression.replace(assignment) as JetBinaryExpression
|
||||
return listOf((assignment.getLeft() as JetQualifiedExpression).getSelectorExpression()!!.getReference())
|
||||
}
|
||||
else {
|
||||
assignment.getLeft()!!.replace(propertyNameExpr)
|
||||
assignment = callExpr.replace(assignment) as JetBinaryExpression
|
||||
return listOf(assignment.getLeft()!!.getReference())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.j2k.usageProcessing
|
||||
|
||||
import com.intellij.psi.PsiReference
|
||||
|
||||
class ElementRenamedCodeProcessor(private val newName: String) : ExternalCodeProcessor {
|
||||
override fun processUsage(reference: PsiReference): Collection<PsiReference>? {
|
||||
val newReference = reference.handleElementRename(newName).getReference()!!
|
||||
return listOf(newReference)
|
||||
}
|
||||
}
|
||||
@@ -17,44 +17,135 @@
|
||||
package org.jetbrains.kotlin.j2k.usageProcessing
|
||||
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.util.IncorrectOperationException
|
||||
import org.jetbrains.kotlin.j2k.AccessorKind
|
||||
import org.jetbrains.kotlin.j2k.CodeConverter
|
||||
import org.jetbrains.kotlin.j2k.ast.*
|
||||
import com.intellij.util.IncorrectOperationException
|
||||
import org.jetbrains.kotlin.psi.JetPsiFactory
|
||||
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
|
||||
|
||||
class FieldToPropertyProcessing(val field: PsiField, val propertyName: String, val isNullable: Boolean) : UsageProcessing {
|
||||
override val targetElement: PsiElement get() = field
|
||||
|
||||
override val convertedCodeProcessor = if (field.getName() != propertyName) {
|
||||
object: ConvertedCodeProcessor {
|
||||
override fun convertVariableUsage(expression: PsiReferenceExpression, codeConverter: CodeConverter): Expression? {
|
||||
val identifier = Identifier(propertyName, isNullable).assignNoPrototype()
|
||||
override val convertedCodeProcessor = if (field.getName() != propertyName) MyConvertedCodeProcessor() else null
|
||||
|
||||
val qualifier = expression.getQualifierExpression()
|
||||
if (qualifier != null) {
|
||||
return QualifiedExpression(codeConverter.convertExpression(qualifier), identifier)
|
||||
override var javaCodeProcessor = if (field.hasModifierProperty(PsiModifier.PRIVATE))
|
||||
null
|
||||
else if (!field.hasModifierProperty(PsiModifier.STATIC))
|
||||
UseAccessorsJavaCodeProcessor()
|
||||
else if (field.getName() != propertyName)
|
||||
ElementRenamedCodeProcessor(propertyName)
|
||||
else
|
||||
null
|
||||
|
||||
override val kotlinCodeProcessor = if (field.getName() != propertyName) ElementRenamedCodeProcessor(propertyName) else null
|
||||
|
||||
private inner class MyConvertedCodeProcessor : ConvertedCodeProcessor {
|
||||
override fun convertVariableUsage(expression: PsiReferenceExpression, codeConverter: CodeConverter): Expression? {
|
||||
val identifier = Identifier(propertyName, isNullable).assignNoPrototype()
|
||||
|
||||
val qualifier = expression.getQualifierExpression()
|
||||
if (qualifier != null) {
|
||||
return QualifiedExpression(codeConverter.convertExpression(qualifier), identifier)
|
||||
}
|
||||
else {
|
||||
// check if field name is shadowed
|
||||
val elementFactory = PsiElementFactory.SERVICE.getInstance(expression.getProject())
|
||||
val refExpr = try {
|
||||
elementFactory.createExpressionFromText(propertyName, expression) as? PsiReferenceExpression ?: return identifier
|
||||
}
|
||||
else {
|
||||
// check if field name is shadowed
|
||||
val elementFactory = PsiElementFactory.SERVICE.getInstance(expression.getProject())
|
||||
val refExpr = try {
|
||||
elementFactory.createExpressionFromText(propertyName, expression) as? PsiReferenceExpression ?: return identifier
|
||||
}
|
||||
catch(e: IncorrectOperationException) {
|
||||
return identifier
|
||||
}
|
||||
return if (refExpr.resolve() == null)
|
||||
identifier
|
||||
else
|
||||
QualifiedExpression(ThisExpression(Identifier.Empty).assignNoPrototype(), identifier) //TODO: this is not correct in case of nested/anonymous classes
|
||||
catch(e: IncorrectOperationException) {
|
||||
return identifier
|
||||
}
|
||||
return if (refExpr.resolve() == null)
|
||||
identifier
|
||||
else
|
||||
QualifiedExpression(ThisExpression(Identifier.Empty).assignNoPrototype(), identifier) //TODO: this is not correct in case of nested/anonymous classes
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
null
|
||||
|
||||
private inner class UseAccessorsJavaCodeProcessor : ExternalCodeProcessor {
|
||||
private val factory = PsiElementFactory.SERVICE.getInstance(field.getProject())
|
||||
|
||||
override fun processUsage(reference: PsiReference): Collection<PsiReference>? {
|
||||
val refExpr = reference.getElement() as? PsiReferenceExpression ?: return null
|
||||
val qualifier = refExpr.getQualifierExpression()
|
||||
|
||||
val parent = refExpr.getParent()
|
||||
when (parent) {
|
||||
is PsiAssignmentExpression -> {
|
||||
if (refExpr == parent.getLExpression()) {
|
||||
if (parent.getOperationTokenType() == JavaTokenType.EQ) {
|
||||
val callExpr = parent.replace(generateSetterCall(qualifier, parent.getRExpression() ?: return null)) as PsiMethodCallExpression
|
||||
return listOf(callExpr.getMethodExpression())
|
||||
}
|
||||
else {
|
||||
val assignmentOpText = parent.getOperationSign().getText()
|
||||
assert(assignmentOpText.endsWith("="))
|
||||
val opText = assignmentOpText.substring(0, assignmentOpText.length() - 1)
|
||||
return parent.replaceWithModificationCalls(qualifier, opText, parent.getRExpression() ?: return null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is PsiPrefixExpression, is PsiPostfixExpression -> {
|
||||
//TODO: what if it's used as value?
|
||||
val operationType = if (parent is PsiPrefixExpression)
|
||||
parent.getOperationTokenType()
|
||||
else
|
||||
(parent as PsiPostfixExpression).getOperationTokenType()
|
||||
val opText = when (operationType) {
|
||||
JavaTokenType.PLUSPLUS -> "+"
|
||||
JavaTokenType.MINUSMINUS -> "-"
|
||||
else -> null
|
||||
}
|
||||
if (opText != null) {
|
||||
return (parent as PsiExpression).replaceWithModificationCalls(qualifier, opText, factory.createExpressionFromText("1", null))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val callExpr = refExpr.replace(generateGetterCall(qualifier)) as PsiMethodCallExpression
|
||||
return listOf(callExpr.getMethodExpression())
|
||||
}
|
||||
|
||||
//TODO: what if qualifier has side effects?
|
||||
private fun PsiExpression.replaceWithModificationCalls(qualifier: PsiExpression?, op: String, value: PsiExpression): Collection<PsiReference> {
|
||||
var getCall = generateGetterCall(qualifier)
|
||||
|
||||
var binary = factory.createExpressionFromText("x $op y", null) as PsiBinaryExpression
|
||||
binary.getLOperand().replace(getCall)
|
||||
binary.getROperand()!!.replace(value)
|
||||
|
||||
var setCall = generateSetterCall(qualifier, binary) as PsiMethodCallExpression
|
||||
setCall = this.replace(setCall) as PsiMethodCallExpression
|
||||
|
||||
binary = setCall.getArgumentList().getExpressions().single() as PsiBinaryExpression
|
||||
getCall = binary.getLOperand() as PsiMethodCallExpression
|
||||
|
||||
return listOf(getCall.getMethodExpression().getReference(), setCall.getMethodExpression().getReference())
|
||||
}
|
||||
|
||||
private fun generateGetterCall(qualifier: PsiExpression?): PsiMethodCallExpression {
|
||||
val text = accessorName(AccessorKind.GETTER) + "()"
|
||||
val expressionText = if (qualifier != null)
|
||||
"${qualifier.getText()}.$text"
|
||||
else
|
||||
text
|
||||
return factory.createExpressionFromText(expressionText, null) as PsiMethodCallExpression
|
||||
}
|
||||
|
||||
private fun generateSetterCall(qualifier: PsiExpression?, value: PsiExpression): PsiExpression {
|
||||
val text = accessorName(AccessorKind.SETTER) + "(" + value.getText() + ")"
|
||||
val expressionText = if (qualifier != null)
|
||||
"${qualifier.getText()}.$text"
|
||||
else
|
||||
text
|
||||
return factory.createExpressionFromText(expressionText, null)
|
||||
}
|
||||
}
|
||||
|
||||
override val javaCodeProcessor: ExternalCodeProcessor? get() = null //TODO
|
||||
|
||||
override val kotlinCodeProcessor: ExternalCodeProcessor? get() = null //TODO
|
||||
private fun accessorName(kind: AccessorKind)
|
||||
= (if (kind == AccessorKind.GETTER) "get" else "set") + propertyName.capitalize()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.j2k.usageProcessing
|
||||
|
||||
import com.intellij.psi.*
|
||||
|
||||
public class MethodIntoObjectProcessing(private val method: PsiMethod, private val objectName: String) : UsageProcessing {
|
||||
override val targetElement: PsiElement get() = method
|
||||
|
||||
override val convertedCodeProcessor: ConvertedCodeProcessor? get() = null
|
||||
|
||||
override val javaCodeProcessor = object: ExternalCodeProcessor {
|
||||
override fun processUsage(reference: PsiReference): Collection<PsiReference>? {
|
||||
val refExpr = reference.getElement() as? PsiReferenceExpression ?: return null
|
||||
val qualifier = refExpr.getQualifierExpression()
|
||||
val factory = PsiElementFactory.SERVICE.getInstance(method.getProject())
|
||||
if (qualifier != null) {
|
||||
val newQualifier = factory.createExpressionFromText(qualifier.getText() + "." + objectName, null)
|
||||
qualifier.replace(newQualifier)
|
||||
return listOf(reference)
|
||||
}
|
||||
else {
|
||||
var qualifiedExpr = factory.createExpressionFromText(objectName + "." + refExpr.getText(), null) as PsiReferenceExpression
|
||||
qualifiedExpr = refExpr.replace(qualifiedExpr) as PsiReferenceExpression
|
||||
return listOf(qualifiedExpr.getReference())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override val kotlinCodeProcessor: ExternalCodeProcessor? get() = null
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.j2k.usageProcessing
|
||||
|
||||
import com.intellij.psi.*
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
|
||||
class ToObjectWithOnlyMethodsProcessing(private val psiClass: PsiClass) : UsageProcessing {
|
||||
override val targetElement: PsiElement get() = psiClass
|
||||
|
||||
override val convertedCodeProcessor: ConvertedCodeProcessor? get() = null
|
||||
|
||||
override val javaCodeProcessor = object: ExternalCodeProcessor {
|
||||
override fun processUsage(reference: PsiReference): Collection<PsiReference>? {
|
||||
val refExpr = reference.getElement() as? PsiReferenceExpression ?: return null
|
||||
val factory = PsiElementFactory.SERVICE.getInstance(psiClass.getProject())
|
||||
var qualifiedExpr = factory.createExpressionFromText(refExpr.getText() + "." + JvmAbi.INSTANCE_FIELD, null) as PsiReferenceExpression
|
||||
qualifiedExpr = refExpr.replace(qualifiedExpr) as PsiReferenceExpression
|
||||
return listOf(qualifiedExpr.getReference())
|
||||
}
|
||||
}
|
||||
|
||||
override val kotlinCodeProcessor: ExternalCodeProcessor? get() = null
|
||||
}
|
||||
@@ -16,10 +16,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.j2k.usageProcessing
|
||||
|
||||
import org.jetbrains.kotlin.j2k.ast.Expression
|
||||
import com.google.common.collect.Multimap
|
||||
import com.intellij.psi.*
|
||||
import org.jetbrains.kotlin.j2k.CodeConverter
|
||||
import org.jetbrains.kotlin.j2k.SpecialExpressionConverter
|
||||
import org.jetbrains.kotlin.j2k.ast.Expression
|
||||
|
||||
trait UsageProcessing {
|
||||
val targetElement: PsiElement
|
||||
@@ -35,24 +36,32 @@ trait ConvertedCodeProcessor {
|
||||
}
|
||||
|
||||
trait ExternalCodeProcessor {
|
||||
fun processUsage(reference: PsiReference)
|
||||
fun processUsage(reference: PsiReference): Collection<PsiReference>?
|
||||
}
|
||||
|
||||
class UsageProcessingExpressionConverter(val processings: Map<PsiElement, UsageProcessing>) : SpecialExpressionConverter {
|
||||
class UsageProcessingExpressionConverter(val processings: Map<PsiElement, Collection<UsageProcessing>>) : SpecialExpressionConverter {
|
||||
override fun convertExpression(expression: PsiExpression, codeConverter: CodeConverter): Expression? {
|
||||
if (processings.isEmpty()) return null
|
||||
|
||||
when (expression) {
|
||||
is PsiReferenceExpression -> {
|
||||
val target = expression.resolve() as? PsiVariable ?: return null
|
||||
val processor = processings[target]?.convertedCodeProcessor ?: return null
|
||||
return processor.convertVariableUsage(expression, codeConverter)
|
||||
val forTarget = processings[target] ?: return null
|
||||
for (processing in forTarget) {
|
||||
val converted = processing.convertedCodeProcessor?.convertVariableUsage(expression, codeConverter)
|
||||
if (converted != null) return converted
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
is PsiMethodCallExpression -> {
|
||||
val target = expression.getMethodExpression().resolve() as? PsiMethod ?: return null
|
||||
val processor = processings[target]?.convertedCodeProcessor ?: return null
|
||||
return processor.convertMethodUsage(expression, codeConverter)
|
||||
val forTarget = processings[target] ?: return null
|
||||
for (processing in forTarget) {
|
||||
val converted = processing.convertedCodeProcessor?.convertMethodUsage(expression, codeConverter)
|
||||
if (converted != null) return converted
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
else -> return null
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
public class AAA {
|
||||
public void foo() {
|
||||
setX(getX() + 1);
|
||||
}
|
||||
|
||||
private static int ourX = 42;
|
||||
|
||||
public static int getX() {
|
||||
return ourX;
|
||||
}
|
||||
|
||||
public static void setX(int x) {
|
||||
ourX = x;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
public class AAA {
|
||||
public fun foo() {
|
||||
x = x + 1
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
public var x: Int = 42
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
public class AAA {
|
||||
private static int ourX = 42;
|
||||
private static int y = 0;
|
||||
private static int z = 0;
|
||||
|
||||
public static int getX() {
|
||||
return ourX;
|
||||
}
|
||||
|
||||
public static void setX(int x) {
|
||||
ourX = x;
|
||||
}
|
||||
|
||||
public static int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public static void setY(int y) {
|
||||
AAA.y = y;
|
||||
}
|
||||
|
||||
public static int getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
public static void setZ(int z) {
|
||||
Other.z = z;
|
||||
}
|
||||
}
|
||||
|
||||
class Other {
|
||||
public static int z = 0;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
public object AAA {
|
||||
public var x: Int = 42
|
||||
public var y: Int = 0
|
||||
public val z: Int = 0
|
||||
|
||||
public fun setZ(z: Int) {
|
||||
Other.z = z
|
||||
}
|
||||
}
|
||||
|
||||
object Other {
|
||||
public var z: Int = 0
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package test;
|
||||
|
||||
class JavaClass {
|
||||
public int field = 0;
|
||||
|
||||
protected int myProperty = 0;
|
||||
|
||||
public int getProperty() {
|
||||
return myProperty;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package test
|
||||
|
||||
open class JavaClass {
|
||||
public var field: Int = 0
|
||||
|
||||
public var property: Int = 0
|
||||
protected set
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package test;
|
||||
|
||||
class C extends JavaClass {
|
||||
public void foo(JavaClass javaClass) {
|
||||
javaClass.field++;
|
||||
--javaClass.field;
|
||||
myProperty = javaClass.field;
|
||||
javaClass.field -= field;
|
||||
field = myProperty;
|
||||
field *= 2;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package test;
|
||||
|
||||
class C extends JavaClass {
|
||||
public void foo(JavaClass javaClass) {
|
||||
javaClass.setField(javaClass.getField() + 1);
|
||||
javaClass.setField(javaClass.getField() - 1);
|
||||
setProperty(javaClass.getField());
|
||||
javaClass.setField(javaClass.getField() - getField());
|
||||
setField(getProperty());
|
||||
setField(getField() * 2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package test
|
||||
|
||||
class C : JavaClass() {
|
||||
public fun foo(javaClass: JavaClass) {
|
||||
javaClass.field++
|
||||
myProperty = javaClass.field
|
||||
field = myProperty
|
||||
field *= 2
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package test
|
||||
|
||||
class C : JavaClass() {
|
||||
public fun foo(javaClass: JavaClass) {
|
||||
javaClass.field++
|
||||
property = javaClass.field
|
||||
field = property
|
||||
field *= 2
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fun foo1(a: AAA) {
|
||||
a.setX(a.getX() + 1)
|
||||
}
|
||||
|
||||
fun foo2(a: AAA?) {
|
||||
a?.setX((a?.getX() ?: 0) + 1)
|
||||
}
|
||||
|
||||
fun AAA.foo() {
|
||||
setX(getX() + 1)
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fun foo1(a: AAA) {
|
||||
a.x = a.x + 1
|
||||
}
|
||||
|
||||
fun foo2(a: AAA?) {
|
||||
a?.x = (a?.x ?: 0) + 1
|
||||
}
|
||||
|
||||
fun AAA.foo() {
|
||||
x = x + 1
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
void foo(AAA a) {
|
||||
a.setX(a.getX() + 1)
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
void foo(AAA a) {
|
||||
a.setX(a.getX() + 1)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package test;
|
||||
|
||||
class ClassWithStatics {
|
||||
public void instanceMethod(){}
|
||||
|
||||
public static void staticMethod(int p) {}
|
||||
|
||||
public static final int staticField = 1;
|
||||
|
||||
protected static int ourValue = 0;
|
||||
|
||||
public static int getValue() { return ourValue; }
|
||||
public static void setValue(int value) { ourValue = value; }
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package test
|
||||
|
||||
open class ClassWithStatics {
|
||||
public fun instanceMethod() {
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
public fun staticMethod(p: Int) {
|
||||
}
|
||||
|
||||
public val staticField: Int = 1
|
||||
|
||||
public var value: Int = 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package test;
|
||||
|
||||
class C {
|
||||
void foo(ClassWithStatics c) {
|
||||
ClassWithStatics.staticMethod(ClassWithStatics.staticField);
|
||||
c.instanceMethod();
|
||||
ClassWithStatics.staticField += 2;
|
||||
}
|
||||
}
|
||||
|
||||
class D extends ClassWithStatics {
|
||||
void foo() {
|
||||
staticMethod(staticField);
|
||||
ourValue *= 2;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package test;
|
||||
|
||||
class C {
|
||||
void foo(ClassWithStatics c) {
|
||||
ClassWithStatics.Companion.staticMethod(ClassWithStatics.staticField);
|
||||
c.instanceMethod();
|
||||
ClassWithStatics.staticField += 2;
|
||||
}
|
||||
}
|
||||
|
||||
class D extends ClassWithStatics {
|
||||
void foo() {
|
||||
Companion.staticMethod(staticField);
|
||||
value *= 2;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package test
|
||||
|
||||
fun foo() {
|
||||
ClassWithStatics.staticMethod(ClassWithStatics.staticField)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package test
|
||||
|
||||
fun foo() {
|
||||
ClassWithStatics.staticMethod(ClassWithStatics.staticField)
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package test;
|
||||
|
||||
class PureUtils {
|
||||
public static void foo1(int p) {}
|
||||
public static int foo2() { return 1; }
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package test
|
||||
|
||||
object PureUtils {
|
||||
public fun foo1(p: Int) {
|
||||
}
|
||||
|
||||
public fun foo2(): Int {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package test;
|
||||
|
||||
class Utils {
|
||||
public static void foo1(int p) {}
|
||||
public static int foo2() { return 1; }
|
||||
|
||||
public static final int staticField = 1;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package test
|
||||
|
||||
object Utils {
|
||||
public fun foo1(p: Int) {
|
||||
}
|
||||
|
||||
public fun foo2(): Int {
|
||||
return 1
|
||||
}
|
||||
|
||||
public val staticField: Int = 1
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package test;
|
||||
|
||||
class C {
|
||||
void foo() {
|
||||
Utils.foo1(Utils.staticField);
|
||||
Utils.staticField += Utils.foo2();
|
||||
PureUtils.foo1(PureUtils.foo2())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package test;
|
||||
|
||||
class C {
|
||||
void foo() {
|
||||
Utils.INSTANCE$.foo1(Utils.staticField);
|
||||
Utils.staticField += Utils.INSTANCE$.foo2();
|
||||
PureUtils.INSTANCE$.foo1(PureUtils.INSTANCE$.foo2())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package test
|
||||
|
||||
fun foo() {
|
||||
Utils.foo1(Utils.staticField)
|
||||
PureUtils.foo1(PureUtils.foo2())
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package test
|
||||
|
||||
fun foo() {
|
||||
Utils.foo1(Utils.staticField)
|
||||
PureUtils.foo1(PureUtils.foo2())
|
||||
}
|
||||
@@ -16,49 +16,74 @@
|
||||
|
||||
package org.jetbrains.kotlin.j2k
|
||||
|
||||
import java.io.File
|
||||
import com.intellij.testFramework.LightPlatformTestCase
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager
|
||||
import org.jetbrains.kotlin.test.JetTestUtils
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.command.WriteCommandAction
|
||||
import org.jetbrains.kotlin.idea.j2k.J2kPostProcessor
|
||||
import org.jetbrains.kotlin.idea.JetWithJdkAndRuntimeLightProjectDescriptor
|
||||
import com.intellij.openapi.progress.EmptyProgressIndicator
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiJavaFile
|
||||
import com.intellij.psi.PsiManager
|
||||
import java.util.ArrayList
|
||||
import org.jetbrains.kotlin.psi.JetFile
|
||||
import com.intellij.testFramework.LightPlatformTestCase
|
||||
import org.jetbrains.kotlin.idea.JetWithJdkAndRuntimeLightProjectDescriptor
|
||||
import org.jetbrains.kotlin.idea.j2k.IdeaResolverForConverter
|
||||
import org.jetbrains.kotlin.idea.j2k.J2kPostProcessor
|
||||
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.psi.JetFile
|
||||
import org.jetbrains.kotlin.test.JetTestUtils
|
||||
import java.io.File
|
||||
import java.util.ArrayList
|
||||
|
||||
public abstract class AbstractJavaToKotlinConverterMultiFileTest : AbstractJavaToKotlinConverterTest() {
|
||||
public fun doTest(dirPath: String) {
|
||||
val project = LightPlatformTestCase.getProject()!!
|
||||
val psiManager = PsiManager.getInstance(project)
|
||||
|
||||
val javaFiles = File(dirPath).listFiles { file, name -> name.endsWith(".java") }
|
||||
val psiFiles = ArrayList<PsiJavaFile>()
|
||||
for (javaFile: File in javaFiles) {
|
||||
val filesToConvert = File(dirPath).listFiles { file, name -> name.endsWith(".java") }
|
||||
val psiFilesToConvert = ArrayList<PsiJavaFile>()
|
||||
for (javaFile in filesToConvert) {
|
||||
val virtualFile = addFile(javaFile, "test")
|
||||
val psiFile = psiManager.findFile(virtualFile) as PsiJavaFile
|
||||
psiFiles.add(psiFile)
|
||||
psiFilesToConvert.add(psiFile)
|
||||
}
|
||||
|
||||
val externalFiles = File(dirPath + File.separator + "external").listFiles { file, name -> name.endsWith(".java") || name.endsWith(".kt") }
|
||||
val externalPsiFiles = ArrayList<PsiFile>()
|
||||
for (file in externalFiles) {
|
||||
val virtualFile = addFile(file, "test")
|
||||
val psiFile = psiManager.findFile(virtualFile)!!
|
||||
externalPsiFiles.add(psiFile)
|
||||
assert(psiFile is PsiJavaFile || psiFile is JetFile)
|
||||
}
|
||||
|
||||
val converter = JavaToKotlinConverter(project, ConverterSettings.defaultSettings,
|
||||
IdeaReferenceSearcher, IdeaResolverForConverter, J2kPostProcessor(formatCode = true))
|
||||
val inputElements = psiFiles.map { JavaToKotlinConverter.InputElement(it, it) }
|
||||
val results: List<String> = converter.elementsToKotlin(inputElements).map { it!!.text }
|
||||
val inputElements = psiFilesToConvert.map { JavaToKotlinConverter.InputElement(it, it) }
|
||||
val (results, externalCodeProcessor) = converter.elementsToKotlin(inputElements)
|
||||
|
||||
fun expectedFile(i: Int) = File(javaFiles[i].getPath().replace(".java", ".kt"))
|
||||
val process = externalCodeProcessor?.invoke(EmptyProgressIndicator())
|
||||
project.executeWriteCommand("") { process?.invoke() }
|
||||
|
||||
val jetFiles = ArrayList<JetFile>()
|
||||
for (i in javaFiles.indices) {
|
||||
deleteFile(psiFiles[i].getVirtualFile())
|
||||
val virtualFile = addFile(results[i], expectedFile(i).getName(), "test")
|
||||
jetFiles.add(psiManager.findFile(virtualFile) as JetFile)
|
||||
fun expectedResultFile(i: Int) = File(filesToConvert[i].getPath().replace(".java", ".kt"))
|
||||
|
||||
val resultFiles = ArrayList<JetFile>()
|
||||
for ((i, javaFile) in psiFilesToConvert.withIndex()) {
|
||||
deleteFile(javaFile.getVirtualFile())
|
||||
val virtualFile = addFile(results.map { it!!.text }[i], expectedResultFile(i).getName(), "test")
|
||||
resultFiles.add(psiManager.findFile(virtualFile) as JetFile)
|
||||
}
|
||||
|
||||
for ((i, jetFile) in jetFiles.withIndex()) {
|
||||
JetTestUtils.assertEqualsToFile(expectedFile(i), addErrorsDump(jetFile))
|
||||
for ((i, kotlinFile) in resultFiles.withIndex()) {
|
||||
JetTestUtils.assertEqualsToFile(expectedResultFile(i), addErrorsDump(kotlinFile))
|
||||
}
|
||||
|
||||
for ((externalFile, externalPsiFile) in externalFiles.zip(externalPsiFiles)) {
|
||||
val expectedFile = File(externalFile.getPath() + ".expected")
|
||||
var resultText = if (externalPsiFile is JetFile) {
|
||||
addErrorsDump(externalPsiFile)
|
||||
}
|
||||
else {
|
||||
//TODO: errors dump for java files too
|
||||
externalPsiFile.getText()
|
||||
}
|
||||
JetTestUtils.assertEqualsToFile(expectedFile, resultText)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ public abstract class AbstractJavaToKotlinConverterSingleFileTest : AbstractJava
|
||||
val converter = JavaToKotlinConverter(project, settings,
|
||||
IdeaReferenceSearcher, IdeaResolverForConverter, J2kPostProcessor(formatCode = false))
|
||||
val inputElements = listOf(JavaToKotlinConverter.InputElement(file, file))
|
||||
return converter.elementsToKotlin(inputElements).single()!!.text
|
||||
return converter.elementsToKotlin(inputElements).results.single()!!.text
|
||||
}
|
||||
|
||||
private fun methodToKotlin(text: String, settings: ConverterSettings, project: Project): String {
|
||||
|
||||
@@ -45,8 +45,8 @@ public abstract class AbstractJavaToKotlinConverterTest : LightCodeInsightFixtur
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
private fun addFile(fileName: String, packageName: String) {
|
||||
addFile(File("j2k/testData/$fileName"), packageName)
|
||||
private fun addFile(fileName: String, dirName: String) {
|
||||
addFile(File("j2k/testData/$fileName"), dirName)
|
||||
}
|
||||
|
||||
protected fun addFile(file: File, dirName: String): VirtualFile {
|
||||
@@ -58,7 +58,7 @@ public abstract class AbstractJavaToKotlinConverterTest : LightCodeInsightFixtur
|
||||
override fun compute(): VirtualFile? {
|
||||
val root = LightPlatformTestCase.getSourceRoot()!!
|
||||
val virtualDir = root.findChild(dirName) ?: root.createChildDirectory(null, dirName)
|
||||
val virtualFile = virtualDir.createChildData(null, fileName)!!
|
||||
val virtualFile = virtualDir.createChildData(null, fileName)
|
||||
virtualFile.getOutputStream(null)!!.writer().use { it.write(text) }
|
||||
return virtualFile
|
||||
}
|
||||
|
||||
@@ -1616,6 +1616,18 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("InCompanionObject.java")
|
||||
public void testInCompanionObject() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/dropAccessors/InCompanionObject.java");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("InObject.java")
|
||||
public void testInObject() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/dropAccessors/InObject.java");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("JavaKeywordPropertyName.java")
|
||||
public void testJavaKeywordPropertyName() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/dropAccessors/JavaKeywordPropertyName.java");
|
||||
|
||||
+18
-3
@@ -30,12 +30,16 @@ import java.util.regex.Pattern;
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("j2k/testData/multiFile")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@InnerTestClasses({
|
||||
})
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public class JavaToKotlinConverterMultiFileTestGenerated extends AbstractJavaToKotlinConverterMultiFileTest {
|
||||
public void testAllFilesPresentInMultiFile() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("j2k/testData/multiFile"), Pattern.compile("^([^\\.]+)$"), true);
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("j2k/testData/multiFile"), Pattern.compile("^([^\\.]+)$"), false);
|
||||
}
|
||||
|
||||
@TestMetadata("FieldToProperty")
|
||||
public void testFieldToProperty() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("j2k/testData/multiFile/FieldToProperty/");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("GetterAndSetterUsages")
|
||||
@@ -44,4 +48,15 @@ public class JavaToKotlinConverterMultiFileTestGenerated extends AbstractJavaToK
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ToCompanionObject")
|
||||
public void testToCompanionObject() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("j2k/testData/multiFile/ToCompanionObject/");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ToObject")
|
||||
public void testToObject() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("j2k/testData/multiFile/ToObject/");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1616,6 +1616,18 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("InCompanionObject.java")
|
||||
public void testInCompanionObject() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/dropAccessors/InCompanionObject.java");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("InObject.java")
|
||||
public void testInObject() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/dropAccessors/InObject.java");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("JavaKeywordPropertyName.java")
|
||||
public void testJavaKeywordPropertyName() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/dropAccessors/JavaKeywordPropertyName.java");
|
||||
|
||||
Reference in New Issue
Block a user