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> { override fun <K, V> getSliceContents(slice: ReadOnlySlice<K, V>): ImmutableMap<K, V> {
val builder = ImmutableMap.builder<K, V>()!! //we need intermediate map cause ImmutableMap doesn't support same entries obtained from different slices
for (delegate in delegates) { var map = hashMapOf<K, V>()
builder.putAll(delegate.getSliceContents(slice)) delegates.forEach { map.putAll(it.getSliceContents(slice)) }
} return ImmutableMap.builder<K, V>().putAll(map).build()
return builder.build()!!
} }
override fun getDiagnostics(): Diagnostics { 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.util.text.StringUtil;
import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowFactory; import com.intellij.openapi.wm.ToolWindowFactory;
import com.intellij.psi.PsiElement;
import com.intellij.ui.content.ContentFactory; import com.intellij.ui.content.ContentFactory;
import com.intellij.ui.content.ContentManager; import com.intellij.ui.content.ContentManager;
import com.intellij.util.Alarm; 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.KotlinCodegenFacade;
import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.Progress; 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.diagnostics.DiagnosticSink;
import org.jetbrains.kotlin.idea.caches.resolve.KotlinCacheService;
import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage; 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.InfinitePeriodicalTask;
import org.jetbrains.kotlin.idea.util.LongRunningReadTask; import org.jetbrains.kotlin.idea.util.LongRunningReadTask;
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil; 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.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 javax.swing.*;
import java.awt.*; import java.awt.*;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.StringWriter; import java.io.StringWriter;
import java.util.ArrayList; import java.util.*;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Scanner;
public class KotlinBytecodeToolWindow extends JPanel implements Disposable { public class KotlinBytecodeToolWindow extends JPanel implements Disposable {
private static final int UPDATE_DELAY = 1000; private static final int UPDATE_DELAY = 1000;
@@ -108,14 +116,21 @@ public class KotlinBytecodeToolWindow extends JPanel implements Disposable {
GenerationState state; GenerationState state;
try { try {
AnalysisResult result = ResolvePackage.analyzeFullyAndGetResult(jetFile); AnalysisResult result = ResolvePackage.analyzeFullyAndGetResult(jetFile);
boolean disableInline = !enableInline.isSelected();
if (!disableInline) {
result = processInlinedDeclarations(jetFile.getProject(), result, Collections.<JetElement>singleton(jetFile), 1);
}
if (result.isError()) { if (result.isError()) {
return printStackTraceToString(result.getError()); return printStackTraceToString(result.getError());
} }
state = new GenerationState(jetFile.getProject(), ClassBuilderFactories.TEST, Progress.DEAF, state = new GenerationState(jetFile.getProject(), ClassBuilderFactories.TEST, Progress.DEAF,
result.getModuleDescriptor(), result.getBindingContext(), result.getModuleDescriptor(), result.getBindingContext(),
Collections.singletonList(jetFile), !enableAssertions.isSelected(), !enableAssertions.isSelected(), Collections.singletonList(jetFile), !enableAssertions.isSelected(), !enableAssertions.isSelected(),
GenerationState.GenerateClassFilter.GENERATE_ALL, GenerationState.GenerateClassFilter.GENERATE_ALL,
!enableInline.isSelected(), !enableOptimization.isSelected(), null, null, disableInline, !enableOptimization.isSelected(), null, null,
DiagnosticSink.DO_NOTHING, null); DiagnosticSink.DO_NOTHING, null);
KotlinCodegenFacade.compileCorrectFiles(state, CompilationErrorHandler.THROW_EXCEPTION); KotlinCodegenFacade.compileCorrectFiles(state, CompilationErrorHandler.THROW_EXCEPTION);
} }
@@ -139,6 +154,34 @@ public class KotlinBytecodeToolWindow extends JPanel implements Disposable {
return answer.toString(); 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 @Override
protected void onResultReady(@NotNull Location requestInfo, String resultText) { protected void onResultReady(@NotNull Location requestInfo, String resultText) {
Editor editor = requestInfo.getEditor(); Editor editor = requestInfo.getEditor();