Convert DebuggerUtils to kotlin
This commit is contained in:
@@ -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();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user