Convert DebuggerUtils to kotlin

This commit is contained in:
Natalia Ukhorskaya
2015-11-25 19:02:54 +03:00
parent 1136c5f54b
commit 028016412e
2 changed files with 112 additions and 148 deletions
@@ -197,12 +197,12 @@ public class KotlinBytecodeToolWindow extends JPanel implements Disposable {
BindingContext bindingContextForFile = resolutionFacade.analyzeFullyAndGetResult(Collections.singletonList(jetFile)).getBindingContext();
kotlin.Pair<BindingContext, List<KtFile>> result = DebuggerUtils.analyzeInlinedFunctions(
kotlin.Pair<BindingContext, List<? extends KtFile>> result = DebuggerUtils.INSTANCE.analyzeInlinedFunctions(
resolutionFacade, bindingContextForFile, jetFile, !enableInline
);
BindingContext bindingContext = result.getFirst();
List<KtFile> toProcess = result.getSecond();
List<? extends KtFile> toProcess = result.getSecond();
GenerationState.GenerateClassFilter generateClassFilter = new GenerationState.GenerateClassFilter() {
@@ -14,215 +14,179 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.util;
package org.jetbrains.kotlin.idea.util
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.psi.PsiElement;
import com.intellij.psi.search.GlobalSearchScope;
import kotlin.Pair;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde;
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade;
import org.jetbrains.kotlin.idea.stubindex.StaticFacadeIndexUtil;
import org.jetbrains.kotlin.name.FqName;
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.jvm.JvmClassName;
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode;
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor;
import com.google.common.collect.Sets
import com.intellij.openapi.project.DumbService
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.io.FileUtilRt
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.idea.stubindex.PackageIndexUtil.findFilesWithExactPackage
import org.jetbrains.kotlin.idea.stubindex.StaticFacadeIndexUtil
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.jvm.JvmClassName
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor
import java.util.*
import java.util.*;
object DebuggerUtils {
import static org.jetbrains.kotlin.idea.stubindex.PackageIndexUtil.findFilesWithExactPackage;
private val KOTLIN_EXTENSIONS = Sets.newHashSet("kt", "kts")
public class DebuggerUtils {
private DebuggerUtils() {
}
fun findSourceFileForClass(
project: Project,
searchScope: GlobalSearchScope,
className: JvmClassName,
fileName: String): KtFile? {
val extension = FileUtilRt.getExtension(fileName)
if (!KOTLIN_EXTENSIONS.contains(extension)) return null
if (DumbService.getInstance(project).isDumb) return null
private static final Set<String> KOTLIN_EXTENSIONS = Sets.newHashSet("kt", "kts");
val filesInPackage = findFilesWithExactPackage(className.packageFqName, searchScope, project)
val filesWithExactName = filesInPackage.filter { it.name == fileName }
@Nullable
public static KtFile findSourceFileForClass(
@NotNull Project project,
@NotNull GlobalSearchScope searchScope,
@NotNull JvmClassName className,
@NotNull final String fileName
) {
String extension = FileUtilRt.getExtension(fileName);
if (!KOTLIN_EXTENSIONS.contains(extension)) return null;
if (DumbService.getInstance(project).isDumb()) return null;
if (filesWithExactName.isEmpty()) return null
Collection<KtFile> filesInPackage = findFilesWithExactPackage(className.getPackageFqName(), searchScope, project);
Collection<KtFile> filesWithExactName = Collections2.filter(filesInPackage, new Predicate<KtFile>() {
@Override
public boolean apply(@Nullable KtFile file) {
return file != null && file.getName().equals(fileName);
}
});
if (filesWithExactName.isEmpty()) return null;
if (filesWithExactName.size() == 1) {
return filesWithExactName.iterator().next();
if (filesWithExactName.size == 1) {
return filesWithExactName.single()
}
// Static facade or inner class of such facade?
FqName partFqName = className.getFqNameForClassNameWithoutDollars();
Collection<KtFile> filesForPart = StaticFacadeIndexUtil.findFilesForFilePart(partFqName, searchScope, project);
val partFqName = className.fqNameForClassNameWithoutDollars
val filesForPart = StaticFacadeIndexUtil.findFilesForFilePart(partFqName, searchScope, project)
if (!filesForPart.isEmpty()) {
for (KtFile file : filesForPart) {
if (file.getName().equals(fileName)) {
return file;
for (file in filesForPart) {
if (file.name == fileName) {
return file
}
}
// Do not fall back to decompiled files (which have different name).
return null;
return null
}
return filesWithExactName.iterator().next();
return filesWithExactName.first()
}
@NotNull
public static Pair<BindingContext, List<KtFile>> analyzeInlinedFunctions(
@NotNull ResolutionFacade resolutionFacadeForFile,
@NotNull BindingContext bindingContextForFile,
@NotNull KtFile file,
boolean analyzeOnlyReifiedInlineFunctions
) {
Set<KtElement> analyzedElements = new HashSet<KtElement>();
BindingContext context = analyzeElementWithInline(
fun analyzeInlinedFunctions(
resolutionFacadeForFile: ResolutionFacade,
bindingContextForFile: BindingContext,
file: KtFile,
analyzeOnlyReifiedInlineFunctions: Boolean
): Pair<BindingContext, List<KtFile>> {
val analyzedElements = HashSet<KtElement>()
val context = analyzeElementWithInline(
resolutionFacadeForFile,
bindingContextForFile,
file,
1,
analyzedElements,
!analyzeOnlyReifiedInlineFunctions);
!analyzeOnlyReifiedInlineFunctions)
//We processing another files just to annotate anonymous classes within their inline functions
//Bytecode not produced for them cause of filtering via generateClassFilter
Set<KtFile> toProcess = new LinkedHashSet<KtFile>();
toProcess.add(file);
val toProcess = LinkedHashSet<KtFile>()
toProcess.add(file)
for (KtElement collectedElement : analyzedElements) {
KtFile containingFile = collectedElement.getContainingKtFile();
toProcess.add(containingFile);
for (collectedElement in analyzedElements) {
val containingFile = collectedElement.getContainingKtFile()
toProcess.add(containingFile)
}
return new Pair<BindingContext, List<KtFile>>(context, new ArrayList<KtFile>(toProcess));
return Pair<BindingContext, List<KtFile>>(context, ArrayList(toProcess))
}
@NotNull
public static Collection<KtElement> analyzeElementWithInline(
@NotNull ResolutionFacade resolutionFacade,
@NotNull BindingContext bindingContext,
@NotNull KtNamedFunction function,
boolean analyzeInlineFunctions
) {
Set<KtElement> analyzedElements = new HashSet<KtElement>();
analyzeElementWithInline(resolutionFacade, bindingContext, function, 1, analyzedElements, !analyzeInlineFunctions);
return analyzedElements;
fun analyzeElementWithInline(
resolutionFacade: ResolutionFacade,
bindingContext: BindingContext,
function: KtNamedFunction,
analyzeInlineFunctions: Boolean): Collection<KtElement> {
val analyzedElements = HashSet<KtElement>()
analyzeElementWithInline(resolutionFacade, bindingContext, function, 1, analyzedElements, !analyzeInlineFunctions)
return analyzedElements
}
@NotNull
private static BindingContext analyzeElementWithInline(
@NotNull ResolutionFacade resolutionFacade,
@NotNull final BindingContext bindingContext,
@NotNull KtElement element,
int deep,
@NotNull final Set<KtElement> analyzedElements,
final boolean analyzeInlineFunctions
) {
final Project project = element.getProject();
final Set<KtNamedFunction> collectedElements = new HashSet<KtNamedFunction>();
private fun analyzeElementWithInline(
resolutionFacade: ResolutionFacade,
bindingContext: BindingContext,
element: KtElement,
deep: Int,
analyzedElements: MutableSet<KtElement>,
analyzeInlineFunctions: Boolean): BindingContext {
val project = element.project
val collectedElements = HashSet<KtNamedFunction>()
element.accept(new KtTreeVisitorVoid() {
@Override
public void visitExpression(@NotNull KtExpression expression) {
super.visitExpression(expression);
element.accept(object : KtTreeVisitorVoid() {
override fun visitExpression(expression: KtExpression) {
super.visitExpression(expression)
Call call = bindingContext.get(BindingContext.CALL, expression);
if (call == null) return;
val call = bindingContext.get(BindingContext.CALL, expression) ?: return
ResolvedCall<?> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, call);
checkResolveCall(resolvedCall);
val resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, call)
checkResolveCall(resolvedCall)
}
@Override
public void visitMultiDeclaration(@NotNull KtMultiDeclaration multiDeclaration) {
super.visitMultiDeclaration(multiDeclaration);
override fun visitMultiDeclaration(multiDeclaration: KtMultiDeclaration) {
super.visitMultiDeclaration(multiDeclaration)
for (KtMultiDeclarationEntry entry : multiDeclaration.getEntries()) {
ResolvedCall<FunctionDescriptor> resolvedCall =
bindingContext.get(BindingContext.COMPONENT_RESOLVED_CALL, entry);
checkResolveCall(resolvedCall);
for (entry in multiDeclaration.entries) {
val resolvedCall = bindingContext.get(BindingContext.COMPONENT_RESOLVED_CALL, entry)
checkResolveCall(resolvedCall)
}
}
@Override
public void visitForExpression(@NotNull KtForExpression expression) {
super.visitForExpression(expression);
override fun visitForExpression(expression: KtForExpression) {
super.visitForExpression(expression)
checkResolveCall(bindingContext.get(BindingContext.LOOP_RANGE_ITERATOR_RESOLVED_CALL, expression.getLoopRange()));
checkResolveCall(bindingContext.get(BindingContext.LOOP_RANGE_HAS_NEXT_RESOLVED_CALL, expression.getLoopRange()));
checkResolveCall(bindingContext.get(BindingContext.LOOP_RANGE_NEXT_RESOLVED_CALL, expression.getLoopRange()));
checkResolveCall(bindingContext.get(BindingContext.LOOP_RANGE_ITERATOR_RESOLVED_CALL, expression.loopRange))
checkResolveCall(bindingContext.get(BindingContext.LOOP_RANGE_HAS_NEXT_RESOLVED_CALL, expression.loopRange))
checkResolveCall(bindingContext.get(BindingContext.LOOP_RANGE_NEXT_RESOLVED_CALL, expression.loopRange))
}
private void checkResolveCall(ResolvedCall<?> resolvedCall) {
if (resolvedCall == null) return;
private fun checkResolveCall(resolvedCall: ResolvedCall<*>?) {
if (resolvedCall == null) return
CallableDescriptor descriptor = resolvedCall.getResultingDescriptor();
if (descriptor instanceof DeserializedSimpleFunctionDescriptor) return;
val descriptor = resolvedCall.resultingDescriptor
if (descriptor is DeserializedSimpleFunctionDescriptor) return
if (InlineUtil.isInline(descriptor) && (analyzeInlineFunctions || hasReifiedTypeParameters(descriptor))) {
PsiElement declaration = DescriptorToSourceUtilsIde.INSTANCE$.getAnyDeclaration(project, descriptor);
if (declaration != null && declaration instanceof KtNamedFunction && !analyzedElements.contains(declaration)) {
collectedElements.add((KtNamedFunction) declaration);
val declaration = DescriptorToSourceUtilsIde.getAnyDeclaration(project, descriptor)
if (declaration != null && declaration is KtNamedFunction && !analyzedElements.contains(declaration)) {
collectedElements.add(declaration)
}
}
}
});
})
analyzedElements.add(element);
analyzedElements.add(element)
if (!collectedElements.isEmpty() && deep < 10) {
List<BindingContext> innerContexts = new ArrayList<BindingContext>();
for (KtNamedFunction inlineFunctions : collectedElements) {
KtExpression body = inlineFunctions.getBodyExpression();
val innerContexts = ArrayList<BindingContext>()
for (inlineFunctions in collectedElements) {
val body = inlineFunctions.bodyExpression
if (body != null) {
BindingContext bindingContextForFunction = resolutionFacade.analyze(body, BodyResolveMode.FULL);
val bindingContextForFunction = resolutionFacade.analyze(body, BodyResolveMode.FULL)
innerContexts.add(analyzeElementWithInline(resolutionFacade, bindingContextForFunction, inlineFunctions, deep + 1,
analyzedElements, analyzeInlineFunctions));
analyzedElements, analyzeInlineFunctions))
}
}
innerContexts.add(bindingContext);
innerContexts.add(bindingContext)
analyzedElements.addAll(collectedElements);
return CompositeBindingContext.Companion.create(innerContexts);
analyzedElements.addAll(collectedElements)
return CompositeBindingContext.create(innerContexts)
}
return bindingContext;
return bindingContext
}
private static boolean hasReifiedTypeParameters(CallableDescriptor descriptor) {
return Iterables.any(descriptor.getTypeParameters(), new Predicate<TypeParameterDescriptor>() {
@Override
public boolean apply(TypeParameterDescriptor input) {
return input.isReified();
}
});
private fun hasReifiedTypeParameters(descriptor: CallableDescriptor): Boolean {
return descriptor.typeParameters.any() { it.isReified }
}
}