diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index b9cb400c8a6cbea54dc524dec857d23a391daeaf..94cb05ea0797ebe7131887b2621e98e9d793d126 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -13,7 +13,7 @@ import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lexer.JetTokens; -import org.jetbrains.jet.resolve.DescriptorUtil; +import org.jetbrains.jet.resolve.DescriptorRenderer; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; @@ -588,7 +588,7 @@ public class ExpressionCodegen extends JetVisitor { methodDescriptor = typeMapper.mapSignature((JetFunction) declarationPsiElement); if (functionParent instanceof NamespaceDescriptorImpl && declarationPsiElement instanceof JetFunction) { pushMethodArguments(expression, methodDescriptor); - final String owner = NamespaceCodegen.getJVMClassName(DescriptorUtil.getFQName(functionParent)); + final String owner = NamespaceCodegen.getJVMClassName(DescriptorRenderer.getFQName(functionParent)); v.invokestatic(owner, methodDescriptor.getName(), methodDescriptor.getDescriptor()); } else if (functionParent instanceof ClassDescriptor && declarationPsiElement instanceof JetFunction) { diff --git a/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java index b51e0c38b2d86b6ac3b19aa324b6edcec3510d68..c82d00dbb52da972f7ccb3c078671f3071fd3c58 100644 --- a/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -8,7 +8,7 @@ import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lexer.JetTokens; -import org.jetbrains.jet.resolve.DescriptorUtil; +import org.jetbrains.jet.resolve.DescriptorRenderer; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import org.objectweb.asm.commons.Method; @@ -87,11 +87,11 @@ public class JetTypeMapper { } static String jvmName(NamespaceDescriptor namespace) { - return NamespaceCodegen.getJVMClassName(DescriptorUtil.getFQName(namespace)); + return NamespaceCodegen.getJVMClassName(DescriptorRenderer.getFQName(namespace)); } public static String jvmNameForInterface(ClassDescriptor descriptor) { - return DescriptorUtil.getFQName(descriptor).replace('.', '/'); + return DescriptorRenderer.getFQName(descriptor).replace('.', '/'); } public static String jvmNameForImplementation(ClassDescriptor descriptor) { diff --git a/idea/src/org/jetbrains/jet/lang/annotations/JetLineMarkerProvider.java b/idea/src/org/jetbrains/jet/lang/annotations/JetLineMarkerProvider.java index 446cbcd4b3b686916e38ca18c51a14222cfc422f..39def9dcbba460f78166cbb9269df4f939d8102f 100644 --- a/idea/src/org/jetbrains/jet/lang/annotations/JetLineMarkerProvider.java +++ b/idea/src/org/jetbrains/jet/lang/annotations/JetLineMarkerProvider.java @@ -16,18 +16,20 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtilBase; import com.intellij.ui.awt.RelativePoint; import com.intellij.util.Function; +import com.intellij.util.Icons; import com.intellij.util.PsiNavigateUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFunction; import org.jetbrains.jet.lang.resolve.AnalyzingUtils; import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.resolve.DescriptorUtil; +import org.jetbrains.jet.resolve.DescriptorRenderer; import javax.swing.*; import java.awt.event.MouseEvent; import java.util.Collection; -import java.util.Iterator; import java.util.List; import java.util.Set; @@ -46,69 +48,78 @@ public class JetLineMarkerProvider implements LineMarkerProvider { JetFile file = PsiTreeUtil.getParentOfType(element, JetFile.class); assert file != null; final BindingContext bindingContext = AnalyzingUtils.analyzeFileWithCache(file); - FunctionDescriptor functionDescriptor = bindingContext.getFunctionDescriptor(jetFunction); + final FunctionDescriptor functionDescriptor = bindingContext.getFunctionDescriptor(jetFunction); if (functionDescriptor == null) return null; final Set overriddenFunctions = functionDescriptor.getOverriddenFunctions(); - if (!overriddenFunctions.isEmpty()) { - return new LineMarkerInfo( - jetFunction, jetFunction.getTextOffset(), OVERRIDING_FUNCTION, Pass.UPDATE_ALL, - new Function() { - @Override - public String fun(JetFunction jetFunction) { - StringBuilder builder = new StringBuilder(); - for (Iterator iterator = overriddenFunctions.iterator(); iterator.hasNext(); ) { - FunctionDescriptor overriddenFunction = iterator.next(); - builder.append(DescriptorUtil.renderPresentableText(overriddenFunction).replace("<", "<")); - if (iterator.hasNext()) { - builder.append("
"); - } - } - return builder.toString(); + Icon icon = isMember(functionDescriptor) ? (overriddenFunctions.isEmpty() ? Icons.METHOD_ICON : OVERRIDING_FUNCTION) : Icons.FUNCTION_ICON; + return new LineMarkerInfo( + jetFunction, jetFunction.getTextOffset(), icon, Pass.UPDATE_ALL, + new Function() { + @Override + public String fun(JetFunction jetFunction) { + StringBuilder builder = new StringBuilder(); + builder.append(DescriptorRenderer.HTML.render(functionDescriptor)); + int overrideCount = overriddenFunctions.size(); + if (overrideCount >= 1) { + builder.append(" overrides ").append(DescriptorRenderer.HTML.render(overriddenFunctions.iterator().next())); } - }, - new GutterIconNavigationHandler() { - @Override - public void navigate(MouseEvent event, JetFunction elt) { - final List list = Lists.newArrayList(); - for (FunctionDescriptor overriddenFunction : overriddenFunctions) { - PsiElement declarationPsiElement = bindingContext.getDeclarationPsiElement(overriddenFunction); - list.add(declarationPsiElement); - } - if (list.isEmpty()) { - String myEmptyText = "empty text"; - final JComponent renderer = HintUtil.createErrorLabel(myEmptyText); - final JBPopup popup = JBPopupFactory.getInstance().createComponentPopupBuilder(renderer, renderer).createPopup(); - if (event != null) { - popup.show(new RelativePoint(event)); - } - return; + if (overrideCount > 1) { + int count = overrideCount - 1; + builder.append(" and ").append(count).append(" other function"); + if (count > 1) { + builder.append("s"); } - if (list.size() == 1) { - PsiNavigateUtil.navigate(list.iterator().next()); + } + + return builder.toString(); + } + }, + new GutterIconNavigationHandler() { + @Override + public void navigate(MouseEvent event, JetFunction elt) { + final List list = Lists.newArrayList(); + for (FunctionDescriptor overriddenFunction : overriddenFunctions) { + PsiElement declarationPsiElement = bindingContext.getDeclarationPsiElement(overriddenFunction); + list.add(declarationPsiElement); + } + if (list.isEmpty()) { + String myEmptyText = "empty text"; + final JComponent renderer = HintUtil.createErrorLabel(myEmptyText); + final JBPopup popup = JBPopupFactory.getInstance().createComponentPopupBuilder(renderer, renderer).createPopup(); + if (event != null) { + popup.show(new RelativePoint(event)); } - else { - final JBPopup popup = NavigationUtil.getPsiElementPopup(PsiUtilBase.toPsiElementArray(list), new DefaultPsiElementCellRenderer() { - @Override - public String getElementText(PsiElement element) { - if (element instanceof JetFunction) { - JetFunction function = (JetFunction) element; - return DescriptorUtil.renderPresentableText(bindingContext.getFunctionDescriptor(function)); - } - return super.getElementText(element); + return; + } + if (list.size() == 1) { + PsiNavigateUtil.navigate(list.iterator().next()); + } + else { + final JBPopup popup = NavigationUtil.getPsiElementPopup(PsiUtilBase.toPsiElementArray(list), new DefaultPsiElementCellRenderer() { + @Override + public String getElementText(PsiElement element) { + if (element instanceof JetFunction) { + JetFunction function = (JetFunction) element; + return DescriptorRenderer.HTML.render(bindingContext.getFunctionDescriptor(function)); } - }, "title"); - if (event != null) { - popup.show(new RelativePoint(event)); - } + return super.getElementText(element); + } + }, DescriptorRenderer.HTML.render(functionDescriptor)); + if (event != null) { + popup.show(new RelativePoint(event)); } } } - ); - } + } + ); } return null; } + private boolean isMember(@NotNull FunctionDescriptor functionDescriptor) { + return functionDescriptor.getContainingDeclaration().getOriginal() instanceof ClassifierDescriptor; + } + @Override public void collectSlowLineMarkers(List elements, Collection result) { } diff --git a/idea/src/org/jetbrains/jet/lang/descriptors/DeclarationDescriptorImpl.java b/idea/src/org/jetbrains/jet/lang/descriptors/DeclarationDescriptorImpl.java index 208c30ee13cd98011ce228a966c2226630ad21fe..fe649f3d5a3d192eb70ff23394968b6391a73931 100644 --- a/idea/src/org/jetbrains/jet/lang/descriptors/DeclarationDescriptorImpl.java +++ b/idea/src/org/jetbrains/jet/lang/descriptors/DeclarationDescriptorImpl.java @@ -2,7 +2,7 @@ package org.jetbrains.jet.lang.descriptors; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.resolve.DescriptorUtil; +import org.jetbrains.jet.resolve.DescriptorRenderer; import java.util.List; @@ -44,6 +44,6 @@ public abstract class DeclarationDescriptorImpl extends AnnotatedImpl implements @Override public String toString() { - return DescriptorUtil.renderPresentableText(this) + "[" + getClass().getCanonicalName() + "@" + System.identityHashCode(this) + "]"; + return DescriptorRenderer.TEXT.render(this) + "[" + getClass().getCanonicalName() + "@" + System.identityHashCode(this) + "]"; } } diff --git a/idea/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java b/idea/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java index 83b7e1a64be3f4621f42194bc18b7dd4b66eb866..a38e8011d0d1549fc28800190ec9418da96d415e 100644 --- a/idea/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java @@ -5,7 +5,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.types.*; -import org.jetbrains.jet.resolve.DescriptorUtil; +import org.jetbrains.jet.resolve.DescriptorRenderer; import java.util.List; import java.util.Map; @@ -176,6 +176,6 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme @Override public String toString() { - return DescriptorUtil.renderPresentableText(this) + "[" + getClass().getCanonicalName() + "@" + System.identityHashCode(this) + "]"; + return DescriptorRenderer.TEXT.render(this) + "[" + getClass().getCanonicalName() + "@" + System.identityHashCode(this) + "]"; } } diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java index 8f3938bdb7c4c93c2b8dd80a383192297f76cd3c..417f2c0c8369ed6be234b7e82582b227507014a2 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java @@ -13,7 +13,7 @@ import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lexer.JetTokens; -import org.jetbrains.jet.resolve.DescriptorUtil; +import org.jetbrains.jet.resolve.DescriptorRenderer; import java.util.*; @@ -245,7 +245,7 @@ public class JetTypeInferrer { case SINGLE_FUNCTION_ARGUMENT_MISMATCH: if (argumentList != null) { // TODO : More helpful message. NOTE: there's a separate handling for this for constructors - trace.getErrorHandler().genericError(argumentList.getNode(), "Arguments do not match " + DescriptorUtil.renderPresentableText(resolutionResult.getFunctionDescriptor())); + trace.getErrorHandler().genericError(argumentList.getNode(), "Arguments do not match " + DescriptorRenderer.TEXT.render(resolutionResult.getFunctionDescriptor())); } else { trace.getErrorHandler().unresolvedReference(referenceExpression); diff --git a/idea/src/org/jetbrains/jet/plugin/JetQuickDocumentationProvider.java b/idea/src/org/jetbrains/jet/plugin/JetQuickDocumentationProvider.java index 29146b30b52fb656b40962a911758c220ac7bd2b..91cf158c3434256cdd0055467e2fd922ded29349 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetQuickDocumentationProvider.java +++ b/idea/src/org/jetbrains/jet/plugin/JetQuickDocumentationProvider.java @@ -9,7 +9,7 @@ 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.resolve.DescriptorUtil; +import org.jetbrains.jet.resolve.DescriptorRenderer; import java.util.Collections; import java.util.List; @@ -49,9 +49,7 @@ public class JetQuickDocumentationProvider implements DocumentationProvider { } private String render(DeclarationDescriptor declarationDescriptor) { - String text = DescriptorUtil.renderPresentableText(declarationDescriptor); - text = text.replaceAll("<", "<"); - return text; + return DescriptorRenderer.HTML.render(declarationDescriptor); } @Override diff --git a/idea/src/org/jetbrains/jet/resolve/DescriptorUtil.java b/idea/src/org/jetbrains/jet/resolve/DescriptorRenderer.java similarity index 72% rename from idea/src/org/jetbrains/jet/resolve/DescriptorUtil.java rename to idea/src/org/jetbrains/jet/resolve/DescriptorRenderer.java index 743a8c409fe0a1ef901c7bc0e5427167292098a6..32640a255d43f20889c0590b203ecc5cf6e56e4c 100644 --- a/idea/src/org/jetbrains/jet/resolve/DescriptorUtil.java +++ b/idea/src/org/jetbrains/jet/resolve/DescriptorRenderer.java @@ -10,39 +10,69 @@ import java.util.List; /** * @author abreslav */ -public class DescriptorUtil { +public class DescriptorRenderer { - private static final DeclarationDescriptorVisitor rootVisitor = new RenderDeclarationDescriptorVisitor(); - private static final DeclarationDescriptorVisitor subVisitor = new RenderDeclarationDescriptorVisitor() { + public static String getFQName(DeclarationDescriptor descriptor) { + DeclarationDescriptor container = descriptor.getContainingDeclaration(); + if (container != null && !(container instanceof ModuleDescriptor)) { + String baseName = getFQName(container); + if (!baseName.isEmpty()) return baseName + "." + descriptor.getName(); + } + + return descriptor.getName(); + } + + public static final DescriptorRenderer TEXT = new DescriptorRenderer(); + public static final DescriptorRenderer HTML = new DescriptorRenderer() { + + @Override + protected String escape(String s) { + return s.replaceAll("<", "<"); + } + + @Override + public String renderKeyword(String keyword) { + return "" + keyword + ""; + } + }; + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + private final DeclarationDescriptorVisitor rootVisitor = new RenderDeclarationDescriptorVisitor(); + + private final DeclarationDescriptorVisitor subVisitor = new RenderDeclarationDescriptorVisitor() { @Override protected void renderName(DeclarationDescriptor descriptor, StringBuilder stringBuilder) { stringBuilder.append(descriptor.getName()); } }; - public static String renderPresentableText(DeclarationDescriptor declarationDescriptor) { - if (declarationDescriptor == null) return ""; - StringBuilder stringBuilder = new StringBuilder(); - declarationDescriptor.accept(rootVisitor, stringBuilder); - return stringBuilder.toString(); + private DescriptorRenderer() {} + + protected String renderKeyword(String keyword) { + return keyword; } - public static String getFQName(DeclarationDescriptor descriptor) { - DeclarationDescriptor container = descriptor.getContainingDeclaration(); - if (container != null && !(container instanceof ModuleDescriptor)) { - String baseName = getFQName(container); - if (!baseName.isEmpty()) return baseName + "." + descriptor.getName(); - } + protected String escape(String s) { + return s; + } - return descriptor.getName(); + private String lt() { + return escape("<"); } - private DescriptorUtil() {} + public String render(DeclarationDescriptor declarationDescriptor) { + if (declarationDescriptor == null) return lt() + "null>"; + StringBuilder stringBuilder = new StringBuilder(); + declarationDescriptor.accept(rootVisitor, stringBuilder); + return stringBuilder.toString(); + } - private static class RenderDeclarationDescriptorVisitor extends DeclarationDescriptorVisitor { + private class RenderDeclarationDescriptorVisitor extends DeclarationDescriptorVisitor { @Override public Void visitValueParameterDescriptor(ValueParameterDescriptor descriptor, StringBuilder builder) { - builder.append("value-parameter "); + builder.append(renderKeyword("value-parameter")).append(" "); return super.visitValueParameterDescriptor(descriptor, builder); } @@ -50,32 +80,32 @@ public class DescriptorUtil { public Void visitVariableDescriptor(VariableDescriptor descriptor, StringBuilder builder) { JetType outType = descriptor.getOutType(); JetType inType = descriptor.getInType(); - String typeString = ""; + String typeString = lt() + "no type>"; if (inType != null && outType != null) { - builder.append("var "); + builder.append(renderKeyword("var")).append(" "); if (inType.equals(outType)) { typeString = outType.toString(); } else { - typeString = ""; + typeString = "<" + renderKeyword("in") + ": " + inType + " " + renderKeyword("out") + ": " + outType + ">"; } } else if (outType != null) { - builder.append("val "); + builder.append(renderKeyword("val")).append(" "); typeString = outType.toString(); } else if (inType != null) { - builder.append(" "); + builder.append(lt()).append("write-only> "); typeString = inType.toString(); } renderName(descriptor, builder); - builder.append(" : ").append(typeString); + builder.append(" : ").append(escape(typeString)); return super.visitVariableDescriptor(descriptor, builder); } @Override public Void visitFunctionDescriptor(FunctionDescriptor descriptor, StringBuilder builder) { - builder.append("fun "); + builder.append(renderKeyword("fun")).append(" "); renderName(descriptor, builder); List typeParameters = descriptor.getTypeParameters(); renderTypeParameters(typeParameters, builder); @@ -87,13 +117,13 @@ public class DescriptorUtil { builder.append(", "); } } - builder.append(") : ").append(descriptor.getUnsubstitutedReturnType()); + builder.append(") : ").append(escape(descriptor.getUnsubstitutedReturnType().toString())); return super.visitFunctionDescriptor(descriptor, builder); } private void renderTypeParameters(List typeParameters, StringBuilder builder) { if (!typeParameters.isEmpty()) { - builder.append("<"); + builder.append(lt()); for (Iterator iterator = typeParameters.iterator(); iterator.hasNext(); ) { TypeParameterDescriptor typeParameterDescriptor = iterator.next(); typeParameterDescriptor.accept(subVisitor, builder); @@ -107,7 +137,7 @@ public class DescriptorUtil { @Override public Void visitTypeParameterDescriptor(TypeParameterDescriptor descriptor, StringBuilder builder) { - builder.append("<"); + builder.append(lt()); renderTypeParameter(descriptor, builder); builder.append(">"); return super.visitTypeParameterDescriptor(descriptor, builder); @@ -115,14 +145,14 @@ public class DescriptorUtil { @Override public Void visitNamespaceDescriptor(NamespaceDescriptor namespaceDescriptor, StringBuilder builder) { - builder.append("namespace "); + builder.append(renderKeyword("namespace")).append(" "); renderName(namespaceDescriptor, builder); return super.visitNamespaceDescriptor(namespaceDescriptor, builder); } @Override public Void visitClassDescriptor(ClassDescriptor descriptor, StringBuilder builder) { - builder.append("class "); + builder.append(renderKeyword("class")).append(" "); renderName(descriptor, builder); renderTypeParameters(descriptor.getTypeConstructor().getParameters(), builder); Collection supertypes = descriptor.getTypeConstructor().getSupertypes(); @@ -145,7 +175,7 @@ public class DescriptorUtil { renderName(containingDeclaration, stringBuilder); stringBuilder.append("::"); } - stringBuilder.append(descriptor.getName()); + stringBuilder.append(escape(descriptor.getName())); } private void renderTypeParameter(TypeParameterDescriptor descriptor, StringBuilder builder) { diff --git a/idea/tests/org/jetbrains/jet/resolve/ExpectedResolveData.java b/idea/tests/org/jetbrains/jet/resolve/ExpectedResolveData.java index bc3854e7ab5f21072231f7ff3e62ee0848214c7a..b84bab18d072b37736d054f0a167a4434cc86c49 100644 --- a/idea/tests/org/jetbrains/jet/resolve/ExpectedResolveData.java +++ b/idea/tests/org/jetbrains/jet/resolve/ExpectedResolveData.java @@ -120,7 +120,7 @@ public class ExpectedResolveData { assertTrue( "Must have been unresolved: " + renderReferenceInContext(referenceExpression) + - " but was resolved to " + DescriptorUtil.renderPresentableText(bindingContext.resolveReferenceExpression(referenceExpression)), + " but was resolved to " + DescriptorRenderer.TEXT.render(bindingContext.resolveReferenceExpression(referenceExpression)), unresolvedReferences.contains(referenceExpression)); continue; }