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(" (...)"); + } + } + } + } +}