Analyze inlined declarations in bytecode toolwindow

This commit is contained in:
Michael Bogdanov
2015-02-04 16:16:36 +03:00
parent 5c9554e703
commit 758c147835
2 changed files with 51 additions and 9 deletions
@@ -45,11 +45,10 @@ public class CompositeBindingContext private (
}
override fun <K, V> getSliceContents(slice: ReadOnlySlice<K, V>): ImmutableMap<K, V> {
val builder = ImmutableMap.builder<K, V>()!!
for (delegate in delegates) {
builder.putAll(delegate.getSliceContents(slice))
}
return builder.build()!!
//we need intermediate map cause ImmutableMap doesn't support same entries obtained from different slices
var map = hashMapOf<K, V>()
delegates.forEach { map.putAll(it.getSliceContents(slice)) }
return ImmutableMap.builder<K, V>().putAll(map).build()
}
override fun getDiagnostics(): Diagnostics {
@@ -31,6 +31,7 @@ import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowFactory;
import com.intellij.psi.PsiElement;
import com.intellij.ui.content.ContentFactory;
import com.intellij.ui.content.ContentManager;
import com.intellij.util.Alarm;
@@ -43,21 +44,28 @@ import org.jetbrains.kotlin.codegen.CompilationErrorHandler;
import org.jetbrains.kotlin.codegen.KotlinCodegenFacade;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.Progress;
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor;
import org.jetbrains.kotlin.diagnostics.DiagnosticSink;
import org.jetbrains.kotlin.idea.caches.resolve.KotlinCacheService;
import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage;
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToDeclarationUtil;
import org.jetbrains.kotlin.idea.util.InfinitePeriodicalTask;
import org.jetbrains.kotlin.idea.util.LongRunningReadTask;
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil;
import org.jetbrains.kotlin.psi.Call;
import org.jetbrains.kotlin.psi.JetElement;
import org.jetbrains.kotlin.psi.JetFile;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor;
import javax.swing.*;
import java.awt.*;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.*;
import java.util.List;
import java.util.Scanner;
public class KotlinBytecodeToolWindow extends JPanel implements Disposable {
private static final int UPDATE_DELAY = 1000;
@@ -108,14 +116,21 @@ public class KotlinBytecodeToolWindow extends JPanel implements Disposable {
GenerationState state;
try {
AnalysisResult result = ResolvePackage.analyzeFullyAndGetResult(jetFile);
boolean disableInline = !enableInline.isSelected();
if (!disableInline) {
result = processInlinedDeclarations(jetFile.getProject(), result, Collections.<JetElement>singleton(jetFile), 1);
}
if (result.isError()) {
return printStackTraceToString(result.getError());
}
state = new GenerationState(jetFile.getProject(), ClassBuilderFactories.TEST, Progress.DEAF,
result.getModuleDescriptor(), result.getBindingContext(),
Collections.singletonList(jetFile), !enableAssertions.isSelected(), !enableAssertions.isSelected(),
GenerationState.GenerateClassFilter.GENERATE_ALL,
!enableInline.isSelected(), !enableOptimization.isSelected(), null, null,
disableInline, !enableOptimization.isSelected(), null, null,
DiagnosticSink.DO_NOTHING, null);
KotlinCodegenFacade.compileCorrectFiles(state, CompilationErrorHandler.THROW_EXCEPTION);
}
@@ -139,6 +154,34 @@ public class KotlinBytecodeToolWindow extends JPanel implements Disposable {
return answer.toString();
}
private AnalysisResult processInlinedDeclarations(Project project, AnalysisResult result, Set<JetElement> originalElements, int deep) {
if (deep >= 10 || result.isError()) {
return result;
}
Set<JetElement> collectedElements = new HashSet<JetElement>();
collectedElements.addAll(originalElements);
Map<Call, ResolvedCall<?>> contents = result.getBindingContext().getSliceContents(BindingContext.RESOLVED_CALL);
Collection<ResolvedCall<?>> values = contents.values();
for (ResolvedCall call : values) {
CallableDescriptor descriptor = call.getResultingDescriptor();
if (!(descriptor instanceof DeserializedSimpleFunctionDescriptor)) {
if (descriptor instanceof SimpleFunctionDescriptor &&
((SimpleFunctionDescriptor) descriptor).getInlineStrategy().isInline()) {
PsiElement declaration =
DescriptorToDeclarationUtil.INSTANCE$.getDeclaration(project, descriptor);
if (declaration != null && declaration instanceof JetElement) {
collectedElements.add((JetElement) declaration);
}
}
}
}
if (collectedElements.size() != originalElements.size()) {
AnalysisResult newResult = KotlinCacheService.getInstance(project).getAnalysisResults(collectedElements);
return processInlinedDeclarations(project, newResult, collectedElements, deep + 1);
}
return result;
}
@Override
protected void onResultReady(@NotNull Location requestInfo, String resultText) {
Editor editor = requestInfo.getEditor();