Optimization

This commit is contained in:
Valentin Kipyatkov
2016-09-02 16:00:33 +03:00
parent 0f32574be0
commit 5ce780cafc
9 changed files with 33 additions and 16 deletions
@@ -22,29 +22,37 @@ import com.intellij.psi.search.SearchRequestCollector
import com.intellij.psi.search.SearchScope import com.intellij.psi.search.SearchScope
import com.intellij.util.Processor import com.intellij.util.Processor
import org.jetbrains.kotlin.idea.references.KtArrayAccessReference import org.jetbrains.kotlin.idea.references.KtArrayAccessReference
import org.jetbrains.kotlin.idea.references.readWriteAccess
import org.jetbrains.kotlin.psi.KtArrayAccessExpression import org.jetbrains.kotlin.psi.KtArrayAccessExpression
import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtFunction import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
//TODO: more effective search of 'set'
class IndexingOperatorReferenceSearcher( class IndexingOperatorReferenceSearcher(
targetFunction: KtFunction, targetFunction: KtFunction,
searchScope: SearchScope, searchScope: SearchScope,
consumer: Processor<PsiReference>, consumer: Processor<PsiReference>,
optimizer: SearchRequestCollector optimizer: SearchRequestCollector,
private val isSet: Boolean
) : OperatorReferenceSearcher<KtArrayAccessExpression>(targetFunction, searchScope, consumer, optimizer, wordsToSearch = listOf("[")) { ) : OperatorReferenceSearcher<KtArrayAccessExpression>(targetFunction, searchScope, consumer, optimizer, wordsToSearch = listOf("[")) {
override fun processSuspiciousExpression(expression: KtExpression) { override fun processSuspiciousExpression(expression: KtExpression) {
val accessExpression = expression.parent as? KtArrayAccessExpression ?: return val accessExpression = expression.parent as? KtArrayAccessExpression ?: return
if (expression != accessExpression.arrayExpression) return if (expression != accessExpression.arrayExpression) return
if (!checkAccessExpression(accessExpression)) return
processReferenceElement(accessExpression) processReferenceElement(accessExpression)
} }
override fun isReferenceToCheck(ref: PsiReference) = ref is KtArrayAccessReference override fun isReferenceToCheck(ref: PsiReference) = ref is KtArrayAccessReference && checkAccessExpression(ref.element as KtArrayAccessExpression)
override fun extractReference(element: PsiElement): PsiReference? { override fun extractReference(element: PsiElement): PsiReference? {
val accessExpression = element as? KtArrayAccessExpression ?: return null val accessExpression = element as? KtArrayAccessExpression ?: return null
if (!checkAccessExpression(accessExpression)) return null
return accessExpression.references.firstIsInstance<KtArrayAccessReference>() return accessExpression.references.firstIsInstance<KtArrayAccessReference>()
} }
private fun checkAccessExpression(accessExpression: KtArrayAccessExpression): Boolean {
val readWriteAccess = accessExpression.readWriteAccess(useResolveForReadWrite = false)
return if (isSet) readWriteAccess.isWrite else readWriteAccess.isRead
}
} }
@@ -133,8 +133,12 @@ abstract class OperatorReferenceSearcher<TReferenceElement : KtElement>(
return UnaryOperatorReferenceSearcher(declaration, unaryOp, searchScope, consumer, optimizer) return UnaryOperatorReferenceSearcher(declaration, unaryOp, searchScope, consumer, optimizer)
} }
if (name in INDEXING_OPERATION_NAMES) { if (name == OperatorNameConventions.GET) {
return IndexingOperatorReferenceSearcher(declaration, searchScope, consumer, optimizer) return IndexingOperatorReferenceSearcher(declaration, searchScope, consumer, optimizer, isSet = false)
}
if (name == OperatorNameConventions.SET) {
return IndexingOperatorReferenceSearcher(declaration, searchScope, consumer, optimizer, isSet = true)
} }
return null return null
@@ -40,8 +40,6 @@ val ALL_SEARCHABLE_OPERATIONS: ImmutableSet<KtToken> = ImmutableSet
.add(KtTokens.BY_KEYWORD) .add(KtTokens.BY_KEYWORD)
.build() .build()
val INDEXING_OPERATION_NAMES = setOf(OperatorNameConventions.GET, OperatorNameConventions.SET)
val DELEGATE_ACCESSOR_NAMES = setOf(Name.identifier("getValue"), Name.identifier("setValue")) val DELEGATE_ACCESSOR_NAMES = setOf(Name.identifier("getValue"), Name.identifier("setValue"))
val IN_OPERATIONS_TO_SEARCH = setOf(KtTokens.IN_KEYWORD) val IN_OPERATIONS_TO_SEARCH = setOf(KtTokens.IN_KEYWORD)
+4 -1
View File
@@ -2,10 +2,13 @@
// OPTIONS: usages // OPTIONS: usages
class B(val n: Int) { class B(val n: Int) {
operator fun <caret>get(i: Int): B = B(i) operator fun <caret>get(i: Int) = ""
operator fun set(i: Int, s: String)
} }
fun test() { fun test() {
B(1).get(2) B(1).get(2)
B(1)[2] B(1)[2]
val b = B(2)
b[3] = "a"
} }
+2 -1
View File
@@ -1,5 +1,6 @@
Checked type of b
Resolved B(1)[2] Resolved B(1)[2]
Searched references to B Searched references to B
Searched references to B.get(i: Int) in Kotlin files Searched references to b in Kotlin files
Used plain search of B.get(i: Int) in LocalSearchScope: Used plain search of B.get(i: Int) in LocalSearchScope:
CLASS:B CLASS:B
@@ -1,2 +1,2 @@
Function call 9 B(1).get(2) Function call 10 B(1).get(2)
Implicit 'get' 10 B(1)[2] Implicit 'get' 11 B(1)[2]
+4 -2
View File
@@ -3,11 +3,13 @@
class B(val n: Int) { class B(val n: Int) {
operator fun <caret>set(i: Int, a: B) {} operator fun <caret>set(i: Int, a: B) {}
operator fun inc() {}
} }
fun test() { fun test() {
var a = B(1) var a = B(1)
a.set(2, B(2)) a.set(2, B(2))
a[2] = B(2) a[1] = B(2)
a[2] a[2]++
a[3]
} }
+1 -1
View File
@@ -1,5 +1,5 @@
Checked type of a Checked type of a
Resolved a[2] Resolved a[1]
Resolved a[2] Resolved a[2]
Searched references to B Searched references to B
Searched references to a in Kotlin files Searched references to a in Kotlin files
@@ -1,2 +1,3 @@
Function call 10 a.set(2, B(2)) Function call 11 a.set(2, B(2))
Implicit 'set' 11 a[2] = B(2) Implicit 'set' 12 a[1] = B(2)
Unclassified usage 13 a[2]++