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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -1,4 +1,3 @@
Searched inheritors of A
Searched references to A
Used plain search in LocalSearchScope:
CLASS:A

View File

@@ -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:

View File

@@ -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:

View File

@@ -1,5 +1,3 @@
// PSI_ELEMENT: org.jetbrains.kotlin.psi.KtParameter
// OPTIONS: usages
import pack.A;
import java.util.Collections;

View File

@@ -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

View File

@@ -0,0 +1,6 @@
import pack.A;
import java.util.List;
public abstract class JavaClass2 implements List<A> {
}

View File

@@ -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]
}

View File

@@ -0,0 +1,6 @@
import pack.A;
import java.util.ArrayList;
public class JavaClass3 extends ArrayList<A> {
}

View File

@@ -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

View File

@@ -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()

View File

@@ -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:

View File

@@ -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

View File

@@ -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()
}

View File

@@ -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

View File

@@ -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()

View File

@@ -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:

View File

@@ -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:

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -1,4 +1,3 @@
Searched inheritors of A
Searched references to A
Used plain search in LocalSearchScope:
CLASS:A

View File

@@ -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

View File

@@ -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

View File

@@ -1,4 +1,3 @@
Searched inheritors of A
Searched references to A
Used plain search in LocalSearchScope:
CLASS:A

View File

@@ -1,4 +1,3 @@
Searched inheritors of test.KotlinDataClass
Searched references to test.KotlinDataClass
Used plain search in LocalSearchScope:
CLASS:KotlinDataClass