diff --git a/idea/idea-j2k/src/org/jetbrains/kotlin/idea/j2k/J2kPostProcessor.kt b/idea/idea-j2k/src/org/jetbrains/kotlin/idea/j2k/J2kPostProcessor.kt index b77f5bf669a..71b192596b6 100644 --- a/idea/idea-j2k/src/org/jetbrains/kotlin/idea/j2k/J2kPostProcessor.kt +++ b/idea/idea-j2k/src/org/jetbrains/kotlin/idea/j2k/J2kPostProcessor.kt @@ -32,8 +32,7 @@ import org.jetbrains.kotlin.idea.core.util.range import org.jetbrains.kotlin.idea.util.ImportInsertHelper import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.kotlin.idea.util.application.runWriteAction -import org.jetbrains.kotlin.j2k.ConverterContext -import org.jetbrains.kotlin.j2k.PostProcessor +import org.jetbrains.kotlin.j2k.* import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtFile @@ -61,11 +60,15 @@ class J2kPostProcessor(private val formatCode: Boolean) : PostProcessor { } override fun doAdditionalProcessing( - file: KtFile, + target: JKPostProcessingTarget, converterContext: ConverterContext?, - rangeMarker: RangeMarker?, onPhaseChanged: ((Int, String) -> Unit)? - ) = + ) { + val (file, rangeMarker) = when (target) { + is JKPieceOfCodePostProcessingTarget -> target.file to target.rangeMarker + is JKMultipleFilesPostProcessingTarget -> target.files.single() to null + } + runBlocking(EDT.ModalityStateElement(ModalityState.defaultModalityState())) { do { var modificationStamp: Long? = file.modificationStamp @@ -109,7 +112,7 @@ class J2kPostProcessor(private val formatCode: Boolean) : PostProcessor { } } } - + } private data class ActionData(val element: KtElement, val action: () -> Unit, val priority: Int, val writeActionNeeded: Boolean) diff --git a/idea/src/org/jetbrains/kotlin/idea/actions/JavaToKotlinAction.kt b/idea/src/org/jetbrains/kotlin/idea/actions/JavaToKotlinAction.kt index 850dce16207..9d8f389a1e7 100644 --- a/idea/src/org/jetbrains/kotlin/idea/actions/JavaToKotlinAction.kt +++ b/idea/src/org/jetbrains/kotlin/idea/actions/JavaToKotlinAction.kt @@ -57,7 +57,6 @@ import org.jetbrains.kotlin.idea.util.isRunningInCidrIde import org.jetbrains.kotlin.j2k.* import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.UserDataProperty -import org.jetbrains.kotlin.utils.addToStdlib.safeAs import java.io.File import java.io.IOException import java.util.* diff --git a/j2k/src/org/jetbrains/kotlin/j2k/AfterConversionPass.kt b/j2k/src/org/jetbrains/kotlin/j2k/AfterConversionPass.kt index a4e0ad8ad7d..656b467e65f 100644 --- a/j2k/src/org/jetbrains/kotlin/j2k/AfterConversionPass.kt +++ b/j2k/src/org/jetbrains/kotlin/j2k/AfterConversionPass.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.j2k +import com.intellij.openapi.editor.RangeMarker import com.intellij.openapi.project.Project import com.intellij.openapi.util.TextRange import org.jetbrains.kotlin.idea.util.application.runReadAction @@ -29,14 +30,19 @@ class AfterConversionPass(val project: Project, val postProcessor: PostProcessor range: TextRange?, onPhaseChanged: ((Int, String) -> Unit)? = null ) { - val rangeMarker = if (range != null) { - val document = kotlinFile.viewProvider.document!! - val marker = runReadAction { document.createRangeMarker(range.startOffset, range.endOffset) } - marker.isGreedyToLeft = true - marker.isGreedyToRight = true - marker - } else null - - postProcessor.doAdditionalProcessing(kotlinFile, converterContext, rangeMarker, onPhaseChanged) + postProcessor.doAdditionalProcessing( + when { + range != null -> JKPieceOfCodePostProcessingTarget(kotlinFile, range.toRangeMarker(kotlinFile)) + else -> JKMultipleFilesPostProcessingTarget(listOf(kotlinFile)) + }, + converterContext, + onPhaseChanged + ) } } + +fun TextRange.toRangeMarker(file: KtFile): RangeMarker = + runReadAction { file.viewProvider.document!!.createRangeMarker(startOffset, endOffset) }.apply { + isGreedyToLeft = true + isGreedyToRight = true + } \ No newline at end of file diff --git a/j2k/src/org/jetbrains/kotlin/j2k/JavaToKotlinConverter.kt b/j2k/src/org/jetbrains/kotlin/j2k/JavaToKotlinConverter.kt index 1d1f9ab9596..d13e80bb64b 100644 --- a/j2k/src/org/jetbrains/kotlin/j2k/JavaToKotlinConverter.kt +++ b/j2k/src/org/jetbrains/kotlin/j2k/JavaToKotlinConverter.kt @@ -26,12 +26,15 @@ import com.intellij.openapi.util.Computable import com.intellij.psi.* import com.intellij.psi.impl.source.DummyHolder import org.jetbrains.kotlin.idea.KotlinLanguage +import org.jetbrains.kotlin.idea.core.util.range +import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.kotlin.j2k.ast.Element import org.jetbrains.kotlin.j2k.usageProcessing.ExternalCodeProcessor import org.jetbrains.kotlin.j2k.usageProcessing.UsageProcessing import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtPsiFactory +import org.jetbrains.kotlin.psi.psiUtil.elementsInRange import org.jetbrains.kotlin.psi.psiUtil.isAncestor import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf import java.util.* @@ -43,13 +46,37 @@ interface PostProcessor { val phasesCount: Int fun doAdditionalProcessing( - file: KtFile, + target: JKPostProcessingTarget, converterContext: ConverterContext?, - rangeMarker: RangeMarker?, onPhaseChanged: ((Int, String) -> Unit)? ) } +sealed class JKPostProcessingTarget + +data class JKPieceOfCodePostProcessingTarget( + val file: KtFile, + val rangeMarker: RangeMarker +) : JKPostProcessingTarget() + + +data class JKMultipleFilesPostProcessingTarget( + val files: List +) : JKPostProcessingTarget() + +fun JKPostProcessingTarget.elements() = when (this) { + is JKPieceOfCodePostProcessingTarget -> runReadAction { + val range = rangeMarker.range ?: return@runReadAction emptyList() + file.elementsInRange(range) + } + is JKMultipleFilesPostProcessingTarget -> files +} + +fun JKPostProcessingTarget.files() = when (this) { + is JKPieceOfCodePostProcessingTarget -> listOf(file) + is JKMultipleFilesPostProcessingTarget -> files +} + enum class ParseContext { TOP_LEVEL, CODE_BLOCK @@ -270,7 +297,7 @@ interface WithProgressProcessor { processItem: (TInputItem) -> TOutputItem ): List - fun updateState(fileIndex: Int, phase: Int, description: String) + fun updateState(fileIndex: Int?, phase: Int, description: String) fun process(action: () -> T): T } @@ -318,7 +345,7 @@ class OldWithProgressProcessor(private val progress: ProgressIndicator?, private throw AbstractMethodError("Should not be called for old J2K") } - override fun updateState(fileIndex: Int, phase: Int, description: String) { + override fun updateState(fileIndex: Int?, phase: Int, description: String) { throw AbstractMethodError("Should not be called for old J2K") } } diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/J2kPostProcessor.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/J2kPostProcessor.kt index 84b70e51e99..f678e67a33c 100644 --- a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/J2kPostProcessor.kt +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/J2kPostProcessor.kt @@ -22,7 +22,9 @@ import org.jetbrains.kotlin.idea.intentions.branchedTransformations.isTrivialSta import org.jetbrains.kotlin.idea.quickfix.* import org.jetbrains.kotlin.idea.util.ImportInsertHelper import org.jetbrains.kotlin.j2k.ConverterContext +import org.jetbrains.kotlin.j2k.JKPostProcessingTarget import org.jetbrains.kotlin.j2k.PostProcessor +import org.jetbrains.kotlin.j2k.files import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext @@ -42,23 +44,23 @@ class NewJ2kPostProcessor : PostProcessor { override val phasesCount = processings.size + override fun doAdditionalProcessing( - file: KtFile, + target: JKPostProcessingTarget, converterContext: ConverterContext?, - rangeMarker: RangeMarker?, onPhaseChanged: ((Int, String) -> Unit)? ) { for ((i, group) in processings.withIndex()) { onPhaseChanged?.invoke(i + 1, group.description) for (processing in group.processings) { try { - processing.runProcessing(file, rangeMarker, converterContext as NewJ2kConverterContext) + processing.runProcessing(target, converterContext as NewJ2kConverterContext) } catch (e: ProcessCanceledException) { throw e } catch (t: Throwable) { LOG.error(t) } finally { - commitFile(file) + target.files().forEach(::commitFile) } } } diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/JKInMemoryFilesSearcher.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/JKInMemoryFilesSearcher.kt new file mode 100644 index 00000000000..a0a08d5652c --- /dev/null +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/JKInMemoryFilesSearcher.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.nj2k.postProcessing + +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiReference +import com.intellij.psi.search.LocalSearchScope +import com.intellij.psi.search.searches.ReferencesSearch +import org.jetbrains.kotlin.psi.KtElement + +internal abstract class JKInMemoryFilesSearcher { + abstract fun search(element: KtElement): Iterable + + companion object { + fun create(files: List) = when { + files.size == 1 -> JKSingleFileInMemoryFilesSearcher(files.single()) + else -> JKMultipleFilesInMemoryFilesSearcher(files) + } + } +} + +internal class JKSingleFileInMemoryFilesSearcher(private val scopeElement: PsiElement) : JKInMemoryFilesSearcher() { + override fun search(element: KtElement): Iterable = + ReferencesSearch.search(element, LocalSearchScope(scopeElement)) +} + + +// it does not cover all cases e.g, just-changed reference +// maybe the solution is to do searching manually +// firstly by-text and then resolving +internal class JKMultipleFilesInMemoryFilesSearcher(private val scopeElements: List) : JKInMemoryFilesSearcher() { + override fun search(element: KtElement): Iterable { + val result = mutableListOf() + for (scopeElement in scopeElements) { + result += ReferencesSearch.search(element, LocalSearchScope(scopeElement)) + } + return result + } +} diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/diagnosticBasedPostProcessing.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/diagnosticBasedPostProcessing.kt index 5d4c3fdb129..768723616f6 100644 --- a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/diagnosticBasedPostProcessing.kt +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/diagnosticBasedPostProcessing.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.nj2k.postProcessing import com.intellij.codeInsight.intention.IntentionAction import com.intellij.openapi.editor.RangeMarker import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.caches.resolve.KotlinCacheService import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.diagnostics.DiagnosticFactory import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade @@ -15,6 +16,7 @@ import org.jetbrains.kotlin.idea.core.util.range import org.jetbrains.kotlin.idea.quickfix.AddExclExclCallFix import org.jetbrains.kotlin.idea.quickfix.KotlinIntentionActionsFactory import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory +import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext import org.jetbrains.kotlin.psi.KtElement @@ -23,7 +25,7 @@ import org.jetbrains.kotlin.psi.psiUtil.elementsInRange import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics import org.jetbrains.kotlin.utils.addToStdlib.safeAs -class DiagnosticBasedPostProcessingGroup(diagnosticBasedProcessings: List) : ProcessingGroup { +class DiagnosticBasedPostProcessingGroup(diagnosticBasedProcessings: List) : FileBasedPostProcessing() { constructor(vararg diagnosticBasedProcessings: DiagnosticBasedProcessing) : this(diagnosticBasedProcessings.toList()) private val diagnosticToFix = @@ -33,8 +35,9 @@ class DiagnosticBasedPostProcessingGroup(diagnosticBasedProcessings: List, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) { + val resolutionFacade = runReadAction { KotlinCacheService.getInstance(converterContext.project).getResolutionFacade(allFiles) } + val diagnostics = runReadAction { analyzeFileRange(file, rangeMarker, resolutionFacade).all() } runUndoTransparentActionInEdt(inWriteAction = true) { for (diagnostic in diagnostics) { val range = rangeMarker?.range ?: file.textRange @@ -49,7 +52,7 @@ class DiagnosticBasedPostProcessingGroup(diagnosticBasedProcessings: List listOf(file) rangeMarker.isValid -> file.elementsInRange(rangeMarker.range!!).filterIsInstance() @@ -57,7 +60,7 @@ class DiagnosticBasedPostProcessingGroup(diagnosticBasedProcessings: List -) : ProcessingGroup { +) : FileBasedPostProcessing() { constructor(vararg processings: InspectionLikeProcessing) : this( runSingleTime = false, acceptNonKtElements = false, @@ -35,8 +33,7 @@ class InspectionLikeProcessingGroup( private val processingsToPriorityMap = processings.mapToIndex() fun priority(processing: InspectionLikeProcessing): Int = processingsToPriorityMap.getValue(processing) - - override fun runProcessing(file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) { + override fun runProcessing(file: KtFile, allFiles: List, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) { do { var modificationStamp: Long? = file.modificationStamp val elementToActions = runReadAction { diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/postProcessings.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/postProcessings.kt index eff0ea13ce1..de75de090e5 100644 --- a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/postProcessings.kt +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/postProcessings.kt @@ -7,27 +7,35 @@ package org.jetbrains.kotlin.nj2k.postProcessing import com.intellij.openapi.editor.RangeMarker import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.idea.core.util.range -import org.jetbrains.kotlin.idea.util.application.runReadAction +import org.jetbrains.kotlin.j2k.JKMultipleFilesPostProcessingTarget +import org.jetbrains.kotlin.j2k.JKPieceOfCodePostProcessingTarget +import org.jetbrains.kotlin.j2k.JKPostProcessingTarget +import org.jetbrains.kotlin.j2k.elements import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.psi.psiUtil.elementsInRange interface GeneralPostProcessing { - fun runProcessing(file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) + fun runProcessing(target: JKPostProcessingTarget, converterContext: NewJ2kConverterContext) } +abstract class FileBasedPostProcessing : GeneralPostProcessing { + final override fun runProcessing(target: JKPostProcessingTarget, converterContext: NewJ2kConverterContext) = when (target) { + is JKPieceOfCodePostProcessingTarget -> + runProcessing(target.file, listOf(target.file), target.rangeMarker, converterContext) + is JKMultipleFilesPostProcessingTarget -> + target.files.forEach { file -> + runProcessing(file, target.files, rangeMarker = null, converterContext = converterContext) + } + } + + abstract fun runProcessing(file: KtFile, allFiles: List, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) +} + abstract class ElementsBasedPostProcessing : GeneralPostProcessing { - final override fun runProcessing(file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) { - val elements = runReadAction { - rangeMarker?.let { marker -> - val range = marker.range ?: return@let emptyList() - file.elementsInRange(range) - } ?: listOf(file) - } - runProcessing(elements, converterContext) + final override fun runProcessing(target: JKPostProcessingTarget, converterContext: NewJ2kConverterContext) { + runProcessing(target.elements(), converterContext) } abstract fun runProcessing(elements: List, converterContext: NewJ2kConverterContext) diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/processings/ConvertGettersAndSettersToPropertyProcessing.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/processings/ConvertGettersAndSettersToPropertyProcessing.kt index 980ad385ad4..60c40f8c316 100644 --- a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/processings/ConvertGettersAndSettersToPropertyProcessing.kt +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/processings/ConvertGettersAndSettersToPropertyProcessing.kt @@ -8,9 +8,9 @@ package org.jetbrains.kotlin.nj2k.postProcessing.processings import com.intellij.psi.PsiElement import com.intellij.psi.search.LocalSearchScope import com.intellij.psi.search.searches.OverridingMethodsSearch -import com.intellij.psi.search.searches.ReferencesSearch import com.intellij.refactoring.rename.RenamePsiElementProcessor import org.jetbrains.kotlin.asJava.toLightMethods +import org.jetbrains.kotlin.caches.resolve.KotlinCacheService import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor @@ -22,17 +22,21 @@ import org.jetbrains.kotlin.idea.refactoring.isInterfaceClass import org.jetbrains.kotlin.idea.references.KtSimpleNameReference import org.jetbrains.kotlin.idea.references.mainReference import org.jetbrains.kotlin.idea.references.readWriteAccess +import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.util.CommentSaver import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.nj2k.* +import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext +import org.jetbrains.kotlin.nj2k.asGetterName +import org.jetbrains.kotlin.nj2k.asSetterName import org.jetbrains.kotlin.nj2k.externalCodeProcessing.JKFakeFieldData import org.jetbrains.kotlin.nj2k.externalCodeProcessing.JKFieldData import org.jetbrains.kotlin.nj2k.externalCodeProcessing.JKMethodData import org.jetbrains.kotlin.nj2k.externalCodeProcessing.NewExternalCodeProcessing +import org.jetbrains.kotlin.nj2k.fqNameWithoutCompanions import org.jetbrains.kotlin.nj2k.postProcessing.* import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.* @@ -51,16 +55,59 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.mapToIndex class ConvertGettersAndSettersToPropertyProcessing : ElementsBasedPostProcessing() { + override fun runProcessing(elements: List, converterContext: NewJ2kConverterContext) { + val ktElements = elements.filterIsInstance() + val resolutionFacade = runReadAction { + KotlinCacheService.getInstance(converterContext.project).getResolutionFacade(ktElements) + } + ConvertGettersAndSettersToPropertyStatefulProcessing( + resolutionFacade, + ktElements, + converterContext.externalCodeProcessor + ).runProcessing() + } +} + +private class ConvertGettersAndSettersToPropertyStatefulProcessing( + private val resolutionFacade: ResolutionFacade, + private val elements: List, + private val externalCodeUpdater: NewExternalCodeProcessing +) { + private val searcher = JKInMemoryFilesSearcher.create(elements) + + + fun runProcessing() { + val collectingState = CollectingState() + val classesWithPropertiesData = runReadAction { + elements + .descendantsOfType() + .sortedByInheritance() + .map { klass -> + klass to klass.collectPropertiesData(collectingState) + } + } + if (classesWithPropertiesData.isEmpty()) return + runUndoTransparentActionInEdt(inWriteAction = true) { + for ((klass, propertiesData) in classesWithPropertiesData) { + convertClass(klass, propertiesData) + } + } + } + private fun KtNamedFunction.hasOverrides(): Boolean = toLightMethods().singleOrNull()?.let { lightMethod -> - OverridingMethodsSearch.search(lightMethod).findFirst() - } != null + if (OverridingMethodsSearch.search(lightMethod).findFirst() != null) return@let true + if (elements.size == 1) return@let false + elements.any { element -> + OverridingMethodsSearch.search(lightMethod, LocalSearchScope(element), true).findFirst() != null + } + } == true private fun KtNamedFunction.hasSuperFunction(): Boolean = - resolveToDescriptorIfAny()?.original?.overriddenDescriptors?.isNotEmpty() == true + resolveToDescriptorIfAny(resolutionFacade)?.original?.overriddenDescriptors?.isNotEmpty() == true private fun KtNamedFunction.hasInvalidSuperDescriptors(): Boolean = - resolveToDescriptorIfAny() + resolveToDescriptorIfAny(resolutionFacade) ?.original ?.overriddenDescriptors ?.any { it.isJavaDescriptor || it is FunctionDescriptor } == true @@ -216,7 +263,7 @@ class ConvertGettersAndSettersToPropertyProcessing : ElementsBasedPostProcessing } private fun KtElement.usages() = - ReferencesSearch.search(this, LocalSearchScope(containingKtFile)) + searcher.search(this) private fun T.withReplacedExpressionInBody( from: KtElement, @@ -249,7 +296,7 @@ class ConvertGettersAndSettersToPropertyProcessing : ElementsBasedPostProcessing val sorted = mutableListOf() val visited = Array(size) { false } - val descriptors = map { it.resolveToDescriptorIfAny()!! } + val descriptors = map { it.resolveToDescriptorIfAny(resolutionFacade)!! } val descriptorToIndex = descriptors.mapToIndex() val outers = descriptors.map { descriptor -> descriptor.superClassAndSuperInterfaces().mapNotNull { descriptorToIndex[it] } @@ -273,25 +320,6 @@ class ConvertGettersAndSettersToPropertyProcessing : ElementsBasedPostProcessing return sorted } - - override fun runProcessing(elements: List, converterContext: NewJ2kConverterContext) { - val collectingState = CollectingState() - val classesWithPropertiesData = runReadAction { - elements - .descendantsOfType() - .sortedByInheritance() - .map { klass -> - klass to klass.collectPropertiesData(collectingState) - } - } - if (classesWithPropertiesData.isEmpty()) return - runUndoTransparentActionInEdt(inWriteAction = true) { - for ((klass, propertiesData) in classesWithPropertiesData) { - convertClass(klass, propertiesData, converterContext.externalCodeProcessor) - } - } - } - private fun causesNameConflictInCurrentDeclarationAndItsParents(name: String, declaration: DeclarationDescriptor?): Boolean = when (declaration) { is ClassDescriptor -> { @@ -310,27 +338,11 @@ class ConvertGettersAndSettersToPropertyProcessing : ElementsBasedPostProcessing } private fun calculatePropertyType(getter: KtNamedFunction?, setter: KtNamedFunction?): KotlinType? { - val getterType = getter?.resolveToDescriptorIfAny()?.returnType - val setterType = setter?.resolveToDescriptorIfAny()?.valueParameters?.singleOrNull()?.type + val getterType = getter?.resolveToDescriptorIfAny(resolutionFacade)?.returnType + val setterType = setter?.resolveToDescriptorIfAny(resolutionFacade)?.valueParameters?.singleOrNull()?.type return calculatePropertyType(getterType, setterType) } - private fun calculatePropertyTypeBasedOnSuperDescriptors(getter: KtNamedFunction?, setter: KtNamedFunction?): KotlinType? { - val superGetterType = getter - ?.resolveToDescriptorIfAny() - ?.overriddenDescriptors - ?.firstOrNull() - ?.returnType - val superSetterType = setter - ?.resolveToDescriptorIfAny() - ?.overriddenDescriptors - ?.firstOrNull() - ?.valueParameters - ?.singleOrNull() - ?.type - return calculatePropertyType(superGetterType, superSetterType) - } - private fun KtClassOrObject.collectPropertiesData(collectingState: CollectingState): List { return declarations .asSequence() @@ -356,7 +368,7 @@ class ConvertGettersAndSettersToPropertyProcessing : ElementsBasedPostProcessing val name = realGetter?.name ?: realSetter?.name!! val superDeclarationOwner = (realGetter?.function ?: realSetter?.function) - ?.resolveToDescriptorIfAny() + ?.resolveToDescriptorIfAny(resolutionFacade) ?.overriddenDescriptors ?.firstOrNull() ?.findPsi() @@ -378,7 +390,7 @@ class ConvertGettersAndSettersToPropertyProcessing : ElementsBasedPostProcessing klass: KtClassOrObject, factory: KtPsiFactory ): List { - val classDescriptor = klass.resolveToDescriptorIfAny() ?: return emptyList() + val classDescriptor = klass.resolveToDescriptorIfAny(resolutionFacade) ?: return emptyList() val variablesDescriptorsMap = (listOfNotNull(classDescriptor.getSuperClassNotAny()) + classDescriptor.getSuperInterfaces()) @@ -462,7 +474,7 @@ class ConvertGettersAndSettersToPropertyProcessing : ElementsBasedPostProcessing val getter = realGetter ?: when { - realProperty?.property?.resolveToDescriptorIfAny()?.overriddenDescriptors?.any { + realProperty?.property?.resolveToDescriptorIfAny(resolutionFacade)?.overriddenDescriptors?.any { it.safeAs()?.isVar == true } == true -> FakeGetter(name, null, "") @@ -487,7 +499,7 @@ class ConvertGettersAndSettersToPropertyProcessing : ElementsBasedPostProcessing realProperty?.property?.isVar == true -> FakeSetter(name, null, "") - realProperty?.property?.resolveToDescriptorIfAny()?.overriddenDescriptors?.any { + realProperty?.property?.resolveToDescriptorIfAny(resolutionFacade)?.overriddenDescriptors?.any { it.safeAs()?.isVar == true } == true || variablesDescriptorsMap[name]?.isVar == true -> @@ -523,7 +535,7 @@ class ConvertGettersAndSettersToPropertyProcessing : ElementsBasedPostProcessing } private fun KtProperty.renameTo(newName: String, factory: KtPsiFactory) { - for (usage in usages().toList()) { + for (usage in usages()) { val element = usage.element val isBackingField = element is KtNameReferenceExpression && element.text == KtTokens.FIELD_KEYWORD.value @@ -540,8 +552,7 @@ class ConvertGettersAndSettersToPropertyProcessing : ElementsBasedPostProcessing private fun convertClass( klass: KtClassOrObject, - propertiesData: List, - externalCodeUpdater: NewExternalCodeProcessing + propertiesData: List ) { val factory = KtPsiFactory(klass) val accessors = propertiesData.filterGettersAndSetters(klass, factory) diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/processings/InferenceProcessing.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/processings/InferenceProcessing.kt index fb61ae7c69c..0b025c86ce5 100644 --- a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/processings/InferenceProcessing.kt +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/processings/InferenceProcessing.kt @@ -5,9 +5,8 @@ package org.jetbrains.kotlin.nj2k.postProcessing.processings -import com.intellij.openapi.editor.RangeMarker -import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade -import org.jetbrains.kotlin.idea.core.util.range +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.caches.resolve.KotlinCacheService import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext @@ -20,19 +19,16 @@ import org.jetbrains.kotlin.nj2k.inference.common.collectors.CommonConstraintsCo import org.jetbrains.kotlin.nj2k.inference.common.collectors.FunctionConstraintsCollector import org.jetbrains.kotlin.nj2k.inference.mutability.* import org.jetbrains.kotlin.nj2k.inference.nullability.* -import org.jetbrains.kotlin.nj2k.postProcessing.GeneralPostProcessing +import org.jetbrains.kotlin.nj2k.postProcessing.ElementsBasedPostProcessing import org.jetbrains.kotlin.psi.KtElement -import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.psi.psiUtil.elementsInRange -abstract class InferenceProcessing : GeneralPostProcessing { - final override fun runProcessing(file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) { - val elements = if (rangeMarker != null) { - val range = rangeMarker.range ?: return - runReadAction { file.elementsInRange(range) }.filterIsInstance() - } else listOf(file) - val resolutionFacade = runReadAction { file.getResolutionFacade() } - createInferenceFacade(resolutionFacade, converterContext).runOn(elements) +abstract class InferenceProcessing : ElementsBasedPostProcessing() { + override fun runProcessing(elements: List, converterContext: NewJ2kConverterContext) { + val kotlinElements = elements.filterIsInstance() + val resolutionFacade = runReadAction { + KotlinCacheService.getInstance(converterContext.project).getResolutionFacade(kotlinElements) + } + createInferenceFacade(resolutionFacade, converterContext).runOn(kotlinElements) } abstract fun createInferenceFacade( diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/processings/ShortenReferenceProcessing.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/processings/ShortenReferenceProcessing.kt index 4dc54cbff55..c740c222c45 100644 --- a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/processings/ShortenReferenceProcessing.kt +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/processings/ShortenReferenceProcessing.kt @@ -10,12 +10,13 @@ import com.intellij.psi.PsiElement import org.jetbrains.kotlin.idea.core.ShortenReferences import org.jetbrains.kotlin.nj2k.JKImportStorage import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext +import org.jetbrains.kotlin.nj2k.postProcessing.FileBasedPostProcessing import org.jetbrains.kotlin.nj2k.postProcessing.GeneralPostProcessing import org.jetbrains.kotlin.nj2k.postProcessing.runUndoTransparentActionInEdt import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtQualifiedExpression -class ShortenReferenceProcessing : GeneralPostProcessing { +class ShortenReferenceProcessing : FileBasedPostProcessing() { private val filter = filter@{ element: PsiElement -> when (element) { is KtQualifiedExpression -> when { @@ -26,7 +27,7 @@ class ShortenReferenceProcessing : GeneralPostProcessing { } } - override fun runProcessing(file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) { + override fun runProcessing(file: KtFile, allFiles: List, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) { runUndoTransparentActionInEdt(inWriteAction = false) { if (rangeMarker != null) { if (rangeMarker.isValid) { diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/processings/processings.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/processings/processings.kt index d33e5f0ed8a..14a43a10b25 100644 --- a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/processings/processings.kt +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/processings/processings.kt @@ -13,16 +13,19 @@ import com.intellij.psi.PsiElementVisitor import com.intellij.psi.codeStyle.CodeStyleManager import org.jetbrains.kotlin.idea.core.util.range import org.jetbrains.kotlin.idea.util.application.runReadAction +import org.jetbrains.kotlin.j2k.JKPostProcessingTarget +import org.jetbrains.kotlin.j2k.elements import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext import org.jetbrains.kotlin.nj2k.asLabel +import org.jetbrains.kotlin.nj2k.postProcessing.FileBasedPostProcessing import org.jetbrains.kotlin.nj2k.postProcessing.GeneralPostProcessing import org.jetbrains.kotlin.nj2k.postProcessing.runUndoTransparentActionInEdt import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.elementsInRange -class FormatCodeProcessing : GeneralPostProcessing { - override fun runProcessing(file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) { +class FormatCodeProcessing : FileBasedPostProcessing() { + override fun runProcessing(file: KtFile, allFiles: List, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) { val codeStyleManager = CodeStyleManager.getInstance(file.project) runUndoTransparentActionInEdt(inWriteAction = true) { if (rangeMarker != null) { @@ -38,28 +41,30 @@ class FormatCodeProcessing : GeneralPostProcessing { class ClearUnknownLabelsProcessing : GeneralPostProcessing { - override fun runProcessing(file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) { + override fun runProcessing(target: JKPostProcessingTarget, converterContext: NewJ2kConverterContext) { val comments = mutableListOf() runUndoTransparentActionInEdt(inWriteAction = true) { - file.accept(object : PsiElementVisitor() { - override fun visitElement(element: PsiElement) { - element.acceptChildren(this) - } - - override fun visitComment(comment: PsiComment) { - if (comment.text.asLabel() != null) { - comments += comment + target.elements().forEach { element -> + element.accept(object : PsiElementVisitor() { + override fun visitElement(element: PsiElement) { + element.acceptChildren(this) } - } - }) + + override fun visitComment(comment: PsiComment) { + if (comment.text.asLabel() != null) { + comments += comment + } + } + }) + } comments.forEach { it.delete() } } } } -class OptimizeImportsProcessing : GeneralPostProcessing { - override fun runProcessing(file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) { +class OptimizeImportsProcessing : FileBasedPostProcessing() { + override fun runProcessing(file: KtFile, allFiles: List, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) { val elements = runReadAction { when { rangeMarker != null && rangeMarker.isValid -> file.elementsInRange(rangeMarker.range!!) diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverter.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverter.kt index e2be8e94671..915495cae05 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverter.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverter.kt @@ -17,10 +17,8 @@ package org.jetbrains.kotlin.nj2k import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.command.CommandProcessor import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.module.Module -import com.intellij.openapi.progress.ProcessCanceledException import com.intellij.openapi.progress.ProgressIndicator import com.intellij.openapi.progress.ProgressManager import com.intellij.openapi.project.Project @@ -28,7 +26,6 @@ import com.intellij.openapi.util.Computable import com.intellij.psi.* import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl import org.jetbrains.kotlin.idea.project.languageVersionSettings -import org.jetbrains.kotlin.idea.util.application.runWriteAction import org.jetbrains.kotlin.j2k.* import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.nj2k.conversions.JKResolver @@ -68,36 +65,27 @@ class NewJavaToKotlinConverter( elementsToKotlin(files, withProgressProcessor) }) - val texts = results.mapIndexed { i, result -> - try { - val kotlinFile = ApplicationManager.getApplication().runReadAction(Computable { - KtPsiFactory(project).createFileWithLightClassSupport("dummy.kt", result!!.text, files[i]) - }) - - ApplicationManager.getApplication().invokeAndWait { - CommandProcessor.getInstance().runUndoTransparentAction { - runWriteAction { - kotlinFile.addImports(result!!.importsToAdd) - } - } + val kotlinFiles = results.mapIndexed { i, result -> + runUndoTransparentActionInEdt(inWriteAction = true) { + val javaFile = files[i] + KtPsiFactory(project).createFileWithLightClassSupport( + javaFile.name.replace(".java", ".kt"), + result!!.text, + files[i] + ).apply { + addImports(result.importsToAdd) } - AfterConversionPass(project, postProcessor).run( - kotlinFile, - context, - range = null, - onPhaseChanged = { phase, description -> - withProgressProcessor.updateState(i, phase + 1, description) - } - ) - kotlinFile.text - } catch (e: ProcessCanceledException) { - throw e - } catch (t: Throwable) { - LOG.error(t) - result!!.text } + } - FilesResult(texts, externalCodeProcessing) + + postProcessor.doAdditionalProcessing( + JKMultipleFilesPostProcessingTarget(kotlinFiles), + context + ) { phase, description -> + withProgressProcessor.updateState(fileIndex = null, phase = phase + 1, description = description) + } + FilesResult(kotlinFiles.map { it.text }, externalCodeProcessing) } } @@ -217,12 +205,13 @@ class NewJ2kWithProgressProcessor( val DEFAULT = NewJ2kWithProgressProcessor(null, null, 0) } - override fun updateState(fileIndex: Int, phase: Int, description: String) { + override fun updateState(fileIndex: Int?, phase: Int, description: String) { progress?.checkCanceled() progress?.fraction = phase / phasesCount.toDouble() progress?.text = "$description - phase $phase of $phasesCount" - if (files != null && files.isNotEmpty()) { - progress?.text2 = files[fileIndex].virtualFile.presentableUrl + progress?.text2 = when { + files != null && files.isNotEmpty() && fileIndex != null -> files[fileIndex].virtualFile.presentableUrl + else -> "" } } diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/psiUtils.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/psiUtils.kt index b728d99153f..c7909ee2d6f 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/psiUtils.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/psiUtils.kt @@ -7,11 +7,14 @@ package org.jetbrains.kotlin.nj2k import com.intellij.codeInsight.generation.GenerateEqualsHelper.getEqualsSignature import com.intellij.lang.jvm.JvmClassKind +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.command.CommandProcessor import com.intellij.psi.* import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.util.InheritanceUtil import com.intellij.psi.util.MethodSignatureUtil import com.intellij.psi.util.PsiUtil +import org.jetbrains.kotlin.idea.util.application.runWriteAction import org.jetbrains.kotlin.j2k.ClassKind import org.jetbrains.kotlin.j2k.ReferenceSearcher import org.jetbrains.kotlin.j2k.isNullLiteral @@ -141,3 +144,16 @@ val KtDeclaration.fqNameWithoutCompanions .filter { it.safeAs()?.isCompanion() != true && it.name != null } .toList() .foldRight(containingKtFile.packageFqName) { container, acc -> acc.child(Name.identifier(container.name!!)) } + +internal fun runUndoTransparentActionInEdt(inWriteAction: Boolean, action: () -> T): T { + var result: T? = null + ApplicationManager.getApplication().invokeAndWait { + CommandProcessor.getInstance().runUndoTransparentAction { + result = when { + inWriteAction -> runWriteAction(action) + else -> action() + } + } + } + return result!! +} \ No newline at end of file diff --git a/nj2k/testData/multiFile/DetectPropertiesMultipleFiles/B.java b/nj2k/testData/multiFile/DetectPropertiesMultipleFiles/B.java new file mode 100644 index 00000000000..cb5f738f17a --- /dev/null +++ b/nj2k/testData/multiFile/DetectPropertiesMultipleFiles/B.java @@ -0,0 +1,31 @@ +package test; + +public class B { + public String getFromB1() { + return ""; + } + + public String getFromB2() { + return ""; + } + + public void setFromB2(String value) { + } + + public String getFromB3() { + return ""; + } + + public void setFromB3(String value) { + } + + public String getFromB4() { + return ""; + } + + public void setFromB4(String value) { + } + + public void setFromB5(String value) { + } +} diff --git a/nj2k/testData/multiFile/DetectPropertiesMultipleFiles/B.kt b/nj2k/testData/multiFile/DetectPropertiesMultipleFiles/B.kt new file mode 100644 index 00000000000..9cb811d296f --- /dev/null +++ b/nj2k/testData/multiFile/DetectPropertiesMultipleFiles/B.kt @@ -0,0 +1,20 @@ +package test + +open class B { + val fromB1: String + get() = "" + + var fromB2: String? + get() = "" + set(value) {} + + var fromB3: String? + get() = "" + set(value) {} + + var fromB4: String? + get() = "" + set(value) {} + + open fun setFromB5(value: String?) {} +} \ No newline at end of file diff --git a/nj2k/testData/multiFile/DetectPropertiesMultipleFiles/C.java b/nj2k/testData/multiFile/DetectPropertiesMultipleFiles/C.java new file mode 100644 index 00000000000..9a1a6fa4484 --- /dev/null +++ b/nj2k/testData/multiFile/DetectPropertiesMultipleFiles/C.java @@ -0,0 +1,57 @@ +package test; + +public abstract class C extends B implements I { + private final int mySomething1; + private int mySomething6; + + C(int something1) { + mySomething1 = something1; + } + + @Override + public int getSomething1() { + return mySomething1; + } + + @Override + public int getSomething2() { + return 0; + } + + @Override + public int getSomething3() { + return 0; + } + + @Override + public void setSomething3(int value) { + } + + @Override + public int getSomething4() { + return 0; + } + + @Override + public void setSomething5(int value) { + + } + + public int getSomething6() { + return mySomething6; + } + + @Override + public void setSomething6(int value) { + mySomething6 = value; + } + + public String getFromB5() { + return ""; + } + + @Override + public void setFromB5(String value) { + super.setFromB5(value); + } +} diff --git a/nj2k/testData/multiFile/DetectPropertiesMultipleFiles/C.kt b/nj2k/testData/multiFile/DetectPropertiesMultipleFiles/C.kt new file mode 100644 index 00000000000..5a6b43abcb1 --- /dev/null +++ b/nj2k/testData/multiFile/DetectPropertiesMultipleFiles/C.kt @@ -0,0 +1,34 @@ +package test + +abstract class C internal constructor(override val something1: Int) : B(), I { + private var mySomething6 = 0 + + override val something2: Int + get() = 0 + + override var something3: Int + get() = 0 + set(value) {} + + override fun getSomething4(): Int { + return 0 + } + + override fun setSomething5(value: Int) {} + fun getSomething6(): Int { + return mySomething6 + } + + override fun setSomething6(value: Int) { + mySomething6 = value + } + + fun getFromB5(): String { + return "" + } + + override fun setFromB5(value: String?) { + super.setFromB5(value) + } + +} \ No newline at end of file diff --git a/nj2k/testData/multiFile/DetectPropertiesMultipleFiles/I.java b/nj2k/testData/multiFile/DetectPropertiesMultipleFiles/I.java new file mode 100644 index 00000000000..303af774e81 --- /dev/null +++ b/nj2k/testData/multiFile/DetectPropertiesMultipleFiles/I.java @@ -0,0 +1,21 @@ +package test; + +public interface I { + int getSomething1(); + + int getSomething2(); + + int getSomething3(); + + void setSomething3(int value); + + int getSomething4(); + + void setSomething4(int value); + + int getSomething5(); + + void setSomething5(int value); + + void setSomething6(int value); +} diff --git a/nj2k/testData/multiFile/DetectPropertiesMultipleFiles/I.kt b/nj2k/testData/multiFile/DetectPropertiesMultipleFiles/I.kt new file mode 100644 index 00000000000..99b8a44c359 --- /dev/null +++ b/nj2k/testData/multiFile/DetectPropertiesMultipleFiles/I.kt @@ -0,0 +1,13 @@ +package test + +interface I { + val something1: Int + val something2: Int + var something3: Int + + fun getSomething4(): Int + fun setSomething4(value: Int) + fun getSomething5(): Int + fun setSomething5(value: Int) + fun setSomething6(value: Int) +} diff --git a/nj2k/testData/multiFile/DetectPropertiesMultipleFiles/I1.java b/nj2k/testData/multiFile/DetectPropertiesMultipleFiles/I1.java new file mode 100644 index 00000000000..2950b6288ac --- /dev/null +++ b/nj2k/testData/multiFile/DetectPropertiesMultipleFiles/I1.java @@ -0,0 +1,7 @@ +package test; + +public interface I1 extends I { + void setSomething1(int value); + + int getSomething6(); +} diff --git a/nj2k/testData/multiFile/DetectPropertiesMultipleFiles/I1.kt b/nj2k/testData/multiFile/DetectPropertiesMultipleFiles/I1.kt new file mode 100644 index 00000000000..7b5bffaaa3b --- /dev/null +++ b/nj2k/testData/multiFile/DetectPropertiesMultipleFiles/I1.kt @@ -0,0 +1,6 @@ +package test + +interface I1 : I { + fun setSomething1(value: Int) + val something6: Int +} diff --git a/nj2k/testData/multiFile/InterfaceWithGetterInOtherFile/IUser.java b/nj2k/testData/multiFile/InterfaceWithGetterInOtherFile/IUser.java new file mode 100644 index 00000000000..0d77e628404 --- /dev/null +++ b/nj2k/testData/multiFile/InterfaceWithGetterInOtherFile/IUser.java @@ -0,0 +1,5 @@ +package test; + +public interface IUser { + String getName(); +} diff --git a/nj2k/testData/multiFile/InterfaceWithGetterInOtherFile/IUser.kt b/nj2k/testData/multiFile/InterfaceWithGetterInOtherFile/IUser.kt new file mode 100644 index 00000000000..837991d7278 --- /dev/null +++ b/nj2k/testData/multiFile/InterfaceWithGetterInOtherFile/IUser.kt @@ -0,0 +1,5 @@ +package test + +interface IUser { + val name: String +} diff --git a/nj2k/testData/multiFile/InterfaceWithGetterInOtherFile/UserImpl.java b/nj2k/testData/multiFile/InterfaceWithGetterInOtherFile/UserImpl.java new file mode 100644 index 00000000000..9e3c75e26ae --- /dev/null +++ b/nj2k/testData/multiFile/InterfaceWithGetterInOtherFile/UserImpl.java @@ -0,0 +1,14 @@ +package test; + +public class UserImpl implements IUser { + private final String name; + + public UserImpl(String name) { + this.name = name; + } + + @Override + public String getName() { + return name; + } +} \ No newline at end of file diff --git a/nj2k/testData/multiFile/InterfaceWithGetterInOtherFile/UserImpl.kt b/nj2k/testData/multiFile/InterfaceWithGetterInOtherFile/UserImpl.kt new file mode 100644 index 00000000000..77f844aa9b7 --- /dev/null +++ b/nj2k/testData/multiFile/InterfaceWithGetterInOtherFile/UserImpl.kt @@ -0,0 +1,3 @@ +package test + +class UserImpl(override val name: String) : IUser diff --git a/nj2k/tests/org/jetbrains/kotlin/nj2k/AbstractNewJavaToKotlinConverterMultiFileTest.kt b/nj2k/tests/org/jetbrains/kotlin/nj2k/AbstractNewJavaToKotlinConverterMultiFileTest.kt index bbc94a35ca6..38cff6463af 100644 --- a/nj2k/tests/org/jetbrains/kotlin/nj2k/AbstractNewJavaToKotlinConverterMultiFileTest.kt +++ b/nj2k/tests/org/jetbrains/kotlin/nj2k/AbstractNewJavaToKotlinConverterMultiFileTest.kt @@ -28,9 +28,11 @@ abstract class AbstractNewJavaToKotlinConverterMultiFileTest : AbstractJavaToKot psiManager.findFile(virtualFile) as PsiJavaFile } - val externalFiles = File(dirPath + File.separator + "external").listFiles { _, name -> - name.endsWith(".java") || name.endsWith(".kt") - }!! + val externalFiles = File(dirPath + File.separator + "external") + .takeIf { it.exists() } + ?.listFiles { _, name -> + name.endsWith(".java") || name.endsWith(".kt") + }.orEmpty() val externalPsiFiles = externalFiles.map { file -> val virtualFile = addFile(file, "test") diff --git a/nj2k/tests/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverterMultiFileTestGenerated.java b/nj2k/tests/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverterMultiFileTestGenerated.java index 4ebddaeef6c..0d8a41bf97e 100644 --- a/nj2k/tests/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverterMultiFileTestGenerated.java +++ b/nj2k/tests/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverterMultiFileTestGenerated.java @@ -34,6 +34,11 @@ public class NewJavaToKotlinConverterMultiFileTestGenerated extends AbstractNewJ runTest("nj2k/testData/multiFile/AnnotationWithArrayParameter/"); } + @TestMetadata("DetectPropertiesMultipleFiles") + public void testDetectPropertiesMultipleFiles() throws Exception { + runTest("nj2k/testData/multiFile/DetectPropertiesMultipleFiles/"); + } + @TestMetadata("FieldToProperty") public void testFieldToProperty() throws Exception { runTest("nj2k/testData/multiFile/FieldToProperty/"); @@ -49,6 +54,11 @@ public class NewJavaToKotlinConverterMultiFileTestGenerated extends AbstractNewJ runTest("nj2k/testData/multiFile/GetterAndSetterUsages/"); } + @TestMetadata("InterfaceWithGetterInOtherFile") + public void testInterfaceWithGetterInOtherFile() throws Exception { + runTest("nj2k/testData/multiFile/InterfaceWithGetterInOtherFile/"); + } + @TestMetadata("KT11952") public void testKT11952() throws Exception { runTest("nj2k/testData/multiFile/KT11952/");