Fixed bug with class using data class as type parameter in supers list

This commit is contained in:
Valentin Kipyatkov
2016-08-30 20:15:23 +03:00
parent b332867b25
commit 06eea53246
28 changed files with 96 additions and 54 deletions
@@ -21,7 +21,6 @@ import com.intellij.lang.java.JavaLanguage
import com.intellij.openapi.application.ApplicationManager
import com.intellij.psi.*
import com.intellij.psi.search.*
import com.intellij.psi.search.searches.ClassInheritorsSearch
import com.intellij.psi.search.searches.ReferencesSearch
import com.intellij.util.Processor
import org.jetbrains.kotlin.KtNodeTypes
@@ -187,29 +186,7 @@ private class Processor(
return
}
val parameters = ClassInheritorsSearch.SearchParameters(psiClass, GlobalSearchScope.allScope(project), true, true, false)
val classesToSearch = listOf(psiClass) + ClassInheritorsSearch.search(parameters).findAll()
testLog?.add("Searched inheritors of ${psiClass.logPresentation()}")
for (classToSearch in classesToSearch) {
testLog?.add("Searched references to ${classToSearch.logPresentation()}")
ReferencesSearch.search(classToSearch).forEach(Processor processor@ { reference -> //TODO: see KT-13607
if (processDataClassUsage(reference)) return@processor true
if (destructuringDeclarationUsageSearchMode != ALWAYS_SMART) {
plainSearchHandler(searchScope)
return@processor false
}
val element = reference.element
val document = PsiDocumentManager.getInstance(project).getDocument(element.containingFile)
val lineAndCol = DiagnosticUtils.offsetToLineAndColumn(document, element.startOffset)
error("Unsupported reference: '${element.text}' in ${element.containingFile.name} line ${lineAndCol.line} column ${lineAndCol.column}")
})
// we must use plain search inside our data class (and inheritors) because implicit 'this' can happen anywhere
(classToSearch as? KtLightClass)?.kotlinOrigin?.let { usePlainSearch(it) }
}
addClassToProcess(psiClass)
processTasks()
@@ -230,6 +207,31 @@ private class Processor(
}
}
private fun addClassToProcess(classToSearch: PsiClass) {
data class ProcessClassUsagesTask(val classToSearch: PsiClass) : Task {
override fun perform() {
testLog?.add("Searched references to ${classToSearch.logPresentation()}")
ReferencesSearch.search(classToSearch).forEach(Processor processor@ { reference -> //TODO: see KT-13607
if (processDataClassUsage(reference)) return@processor true
if (destructuringDeclarationUsageSearchMode != ALWAYS_SMART) {
plainSearchHandler(searchScope)
return@processor false
}
val element = reference.element
val document = PsiDocumentManager.getInstance(project).getDocument(element.containingFile)
val lineAndCol = DiagnosticUtils.offsetToLineAndColumn(document, element.startOffset)
error("Unsupported reference: '${element.text}' in ${element.containingFile.name} line ${lineAndCol.line} column ${lineAndCol.column}")
})
// we must use plain search inside our data class (and inheritors) because implicit 'this' can happen anywhere
(classToSearch as? KtLightClass)?.kotlinOrigin?.let { usePlainSearch(it) }
}
}
addTask(ProcessClassUsagesTask(classToSearch))
}
private enum class CallableToProcessKind {
HAS_DATA_CLASS_TYPE,
PROCESS_LAMBDAS
@@ -407,15 +409,20 @@ private class Processor(
}
is KtConstructorCalleeExpression -> {
if (typeRefParent.parent is KtSuperTypeCallEntry) {
// usage in super type list - just ignore, inheritors are processed above
val parent = typeRefParent.parent
if (parent is KtSuperTypeCallEntry) {
val classOrObject = (parent.parent as KtSuperTypeList).parent as KtClassOrObject
val psiClass = classOrObject.toLightClass()
psiClass?.let { addClassToProcess(it) }
return true
}
}
is KtSuperTypeListEntry -> {
if (typeRef == typeRefParent.typeReference) {
// usage in super type list - just ignore, inheritors are processed above
val classOrObject = (typeRefParent.parent as KtSuperTypeList).parent as KtClassOrObject
val psiClass = classOrObject.toLightClass()
psiClass?.let { addClassToProcess(it) }
return true
}
}
@@ -492,6 +499,16 @@ private class Processor(
}
break@ParentsLoop
}
is PsiReferenceList -> {
if (parent.role == PsiReferenceList.Role.EXTENDS_LIST || parent.role == PsiReferenceList.Role.IMPLEMENTS_LIST) {
val psiClass = parent.parent as PsiClass
if (!psiClass.isPrivateOrLocal()) {
addClassToProcess(psiClass)
}
}
break@ParentsLoop
}
}
prev = parent
@@ -1,5 +1,4 @@
Resolved java class to descriptor: JavaSAM
Searched inheritors of pack.A
Searched references to JavaClass.takeSAM() in Kotlin files
Searched references to JavaSAM in java files
Searched references to pack.A
@@ -6,7 +6,6 @@ Checked type of X.f2()
Checked type of constructor
Checked type of fun2
Checked type of fun3
Searched inheritors of A
Searched references to A
Searched references to X.f2() in Kotlin files
Searched references to constructor in Kotlin files
@@ -1,4 +1,3 @@
Searched inheritors of A
Searched references to A
Used plain search in LocalSearchScope:
CLASS:A
@@ -1,6 +1,5 @@
Checked type of (x, y)
Checked type of f()
Searched inheritors of X
Searched references to X
Searched references to f() in Kotlin files
Used plain search in LocalSearchScope:
@@ -1,7 +1,6 @@
Checked type of (x1, y1)
Checked type of f()
Checked type of g()
Searched inheritors of X
Searched references to X
Searched references to f() in Kotlin files
Used plain search in LocalSearchScope:
@@ -1,5 +1,3 @@
// PSI_ELEMENT: org.jetbrains.kotlin.psi.KtParameter
// OPTIONS: usages
import pack.A;
import java.util.Collections;
@@ -24,4 +24,4 @@ fun List<A>.ext1() {
val (x, y) = get(0)
}
fun <T> T.getThis(): T = this
fun <T> T.getThis(): T = this
@@ -0,0 +1,6 @@
import pack.A;
import java.util.List;
public abstract class JavaClass2 implements List<A> {
}
@@ -20,3 +20,8 @@ fun g() = A()
fun h() = g()
fun listOfA() = listOf<A>(A(1, "", ""))
fun test2(p1: JavaClass2, p2: JavaClass3) {
val (x1, y1) = p1[0]
val (x2, y2) = p2[0]
}
@@ -0,0 +1,6 @@
import pack.A;
import java.util.ArrayList;
public class JavaClass3 extends ArrayList<A> {
}
@@ -1,5 +1,7 @@
Checked type of (x, y, z)
Checked type of (x1, y1)
Checked type of (x1, y1, z1)
Checked type of (x2, y2)
Checked type of (x2, y2, z2)
Checked type of (x3, y3, z3)
Checked type of (x4, y4, z4)
@@ -9,15 +11,20 @@ Checked type of g()
Checked type of h()
Checked type of listOfA()
Checked type of listOfA()
Searched inheritors of pack.A
Searched references to JavaClass.getA() in Kotlin files
Searched references to JavaClass2
Searched references to JavaClass3
Searched references to a in Kotlin files
Searched references to f() in Kotlin files
Searched references to g() in Kotlin files
Searched references to h() in Kotlin files
Searched references to listOfA() in Kotlin files
Searched references to pack.A
Searched references to pack.X
Searched references to parameter p1 in test2() in Kotlin files
Searched references to parameter p2 in test2() in Kotlin files
Used plain search in LocalSearchScope:
CLASS:A
CLASS:X
FUN:ext1
FUN:ext1
@@ -5,6 +5,8 @@
[dataClass.1.kt] Value read 11 val (x3, y3, z3) = h()
[dataClass.1.kt] Value read 13 val (x4, y4, z4) = listOfA()[0]
[dataClass.1.kt] Value read 15 val (x5, y5, z5) = javaClass.getA()[0]
[dataClass.1.kt] Value read 25 val (x1, y1) = p1[0]
[dataClass.1.kt] Value read 26 val (x2, y2) = p2[0]
[dataClass.1.kt] Value read 5 a.n
[dataClass.1.kt] Value read 8 val (x, y, z) = a
[dataClass.1.kt] Value read 9 val (x1, y1, z1) = f()
@@ -1,6 +1,5 @@
Checked type of (x, y, z)
Checked type of a
Searched inheritors of A
Searched references to A
Searched references to a in Kotlin files
Used plain search in LocalSearchScope:
@@ -2,9 +2,6 @@ Checked type of (a, n)
Checked type of (a1, n1)
Checked type of (x, y, z)
Checked type of (x1, y1, z1)
Searched inheritors of A
Searched inheritors of B
Searched inheritors of C
Searched references to A
Searched references to B
Searched references to C
@@ -5,6 +5,13 @@ interface X
class Y : X
open class G<T> {
fun get(): T = TODO()
}
abstract class Z1 : List<X>
abstract class Z2 : G<X>()
operator fun X.component1(): Int = 0
operator fun X.<caret>component2(): Int = 1
@@ -17,3 +24,8 @@ fun test() {
fun Y.ext() {
val (a, b) = this
}
fun g(z1: Z1, z2: Z2) {
val (x1, y1) = z1[0]
val (x2, y2) = z2.get()
}
@@ -1,12 +1,19 @@
Checked type of (x, y)
Checked type of (x1, y1)
Checked type of (x2, y2)
Checked type of f()
Searched inheritors of X
Searched references to X
Searched references to Y
Searched references to Z1
Searched references to Z2
Searched references to f() in Kotlin files
Searched references to parameter z1 in g() in Kotlin files
Searched references to parameter z2 in g() in Kotlin files
Used plain search in LocalSearchScope:
CLASS:X
CLASS:Y
CLASS:Z1
CLASS:Z2
FUN:component1
FUN:component2
FUN:ext
@@ -1,2 +1,4 @@
Value read 14 val (x, y) = f()
Value read 18 val (a, b) = this
Value read 21 val (x, y) = f()
Value read 25 val (a, b) = this
Value read 29 val (x1, y1) = z1[0]
Value read 30 val (x2, y2) = z2.get()
@@ -1,7 +1,6 @@
Checked type of (x, y)
Checked type of (x, y, z)
Checked type of parameter a in FOR
Searched inheritors of A
Searched references to A
Searched references to parameter a in FOR in Kotlin files
Used plain search in LocalSearchScope:
@@ -1,7 +1,6 @@
Checked type of (x, y)
Checked type of (x1, y1)
Checked type of list
Searched inheritors of A
Searched references to A
Searched references to list in Kotlin files
Used plain search in LocalSearchScope:
@@ -1,4 +1,3 @@
Searched inheritors of A
Searched references to A
Searched references to parameter p in foo() in Kotlin files
Searched references to parameter p in takeExtFun() in Kotlin files
@@ -1,6 +1,5 @@
Checked type of (x1, y1)
Checked type of y1()
Searched inheritors of A
Searched references to A
Searched references to parameter a in condition() in Kotlin files
Searched references to parameter a in x() in Kotlin files
@@ -4,7 +4,6 @@ Checked type of (x2, y2)
Checked type of f()
Checked type of g()
Checked type of h()
Searched inheritors of X
Searched references to X
Searched references to Y
Searched references to Z
@@ -1,4 +1,3 @@
Searched inheritors of A
Searched references to A
Used plain search in LocalSearchScope:
CLASS:A
@@ -1,7 +1,6 @@
Checked type of (a1, n1)
Checked type of (a2, n2)
Checked type of (a2, n2)
Searched inheritors of A
Searched references to A
Searched references to parameter a in A() in Kotlin files
Searched references to parameter a in f() in Kotlin files
@@ -1,7 +1,5 @@
Checked type of (a1, s)
Checked type of (b, n)
Searched inheritors of A
Searched inheritors of B
Searched references to A
Searched references to B
Searched references to a1 in Kotlin files
@@ -1,4 +1,3 @@
Searched inheritors of A
Searched references to A
Used plain search in LocalSearchScope:
CLASS:A
@@ -1,4 +1,3 @@
Searched inheritors of test.KotlinDataClass
Searched references to test.KotlinDataClass
Used plain search in LocalSearchScope:
CLASS:KotlinDataClass