Fix for KT-12677. J2K: Invalid SAM constructor redundancy detection
Now all J2kPostProcessing's executing in fixed order, dependent on it index in J2kPostProcessingRegistrar._processings
This commit is contained in:
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.psi.*
|
|||||||
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType
|
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
||||||
|
import org.jetbrains.kotlin.utils.mapToIndex
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
interface J2kPostProcessing {
|
interface J2kPostProcessing {
|
||||||
@@ -49,6 +50,12 @@ object J2KPostProcessingRegistrar {
|
|||||||
val processings: Collection<J2kPostProcessing>
|
val processings: Collection<J2kPostProcessing>
|
||||||
get() = _processings
|
get() = _processings
|
||||||
|
|
||||||
|
private val processingsToPriorityMap = HashMap<J2kPostProcessing, Int>()
|
||||||
|
|
||||||
|
fun priority(processing: J2kPostProcessing): Int {
|
||||||
|
return processingsToPriorityMap[processing]!!
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
_processings.add(RemoveExplicitTypeArgumentsProcessing())
|
_processings.add(RemoveExplicitTypeArgumentsProcessing())
|
||||||
_processings.add(RemoveRedundantOverrideVisibilityProcessing())
|
_processings.add(RemoveRedundantOverrideVisibilityProcessing())
|
||||||
@@ -111,18 +118,13 @@ object J2KPostProcessingRegistrar {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private inline fun <reified TElement : KtElement, TIntention: SelfTargetingRangeIntention<TElement>> registerIntentionBasedProcessing(
|
processingsToPriorityMap.putAll(_processings.mapToIndex())
|
||||||
intention: TIntention
|
|
||||||
) {
|
|
||||||
//TODO: replace with optional argument when supported for inline functions
|
|
||||||
return registerIntentionBasedProcessing<TElement, TIntention>(intention, { true })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun <reified TElement : KtElement, TIntention: SelfTargetingRangeIntention<TElement>> registerIntentionBasedProcessing(
|
private inline fun <reified TElement : KtElement, TIntention: SelfTargetingRangeIntention<TElement>> registerIntentionBasedProcessing(
|
||||||
intention: TIntention,
|
intention: TIntention,
|
||||||
noinline additionalChecker: (TElement) -> Boolean
|
noinline additionalChecker: (TElement) -> Boolean = { true }
|
||||||
) {
|
) {
|
||||||
_processings.add(object : J2kPostProcessing {
|
_processings.add(object : J2kPostProcessing {
|
||||||
override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? {
|
override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? {
|
||||||
|
|||||||
@@ -21,9 +21,6 @@ import com.intellij.openapi.util.TextRange
|
|||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiRecursiveElementVisitor
|
import com.intellij.psi.PsiRecursiveElementVisitor
|
||||||
import com.intellij.psi.codeStyle.CodeStyleManager
|
import com.intellij.psi.codeStyle.CodeStyleManager
|
||||||
import com.intellij.psi.impl.PsiModificationTrackerImpl
|
|
||||||
import com.intellij.psi.util.PsiModificationTracker
|
|
||||||
import com.intellij.util.SmartList
|
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference
|
||||||
import org.jetbrains.kotlin.idea.conversion.copy.range
|
import org.jetbrains.kotlin.idea.conversion.copy.range
|
||||||
@@ -54,14 +51,12 @@ class J2kPostProcessor(private val formatCode: Boolean) : PostProcessor {
|
|||||||
while (elementToActions.isNotEmpty()) {
|
while (elementToActions.isNotEmpty()) {
|
||||||
var modificationStamp: Long? = file.modificationStamp
|
var modificationStamp: Long? = file.modificationStamp
|
||||||
|
|
||||||
for ((element, actions) in elementToActions) {
|
for ((element, action, processing) in elementToActions) {
|
||||||
for ((action, processing) in actions) {
|
if (element.isValid) {
|
||||||
if (element.isValid) {
|
action()
|
||||||
action()
|
}
|
||||||
}
|
else {
|
||||||
else {
|
modificationStamp = null
|
||||||
modificationStamp = null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,14 +78,14 @@ class J2kPostProcessor(private val formatCode: Boolean) : PostProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private data class ActionData(val action: () -> Unit, val processing: J2kPostProcessing)
|
private data class ActionData(val element: KtElement, val action: () -> Unit, val priority: Int)
|
||||||
|
|
||||||
private fun collectAvailableActions(file: KtFile, rangeMarker: RangeMarker?): LinkedHashMap<KtElement, SmartList<ActionData>> {
|
private fun collectAvailableActions(file: KtFile, rangeMarker: RangeMarker?): List<ActionData> {
|
||||||
val diagnostics = analyzeFileRange(file, rangeMarker)
|
val diagnostics = analyzeFileRange(file, rangeMarker)
|
||||||
|
|
||||||
val elementToActions = LinkedHashMap<KtElement, SmartList<ActionData>>()
|
val availableActions = ArrayList<ActionData>()
|
||||||
|
|
||||||
file.accept(object : PsiRecursiveElementVisitor(){
|
file.accept(object : PsiRecursiveElementVisitor() {
|
||||||
override fun visitElement(element: PsiElement) {
|
override fun visitElement(element: PsiElement) {
|
||||||
if (element is KtElement) {
|
if (element is KtElement) {
|
||||||
val rangeResult = rangeFilter(element, rangeMarker)
|
val rangeResult = rangeFilter(element, rangeMarker)
|
||||||
@@ -102,15 +97,15 @@ class J2kPostProcessor(private val formatCode: Boolean) : PostProcessor {
|
|||||||
J2KPostProcessingRegistrar.processings.forEach { processing ->
|
J2KPostProcessingRegistrar.processings.forEach { processing ->
|
||||||
val action = processing.createAction(element, diagnostics)
|
val action = processing.createAction(element, diagnostics)
|
||||||
if (action != null) {
|
if (action != null) {
|
||||||
elementToActions.getOrPut(element) { SmartList() }.add(ActionData(action, processing))
|
availableActions.add(ActionData(element, action, J2KPostProcessingRegistrar.priority(processing)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
availableActions.sortBy { it.priority }
|
||||||
return elementToActions
|
return availableActions
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun analyzeFileRange(file: KtFile, rangeMarker: RangeMarker?): Diagnostics {
|
private fun analyzeFileRange(file: KtFile, rangeMarker: RangeMarker?): Diagnostics {
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package test;
|
||||||
|
public class Stage {
|
||||||
|
public void context(Acceptor acceptor) {
|
||||||
|
acceptor.acceptFace(new Face() {
|
||||||
|
@Override public void subject(String p) {
|
||||||
|
System.out.println(p);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
acceptor.setFace(new Face() {
|
||||||
|
@Override public void subject(String p) {
|
||||||
|
System.out.println(p);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
class Stage {
|
||||||
|
fun context(acceptor: Acceptor) {
|
||||||
|
acceptor.acceptFace { p -> println(p) }
|
||||||
|
acceptor.face = Face { p -> println(p) }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package test;
|
||||||
|
public class Acceptor {
|
||||||
|
private Face face;
|
||||||
|
public Face getFace() { return face; }
|
||||||
|
public void setFace(Face face) { this.face = face; }
|
||||||
|
|
||||||
|
public void acceptFace(Face face) {}
|
||||||
|
}
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
package test;
|
||||||
|
public class Acceptor {
|
||||||
|
private Face face;
|
||||||
|
public Face getFace() { return face; }
|
||||||
|
public void setFace(Face face) { this.face = face; }
|
||||||
|
|
||||||
|
public void acceptFace(Face face) {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
package test;
|
||||||
|
public interface Face {
|
||||||
|
void subject(String p);
|
||||||
|
}
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
package test;
|
||||||
|
public interface Face {
|
||||||
|
void subject(String p);
|
||||||
|
}
|
||||||
@@ -47,6 +47,12 @@ public class JavaToKotlinConverterMultiFileTestGenerated extends AbstractJavaToK
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("FunctionalInterfaceAcceptor")
|
||||||
|
public void testFunctionalInterfaceAcceptor() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/multiFile/FunctionalInterfaceAcceptor/");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("GetterAndSetterUsages")
|
@TestMetadata("GetterAndSetterUsages")
|
||||||
public void testGetterAndSetterUsages() throws Exception {
|
public void testGetterAndSetterUsages() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/multiFile/GetterAndSetterUsages/");
|
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/multiFile/GetterAndSetterUsages/");
|
||||||
|
|||||||
Reference in New Issue
Block a user