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:
Simon Ogorodnik
2016-10-14 15:21:20 +03:00
parent 0b57d8eb49
commit 0cebcc9f3c
9 changed files with 75 additions and 25 deletions
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
import org.jetbrains.kotlin.utils.mapToIndex
import java.util.*
interface J2kPostProcessing {
@@ -49,6 +50,12 @@ object J2KPostProcessingRegistrar {
val processings: Collection<J2kPostProcessing>
get() = _processings
private val processingsToPriorityMap = HashMap<J2kPostProcessing, Int>()
fun priority(processing: J2kPostProcessing): Int {
return processingsToPriorityMap[processing]!!
}
init {
_processings.add(RemoveExplicitTypeArgumentsProcessing())
_processings.add(RemoveRedundantOverrideVisibilityProcessing())
@@ -111,18 +118,13 @@ object J2KPostProcessingRegistrar {
}
}
}
}
private inline fun <reified TElement : KtElement, TIntention: SelfTargetingRangeIntention<TElement>> registerIntentionBasedProcessing(
intention: TIntention
) {
//TODO: replace with optional argument when supported for inline functions
return registerIntentionBasedProcessing<TElement, TIntention>(intention, { true })
processingsToPriorityMap.putAll(_processings.mapToIndex())
}
private inline fun <reified TElement : KtElement, TIntention: SelfTargetingRangeIntention<TElement>> registerIntentionBasedProcessing(
intention: TIntention,
noinline additionalChecker: (TElement) -> Boolean
noinline additionalChecker: (TElement) -> Boolean = { true }
) {
_processings.add(object : J2kPostProcessing {
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.PsiRecursiveElementVisitor
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.resolveImportReference
import org.jetbrains.kotlin.idea.conversion.copy.range
@@ -54,14 +51,12 @@ class J2kPostProcessor(private val formatCode: Boolean) : PostProcessor {
while (elementToActions.isNotEmpty()) {
var modificationStamp: Long? = file.modificationStamp
for ((element, actions) in elementToActions) {
for ((action, processing) in actions) {
if (element.isValid) {
action()
}
else {
modificationStamp = null
}
for ((element, action, processing) in elementToActions) {
if (element.isValid) {
action()
}
else {
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 elementToActions = LinkedHashMap<KtElement, SmartList<ActionData>>()
val availableActions = ArrayList<ActionData>()
file.accept(object : PsiRecursiveElementVisitor(){
file.accept(object : PsiRecursiveElementVisitor() {
override fun visitElement(element: PsiElement) {
if (element is KtElement) {
val rangeResult = rangeFilter(element, rangeMarker)
@@ -102,15 +97,15 @@ class J2kPostProcessor(private val formatCode: Boolean) : PostProcessor {
J2KPostProcessingRegistrar.processings.forEach { processing ->
val action = processing.createAction(element, diagnostics)
if (action != null) {
elementToActions.getOrPut(element) { SmartList() }.add(ActionData(action, processing))
availableActions.add(ActionData(element, action, J2KPostProcessingRegistrar.priority(processing)))
}
}
}
}
}
})
return elementToActions
availableActions.sortBy { it.priority }
return availableActions
}
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) {}
}
@@ -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);
}
@@ -0,0 +1,4 @@
package test;
public interface Face {
void subject(String p);
}
@@ -47,6 +47,12 @@ public class JavaToKotlinConverterMultiFileTestGenerated extends AbstractJavaToK
doTest(fileName);
}
@TestMetadata("FunctionalInterfaceAcceptor")
public void testFunctionalInterfaceAcceptor() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/multiFile/FunctionalInterfaceAcceptor/");
doTest(fileName);
}
@TestMetadata("GetterAndSetterUsages")
public void testGetterAndSetterUsages() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/multiFile/GetterAndSetterUsages/");