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