Partial body resolve works for local Nothing functions + does not go inside local functions and classes
This commit is contained in:
@@ -391,3 +391,6 @@ public fun Call.isSafeCall(): Boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fun Call.isExplicitSafeCall(): Boolean = getCallOperationNode()?.getElementType() == JetTokens.SAFE_ACCESS
|
public fun Call.isExplicitSafeCall(): Boolean = getCallOperationNode()?.getElementType() == JetTokens.SAFE_ACCESS
|
||||||
|
|
||||||
|
public fun JetTypeReference?.isProbablyNothing(): Boolean
|
||||||
|
= (this?.getTypeElement() as? JetUserType)?.getReferencedName() == "Nothing"
|
||||||
+2
-1
@@ -24,6 +24,7 @@ import com.intellij.util.io.StringRef;
|
|||||||
import org.jetbrains.annotations.NonNls;
|
import org.jetbrains.annotations.NonNls;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
|
import org.jetbrains.jet.lang.psi.psiUtil.PsiUtilPackage;
|
||||||
import org.jetbrains.jet.lang.psi.stubs.KotlinFunctionStub;
|
import org.jetbrains.jet.lang.psi.stubs.KotlinFunctionStub;
|
||||||
import org.jetbrains.jet.lang.psi.stubs.impl.KotlinFunctionStubImpl;
|
import org.jetbrains.jet.lang.psi.stubs.impl.KotlinFunctionStubImpl;
|
||||||
import org.jetbrains.jet.lang.resolve.lazy.ResolveSessionUtils;
|
import org.jetbrains.jet.lang.resolve.lazy.ResolveSessionUtils;
|
||||||
@@ -46,7 +47,7 @@ public class JetFunctionElementType extends JetStubElementType<KotlinFunctionStu
|
|||||||
boolean hasBody = psi.hasBody();
|
boolean hasBody = psi.hasBody();
|
||||||
return new KotlinFunctionStubImpl(parentStub, StringRef.fromString(psi.getName()), isTopLevel, fqName,
|
return new KotlinFunctionStubImpl(parentStub, StringRef.fromString(psi.getName()), isTopLevel, fqName,
|
||||||
isExtension, hasBlockBody, hasBody, psi.hasTypeParameterListBeforeFunctionName(),
|
isExtension, hasBlockBody, hasBody, psi.hasTypeParameterListBeforeFunctionName(),
|
||||||
ElementsPackage.isProbablyNothing(psi.getTypeReference()));
|
PsiUtilPackage.isProbablyNothing(psi.getTypeReference()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+2
-1
@@ -24,6 +24,7 @@ import com.intellij.util.io.StringRef;
|
|||||||
import org.jetbrains.annotations.NonNls;
|
import org.jetbrains.annotations.NonNls;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.psi.JetProperty;
|
import org.jetbrains.jet.lang.psi.JetProperty;
|
||||||
|
import org.jetbrains.jet.lang.psi.psiUtil.PsiUtilPackage;
|
||||||
import org.jetbrains.jet.lang.psi.stubs.KotlinPropertyStub;
|
import org.jetbrains.jet.lang.psi.stubs.KotlinPropertyStub;
|
||||||
import org.jetbrains.jet.lang.psi.stubs.impl.KotlinPropertyStubImpl;
|
import org.jetbrains.jet.lang.psi.stubs.impl.KotlinPropertyStubImpl;
|
||||||
import org.jetbrains.jet.lang.resolve.lazy.ResolveSessionUtils;
|
import org.jetbrains.jet.lang.resolve.lazy.ResolveSessionUtils;
|
||||||
@@ -47,7 +48,7 @@ public class JetPropertyElementType extends JetStubElementType<KotlinPropertyStu
|
|||||||
psi.isVar(), psi.isTopLevel(), psi.hasDelegate(),
|
psi.isVar(), psi.isTopLevel(), psi.hasDelegate(),
|
||||||
psi.hasDelegateExpression(), psi.hasInitializer(),
|
psi.hasDelegateExpression(), psi.hasInitializer(),
|
||||||
psi.getReceiverTypeReference() != null, psi.getTypeReference() != null,
|
psi.getReceiverTypeReference() != null, psi.getTypeReference() != null,
|
||||||
ElementsPackage.isProbablyNothing(psi.getTypeReference()),
|
PsiUtilPackage.isProbablyNothing(psi.getTypeReference()),
|
||||||
ResolveSessionUtils.safeFqNameForLazyResolve(psi)
|
ResolveSessionUtils.safeFqNameForLazyResolve(psi)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2014 JetBrains s.r.o.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.jet.lang.psi.stubs.elements
|
|
||||||
|
|
||||||
import org.jetbrains.jet.lang.psi.JetUserType
|
|
||||||
import org.jetbrains.jet.lang.psi.JetTypeReference
|
|
||||||
|
|
||||||
fun JetTypeReference?.isProbablyNothing()
|
|
||||||
= (this?.getTypeElement() as? JetUserType)?.getReferencedName() == "Nothing"
|
|
||||||
+24
-6
@@ -26,6 +26,9 @@ import java.util.HashMap
|
|||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.jet.JetNodeTypes
|
import org.jetbrains.jet.JetNodeTypes
|
||||||
import org.jetbrains.jet.lang.psi.psiUtil.isAncestor
|
import org.jetbrains.jet.lang.psi.psiUtil.isAncestor
|
||||||
|
import org.jetbrains.jet.lang.psi.psiUtil.isProbablyNothing
|
||||||
|
|
||||||
|
//TODO: do resolve anonymous object's body
|
||||||
|
|
||||||
class PartialBodyResolveFilter(
|
class PartialBodyResolveFilter(
|
||||||
elementToResolve: JetElement,
|
elementToResolve: JetElement,
|
||||||
@@ -35,12 +38,27 @@ class PartialBodyResolveFilter(
|
|||||||
|
|
||||||
private val statementsToResolve = HashSet<JetExpression>()
|
private val statementsToResolve = HashSet<JetExpression>()
|
||||||
private val processedBlocks = HashSet<JetBlockExpression>()
|
private val processedBlocks = HashSet<JetBlockExpression>()
|
||||||
private val nothingFunctionNames = probablyNothingCallableNamesService.functionNames()
|
|
||||||
|
private val nothingFunctionNames = HashSet(probablyNothingCallableNamesService.functionNames())
|
||||||
private val nothingPropertyNames = probablyNothingCallableNamesService.propertyNames()
|
private val nothingPropertyNames = probablyNothingCallableNamesService.propertyNames()
|
||||||
|
|
||||||
;{
|
;{
|
||||||
assert(body.isAncestor(elementToResolve, strict = false))
|
assert(body.isAncestor(elementToResolve, strict = false))
|
||||||
|
|
||||||
|
body.accept(object : JetVisitorVoid(){
|
||||||
|
override fun visitNamedFunction(function: JetNamedFunction) {
|
||||||
|
super.visitNamedFunction(function)
|
||||||
|
|
||||||
|
if (function.getTypeReference().isProbablyNothing()) {
|
||||||
|
nothingFunctionNames.add(function.getName())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitElement(element: PsiElement) {
|
||||||
|
element.acceptChildren(this)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
addStatementsToResolve(elementToResolve)
|
addStatementsToResolve(elementToResolve)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,8 +72,7 @@ class PartialBodyResolveFilter(
|
|||||||
|
|
||||||
private fun addStatementsToResolve(element: JetElement) {
|
private fun addStatementsToResolve(element: JetElement) {
|
||||||
if (element == body) return
|
if (element == body) return
|
||||||
val parent = element.getParent() as? JetElement
|
val parent = element.getParent() as? JetElement ?: return
|
||||||
?: return
|
|
||||||
|
|
||||||
if (parent is JetBlockExpression) {
|
if (parent is JetBlockExpression) {
|
||||||
processBlock(parent)
|
processBlock(parent)
|
||||||
@@ -67,6 +84,7 @@ class PartialBodyResolveFilter(
|
|||||||
|
|
||||||
for (statement in element.siblings(forward = false, withItself = false)) {
|
for (statement in element.siblings(forward = false, withItself = false)) {
|
||||||
if (statement !is JetExpression) continue
|
if (statement !is JetExpression) continue
|
||||||
|
if (statement is JetClassBody) continue
|
||||||
|
|
||||||
val smartCastPlaces = potentialSmartCastPlaces(statement)
|
val smartCastPlaces = potentialSmartCastPlaces(statement)
|
||||||
if (!smartCastPlaces.isEmpty()) {
|
if (!smartCastPlaces.isEmpty()) {
|
||||||
@@ -312,15 +330,15 @@ class PartialBodyResolveFilter(
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private abstract class ControlFlowVisitor : JetVisitorVoid() {
|
private inner abstract class ControlFlowVisitor : JetVisitorVoid() {
|
||||||
override fun visitJetElement(element: JetElement) {
|
override fun visitJetElement(element: JetElement) {
|
||||||
if (element.noControlFlowInside()) return
|
if (element.noControlFlowInside()) return
|
||||||
element.acceptChildren(this)
|
element.acceptChildren(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
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 fun MutableSet<JetExpression>.addStatementsForPlaces(thisStatement: JetExpression, places: Collection<JetExpression>) {
|
private fun MutableSet<JetExpression>.addStatementsForPlaces(thisStatement: JetExpression, places: Collection<JetExpression>) {
|
||||||
@PlacesLoop
|
@PlacesLoop
|
||||||
for (place in places) {
|
for (place in places) {
|
||||||
|
|||||||
@@ -99,7 +99,6 @@ public class ResolveElementCache extends ElementResolver {
|
|||||||
set.addAll(hardcodedNames);
|
set.addAll(hardcodedNames);
|
||||||
set.addAll(indexedNames);
|
set.addAll(indexedNames);
|
||||||
return set;
|
return set;
|
||||||
//TODO: what about local declarations?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
Resolve target: value-parameter val p: kotlin.String?
|
||||||
|
Skipped statements:
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
open class C(p: Int) {
|
||||||
|
open fun f(){}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(p: String?) {
|
||||||
|
val o = object : Runnable {
|
||||||
|
override fun run() {
|
||||||
|
if (p == null) return
|
||||||
|
print(p.size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val c = object : C(p!!.size) {
|
||||||
|
override fun f() {
|
||||||
|
super.f()
|
||||||
|
if (p == null) return
|
||||||
|
print(p.size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<caret>p?.size
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
Resolve target: value-parameter val p: kotlin.String?
|
||||||
|
Skipped statements:
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fun foo(p: String?) {
|
||||||
|
class LocalClass {
|
||||||
|
fun f(): String? {
|
||||||
|
if (p == null) return null
|
||||||
|
print(p.size)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<caret>p?.size
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
Resolve target: value-parameter val p: kotlin.String?
|
||||||
|
Skipped statements:
|
||||||
|
if (p == null) return null
|
||||||
|
print(p.size)
|
||||||
|
return ""
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
fun foo(p: String?) {
|
||||||
|
fun local(): String? {
|
||||||
|
if (p == null) return null
|
||||||
|
print(p.size)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
<caret>p?.size
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
Resolve target: value-parameter val p: kotlin.String? smart-casted to kotlin.String
|
||||||
|
Skipped statements:
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
fun foo(p: String?, p1: Any?) {
|
||||||
|
if (p1 == null) return
|
||||||
|
|
||||||
|
fun localError(): Nothing = throw Exception()
|
||||||
|
|
||||||
|
if (p == null) {
|
||||||
|
localError()
|
||||||
|
}
|
||||||
|
<caret>p.size
|
||||||
|
}
|
||||||
@@ -19,7 +19,6 @@ package org.jetbrains.jet.resolve;
|
|||||||
import com.intellij.testFramework.TestDataPath;
|
import com.intellij.testFramework.TestDataPath;
|
||||||
import org.jetbrains.jet.JUnit3RunnerWithInners;
|
import org.jetbrains.jet.JUnit3RunnerWithInners;
|
||||||
import org.jetbrains.jet.JetTestUtils;
|
import org.jetbrains.jet.JetTestUtils;
|
||||||
import org.jetbrains.jet.test.InnerTestClasses;
|
|
||||||
import org.jetbrains.jet.test.TestMetadata;
|
import org.jetbrains.jet.test.TestMetadata;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
@@ -36,6 +35,12 @@ public class PartialBodyResolveTestGenerated extends AbstractPartialBodyResolveT
|
|||||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/resolve/partialBodyResolve"), Pattern.compile("^(.+)\\.kt$"), true);
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/resolve/partialBodyResolve"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("AnonymousObjects.kt")
|
||||||
|
public void testAnonymousObjects() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/resolve/partialBodyResolve/AnonymousObjects.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("As.kt")
|
@TestMetadata("As.kt")
|
||||||
public void testAs() throws Exception {
|
public void testAs() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/resolve/partialBodyResolve/As.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/resolve/partialBodyResolve/As.kt");
|
||||||
@@ -234,6 +239,24 @@ public class PartialBodyResolveTestGenerated extends AbstractPartialBodyResolveT
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("LocalClass.kt")
|
||||||
|
public void testLocalClass() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/resolve/partialBodyResolve/LocalClass.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("LocalFun.kt")
|
||||||
|
public void testLocalFun() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/resolve/partialBodyResolve/LocalFun.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("LocalNothingFun.kt")
|
||||||
|
public void testLocalNothingFun() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/resolve/partialBodyResolve/LocalNothingFun.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("Simple.kt")
|
@TestMetadata("Simple.kt")
|
||||||
public void testSimple() throws Exception {
|
public void testSimple() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/resolve/partialBodyResolve/Simple.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/resolve/partialBodyResolve/Simple.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user