diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index f8b8aeaaf52..acbebe0abdd 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -58,6 +58,7 @@
+
diff --git a/idea/src/org/jetbrains/jet/plugin/JetIconProvider.java b/idea/src/org/jetbrains/jet/plugin/JetIconProvider.java
index 4b306fd6f06..d6a535fa329 100644
--- a/idea/src/org/jetbrains/jet/plugin/JetIconProvider.java
+++ b/idea/src/org/jetbrains/jet/plugin/JetIconProvider.java
@@ -59,6 +59,9 @@ public class JetIconProvider extends IconProvider {
}
return icon;
}
+ if (psiElement instanceof JetObjectDeclaration) {
+ return ICON_FOR_OBJECT;
+ }
if (psiElement instanceof JetParameter) {
if (((JetParameter) psiElement).getValOrVarNode() != null) {
JetParameterList parameterList = PsiTreeUtil.getParentOfType(psiElement, JetParameterList.class);
diff --git a/idea/src/org/jetbrains/jet/plugin/projectView/JetClassOrObjectTreeNode.java b/idea/src/org/jetbrains/jet/plugin/projectView/JetClassOrObjectTreeNode.java
new file mode 100644
index 00000000000..f6f79699925
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/plugin/projectView/JetClassOrObjectTreeNode.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jetbrains.jet.plugin.projectView;
+
+import com.intellij.ide.projectView.PresentationData;
+import com.intellij.ide.projectView.ViewSettings;
+import com.intellij.ide.projectView.impl.nodes.AbstractPsiBasedNode;
+import com.intellij.ide.util.treeView.AbstractTreeNode;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import org.jetbrains.jet.lang.psi.JetClassOrObject;
+import org.jetbrains.jet.lang.psi.JetDeclaration;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * User: Alefas
+ * Date: 15.02.12
+ */
+public class JetClassOrObjectTreeNode extends AbstractPsiBasedNode {
+ protected JetClassOrObjectTreeNode(Project project, JetClassOrObject jetClassOrObject, ViewSettings viewSettings) {
+ super(project, jetClassOrObject, viewSettings);
+ }
+
+ @Override
+ protected PsiElement extractPsiFromValue() {
+ return getValue();
+ }
+
+ @Override
+ protected Collection getChildrenImpl() {
+ if (getSettings().isShowMembers()) {
+ ArrayList result = new ArrayList();
+ List declarations = getValue().getDeclarations();
+ for (JetDeclaration declaration : declarations) {
+ if (declaration instanceof JetClassOrObject) {
+ result.add(new JetClassOrObjectTreeNode(getProject(), (JetClassOrObject) declaration, getSettings()));
+ } else {
+ result.add(new JetDeclarationTreeNode(getProject(), declaration, getSettings()));
+ }
+ }
+ return result;
+ } else return Collections.emptyList();
+ }
+
+ @Override
+ protected void updateImpl(PresentationData data) {
+ JetClassOrObject value = getValue();
+ if (value != null) {
+ data.setPresentableText(value.getName());
+ }
+ }
+
+ @Override
+ public boolean canRepresent(Object element) {
+ if (!isValid()) return false;
+ return super.canRepresent(element) || canRepresent(getValue(), element);
+ }
+
+ private boolean canRepresent(JetClassOrObject value, Object element) {
+ if (value == null || !value.isValid()) return false;
+ PsiFile file = value.getContainingFile();
+ if (file != null && (file == element || file.getVirtualFile() == element)) return true;
+
+ if (value == element) return true;
+ if (!getSettings().isShowMembers()) {
+ if (element instanceof PsiElement && ((PsiElement) element).getContainingFile() != null) {
+ PsiFile elementFile = ((PsiElement) element).getContainingFile();
+ if (elementFile != null && file != null) {
+ return elementFile.equals(file);
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/idea/src/org/jetbrains/jet/plugin/projectView/JetDeclarationTreeNode.java b/idea/src/org/jetbrains/jet/plugin/projectView/JetDeclarationTreeNode.java
new file mode 100644
index 00000000000..f3eca556ea7
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/plugin/projectView/JetDeclarationTreeNode.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jetbrains.jet.plugin.projectView;
+
+import com.intellij.ide.projectView.PresentationData;
+import com.intellij.ide.projectView.ViewSettings;
+import com.intellij.ide.projectView.impl.nodes.AbstractPsiBasedNode;
+import com.intellij.ide.util.treeView.AbstractTreeNode;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
+import org.jetbrains.jet.lang.psi.JetClassInitializer;
+import org.jetbrains.jet.lang.psi.JetDeclaration;
+import org.jetbrains.jet.lang.psi.JetFile;
+import org.jetbrains.jet.lang.resolve.BindingContext;
+import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
+import org.jetbrains.jet.plugin.structureView.JetStructureViewElement;
+
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * User: Alefas
+ * Date: 15.02.12
+ */
+public class JetDeclarationTreeNode extends AbstractPsiBasedNode {
+ protected JetDeclarationTreeNode(Project project, JetDeclaration jetDeclaration, ViewSettings viewSettings) {
+ super(project, jetDeclaration, viewSettings);
+ }
+
+ @Override
+ protected PsiElement extractPsiFromValue() {
+ return getValue();
+ }
+
+ @Override
+ protected Collection getChildrenImpl() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ protected void updateImpl(PresentationData data) {
+ JetDeclaration declaration = getValue();
+ if (declaration != null) {
+ BindingContext context = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(
+ (JetFile) declaration.getContainingFile());
+
+ final DeclarationDescriptor descriptor =
+ context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration);
+ if (descriptor != null) {
+ String text = JetStructureViewElement.getDescriptorTreeText(descriptor);
+ if (declaration instanceof JetClassInitializer) {
+ text = "";
+ }
+ data.setPresentableText(text);
+ } else {
+ String text = declaration.getName();
+ if (declaration instanceof JetClassInitializer) {
+ text = "";
+ }
+ data.setPresentableText(text);
+ }
+ }
+ }
+}
diff --git a/idea/src/org/jetbrains/jet/plugin/projectView/JetFileTreeNode.java b/idea/src/org/jetbrains/jet/plugin/projectView/JetFileTreeNode.java
new file mode 100644
index 00000000000..fd7b4532006
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/plugin/projectView/JetFileTreeNode.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jetbrains.jet.plugin.projectView;
+
+import com.intellij.ide.projectView.ViewSettings;
+import com.intellij.ide.projectView.impl.nodes.PsiFileNode;
+import com.intellij.ide.util.treeView.AbstractTreeNode;
+import com.intellij.openapi.project.Project;
+import org.jetbrains.jet.lang.psi.JetClassOrObject;
+import org.jetbrains.jet.lang.psi.JetDeclaration;
+import org.jetbrains.jet.lang.psi.JetFile;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * User: Alefas
+ * Date: 15.02.12
+ */
+public class JetFileTreeNode extends PsiFileNode {
+ public JetFileTreeNode(Project project, JetFile value, ViewSettings viewSettings) {
+ super(project, value, viewSettings);
+ }
+
+ @Override
+ public Collection getChildrenImpl() {
+ JetFile file = (JetFile) getValue();
+
+ if (file == null) return Collections.emptyList();
+ ArrayList result = new ArrayList();
+
+ List declarations = file.getDeclarations();
+
+ for (JetDeclaration declaration : declarations) {
+ if (declaration instanceof JetClassOrObject) {
+ result.add(new JetClassOrObjectTreeNode(file.getProject(), (JetClassOrObject) declaration, getSettings()));
+ } else if (getSettings().isShowMembers()) {
+ result.add(new JetDeclarationTreeNode(getProject(), declaration, getSettings()));
+ }
+ }
+
+ return result;
+ }
+}
diff --git a/idea/src/org/jetbrains/jet/plugin/projectView/JetProjectViewProvider.java b/idea/src/org/jetbrains/jet/plugin/projectView/JetProjectViewProvider.java
new file mode 100644
index 00000000000..347f66ef6d5
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/plugin/projectView/JetProjectViewProvider.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jetbrains.jet.plugin.projectView;
+
+import com.intellij.ide.projectView.SelectableTreeStructureProvider;
+import com.intellij.ide.projectView.ViewSettings;
+import com.intellij.ide.util.treeView.AbstractTreeNode;
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ProjectFileIndex;
+import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import org.jetbrains.jet.lang.psi.JetClassBody;
+import org.jetbrains.jet.lang.psi.JetClassOrObject;
+import org.jetbrains.jet.lang.psi.JetDeclaration;
+import org.jetbrains.jet.lang.psi.JetFile;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * User: Alefas
+ * Date: 15.02.12
+ */
+public class JetProjectViewProvider implements SelectableTreeStructureProvider, DumbAware {
+ private Project myProject;
+
+ public JetProjectViewProvider(Project project) {
+ myProject = project;
+ }
+
+ @Override
+ public Collection modify(AbstractTreeNode parent, Collection children, ViewSettings settings) {
+ List result = new ArrayList();
+
+ for (AbstractTreeNode child : children) {
+ Object childValue = child.getValue();
+
+ if (childValue instanceof JetFile) {
+ JetFile file = (JetFile) childValue;
+ List declarations = file.getDeclarations();
+
+ ArrayList classDeclarations = new ArrayList();
+ for (JetDeclaration declaration : declarations) {
+ if (declaration instanceof JetClassOrObject) {
+ classDeclarations.add((JetClassOrObject) declaration);
+ }
+ }
+ VirtualFile virtualFile = file.getVirtualFile();
+ String nameWithoutExtension = virtualFile != null ? virtualFile.getNameWithoutExtension() : file.getName();
+ if (classDeclarations.size() == 1 && (!settings.isShowMembers() || declarations.size() == 1) &&
+ nameWithoutExtension.equals(classDeclarations.get(0).getName())) {
+ result.add(new JetClassOrObjectTreeNode(file.getProject(), classDeclarations.get(0), settings));
+ } else {
+ result.add(new JetFileTreeNode(file.getProject(), file, settings));
+ }
+ } else {
+ result.add(child);
+ }
+
+ }
+
+ return result;
+ }
+
+ @Override
+ public Object getData(Collection selected, String dataName) {
+ return null;
+ }
+
+ @Override
+ public PsiElement getTopLevelElement(PsiElement element) {
+ PsiFile file = element.getContainingFile();
+ if (file == null || !(file instanceof JetFile)) return null;
+
+ VirtualFile virtualFile = file.getVirtualFile();
+ if (!fileInRoots(virtualFile)) return file;
+
+ PsiElement current = element;
+ while (current != null) {
+ if (isSelectable(current)) break;
+ current = current.getParent();
+ }
+
+ if (current instanceof JetFile) {
+ List declarations = ((JetFile) current).getDeclarations();
+ String nameWithoutExtension = virtualFile != null ? virtualFile.getNameWithoutExtension() : file.getName();
+ if (declarations.size() == 1 && declarations.get(0) instanceof JetClassOrObject &&
+ nameWithoutExtension.equals(declarations.get(0).getName())) {
+ current = declarations.get(0);
+ }
+ }
+
+ return current != null ? current : file;
+ }
+
+ private boolean isSelectable(PsiElement element) {
+ if (element instanceof JetFile) return true;
+ if (element instanceof JetDeclaration) {
+ PsiElement parent = element.getParent();
+ if (parent instanceof JetFile) {
+ return true;
+ } else if (parent instanceof JetClassBody) {
+ parent = parent.getParent();
+ if (parent instanceof JetClassOrObject) {
+ return isSelectable(parent);
+ } else return false;
+ } else return false;
+ } else return false;
+ }
+
+ private boolean fileInRoots(VirtualFile file) {
+ final ProjectFileIndex index = ProjectRootManager.getInstance(myProject).getFileIndex();
+ return file != null && (index.isInSourceContent(file) || index.isInLibraryClasses(file) || index.isInLibrarySource(file));
+ }
+}