diff --git a/idea/META-INF/plugin.xml b/idea/META-INF/plugin.xml
index 4e8789e38b9..d06ca31e619 100644
--- a/idea/META-INF/plugin.xml
+++ b/idea/META-INF/plugin.xml
@@ -24,5 +24,6 @@
+
diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetReferenceExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetReferenceExpression.java
index 8268cf6fa79..923c6185e23 100644
--- a/idea/src/org/jetbrains/jet/lang/psi/JetReferenceExpression.java
+++ b/idea/src/org/jetbrains/jet/lang/psi/JetReferenceExpression.java
@@ -5,6 +5,7 @@ import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.psi.tree.TokenSet;
+import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -61,12 +62,12 @@ public class JetReferenceExpression extends JetExpression {
@Override
public PsiElement resolve() {
PsiElement element = getElement();
- while (element != null && false == element instanceof JetFile) {
- element = element.getParent();
- }
- JetFile file = (JetFile) element;
+ JetFile file = PsiTreeUtil.getParentOfType(element, JetFile.class);
BindingContext bindingContext = AnalyzingUtils.analyzeFile(file, ErrorHandler.DO_NOTHING);
- return bindingContext.resolveToDeclarationPsiElement(JetReferenceExpression.this);
+ PsiElement psiElement = bindingContext.resolveToDeclarationPsiElement(JetReferenceExpression.this);
+ return psiElement == null
+ ? file
+ : psiElement;
}
@NotNull
@@ -87,7 +88,7 @@ public class JetReferenceExpression extends JetExpression {
@Override
public boolean isReferenceTo(PsiElement element) {
- return false;
+ return resolve() == element;
}
@NotNull
diff --git a/idea/src/org/jetbrains/jet/lang/resolve/LazySubstitutingClassDescriptor.java b/idea/src/org/jetbrains/jet/lang/resolve/LazySubstitutingClassDescriptor.java
index e16eb02fe4a..6bdb5e63c09 100644
--- a/idea/src/org/jetbrains/jet/lang/resolve/LazySubstitutingClassDescriptor.java
+++ b/idea/src/org/jetbrains/jet/lang/resolve/LazySubstitutingClassDescriptor.java
@@ -51,4 +51,14 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor {
public DeclarationDescriptor getOriginal() {
return original.getOriginal();
}
+
+ @Override
+ public R accept(DeclarationDescriptorVisitor visitor, D data) {
+ return visitor.visitClassDescriptor(this, data);
+ }
+
+ @Override
+ public void acceptVoid(DeclarationDescriptorVisitor visitor) {
+ throw new UnsupportedOperationException(); // TODO
+ }
}
diff --git a/idea/src/org/jetbrains/jet/lang/resolve/MutableClassDescriptor.java b/idea/src/org/jetbrains/jet/lang/resolve/MutableClassDescriptor.java
index 3e8eb569c7a..bd21327f760 100644
--- a/idea/src/org/jetbrains/jet/lang/resolve/MutableClassDescriptor.java
+++ b/idea/src/org/jetbrains/jet/lang/resolve/MutableClassDescriptor.java
@@ -37,4 +37,9 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
public WritableScope getUnsubstitutedMemberScope() {
return unsubstitutedMemberScope;
}
+
+ @Override
+ public R accept(DeclarationDescriptorVisitor visitor, D data) {
+ return visitor.visitClassDescriptor(this, data);
+ }
}
diff --git a/idea/src/org/jetbrains/jet/lang/resolve/MutableDeclarationDescriptor.java b/idea/src/org/jetbrains/jet/lang/resolve/MutableDeclarationDescriptor.java
index 1743c1dc651..1554228f518 100644
--- a/idea/src/org/jetbrains/jet/lang/resolve/MutableDeclarationDescriptor.java
+++ b/idea/src/org/jetbrains/jet/lang/resolve/MutableDeclarationDescriptor.java
@@ -2,13 +2,14 @@ package org.jetbrains.jet.lang.resolve;
import org.jetbrains.jet.lang.types.Attribute;
import org.jetbrains.jet.lang.types.DeclarationDescriptor;
+import org.jetbrains.jet.lang.types.DeclarationDescriptorVisitor;
import java.util.List;
/**
* @author abreslav
*/
-public class MutableDeclarationDescriptor implements DeclarationDescriptor {
+public abstract class MutableDeclarationDescriptor implements DeclarationDescriptor {
private String name;
@Override
@@ -29,4 +30,9 @@ public class MutableDeclarationDescriptor implements DeclarationDescriptor {
public DeclarationDescriptor getOriginal() {
return this;
}
+
+ @Override
+ public void acceptVoid(DeclarationDescriptorVisitor visitor) {
+ accept(visitor, null);
+ }
}
diff --git a/idea/src/org/jetbrains/jet/lang/resolve/MutableFunctionDescriptor.java b/idea/src/org/jetbrains/jet/lang/resolve/MutableFunctionDescriptor.java
deleted file mode 100644
index eaeb16161fd..00000000000
--- a/idea/src/org/jetbrains/jet/lang/resolve/MutableFunctionDescriptor.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package org.jetbrains.jet.lang.resolve;
-
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.jet.lang.types.FunctionDescriptor;
-import org.jetbrains.jet.lang.types.Type;
-import org.jetbrains.jet.lang.types.TypeParameterDescriptor;
-import org.jetbrains.jet.lang.types.ValueParameterDescriptor;
-
-import java.util.List;
-
-/**
- * @author abreslav
- */
-public class MutableFunctionDescriptor extends MutableDeclarationDescriptor implements FunctionDescriptor {
- @NotNull
- @Override
- public List getTypeParameters() {
- throw new UnsupportedOperationException(); // TODO
- }
-
- @NotNull
- @Override
- public List getUnsubstitutedValueParameters() {
- throw new UnsupportedOperationException(); // TODO
- }
-
- @NotNull
- @Override
- public Type getUnsubstitutedReturnType() {
- throw new UnsupportedOperationException(); // TODO
- }
-
- @Override
- public FunctionDescriptor getOriginal() {
- throw new UnsupportedOperationException(); // TODO
- }
-}
diff --git a/idea/src/org/jetbrains/jet/lang/types/ClassDescriptorImpl.java b/idea/src/org/jetbrains/jet/lang/types/ClassDescriptorImpl.java
index 5d32d6020ca..5d2e80e53c4 100644
--- a/idea/src/org/jetbrains/jet/lang/types/ClassDescriptorImpl.java
+++ b/idea/src/org/jetbrains/jet/lang/types/ClassDescriptorImpl.java
@@ -45,4 +45,9 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl
Map substitutionContext = TypeSubstitutor.INSTANCE.buildSubstitutionContext(typeConstructor.getParameters(), typeArguments);
return new SubstitutingScope(memberDeclarations, substitutionContext);
}
+
+ @Override
+ public R accept(DeclarationDescriptorVisitor visitor, D data) {
+ return visitor.visitClassDescriptor(this, data);
+ }
}
\ No newline at end of file
diff --git a/idea/src/org/jetbrains/jet/lang/types/DeclarationDescriptor.java b/idea/src/org/jetbrains/jet/lang/types/DeclarationDescriptor.java
index 0b17173f856..ae3d1957214 100644
--- a/idea/src/org/jetbrains/jet/lang/types/DeclarationDescriptor.java
+++ b/idea/src/org/jetbrains/jet/lang/types/DeclarationDescriptor.java
@@ -11,4 +11,7 @@ public interface DeclarationDescriptor extends Annotated, Named {
* returns this object if the current descriptor is original itself
*/
DeclarationDescriptor getOriginal();
+
+ R accept(DeclarationDescriptorVisitor visitor, D data);
+ void acceptVoid(DeclarationDescriptorVisitor visitor);
}
diff --git a/idea/src/org/jetbrains/jet/lang/types/DeclarationDescriptorImpl.java b/idea/src/org/jetbrains/jet/lang/types/DeclarationDescriptorImpl.java
index e8143ec8f2d..97c207623e9 100644
--- a/idea/src/org/jetbrains/jet/lang/types/DeclarationDescriptorImpl.java
+++ b/idea/src/org/jetbrains/jet/lang/types/DeclarationDescriptorImpl.java
@@ -23,4 +23,9 @@ public abstract class DeclarationDescriptorImpl extends AnnotatedImpl implements
public DeclarationDescriptor getOriginal() {
return this;
}
+
+ @Override
+ public void acceptVoid(DeclarationDescriptorVisitor visitor) {
+ accept(visitor, null);
+ }
}
diff --git a/idea/src/org/jetbrains/jet/lang/types/DeclarationDescriptorVisitor.java b/idea/src/org/jetbrains/jet/lang/types/DeclarationDescriptorVisitor.java
new file mode 100644
index 00000000000..374a2a01536
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/lang/types/DeclarationDescriptorVisitor.java
@@ -0,0 +1,28 @@
+package org.jetbrains.jet.lang.types;
+
+import org.jetbrains.jet.lang.resolve.LazySubstitutingClassDescriptor;
+
+/**
+ * @author abreslav
+ */
+public class DeclarationDescriptorVisitor {
+ public R visitPropertyDescriptor(PropertyDescriptor descriptor, D data) {
+ return null;
+ }
+
+ public R visitFunctionDescriptor(FunctionDescriptor descriptor, D data) {
+ return null;
+ }
+
+ public R visitTypeParameterDescriptor(TypeParameterDescriptor descriptor, D data) {
+ return null;
+ }
+
+ public R visitNamespaceDescriptor(NamespaceDescriptor namespaceDescriptor, D data) {
+ return null;
+ }
+
+ public R visitClassDescriptor(ClassDescriptor descriptor, D data) {
+ return null;
+ }
+}
diff --git a/idea/src/org/jetbrains/jet/lang/types/FunctionDescriptorImpl.java b/idea/src/org/jetbrains/jet/lang/types/FunctionDescriptorImpl.java
index 0e70599936c..a8d8adbd16f 100644
--- a/idea/src/org/jetbrains/jet/lang/types/FunctionDescriptorImpl.java
+++ b/idea/src/org/jetbrains/jet/lang/types/FunctionDescriptorImpl.java
@@ -55,4 +55,8 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
return original;
}
+ @Override
+ public R accept(DeclarationDescriptorVisitor visitor, D data) {
+ return visitor.visitFunctionDescriptor(this, data);
+ }
}
diff --git a/idea/src/org/jetbrains/jet/lang/types/LazySubstitutedPropertyDescriptorImpl.java b/idea/src/org/jetbrains/jet/lang/types/LazySubstitutedPropertyDescriptorImpl.java
index 2bbc5ff30c2..845b9f6d8e5 100644
--- a/idea/src/org/jetbrains/jet/lang/types/LazySubstitutedPropertyDescriptorImpl.java
+++ b/idea/src/org/jetbrains/jet/lang/types/LazySubstitutedPropertyDescriptorImpl.java
@@ -41,4 +41,14 @@ public class LazySubstitutedPropertyDescriptorImpl implements PropertyDescriptor
public DeclarationDescriptor getOriginal() {
return propertyDescriptor.getOriginal();
}
+
+ @Override
+ public R accept(DeclarationDescriptorVisitor visitor, D data) {
+ return visitor.visitPropertyDescriptor(this, data);
+ }
+
+ @Override
+ public void acceptVoid(DeclarationDescriptorVisitor visitor) {
+ accept(visitor, null);
+ }
}
diff --git a/idea/src/org/jetbrains/jet/lang/types/LazySubstitutingFunctionDescriptor.java b/idea/src/org/jetbrains/jet/lang/types/LazySubstitutingFunctionDescriptor.java
index e7fa600b63f..1c48ccebdff 100644
--- a/idea/src/org/jetbrains/jet/lang/types/LazySubstitutingFunctionDescriptor.java
+++ b/idea/src/org/jetbrains/jet/lang/types/LazySubstitutingFunctionDescriptor.java
@@ -74,6 +74,14 @@ public class LazySubstitutingFunctionDescriptor implements FunctionDescriptor {
return functionDescriptor.getName();
}
+ @Override
+ public R accept(DeclarationDescriptorVisitor visitor, D data) {
+ return visitor.visitFunctionDescriptor(this, data);
+ }
+ @Override
+ public void acceptVoid(DeclarationDescriptorVisitor visitor) {
+ accept(visitor, null);
+ }
}
diff --git a/idea/src/org/jetbrains/jet/lang/types/NamespaceDescriptor.java b/idea/src/org/jetbrains/jet/lang/types/NamespaceDescriptor.java
index 254acee2c1c..32503a91da8 100644
--- a/idea/src/org/jetbrains/jet/lang/types/NamespaceDescriptor.java
+++ b/idea/src/org/jetbrains/jet/lang/types/NamespaceDescriptor.java
@@ -26,4 +26,9 @@ public class NamespaceDescriptor extends DeclarationDescriptorImpl {
}
return namespaceType;
}
+
+ @Override
+ public R accept(DeclarationDescriptorVisitor visitor, D data) {
+ return visitor.visitNamespaceDescriptor(this, data);
+ }
}
diff --git a/idea/src/org/jetbrains/jet/lang/types/PropertyDescriptorImpl.java b/idea/src/org/jetbrains/jet/lang/types/PropertyDescriptorImpl.java
index 4005a6e9ce5..81430a61157 100644
--- a/idea/src/org/jetbrains/jet/lang/types/PropertyDescriptorImpl.java
+++ b/idea/src/org/jetbrains/jet/lang/types/PropertyDescriptorImpl.java
@@ -17,4 +17,9 @@ public class PropertyDescriptorImpl extends DeclarationDescriptorImpl implements
public Type getType() {
return type;
}
+
+ @Override
+ public R accept(DeclarationDescriptorVisitor visitor, D data) {
+ return visitor.visitPropertyDescriptor(this, data);
+ }
}
diff --git a/idea/src/org/jetbrains/jet/lang/types/TypeParameterDescriptor.java b/idea/src/org/jetbrains/jet/lang/types/TypeParameterDescriptor.java
index 68d54e76b7a..07bb6efba43 100644
--- a/idea/src/org/jetbrains/jet/lang/types/TypeParameterDescriptor.java
+++ b/idea/src/org/jetbrains/jet/lang/types/TypeParameterDescriptor.java
@@ -45,4 +45,9 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl {
public String toString() {
return typeConstructor.toString();
}
+
+ @Override
+ public R accept(DeclarationDescriptorVisitor visitor, D data) {
+ return visitor.visitTypeParameterDescriptor(this, data);
+ }
}
diff --git a/idea/src/org/jetbrains/jet/plugin/JetQuickDocumentationProvider.java b/idea/src/org/jetbrains/jet/plugin/JetQuickDocumentationProvider.java
new file mode 100644
index 00000000000..66ee888cded
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/plugin/JetQuickDocumentationProvider.java
@@ -0,0 +1,34 @@
+package org.jetbrains.jet.plugin;
+
+import com.intellij.lang.documentation.QuickDocumentationProvider;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.util.PsiTreeUtil;
+import org.jetbrains.jet.lang.ErrorHandler;
+import org.jetbrains.jet.lang.psi.JetFile;
+import org.jetbrains.jet.lang.psi.JetReferenceExpression;
+import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
+import org.jetbrains.jet.lang.resolve.BindingContext;
+import org.jetbrains.jet.lang.types.DeclarationDescriptor;
+import org.jetbrains.jet.resolve.DescriptorUtil;
+
+/**
+ * @author abreslav
+ */
+public class JetQuickDocumentationProvider extends QuickDocumentationProvider {
+
+ @Override
+ public String getQuickNavigateInfo(PsiElement element, PsiElement originalElement) {
+ JetReferenceExpression ref = PsiTreeUtil.getParentOfType(originalElement, JetReferenceExpression.class);
+ if (ref != null) {
+ BindingContext bindingContext = AnalyzingUtils.analyzeFile(PsiTreeUtil.getParentOfType(originalElement, JetFile.class), ErrorHandler.DO_NOTHING);
+ DeclarationDescriptor declarationDescriptor = bindingContext.resolveReferenceExpression(ref);
+ if (declarationDescriptor != null) {
+ String text = DescriptorUtil.renderPresentableText(declarationDescriptor);
+ text = text.replaceAll("<", "<");
+ return text;
+ }
+ return "Unresolved";
+ }
+ return "Not a reference";
+ }
+}
diff --git a/idea/src/org/jetbrains/jet/resolve/DescriptorUtil.java b/idea/src/org/jetbrains/jet/resolve/DescriptorUtil.java
new file mode 100644
index 00000000000..8a3fdbfc0de
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/resolve/DescriptorUtil.java
@@ -0,0 +1,91 @@
+package org.jetbrains.jet.resolve;
+
+import org.jetbrains.jet.lang.types.*;
+
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * @author abreslav
+ */
+public class DescriptorUtil {
+ public static String renderPresentableText(DeclarationDescriptor declarationDescriptor) {
+ StringBuilder stringBuilder = new StringBuilder();
+ declarationDescriptor.accept(
+ new DeclarationDescriptorVisitor() {
+ @Override
+ public Void visitPropertyDescriptor(PropertyDescriptor descriptor, StringBuilder builder) {
+ Type type = descriptor.getType();
+ builder.append(descriptor.getName()).append(" : ").append(type);
+ return super.visitPropertyDescriptor(descriptor, builder);
+ }
+
+ @Override
+ public Void visitFunctionDescriptor(FunctionDescriptor descriptor, StringBuilder builder) {
+ builder.append("fun ").append(descriptor.getName());
+ List typeParameters = descriptor.getTypeParameters();
+ renderTypeParameters(typeParameters, builder);
+ builder.append("(");
+ for (Iterator iterator = descriptor.getUnsubstitutedValueParameters().iterator(); iterator.hasNext(); ) {
+ ValueParameterDescriptor parameterDescriptor = iterator.next();
+ visitPropertyDescriptor(parameterDescriptor, builder);
+ if (iterator.hasNext()) {
+ builder.append(", ");
+ }
+ }
+ builder.append(") : ").append(descriptor.getUnsubstitutedReturnType());
+ return super.visitFunctionDescriptor(descriptor, builder);
+ }
+
+ private void renderTypeParameters(List typeParameters, StringBuilder builder) {
+ if (!typeParameters.isEmpty()) {
+ builder.append("<");
+ for (Iterator iterator = typeParameters.iterator(); iterator.hasNext(); ) {
+ TypeParameterDescriptor typeParameterDescriptor = iterator.next();
+ renderTypeParameter(typeParameterDescriptor, builder);
+ if (iterator.hasNext()) {
+ builder.append(", ");
+ }
+ }
+ builder.append(">");
+ }
+ }
+
+ @Override
+ public Void visitTypeParameterDescriptor(TypeParameterDescriptor descriptor, StringBuilder builder) {
+ builder.append("<");
+ renderTypeParameter(descriptor, builder);
+ builder.append(">");
+ return super.visitTypeParameterDescriptor(descriptor, builder);
+ }
+
+ @Override
+ public Void visitNamespaceDescriptor(NamespaceDescriptor namespaceDescriptor, StringBuilder builder) {
+ builder.append("namespace ").append(namespaceDescriptor.getName());
+ return super.visitNamespaceDescriptor(namespaceDescriptor, builder);
+ }
+
+ @Override
+ public Void visitClassDescriptor(ClassDescriptor descriptor, StringBuilder builder) {
+ builder.append("class ").append(descriptor.getName());
+ renderTypeParameters(descriptor.getTypeConstructor().getParameters(), builder);
+ return super.visitClassDescriptor(descriptor, builder);
+ }
+ },
+ stringBuilder);
+ return stringBuilder.toString();
+ }
+
+ private static void renderTypeParameter(TypeParameterDescriptor descriptor, StringBuilder builder) {
+ builder.append(descriptor.getName());
+ if (!descriptor.getUpperBounds().isEmpty()) {
+ Type bound = descriptor.getUpperBounds().iterator().next();
+ if (bound != JetStandardClasses.getAnyType()) {
+ builder.append(" : ").append(bound);
+ if (descriptor.getUpperBounds().size() > 1) {
+ builder.append(" (...)");
+ }
+ }
+ }
+ }
+}