Fixed bug in partial body resolve
This commit is contained in:
@@ -94,14 +94,14 @@ class PartialBodyResolveFilter(
|
|||||||
|
|
||||||
if (statement is JetNamedDeclaration) {
|
if (statement is JetNamedDeclaration) {
|
||||||
val name = statement.getName()
|
val name = statement.getName()
|
||||||
if (name != null && nameFilter.accepts(name)) {
|
if (name != null && nameFilter(name)) {
|
||||||
statementMarks.mark(statement, MarkLevel.NEED_REFERENCE_RESOLVE)
|
statementMarks.mark(statement, MarkLevel.NEED_REFERENCE_RESOLVE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (statement is JetMultiDeclaration) {
|
else if (statement is JetMultiDeclaration) {
|
||||||
if (statement.getEntries().any {
|
if (statement.getEntries().any {
|
||||||
val name = it.getName()
|
val name = it.getName()
|
||||||
name != null && nameFilter.accepts(name)
|
name != null && nameFilter(name)
|
||||||
}) {
|
}) {
|
||||||
statementMarks.mark(statement, MarkLevel.NEED_REFERENCE_RESOLVE)
|
statementMarks.mark(statement, MarkLevel.NEED_REFERENCE_RESOLVE)
|
||||||
}
|
}
|
||||||
@@ -118,7 +118,7 @@ class PartialBodyResolveFilter(
|
|||||||
updateNameFilter()
|
updateNameFilter()
|
||||||
|
|
||||||
if (!nameFilter.isEmpty) {
|
if (!nameFilter.isEmpty) {
|
||||||
val smartCastPlaces = potentialSmartCastPlaces(statement, { it.identifiers().all { nameFilter.accepts(it) } })
|
val smartCastPlaces = potentialSmartCastPlaces(statement, { it.affectsNames(nameFilter) })
|
||||||
if (!smartCastPlaces.isEmpty()) {
|
if (!smartCastPlaces.isEmpty()) {
|
||||||
//TODO: do we really need correct resolve for ALL smart cast places?
|
//TODO: do we really need correct resolve for ALL smart cast places?
|
||||||
smartCastPlaces.values()
|
smartCastPlaces.values()
|
||||||
@@ -179,7 +179,7 @@ class PartialBodyResolveFilter(
|
|||||||
override fun visitBinaryWithTypeRHSExpression(expression: JetBinaryExpressionWithTypeRHS) {
|
override fun visitBinaryWithTypeRHSExpression(expression: JetBinaryExpressionWithTypeRHS) {
|
||||||
expression.acceptChildren(this)
|
expression.acceptChildren(this)
|
||||||
|
|
||||||
if (expression.getOperationReference()?.getReferencedNameElementType() == JetTokens.AS_KEYWORD) {
|
if (expression.getOperationReference().getReferencedNameElementType() == JetTokens.AS_KEYWORD) {
|
||||||
addIfCanBeSmartCast(expression.getLeft())
|
addIfCanBeSmartCast(expression.getLeft())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -262,7 +262,7 @@ class PartialBodyResolveFilter(
|
|||||||
override fun visitIsExpression(expression: JetIsExpression) {
|
override fun visitIsExpression(expression: JetIsExpression) {
|
||||||
expression.acceptChildren(this)
|
expression.acceptChildren(this)
|
||||||
|
|
||||||
result.addIfNotNull(expression.getLeftHandSide()?.smartCastExpressionName())
|
result.addIfNotNull(expression.getLeftHandSide().smartCastExpressionName())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return result
|
return result
|
||||||
@@ -379,18 +379,25 @@ class PartialBodyResolveFilter(
|
|||||||
private fun JetElement.noControlFlowInside() = this is JetFunction || this is JetClass || this is JetClassBody
|
private fun JetElement.noControlFlowInside() = this is JetFunction || this is JetClass || this is JetClassBody
|
||||||
}
|
}
|
||||||
|
|
||||||
private data class SmartCastName(val receiverName: SmartCastName?, val selectorName: String) {
|
private data class SmartCastName(
|
||||||
override fun toString(): String = if (receiverName != null) receiverName.toString() + "." + selectorName else selectorName
|
private val receiverName: SmartCastName?,
|
||||||
|
private val selectorName: String? /* null means "this" (and receiverName should be null */
|
||||||
|
) {
|
||||||
|
{
|
||||||
|
if (selectorName == null) {
|
||||||
|
assert(receiverName == null, "selectorName is allowed to be null only when receiverName is also null (which means 'this')")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun identifiers(): Collection<String> {
|
override fun toString(): String = if (receiverName != null) receiverName.toString() + "." + selectorName else selectorName ?: "this"
|
||||||
return if (receiverName != null)
|
|
||||||
receiverName.identifiers() + listOf(selectorName)
|
fun affectsNames(nameFilter: (String) -> Boolean): Boolean {
|
||||||
else
|
if (selectorName == null) return true
|
||||||
listOf(selectorName)
|
if (!nameFilter(selectorName)) return false
|
||||||
|
return receiverName == null || receiverName.affectsNames(nameFilter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: this can be smart-cast too!
|
|
||||||
private fun JetExpression.smartCastExpressionName(): SmartCastName? {
|
private fun JetExpression.smartCastExpressionName(): SmartCastName? {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is JetSimpleNameExpression -> SmartCastName(null, this.getReferencedName())
|
is JetSimpleNameExpression -> SmartCastName(null, this.getReferencedName())
|
||||||
@@ -406,15 +413,17 @@ class PartialBodyResolveFilter(
|
|||||||
return SmartCastName(receiverName, selectorName)
|
return SmartCastName(receiverName, selectorName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is JetThisExpression -> SmartCastName(null, null)
|
||||||
|
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: declarations with special names (e.g. "get")
|
//TODO: declarations with special names (e.g. "get")
|
||||||
private class NameFilter {
|
private class NameFilter : (String) -> Boolean {
|
||||||
private var names: MutableSet<String>? = HashSet()
|
private var names: MutableSet<String>? = HashSet()
|
||||||
|
|
||||||
fun accepts(name: String) = names == null || name in names!!
|
override fun invoke(name: String) = names == null || name in names!!
|
||||||
|
|
||||||
val isEmpty: Boolean
|
val isEmpty: Boolean
|
||||||
get() = names?.isEmpty() ?: false
|
get() = names?.isEmpty() ?: false
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
Resolve target: fun foo(): kotlin.Unit
|
||||||
|
----------------------------------------------
|
||||||
|
class C {
|
||||||
|
fun foo(){}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Any.f() {
|
||||||
|
if (this !is C) return
|
||||||
|
<caret>foo()
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
class C {
|
||||||
|
fun foo(){}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Any.f() {
|
||||||
|
if (this !is C) return
|
||||||
|
<caret>foo()
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
Resolve target: fun foo(): kotlin.Unit
|
||||||
|
----------------------------------------------
|
||||||
|
class C {
|
||||||
|
fun foo(){}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Any.f() {
|
||||||
|
if (this !is C) return
|
||||||
|
this.<caret>foo()
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
class C {
|
||||||
|
fun foo(){}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Any.f() {
|
||||||
|
if (this !is C) return
|
||||||
|
this.<caret>foo()
|
||||||
|
}
|
||||||
@@ -360,6 +360,18 @@ public class PartialBodyResolveTestGenerated extends AbstractPartialBodyResolveT
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("SmartCastOfThis1.kt")
|
||||||
|
public void testSmartCastOfThis1() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/resolve/partialBodyResolve/SmartCastOfThis1.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("SmartCastOfThis2.kt")
|
||||||
|
public void testSmartCastOfThis2() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/resolve/partialBodyResolve/SmartCastOfThis2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("SmartCastPointsResolveRequired1.kt")
|
@TestMetadata("SmartCastPointsResolveRequired1.kt")
|
||||||
public void testSmartCastPointsResolveRequired1() throws Exception {
|
public void testSmartCastPointsResolveRequired1() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/resolve/partialBodyResolve/SmartCastPointsResolveRequired1.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/resolve/partialBodyResolve/SmartCastPointsResolveRequired1.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user