diff --git a/idea/src/org/jetbrains/kotlin/idea/internal/KotlinBytecodeToolWindow.java b/idea/src/org/jetbrains/kotlin/idea/internal/KotlinBytecodeToolWindow.java index 632a8419f02..a419a7c36e8 100644 --- a/idea/src/org/jetbrains/kotlin/idea/internal/KotlinBytecodeToolWindow.java +++ b/idea/src/org/jetbrains/kotlin/idea/internal/KotlinBytecodeToolWindow.java @@ -39,7 +39,6 @@ import com.intellij.ui.content.ContentFactory; import com.intellij.ui.content.ContentManager; import com.intellij.util.Alarm; import org.jetbrains.annotations.NotNull; -import org.jetbrains.kotlin.analyzer.AnalysisResult; import org.jetbrains.kotlin.backend.common.output.OutputFile; import org.jetbrains.kotlin.backend.common.output.OutputFileCollection; import org.jetbrains.kotlin.codegen.ClassBuilderFactories; @@ -59,8 +58,10 @@ import org.jetbrains.kotlin.idea.util.LongRunningReadTask; import org.jetbrains.kotlin.idea.util.ProjectRootsUtil; import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.resolve.BindingContext; +import org.jetbrains.kotlin.resolve.CompositeBindingContext; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.inline.InlineUtil; +import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode; import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor; import javax.swing.*; @@ -206,16 +207,11 @@ public class KotlinBytecodeToolWindow extends JPanel implements Disposable { try { ResolutionFacade resolutionFacade = ResolvePackage.getResolutionFacade(jetFile); - Ref> ref = Ref.create(); - BindingContext bindingContext = processInlinedDeclarations( - jetFile.getProject(), - resolutionFacade, - Collections.singleton(jetFile), - 1, - ref, - !enableInline - ); + Ref> ref = Ref.>create(new HashSet()); + BindingContext bindingContextForFile = resolutionFacade.analyzeFullyAndGetResult(Collections.singletonList(jetFile)).getBindingContext(); + + BindingContext bindingContext = analyzeElementWithInline(resolutionFacade, bindingContextForFile, jetFile, 1, ref, enableInline); //We processing another files just to annotate anonymous classes within their inline functions //Bytecode not produced for them cause of filtering via generateClassFilter @@ -280,42 +276,58 @@ public class KotlinBytecodeToolWindow extends JPanel implements Disposable { return answer.toString(); } - private static BindingContext processInlinedDeclarations( - @NotNull Project project, + private static BindingContext analyzeElementWithInline( @NotNull ResolutionFacade resolutionFacade, - @NotNull Set originalElements, + @NotNull final BindingContext bindingContext, + @NotNull JetElement element, int deep, @NotNull Ref> resultElements, - boolean processOnlyReifiedInline + final boolean enableInline ) { - AnalysisResult newResult = resolutionFacade.analyzeFullyAndGetResult(originalElements); - BindingContext bindingContext = newResult.getBindingContext(); + final Project project = element.getProject(); + final Set collectedElements = new HashSet(); - Set collectedElements = new HashSet(); - collectedElements.addAll(originalElements); - Map> contents = bindingContext.getSliceContents(BindingContext.RESOLVED_CALL); - for (ResolvedCall call : contents.values()) { - CallableDescriptor descriptor = call.getResultingDescriptor(); - if (!(descriptor instanceof DeserializedSimpleFunctionDescriptor) && InlineUtil.isInline(descriptor)) { - if (!processOnlyReifiedInline || hasReifiedTypeParameters(descriptor)) { + element.accept(new JetTreeVisitorVoid() { + @Override + public void visitExpression(@NotNull JetExpression expression) { + super.visitExpression(expression); + + Call call = bindingContext.get(BindingContext.CALL, expression); + if (call == null) return; + + ResolvedCall resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, call); + if (resolvedCall == null) return; + + CallableDescriptor descriptor = resolvedCall.getResultingDescriptor(); + if (descriptor instanceof DeserializedSimpleFunctionDescriptor) return; + + if (InlineUtil.isInline(descriptor) && (enableInline || hasReifiedTypeParameters(descriptor))) { PsiElement declaration = DescriptorToSourceUtilsIde.INSTANCE$.getAnyDeclaration(project, descriptor); - if (declaration != null && declaration instanceof JetElement) { - collectedElements.add((JetElement) declaration); + if (declaration != null && declaration instanceof JetNamedFunction) { + collectedElements.add((JetNamedFunction) declaration); } } } - } + }); - if (collectedElements.size() != originalElements.size()) { - if (newResult.isError() || deep >= 10) { - resultElements.set(collectedElements); - return bindingContext; + resultElements.get().add(element); + + if (!collectedElements.isEmpty() && deep < 10) { + List innerContexts = new ArrayList(); + for (JetNamedFunction inlineFunctions : collectedElements) { + JetExpression body = inlineFunctions.getBodyExpression(); + assert body != null : "Inline function should have a body: " + inlineFunctions.getText(); + + BindingContext bindingContextForFunction = resolutionFacade.analyze(body, BodyResolveMode.FULL); + innerContexts.add(analyzeElementWithInline(resolutionFacade, bindingContextForFunction, inlineFunctions, deep + 1, resultElements, enableInline)); } - return processInlinedDeclarations(project, resolutionFacade, collectedElements, deep + 1, resultElements, processOnlyReifiedInline); + innerContexts.add(bindingContext); + + resultElements.get().addAll(collectedElements); + return CompositeBindingContext.Companion.create(innerContexts); } - resultElements.set(collectedElements); return bindingContext; }