KT-984 Make structure window work with kotlin files

This commit is contained in:
Nikolay Krasko
2012-01-13 11:36:35 +04:00
parent de3ba203a6
commit f457b1cb7a
5 changed files with 124 additions and 28 deletions
@@ -5,7 +5,6 @@ import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver;
@@ -188,5 +187,4 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorImpl i
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) { public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
return visitor.visitFunctionDescriptor(this, data); return visitor.visitFunctionDescriptor(this, data);
} }
} }
@@ -21,6 +21,9 @@ public class JetIconProvider extends IconProvider {
@Override @Override
public Icon getIcon(@NotNull PsiElement psiElement, int flags) { public Icon getIcon(@NotNull PsiElement psiElement, int flags) {
if (psiElement instanceof JetFile) {
return KOTLIN_ICON;
}
if (psiElement instanceof JetNamespaceHeader) { if (psiElement instanceof JetNamespaceHeader) {
return (flags & Iconable.ICON_FLAG_OPEN) != 0 ? PlatformIcons.PACKAGE_OPEN_ICON : PlatformIcons.PACKAGE_ICON; return (flags & Iconable.ICON_FLAG_OPEN) != 0 ? PlatformIcons.PACKAGE_OPEN_ICON : PlatformIcons.PACKAGE_ICON;
} }
@@ -6,8 +6,16 @@ import com.intellij.navigation.ItemPresentation;
import com.intellij.openapi.util.Iconable; import com.intellij.openapi.util.Iconable;
import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.NavigatablePsiElement; import com.intellij.psi.NavigatablePsiElement;
import com.intellij.util.Function;
import com.intellij.util.PsiIconUtil; import com.intellij.util.PsiIconUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
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.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.resolve.DescriptorRenderer;
import javax.swing.*; import javax.swing.*;
import java.util.ArrayList; import java.util.ArrayList;
@@ -19,8 +27,17 @@ import java.util.List;
public class JetStructureViewElement implements StructureViewTreeElement { public class JetStructureViewElement implements StructureViewTreeElement {
private final NavigatablePsiElement myElement; private final NavigatablePsiElement myElement;
public JetStructureViewElement(NavigatablePsiElement element) { // For file context will be updated after each construction
// For other tree sub-elements it's immutable.
private BindingContext context;
public JetStructureViewElement(NavigatablePsiElement element, BindingContext context) {
myElement = element; myElement = element;
this.context = context;
}
public JetStructureViewElement(JetFile fileElement) {
myElement = fileElement;
} }
@Override @Override
@@ -48,13 +65,29 @@ public class JetStructureViewElement implements StructureViewTreeElement {
return new ItemPresentation() { return new ItemPresentation() {
@Override @Override
public String getPresentableText() { public String getPresentableText() {
String name = myElement.getName(); String text = "";
if (StringUtil.isEmpty(name)) {
// Try to find text in correspondent descriptor
// if (myElement instanceof JetDeclaration) {
// JetDeclaration declaration = (JetDeclaration) myElement;
// final DeclarationDescriptor descriptor =
// context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration);
//
// if (descriptor != null) {
// text = getDescriptorTreeText(descriptor);
// }
// }
if (StringUtil.isEmpty(text)) {
text = myElement.getName();
}
if (StringUtil.isEmpty(text)) {
if (myElement instanceof JetClassInitializer) { if (myElement instanceof JetClassInitializer) {
return "<class initializer>"; return "<class initializer>";
} }
} }
return name; return text;
} }
@Override @Override
@@ -64,9 +97,13 @@ public class JetStructureViewElement implements StructureViewTreeElement {
@Override @Override
public Icon getIcon(boolean open) { public Icon getIcon(boolean open) {
return myElement.isValid() if (myElement.isValid()) {
? PsiIconUtil.getProvidersIcon(myElement, open ? Iconable.ICON_FLAG_OPEN : Iconable.ICON_FLAG_CLOSED) return PsiIconUtil.getProvidersIcon(
: null; myElement,
open ? Iconable.ICON_FLAG_OPEN : Iconable.ICON_FLAG_CLOSED);
}
return null;
} }
}; };
} }
@@ -74,10 +111,12 @@ public class JetStructureViewElement implements StructureViewTreeElement {
@Override @Override
public TreeElement[] getChildren() { public TreeElement[] getChildren() {
if (myElement instanceof JetFile) { if (myElement instanceof JetFile) {
return new TreeElement[] { new JetStructureViewElement(myElement) }; final JetFile jetFile = (JetFile) myElement;
}
else if (myElement instanceof JetFile) { // TODO: Understand why it significantly reduce responsibility of IDEA during typing
return wrapDeclarations(((JetFile) myElement).getDeclarations()); // context = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(jetFile);
return wrapDeclarations(jetFile.getDeclarations());
} }
else if (myElement instanceof JetClass) { else if (myElement instanceof JetClass) {
JetClass jetClass = (JetClass) myElement; JetClass jetClass = (JetClass) myElement;
@@ -89,7 +128,6 @@ public class JetStructureViewElement implements StructureViewTreeElement {
} }
declarations.addAll(jetClass.getDeclarations()); declarations.addAll(jetClass.getDeclarations());
return wrapDeclarations(declarations); return wrapDeclarations(declarations);
} }
else if (myElement instanceof JetClassOrObject) { else if (myElement instanceof JetClassOrObject) {
return wrapDeclarations(((JetClassOrObject) myElement).getDeclarations()); return wrapDeclarations(((JetClassOrObject) myElement).getDeclarations());
@@ -97,11 +135,61 @@ public class JetStructureViewElement implements StructureViewTreeElement {
return new TreeElement[0]; return new TreeElement[0];
} }
private static TreeElement[] wrapDeclarations(List<JetDeclaration> declarations) { private TreeElement[] wrapDeclarations(List<JetDeclaration> declarations) {
TreeElement[] result = new TreeElement[declarations.size()]; TreeElement[] result = new TreeElement[declarations.size()];
for (int i = 0; i < declarations.size(); i++) { for (int i = 0; i < declarations.size(); i++) {
result[i] = new JetStructureViewElement(declarations.get(i)); result[i] = new JetStructureViewElement(declarations.get(i), context);
} }
return result; return result;
} }
public static String getDescriptorTreeText(@NotNull DeclarationDescriptor descriptor) {
StringBuilder textBuilder;
if (descriptor instanceof FunctionDescriptor) {
textBuilder = new StringBuilder();
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
ReceiverDescriptor receiver = functionDescriptor.getReceiverParameter();
if (receiver.exists()) {
textBuilder.append(DescriptorRenderer.TEXT.renderType(receiver.getType())).append(".");
}
textBuilder.append(functionDescriptor.getName());
String parametersString = StringUtil.join(
functionDescriptor.getValueParameters(),
new Function<ValueParameterDescriptor, String>() {
@Override
public String fun(ValueParameterDescriptor valueParameterDescriptor) {
return valueParameterDescriptor.getName() + ":" +
DescriptorRenderer.TEXT.renderType(valueParameterDescriptor.getOutType());
}
},
",");
textBuilder.append("(").append(parametersString).append(")");
JetType returnType = functionDescriptor.getReturnType();
textBuilder.append(":").append(DescriptorRenderer.TEXT.renderType(returnType));
}
else if (descriptor instanceof VariableDescriptor) {
JetType outType = ((VariableDescriptor) descriptor).getOutType();
textBuilder = new StringBuilder(descriptor.getName());
textBuilder.append(":").append(DescriptorRenderer.TEXT.renderType(outType));
}
else if (descriptor instanceof ClassDescriptor) {
textBuilder = new StringBuilder(descriptor.getName());
textBuilder
.append(" (")
.append(DescriptorUtils.getFQName(descriptor.getContainingDeclaration()))
.append(")");
}
else {
return DescriptorRenderer.TEXT.render(descriptor);
}
return textBuilder.toString();
}
} }
@@ -6,6 +6,7 @@ import com.intellij.ide.structureView.TreeBasedStructureViewBuilder;
import com.intellij.lang.PsiStructureViewFactory; import com.intellij.lang.PsiStructureViewFactory;
import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetFile;
/** /**
* @author yole * @author yole
@@ -13,12 +14,18 @@ import org.jetbrains.annotations.NotNull;
public class JetStructureViewFactory implements PsiStructureViewFactory { public class JetStructureViewFactory implements PsiStructureViewFactory {
@Override @Override
public StructureViewBuilder getStructureViewBuilder(final PsiFile psiFile) { public StructureViewBuilder getStructureViewBuilder(final PsiFile psiFile) {
return new TreeBasedStructureViewBuilder() { if (psiFile instanceof JetFile) {
@NotNull final JetFile file = (JetFile) psiFile;
@Override
public StructureViewModel createStructureViewModel() { return new TreeBasedStructureViewBuilder() {
return new JetStructureViewModel(psiFile); @NotNull
} @Override
}; public StructureViewModel createStructureViewModel() {
return new JetStructureViewModel(file);
}
};
}
return null;
} }
} }
@@ -1,16 +1,16 @@
package org.jetbrains.jet.plugin.structureView; package org.jetbrains.jet.plugin.structureView;
import com.intellij.ide.structureView.StructureViewModelBase; import com.intellij.ide.structureView.StructureViewModelBase;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetDeclaration; import org.jetbrains.jet.lang.psi.JetDeclaration;
import org.jetbrains.jet.lang.psi.JetFile;
/** /**
* @author yole * @author yole
*/ */
public class JetStructureViewModel extends StructureViewModelBase { public class JetStructureViewModel extends StructureViewModelBase {
public JetStructureViewModel(@NotNull PsiFile psiFile) { public JetStructureViewModel(@NotNull JetFile jetFile) {
super(psiFile, new JetStructureViewElement(psiFile)); super(jetFile, new JetStructureViewElement(jetFile));
withSuitableClasses(JetDeclaration.class); withSuitableClasses(JetDeclaration.class);
} }
} }