diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/binding/PsiCodegenPredictor.java b/compiler/backend/src/org/jetbrains/jet/codegen/binding/PsiCodegenPredictor.java index a17f8d8d172..f3586b35230 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/binding/PsiCodegenPredictor.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/binding/PsiCodegenPredictor.java @@ -16,19 +16,26 @@ package org.jetbrains.jet.codegen.binding; +import com.intellij.openapi.util.Ref; import com.intellij.psi.PsiElement; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.codegen.NamespaceCodegen; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace; import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.lang.resolve.java.JvmClassName; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.Name; +import org.jetbrains.jet.util.slicedmap.WritableSlice; + +import java.util.List; import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration; @@ -175,4 +182,42 @@ public final class PsiCodegenPredictor { return null; } + + @Nullable + public static JetFile getFileForNamespacePartName(@NotNull List allNamespaceFiles, @NotNull JvmClassName className) { + for (JetFile file : allNamespaceFiles) { + String internalName = NamespaceCodegen.getNamespacePartInternalName(file); + JvmClassName jvmClassName = JvmClassName.byInternalName(internalName); + if (jvmClassName.equals(className)) { + return file; + } + } + return null; + } + + @Nullable + public static JetFile getFileForCodegenNamedClass( + @NotNull BindingContext context, + @NotNull List allNamespaceFiles, + @NotNull final JvmClassName className + ) { + final Ref resultingDescriptor = Ref.create(); + + DelegatingBindingTrace trace = new DelegatingBindingTrace(context) { + @Override + public void record(WritableSlice slice, K key, V value) { + super.record(slice, key, value); + if (slice == CodegenBinding.FQN && key instanceof DeclarationDescriptor) { + if (className.equals(value)) { + resultingDescriptor.set((DeclarationDescriptor) key); + } + } + } + }; + + CodegenBinding.initTrace(trace, allNamespaceFiles); + + return resultingDescriptor.isNull() ? null + : BindingContextUtils.getContainingFile(trace.getBindingContext(), resultingDescriptor.get()); + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.java index 34d09977ebb..b3386e14b0c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.java @@ -112,6 +112,19 @@ public class BindingContextUtils { return null; } + @Nullable + public static JetFile getContainingFile(@NotNull BindingContext context, @NotNull DeclarationDescriptor declarationDescriptor) { + // declarationDescriptor may describe a synthesized element which doesn't have PSI + // To workaround that, we find a top-level parent (which is inside a NamespaceDescriptor), which is guaranteed to have PSI + DeclarationDescriptor descriptor = DescriptorUtils.findTopLevelParent(declarationDescriptor); + if (descriptor == null) return null; + + PsiElement declaration = descriptorToDeclaration(context, descriptor); + if (declaration == null) return null; + + return (JetFile) declaration.getContainingFile(); + } + // TODO these helper methods are added as a workaround to some compiler bugs in Kotlin... // NOTE this is used by KDoc diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java index b937d218892..5da0a811f2a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java @@ -129,8 +129,17 @@ public class DescriptorUtils { return getFQName(containingDeclaration).child(descriptor.getName()); } - public static boolean isTopLevelFunction(@NotNull SimpleFunctionDescriptor functionDescriptor) { - return functionDescriptor.getContainingDeclaration() instanceof NamespaceDescriptor; + public static boolean isTopLevelDeclaration(@NotNull DeclarationDescriptor descriptor) { + return descriptor.getContainingDeclaration() instanceof NamespaceDescriptor; + } + + @Nullable + public static DeclarationDescriptor findTopLevelParent(@NotNull DeclarationDescriptor declarationDescriptor) { + DeclarationDescriptor descriptor = declarationDescriptor; + while (!(descriptor == null || isTopLevelDeclaration(descriptor))) { + descriptor = descriptor.getContainingDeclaration(); + } + return descriptor; } @Nullable diff --git a/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.java b/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.java index 1409c43edb7..aff9930e5bc 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.java @@ -187,7 +187,7 @@ public class JetFunctionInsertHandler implements InsertHandler { return; } - if (DescriptorUtils.isTopLevelFunction(functionDescriptor)) { + if (DescriptorUtils.isTopLevelDeclaration(functionDescriptor)) { ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() {