Inline util functions renaming
This commit is contained in:
@@ -152,7 +152,7 @@ public class ClosureCodegen extends MemberCodegen<JetElement> {
|
||||
@Nullable
|
||||
@Override
|
||||
protected ClassDescriptor classForInnerClassRecord() {
|
||||
return JvmCodegenUtil.isLambdaWhichWillBeInlined(bindingContext, funDescriptor) ? null : classDescriptor;
|
||||
return JvmCodegenUtil.isArgumentWhichWillBeInlined(bindingContext, funDescriptor) ? null : classDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1849,7 +1849,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
if (isFunctionLiteral(descriptor)) {
|
||||
//non labeled return couldn't be local in lambda
|
||||
FunctionDescriptor containingFunction =
|
||||
BindingContextUtils.getContainingFunctionSkipFunctionLiterals(descriptor, false).getFirst();
|
||||
BindingContextUtils.getContainingFunctionSkipFunctionLiterals(descriptor, true).getFirst();
|
||||
//FIRST_FUN_LABEL to prevent clashing with existing labels
|
||||
return new NonLocalReturnInfo(typeMapper.mapReturnType(containingFunction), InlineCodegenUtil.FIRST_FUN_LABEL);
|
||||
} else {
|
||||
|
||||
@@ -230,10 +230,10 @@ public class JvmCodegenUtil {
|
||||
: descriptor;
|
||||
}
|
||||
|
||||
public static boolean isLambdaWhichWillBeInlined(@NotNull BindingContext bindingContext, @NotNull DeclarationDescriptor descriptor) {
|
||||
public static boolean isArgumentWhichWillBeInlined(@NotNull BindingContext bindingContext, @NotNull DeclarationDescriptor descriptor) {
|
||||
PsiElement declaration = DescriptorToSourceUtils.descriptorToDeclaration(descriptor);
|
||||
return InlineUtil.isFunctionalExpression(declaration) &&
|
||||
InlineUtil.isInlineLambda((JetFunction)declaration, bindingContext, false);
|
||||
return InlineUtil.canBeInlineArgument(declaration) &&
|
||||
InlineUtil.isInlinedArgument((JetFunction) declaration, bindingContext, false);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -174,7 +174,7 @@ public class CodegenBinding {
|
||||
|
||||
// Note: at the moment this is needed for light classes only
|
||||
// TODO: refactor this out
|
||||
if (enclosing != null && !JvmCodegenUtil.isLambdaWhichWillBeInlined(trace.getBindingContext(), classDescriptor)) {
|
||||
if (enclosing != null && !JvmCodegenUtil.isArgumentWhichWillBeInlined(trace.getBindingContext(), classDescriptor)) {
|
||||
recordInnerClass(trace, enclosing, classDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.inline;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
@@ -60,7 +59,6 @@ import java.util.*;
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.getMethodAsmFlags;
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive;
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.addInlineMarker;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isFunctionExpression;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isFunctionLiteral;
|
||||
import static org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage.getResolvedCallWithAssert;
|
||||
|
||||
|
||||
+2
-2
@@ -69,9 +69,9 @@ class CapturingInClosureChecker : CallChecker {
|
||||
context: BindingContext, scopeContainer: DeclarationDescriptor, variableParent: DeclarationDescriptor
|
||||
): Boolean {
|
||||
val scopeDeclaration = DescriptorToSourceUtils.descriptorToDeclaration(scopeContainer)
|
||||
if (!InlineUtil.isFunctionalExpression(scopeDeclaration)) return false
|
||||
if (!InlineUtil.canBeInlineArgument(scopeDeclaration)) return false
|
||||
|
||||
if (InlineUtil.isInlineLambda(scopeDeclaration as JetFunction, context, false)) {
|
||||
if (InlineUtil.isInlinedArgument(scopeDeclaration as JetFunction, context, false)) {
|
||||
val scopeContainerParent = scopeContainer.getContainingDeclaration()
|
||||
assert(scopeContainerParent != null) { "parent is null for " + scopeContainer }
|
||||
return !isCapturedVariable(variableParent, scopeContainerParent) || isCapturedInInline(context, scopeContainerParent, variableParent)
|
||||
|
||||
@@ -102,8 +102,8 @@ public class InlineUtil {
|
||||
|
||||
BindingContext bindingContext = trace.getBindingContext();
|
||||
|
||||
while (isFunctionalExpression(containingFunction) && fromFunction != containingFunctionDescriptor) {
|
||||
if (!isInlineLambda((JetFunction) containingFunction, bindingContext, true)) {
|
||||
while (canBeInlineArgument(containingFunction) && fromFunction != containingFunctionDescriptor) {
|
||||
if (!isInlinedArgument((JetFunction) containingFunction, bindingContext, true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -117,20 +117,20 @@ public class InlineUtil {
|
||||
return fromFunction == containingFunctionDescriptor;
|
||||
}
|
||||
|
||||
public static boolean isInlineLambda(
|
||||
@NotNull JetFunction functionalExpression,
|
||||
public static boolean isInlinedArgument(
|
||||
@NotNull JetFunction argument,
|
||||
@NotNull BindingContext bindingContext,
|
||||
boolean checkNonLocalReturn
|
||||
) {
|
||||
if (!isFunctionalExpression(functionalExpression)) return false;
|
||||
if (!canBeInlineArgument(argument)) return false;
|
||||
|
||||
JetExpression call = JetPsiUtil.getParentCallIfPresent(functionalExpression);
|
||||
JetExpression call = JetPsiUtil.getParentCallIfPresent(argument);
|
||||
if (call != null) {
|
||||
ResolvedCall<?> resolvedCall = CallUtilPackage.getResolvedCall(call, bindingContext);
|
||||
if (resolvedCall != null && isInline(resolvedCall.getResultingDescriptor())) {
|
||||
ValueArgument argument = CallUtilPackage.getValueArgumentForExpression(resolvedCall.getCall(), functionalExpression);
|
||||
if (argument != null) {
|
||||
ArgumentMapping mapping = resolvedCall.getArgumentMapping(argument);
|
||||
ValueArgument valueArgument = CallUtilPackage.getValueArgumentForExpression(resolvedCall.getCall(), argument);
|
||||
if (valueArgument != null) {
|
||||
ArgumentMapping mapping = resolvedCall.getArgumentMapping(valueArgument);
|
||||
if (mapping instanceof ArgumentMatch) {
|
||||
ValueParameterDescriptor parameter = ((ArgumentMatch) mapping).getValueParameter();
|
||||
if (isInlineLambdaParameter(parameter)) {
|
||||
@@ -143,7 +143,7 @@ public class InlineUtil {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isFunctionalExpression(@Nullable PsiElement functionalExpression) {
|
||||
public static boolean canBeInlineArgument(@Nullable PsiElement functionalExpression) {
|
||||
return functionalExpression instanceof JetFunctionLiteral || functionalExpression instanceof JetNamedFunction;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,11 +27,11 @@ import com.intellij.refactoring.util.CommonRefactoringUtil;
|
||||
import com.intellij.util.text.CharArrayUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.types.JetType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.*;
|
||||
@@ -138,35 +138,37 @@ public class CodeInsightUtils {
|
||||
return element;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiElement[] findElementsOfClassInRange(@NotNull PsiFile file, int startOffset, int endOffset, Class<? extends PsiElement> aClass) {
|
||||
@NotNull
|
||||
public static List<PsiElement> findElementsOfClassInRange(@NotNull PsiFile file, int startOffset, int endOffset, Class<? extends PsiElement> ... classes) {
|
||||
PsiElement element1 = getElementAtOffsetIgnoreWhitespaceBefore(file, startOffset);
|
||||
PsiElement element2 = getElementAtOffsetIgnoreWhitespaceAfter(file, endOffset);
|
||||
|
||||
if (element1 == null || element2 == null) return PsiElement.EMPTY_ARRAY;
|
||||
if (element1 == null || element2 == null) return Collections.emptyList();
|
||||
|
||||
startOffset = element1.getTextRange().getStartOffset();
|
||||
endOffset = element2.getTextRange().getEndOffset();
|
||||
|
||||
PsiElement parent = PsiTreeUtil.findCommonParent(element1, element2);
|
||||
if (parent == null) return PsiElement.EMPTY_ARRAY;
|
||||
if (parent == null) return Collections.emptyList();
|
||||
|
||||
element1 = getTopmostParentInside(element1, parent);
|
||||
if (startOffset != element1.getTextRange().getStartOffset()) return PsiElement.EMPTY_ARRAY;
|
||||
if (startOffset != element1.getTextRange().getStartOffset()) return Collections.emptyList();
|
||||
|
||||
element2 = getTopmostParentInside(element2, parent);
|
||||
if (endOffset != element2.getTextRange().getEndOffset()) return PsiElement.EMPTY_ARRAY;
|
||||
if (endOffset != element2.getTextRange().getEndOffset()) return Collections.emptyList();
|
||||
|
||||
PsiElement stopElement = element2.getNextSibling();
|
||||
List<PsiElement> array = new ArrayList<PsiElement>();
|
||||
List<PsiElement> result = new ArrayList<PsiElement>();
|
||||
for (PsiElement currentElement = element1; currentElement != stopElement && currentElement != null; currentElement = currentElement.getNextSibling()) {
|
||||
if (aClass.isInstance(currentElement)) {
|
||||
array.add(currentElement);
|
||||
for (Class aClass : classes) {
|
||||
if (aClass.isInstance(currentElement)) {
|
||||
result.add(currentElement);
|
||||
}
|
||||
result.addAll(PsiTreeUtil.findChildrenOfType(currentElement, aClass));
|
||||
}
|
||||
array.addAll(PsiTreeUtil.findChildrenOfType(currentElement, aClass));
|
||||
}
|
||||
|
||||
return PsiUtilCore.toPsiElementArray(array);
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -83,9 +83,9 @@ public class JetPositionManager(private val myDebugProcess: DebugProcess) : Mult
|
||||
|
||||
|
||||
if (lineNumber >= 0) {
|
||||
val lambdaIfInside = getLambdaOrFunIfInside(location, psiFile as JetFile, lineNumber)
|
||||
if (lambdaIfInside != null) {
|
||||
return SourcePosition.createFromElement(lambdaIfInside.getBodyExpression())
|
||||
val lambdaOrFunIfInside = getLambdaOrFunIfInside(location, psiFile as JetFile, lineNumber)
|
||||
if (lambdaOrFunIfInside != null) {
|
||||
return SourcePosition.createFromElement(lambdaOrFunIfInside.getBodyExpression())
|
||||
}
|
||||
return SourcePosition.createFromLine(psiFile, lineNumber)
|
||||
}
|
||||
@@ -101,15 +101,11 @@ public class JetPositionManager(private val myDebugProcess: DebugProcess) : Mult
|
||||
val end = CodeInsightUtils.getEndLineOffset(file, lineNumber)
|
||||
if (start == null || end == null) return null
|
||||
|
||||
val functionLiterals: Array<out PsiElement>? = CodeInsightUtils.findElementsOfClassInRange(file, start, end, javaClass<JetFunctionLiteral>())
|
||||
val functionalExpression: Array<out PsiElement>? = CodeInsightUtils.findElementsOfClassInRange(file, start, end, javaClass<JetNamedFunction>())
|
||||
val literals =
|
||||
if (functionLiterals == null) functionalExpression
|
||||
else if (functionalExpression == null) functionLiterals
|
||||
else functionLiterals.plus(functionalExpression).toTypedArray()
|
||||
val literalsOrFunctions = CodeInsightUtils.
|
||||
findElementsOfClassInRange(file, start, end, javaClass<JetFunctionLiteral>(), javaClass<JetNamedFunction>()).
|
||||
filter { JetPsiUtil.getParentCallIfPresent(it as JetExpression) != null }
|
||||
|
||||
|
||||
if (literals == null || literals.size() == 0) return null;
|
||||
if (literalsOrFunctions.isEmpty()) return null;
|
||||
|
||||
val isInLibrary = LibraryUtil.findLibraryEntry(file.getVirtualFile(), file.getProject()) != null
|
||||
val typeMapper = if (!isInLibrary)
|
||||
@@ -118,7 +114,7 @@ public class JetPositionManager(private val myDebugProcess: DebugProcess) : Mult
|
||||
createTypeMapperForLibraryFile(file.findElementAt(start), file)
|
||||
|
||||
val currentLocationClassName = JvmClassName.byFqNameWithoutInnerClasses(FqName(currentLocationFqName)).getInternalName()
|
||||
for (literal in literals) {
|
||||
for (literal in literalsOrFunctions) {
|
||||
val functionLiteral = literal as JetFunction
|
||||
if (isInlinedLambda(functionLiteral, typeMapper.getBindingContext())) {
|
||||
continue
|
||||
@@ -400,7 +396,7 @@ public class JetPositionManager(private val myDebugProcess: DebugProcess) : Mult
|
||||
}
|
||||
|
||||
public fun isInlinedLambda(functionLiteral: JetFunction, context: BindingContext): Boolean {
|
||||
return InlineUtil.isInlineLambda(functionLiteral, context, false)
|
||||
return InlineUtil.isInlinedArgument(functionLiteral, context, false)
|
||||
}
|
||||
|
||||
private fun createKeyForTypeMapper(file: JetFile) = PackagePartClassUtils.getPackagePartInternalName(file)
|
||||
|
||||
+2
-3
@@ -84,9 +84,8 @@ private fun JetExpression.getRelevantFunction(): JetFunction? {
|
||||
(this.getTargetLabel()?.getReference()?.resolve() as? JetFunction)?.let { return it }
|
||||
}
|
||||
for (parent in parents(false)) {
|
||||
when (parent) {
|
||||
is JetFunctionLiteral,
|
||||
is JetNamedFunction -> if (!InlineUtil.isInlineLambda(parent as JetFunction, parent.analyze(), false)) return parent
|
||||
if (InlineUtil.canBeInlineArgument(parent) && !InlineUtil.isInlinedArgument(parent as JetFunction, parent.analyze(), false)) {
|
||||
return parent as JetFunction
|
||||
}
|
||||
}
|
||||
return null
|
||||
|
||||
+2
-2
@@ -56,8 +56,8 @@ public class KotlinRecursiveCallLineMarkerProvider() : LineMarkerProvider {
|
||||
private fun getEnclosingFunction(element: JetElement): JetNamedFunction? {
|
||||
for (parent in element.parents(false)) {
|
||||
when (parent) {
|
||||
is JetFunctionLiteral -> if (!InlineUtil.isInlineLambda(parent, parent.analyze(), false)) return null
|
||||
is JetNamedFunction -> if (!InlineUtil.isInlineLambda(parent, parent.analyze(), false)) return parent
|
||||
is JetFunctionLiteral -> if (!InlineUtil.isInlinedArgument(parent, parent.analyze(), false)) return null
|
||||
is JetNamedFunction -> if (!InlineUtil.isInlinedArgument(parent, parent.analyze(), false)) return parent
|
||||
is JetClassOrObject -> return null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
fun f(a: Int) {
|
||||
run(fun () {
|
||||
run2(fun () {
|
||||
<lineMarker>f</lineMarker>(a - 1)
|
||||
})
|
||||
}
|
||||
@@ -12,3 +12,5 @@ fun ff(a: Int) {
|
||||
|
||||
inline fun <T> run1(noinline f: () -> T): T { }
|
||||
|
||||
inline fun <T> run2(f: () -> T): T { }
|
||||
|
||||
|
||||
+1
-1
@@ -5,4 +5,4 @@ fun test() {
|
||||
<lineMarker descr="Recursive call">f</lineMarker>(a-1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -202,12 +202,6 @@ public class LineMarkersTestGenerated extends AbstractLineMarkersTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("functionalExpression.kt")
|
||||
public void testFunctionalExpression() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/lineMarker/recursiveCall/functionalExpression.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("generic.kt")
|
||||
public void testGeneric() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/lineMarker/recursiveCall/generic.kt");
|
||||
@@ -238,6 +232,12 @@ public class LineMarkersTestGenerated extends AbstractLineMarkersTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("localFun.kt")
|
||||
public void testLocalFun() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/lineMarker/recursiveCall/localFun.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("methodReference.kt")
|
||||
public void testMethodReference() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/lineMarker/recursiveCall/methodReference.kt");
|
||||
|
||||
Reference in New Issue
Block a user