Control-Flow Analysis: Compute STATEMENT slice using control-flow information
This commit is contained in:
@@ -42,6 +42,7 @@ public class ConvertToForEachLoopIntention : JetSelfTargetingIntention<JetExpres
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
is JetBinaryExpression -> element.getRight()
|
||||
|
||||
+2
-12
@@ -28,7 +28,6 @@ import org.jetbrains.jet.plugin.refactoring.introduce.introduceVariable.KotlinIn
|
||||
import org.jetbrains.jet.lang.psi.JetSafeQualifiedExpression
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext
|
||||
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.jet.plugin.refactoring.inline.KotlinInlineValHandler
|
||||
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression
|
||||
@@ -43,6 +42,7 @@ import org.jetbrains.jet.lang.psi.JetPostfixExpression
|
||||
import org.jetbrains.jet.lang.psi.JetCallExpression
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils
|
||||
import org.jetbrains.jet.lang.psi.JetElement
|
||||
import org.jetbrains.jet.lang.resolve.bindingContextUtil.isUsedAsStatement
|
||||
|
||||
val NULL_PTR_EXCEPTION = "NullPointerException"
|
||||
val NULL_PTR_EXCEPTION_FQ = "java.lang.NullPointerException"
|
||||
@@ -72,17 +72,7 @@ fun JetExpression.extractExpressionIfSingle(): JetExpression? {
|
||||
return innerExpression
|
||||
}
|
||||
|
||||
fun JetExpression.isStatement(): Boolean {
|
||||
val context = AnalyzerFacadeWithCache.getContextForElement(this)
|
||||
|
||||
val expectedType = context.get(BindingContext.EXPECTED_EXPRESSION_TYPE, this);
|
||||
val isUnit = expectedType != null && KotlinBuiltIns.getInstance().isUnit(expectedType);
|
||||
|
||||
// Some "statements" are actually expressions returned from lambdas, their expected types are non-null
|
||||
val isStatement = context.get(BindingContext.STATEMENT, this) == true && expectedType == null;
|
||||
|
||||
return isStatement || isUnit
|
||||
}
|
||||
fun JetExpression.isStatement(): Boolean = isUsedAsStatement(AnalyzerFacadeWithCache.getContextForElement(this))
|
||||
|
||||
fun JetBinaryExpression.getNonNullExpression(): JetExpression? = when {
|
||||
this.getLeft()?.isNullExpression() == false ->
|
||||
|
||||
+1
-1
@@ -35,9 +35,9 @@ import com.intellij.codeInsight.template.TemplateBuilderImpl
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import org.apache.commons.lang.StringEscapeUtils.escapeJava
|
||||
import org.jetbrains.jet.plugin.intentions.branchedTransformations.convertToIfNullExpression
|
||||
import org.jetbrains.jet.plugin.intentions.branchedTransformations.isStatement
|
||||
import org.jetbrains.jet.plugin.intentions.branchedTransformations.NULL_PTR_EXCEPTION
|
||||
import org.jetbrains.jet.plugin.intentions.branchedTransformations.KOTLIN_NULL_PTR_EXCEPTION
|
||||
import org.jetbrains.jet.plugin.intentions.branchedTransformations.isStatement
|
||||
|
||||
public class DoubleBangToIfThenIntention : JetSelfTargetingIntention<JetPostfixExpression>("double.bang.to.if.then", javaClass()) {
|
||||
|
||||
|
||||
+1
-2
@@ -32,9 +32,8 @@ import org.jetbrains.jet.plugin.intentions.branchedTransformations.extractExpres
|
||||
import org.jetbrains.jet.lang.psi.JetThrowExpression
|
||||
import org.jetbrains.jet.plugin.JetBundle
|
||||
import org.jetbrains.jet.plugin.intentions.branchedTransformations.isNullExpressionOrEmptyBlock
|
||||
import org.jetbrains.jet.plugin.intentions.branchedTransformations.isStatement
|
||||
import org.jetbrains.jet.plugin.intentions.branchedTransformations.throwsNullPointerExceptionWithNoArguments
|
||||
|
||||
import org.jetbrains.jet.plugin.intentions.branchedTransformations.isStatement
|
||||
|
||||
public class IfThenToDoubleBangIntention : JetSelfTargetingIntention<JetIfExpression>("if.then.to.double.bang", javaClass()) {
|
||||
|
||||
|
||||
+1
-1
@@ -25,8 +25,8 @@ import org.jetbrains.jet.lang.psi.JetBinaryExpression
|
||||
import org.jetbrains.jet.plugin.intentions.branchedTransformations.convertToIfNotNullExpression
|
||||
import org.jetbrains.jet.plugin.intentions.branchedTransformations.introduceValueForCondition
|
||||
import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression
|
||||
import org.jetbrains.jet.plugin.intentions.branchedTransformations.isStatement
|
||||
import org.jetbrains.jet.plugin.intentions.branchedTransformations.isStableVariable
|
||||
import org.jetbrains.jet.plugin.intentions.branchedTransformations.isStatement
|
||||
|
||||
public class SafeAccessToIfThenIntention : JetSelfTargetingIntention<JetSafeQualifiedExpression>("safe.access.to.if.then", javaClass()) {
|
||||
override fun isApplicableTo(element: JetSafeQualifiedExpression): Boolean = true
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.analyzer.AnalyzerPackage;
|
||||
import org.jetbrains.jet.di.InjectorForBodyResolve;
|
||||
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.Annotated;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
@@ -173,6 +174,8 @@ public class ResolveElementCache {
|
||||
assert false : "Invalid type of the topmost parent";
|
||||
}
|
||||
|
||||
new JetFlowInformationProvider(resolveElement, trace).checkDeclaration();
|
||||
|
||||
return trace.getBindingContext();
|
||||
}
|
||||
|
||||
@@ -315,6 +318,10 @@ public class ResolveElementCache {
|
||||
}
|
||||
|
||||
bodyResolver.resolvePropertyAccessors(bodyResolveContext, jetProperty, descriptor);
|
||||
|
||||
for (JetPropertyAccessor accessor : jetProperty.getAccessors()) {
|
||||
new JetFlowInformationProvider(accessor, trace).checkDeclaration();
|
||||
}
|
||||
}
|
||||
|
||||
private static void functionAdditionalResolve(
|
||||
|
||||
+4
-4
@@ -64,6 +64,7 @@ import org.jetbrains.jet.lang.cfg.pseudocodeTraverser.TraversalOrder
|
||||
import org.jetbrains.jet.lang.resolve.bindingContextUtil.getTargetFunctionDescriptor
|
||||
import com.intellij.psi.PsiWhiteSpace
|
||||
import org.jetbrains.jet.lang.resolve.OverridingUtil
|
||||
import org.jetbrains.jet.lang.resolve.bindingContextUtil.isUsedAsStatement
|
||||
import org.jetbrains.jet.lang.psi.psiUtil.isAncestor
|
||||
import org.jetbrains.jet.plugin.intentions.declarations.DeclarationUtils
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils
|
||||
@@ -93,7 +94,6 @@ private fun List<Instruction>.getExitPoints(): List<Instruction> =
|
||||
filter { localInstruction -> localInstruction.nextInstructions.any { it !in this } }
|
||||
|
||||
private fun List<Instruction>.getResultType(
|
||||
pseudocode: Pseudocode,
|
||||
bindingContext: BindingContext,
|
||||
options: ExtractionOptions): JetType {
|
||||
fun instructionToType(instruction: Instruction): JetType? {
|
||||
@@ -106,7 +106,7 @@ private fun List<Instruction>.getResultType(
|
||||
}
|
||||
|
||||
if (expression == null) return null
|
||||
if (options.inferUnitTypeForUnusedValues && expression.isStatement(pseudocode)) return null
|
||||
if (options.inferUnitTypeForUnusedValues && expression.isUsedAsStatement(bindingContext)) return null
|
||||
|
||||
return bindingContext[BindingContext.EXPRESSION_TYPE, expression]
|
||||
}
|
||||
@@ -206,8 +206,8 @@ private fun ExtractionData.analyzeControlFlow(
|
||||
val nonLocallyUsedDeclarations = getLocalDeclarationsWithNonLocalUsages(pseudocode, localInstructions, bindingContext)
|
||||
val (declarationsToCopy, declarationsToReport) = nonLocallyUsedDeclarations.partition { it is JetProperty && it.isLocal() }
|
||||
|
||||
val typeOfDefaultFlow = defaultExits.getResultType(pseudocode, bindingContext, options)
|
||||
val returnValueType = valuedReturnExits.getResultType(pseudocode, bindingContext, options)
|
||||
val typeOfDefaultFlow = defaultExits.getResultType(bindingContext, options)
|
||||
val returnValueType = valuedReturnExits.getResultType(bindingContext, options)
|
||||
|
||||
val defaultReturnType = if (returnValueType.isMeaningful()) returnValueType else typeOfDefaultFlow
|
||||
if (defaultReturnType.isError()) return Pair(DefaultControlFlow(DEFAULT_RETURN_TYPE, declarationsToCopy), ErrorMessage.ERROR_TYPES)
|
||||
|
||||
Reference in New Issue
Block a user