Added navigation to namespace properties.
This commit is contained in:
@@ -33,15 +33,22 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import org.jetbrains.jet.lang.ModuleConfiguration;
|
import org.jetbrains.jet.lang.ModuleConfiguration;
|
||||||
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.ClassOrNamespaceDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
|
import org.jetbrains.jet.lang.resolve.FqName;
|
||||||
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||||
import org.jetbrains.jet.plugin.JetFileType;
|
import org.jetbrains.jet.plugin.JetFileType;
|
||||||
|
import org.jetbrains.jet.resolve.DescriptorRenderer;
|
||||||
|
import org.jetbrains.jet.util.slicedmap.WritableSlice;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Evgeny Gerashchenko
|
* @author Evgeny Gerashchenko
|
||||||
@@ -52,17 +59,33 @@ public class JetSourceNavigationHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static Tuple2<BindingContext, ClassDescriptor> getBindingContextAndClassDescriptor(@NotNull JetClass decompiledClass) {
|
private static<D extends ClassOrNamespaceDescriptor> Tuple2<BindingContext, D>
|
||||||
for (VirtualFile sourceDir : getAllSourceDirs(decompiledClass)) {
|
getBindingContextAndClassOrNamespaceDescriptor(@NotNull WritableSlice<FqName, D> slice,
|
||||||
BindingContext bindingContext = analyzeLibrary(sourceDir, decompiledClass.getProject());
|
@NotNull PsiElement psiElement,
|
||||||
ClassDescriptor cd = bindingContext.get(BindingContext.FQNAME_TO_CLASS_DESCRIPTOR, JetPsiUtil.getFQName(decompiledClass));
|
@Nullable FqName fqName) {
|
||||||
if (cd != null) {
|
if (fqName == null) {
|
||||||
return new Tuple2<BindingContext, ClassDescriptor>(bindingContext, cd);
|
return null;
|
||||||
|
}
|
||||||
|
for (VirtualFile sourceDir : getAllSourceDirs(psiElement)) {
|
||||||
|
BindingContext bindingContext = analyzeLibrary(sourceDir, psiElement.getProject());
|
||||||
|
D descriptor = bindingContext.get(slice, fqName);
|
||||||
|
if (descriptor != null) {
|
||||||
|
return new Tuple2<BindingContext, D>(bindingContext, descriptor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static Tuple2<BindingContext, ClassDescriptor> getBindingContextAndClassDescriptor(@NotNull JetClass decompiledClass) {
|
||||||
|
return getBindingContextAndClassOrNamespaceDescriptor(BindingContext.FQNAME_TO_CLASS_DESCRIPTOR, decompiledClass, JetPsiUtil.getFQName(decompiledClass));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static Tuple2<BindingContext, NamespaceDescriptor> getBindingContextAndNamespaceDescriptor(@NotNull JetFile decompiledNamespaceFile) {
|
||||||
|
return getBindingContextAndClassOrNamespaceDescriptor(BindingContext.FQNAME_TO_NAMESPACE_DESCRIPTOR, decompiledNamespaceFile, JetPsiUtil.getFQName(decompiledNamespaceFile));
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static JetClass getSourceClass(@NotNull JetClass decompiledClass) {
|
public static JetClass getSourceClass(@NotNull JetClass decompiledClass) {
|
||||||
Tuple2<BindingContext, ClassDescriptor> bindingContextAndClassDescriptor = getBindingContextAndClassDescriptor(decompiledClass);
|
Tuple2<BindingContext, ClassDescriptor> bindingContextAndClassDescriptor = getBindingContextAndClassDescriptor(decompiledClass);
|
||||||
@@ -91,12 +114,12 @@ public class JetSourceNavigationHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static List<VirtualFile> getAllSourceDirs(@NotNull JetClass decompiledClass) {
|
private static List<VirtualFile> getAllSourceDirs(@NotNull PsiElement psiElement) {
|
||||||
List<VirtualFile> allSourceDirs = new ArrayList<VirtualFile>();
|
List<VirtualFile> allSourceDirs = new ArrayList<VirtualFile>();
|
||||||
|
|
||||||
VirtualFile decompiledFile = decompiledClass.getContainingFile().getVirtualFile();
|
VirtualFile decompiledFile = psiElement.getContainingFile().getVirtualFile();
|
||||||
if (decompiledFile != null) {
|
if (decompiledFile != null) {
|
||||||
ProjectFileIndex projectFileIndex = ProjectFileIndex.SERVICE.getInstance(decompiledClass.getProject());
|
ProjectFileIndex projectFileIndex = ProjectFileIndex.SERVICE.getInstance(psiElement.getProject());
|
||||||
List<OrderEntry> orderEntries = projectFileIndex.getOrderEntriesForFile(decompiledFile);
|
List<OrderEntry> orderEntries = projectFileIndex.getOrderEntriesForFile(decompiledFile);
|
||||||
for (OrderEntry orderEntry : orderEntries) {
|
for (OrderEntry orderEntry : orderEntries) {
|
||||||
Collections.addAll(allSourceDirs, orderEntry.getFiles(OrderRootType.SOURCES));
|
Collections.addAll(allSourceDirs, orderEntry.getFiles(OrderRootType.SOURCES));
|
||||||
@@ -115,8 +138,30 @@ public class JetSourceNavigationHelper {
|
|||||||
|
|
||||||
PsiElement propertyContainer = decompiledProperty.getParent();
|
PsiElement propertyContainer = decompiledProperty.getParent();
|
||||||
if (propertyContainer instanceof JetFile) {
|
if (propertyContainer instanceof JetFile) {
|
||||||
// TODO global property, may be extension
|
Tuple2<BindingContext, NamespaceDescriptor> bindingContextAndNamespaceDescriptor = getBindingContextAndNamespaceDescriptor((JetFile) propertyContainer);
|
||||||
return null;
|
if (bindingContextAndNamespaceDescriptor == null) return null;
|
||||||
|
BindingContext bindingContext = bindingContextAndNamespaceDescriptor._1;
|
||||||
|
NamespaceDescriptor namespaceDescriptor = bindingContextAndNamespaceDescriptor._2;
|
||||||
|
JetTypeReference receiverType = decompiledProperty.getReceiverTypeRef();
|
||||||
|
if (receiverType == null) {
|
||||||
|
// non-extension property
|
||||||
|
Set<VariableDescriptor> properties = namespaceDescriptor.getMemberScope().getProperties(propertyName);
|
||||||
|
assert properties.size() <= 1;
|
||||||
|
if (properties.size() > 0) {
|
||||||
|
return (JetDeclaration) bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, properties.iterator().next());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// extension property
|
||||||
|
String expectedTypeString = receiverType.getText();
|
||||||
|
for (VariableDescriptor vd : namespaceDescriptor.getMemberScope().getProperties(propertyName)) {
|
||||||
|
if (vd.getReceiverParameter() != ReceiverDescriptor.NO_RECEIVER) {
|
||||||
|
String thisReceiverType = DescriptorRenderer.TEXT.renderType(vd.getReceiverParameter().getType());
|
||||||
|
if (expectedTypeString.equals(thisReceiverType)) {
|
||||||
|
return (JetDeclaration) bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, vd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (propertyContainer instanceof JetClassBody) {
|
else if (propertyContainer instanceof JetClassBody) {
|
||||||
Tuple2<BindingContext, ClassDescriptor> bindingContextAndClassDescriptor = getBindingContextAndClassDescriptor((JetClass) propertyContainer.getParent());
|
Tuple2<BindingContext, ClassDescriptor> bindingContextAndClassDescriptor = getBindingContextAndClassDescriptor((JetClass) propertyContainer.getParent());
|
||||||
|
|||||||
Reference in New Issue
Block a user