A couple utility methods
PsiCodegenPredictor.getFileForCodegenNamedClass() returns JetFile which contains a declaration which will produce a class with a given name. PsiCodegenPredictor.getFileForNamespacePartName() returns JetFile which produces a namespace part with the given name. BindingContextUtils.getContainingFile() returns JetFile which contains a declaration which is matched to a given descriptor. DescriptorUtils.findTopLevelParent() finds a top-level (i.e. its containing declaration is NamespaceDescriptor) parent for a descriptor. Also DescriptorUtils.isTopLevelFunction() is changed a little to accept not only a function, but any descriptor
This commit is contained in:
@@ -16,19 +16,26 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.codegen.binding;
|
package org.jetbrains.jet.codegen.binding;
|
||||||
|
|
||||||
|
import com.intellij.openapi.util.Ref;
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import com.intellij.psi.util.PsiTreeUtil;
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.jet.codegen.NamespaceCodegen;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
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.BindingTrace;
|
||||||
|
import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
||||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
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;
|
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration;
|
||||||
|
|
||||||
@@ -175,4 +182,42 @@ public final class PsiCodegenPredictor {
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static JetFile getFileForNamespacePartName(@NotNull List<JetFile> 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<JetFile> allNamespaceFiles,
|
||||||
|
@NotNull final JvmClassName className
|
||||||
|
) {
|
||||||
|
final Ref<DeclarationDescriptor> resultingDescriptor = Ref.create();
|
||||||
|
|
||||||
|
DelegatingBindingTrace trace = new DelegatingBindingTrace(context) {
|
||||||
|
@Override
|
||||||
|
public <K, V> void record(WritableSlice<K, V> 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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,6 +112,19 @@ public class BindingContextUtils {
|
|||||||
return null;
|
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...
|
// TODO these helper methods are added as a workaround to some compiler bugs in Kotlin...
|
||||||
|
|
||||||
// NOTE this is used by KDoc
|
// NOTE this is used by KDoc
|
||||||
|
|||||||
@@ -129,8 +129,17 @@ public class DescriptorUtils {
|
|||||||
return getFQName(containingDeclaration).child(descriptor.getName());
|
return getFQName(containingDeclaration).child(descriptor.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isTopLevelFunction(@NotNull SimpleFunctionDescriptor functionDescriptor) {
|
public static boolean isTopLevelDeclaration(@NotNull DeclarationDescriptor descriptor) {
|
||||||
return functionDescriptor.getContainingDeclaration() instanceof NamespaceDescriptor;
|
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
|
@Nullable
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ public class JetFunctionInsertHandler implements InsertHandler<LookupElement> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DescriptorUtils.isTopLevelFunction(functionDescriptor)) {
|
if (DescriptorUtils.isTopLevelDeclaration(functionDescriptor)) {
|
||||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|||||||
Reference in New Issue
Block a user