Beautified line icons and display function signatures

This commit is contained in:
Andrey Breslav
2011-05-13 21:58:34 +04:00
parent e087b080e9
commit a6b31b6c25
9 changed files with 139 additions and 100 deletions
@@ -13,7 +13,7 @@ import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lexer.JetTokens; 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.Label;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
@@ -588,7 +588,7 @@ public class ExpressionCodegen extends JetVisitor {
methodDescriptor = typeMapper.mapSignature((JetFunction) declarationPsiElement); methodDescriptor = typeMapper.mapSignature((JetFunction) declarationPsiElement);
if (functionParent instanceof NamespaceDescriptorImpl && declarationPsiElement instanceof JetFunction) { if (functionParent instanceof NamespaceDescriptorImpl && declarationPsiElement instanceof JetFunction) {
pushMethodArguments(expression, methodDescriptor); 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()); v.invokestatic(owner, methodDescriptor.getName(), methodDescriptor.getDescriptor());
} }
else if (functionParent instanceof ClassDescriptor && declarationPsiElement instanceof JetFunction) { else if (functionParent instanceof ClassDescriptor && declarationPsiElement instanceof JetFunction) {
@@ -8,7 +8,7 @@ import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lexer.JetTokens; 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.Opcodes;
import org.objectweb.asm.Type; import org.objectweb.asm.Type;
import org.objectweb.asm.commons.Method; import org.objectweb.asm.commons.Method;
@@ -87,11 +87,11 @@ public class JetTypeMapper {
} }
static String jvmName(NamespaceDescriptor namespace) { static String jvmName(NamespaceDescriptor namespace) {
return NamespaceCodegen.getJVMClassName(DescriptorUtil.getFQName(namespace)); return NamespaceCodegen.getJVMClassName(DescriptorRenderer.getFQName(namespace));
} }
public static String jvmNameForInterface(ClassDescriptor descriptor) { public static String jvmNameForInterface(ClassDescriptor descriptor) {
return DescriptorUtil.getFQName(descriptor).replace('.', '/'); return DescriptorRenderer.getFQName(descriptor).replace('.', '/');
} }
public static String jvmNameForImplementation(ClassDescriptor descriptor) { public static String jvmNameForImplementation(ClassDescriptor descriptor) {
@@ -16,18 +16,20 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtilBase; import com.intellij.psi.util.PsiUtilBase;
import com.intellij.ui.awt.RelativePoint; import com.intellij.ui.awt.RelativePoint;
import com.intellij.util.Function; import com.intellij.util.Function;
import com.intellij.util.Icons;
import com.intellij.util.PsiNavigateUtil; 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.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetFunction; import org.jetbrains.jet.lang.psi.JetFunction;
import org.jetbrains.jet.lang.resolve.AnalyzingUtils; import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.resolve.DescriptorUtil; import org.jetbrains.jet.resolve.DescriptorRenderer;
import javax.swing.*; import javax.swing.*;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.util.Collection; import java.util.Collection;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@@ -46,69 +48,78 @@ public class JetLineMarkerProvider implements LineMarkerProvider {
JetFile file = PsiTreeUtil.getParentOfType(element, JetFile.class); JetFile file = PsiTreeUtil.getParentOfType(element, JetFile.class);
assert file != null; assert file != null;
final BindingContext bindingContext = AnalyzingUtils.analyzeFileWithCache(file); final BindingContext bindingContext = AnalyzingUtils.analyzeFileWithCache(file);
FunctionDescriptor functionDescriptor = bindingContext.getFunctionDescriptor(jetFunction); final FunctionDescriptor functionDescriptor = bindingContext.getFunctionDescriptor(jetFunction);
if (functionDescriptor == null) return null; if (functionDescriptor == null) return null;
final Set<? extends FunctionDescriptor> overriddenFunctions = functionDescriptor.getOverriddenFunctions(); final Set<? extends FunctionDescriptor> overriddenFunctions = functionDescriptor.getOverriddenFunctions();
if (!overriddenFunctions.isEmpty()) { Icon icon = isMember(functionDescriptor) ? (overriddenFunctions.isEmpty() ? Icons.METHOD_ICON : OVERRIDING_FUNCTION) : Icons.FUNCTION_ICON;
return new LineMarkerInfo<JetFunction>( return new LineMarkerInfo<JetFunction>(
jetFunction, jetFunction.getTextOffset(), OVERRIDING_FUNCTION, Pass.UPDATE_ALL, jetFunction, jetFunction.getTextOffset(), icon, Pass.UPDATE_ALL,
new Function<JetFunction, String>() { new Function<JetFunction, String>() {
@Override @Override
public String fun(JetFunction jetFunction) { public String fun(JetFunction jetFunction) {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
for (Iterator<? extends FunctionDescriptor> iterator = overriddenFunctions.iterator(); iterator.hasNext(); ) { builder.append(DescriptorRenderer.HTML.render(functionDescriptor));
FunctionDescriptor overriddenFunction = iterator.next(); int overrideCount = overriddenFunctions.size();
builder.append(DescriptorUtil.renderPresentableText(overriddenFunction).replace("<", "&lt;")); if (overrideCount >= 1) {
if (iterator.hasNext()) { builder.append(" overrides ").append(DescriptorRenderer.HTML.render(overriddenFunctions.iterator().next()));
builder.append("<br/>");
}
}
return builder.toString();
} }
}, if (overrideCount > 1) {
new GutterIconNavigationHandler<JetFunction>() { int count = overrideCount - 1;
@Override builder.append(" and ").append(count).append(" other function");
public void navigate(MouseEvent event, JetFunction elt) { if (count > 1) {
final List<PsiElement> list = Lists.newArrayList(); builder.append("s");
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); return builder.toString();
final JBPopup popup = JBPopupFactory.getInstance().createComponentPopupBuilder(renderer, renderer).createPopup(); }
if (event != null) { },
popup.show(new RelativePoint(event)); new GutterIconNavigationHandler<JetFunction>() {
} @Override
return; public void navigate(MouseEvent event, JetFunction elt) {
final List<PsiElement> 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));
} }
if (list.size() == 1) { return;
PsiNavigateUtil.navigate(list.iterator().next()); }
} if (list.size() == 1) {
else { PsiNavigateUtil.navigate(list.iterator().next());
final JBPopup popup = NavigationUtil.getPsiElementPopup(PsiUtilBase.toPsiElementArray(list), new DefaultPsiElementCellRenderer() { }
@Override else {
public String getElementText(PsiElement element) { final JBPopup popup = NavigationUtil.getPsiElementPopup(PsiUtilBase.toPsiElementArray(list), new DefaultPsiElementCellRenderer() {
if (element instanceof JetFunction) { @Override
JetFunction function = (JetFunction) element; public String getElementText(PsiElement element) {
return DescriptorUtil.renderPresentableText(bindingContext.getFunctionDescriptor(function)); if (element instanceof JetFunction) {
} JetFunction function = (JetFunction) element;
return super.getElementText(element); return DescriptorRenderer.HTML.render(bindingContext.getFunctionDescriptor(function));
} }
}, "title"); return super.getElementText(element);
if (event != null) { }
popup.show(new RelativePoint(event)); }, DescriptorRenderer.HTML.render(functionDescriptor));
} if (event != null) {
popup.show(new RelativePoint(event));
} }
} }
} }
); }
} );
} }
return null; return null;
} }
private boolean isMember(@NotNull FunctionDescriptor functionDescriptor) {
return functionDescriptor.getContainingDeclaration().getOriginal() instanceof ClassifierDescriptor;
}
@Override @Override
public void collectSlowLineMarkers(List<PsiElement> elements, Collection<LineMarkerInfo> result) { public void collectSlowLineMarkers(List<PsiElement> elements, Collection<LineMarkerInfo> result) {
} }
@@ -2,7 +2,7 @@ package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.resolve.DescriptorUtil; import org.jetbrains.jet.resolve.DescriptorRenderer;
import java.util.List; import java.util.List;
@@ -44,6 +44,6 @@ public abstract class DeclarationDescriptorImpl extends AnnotatedImpl implements
@Override @Override
public String toString() { public String toString() {
return DescriptorUtil.renderPresentableText(this) + "[" + getClass().getCanonicalName() + "@" + System.identityHashCode(this) + "]"; return DescriptorRenderer.TEXT.render(this) + "[" + getClass().getCanonicalName() + "@" + System.identityHashCode(this) + "]";
} }
} }
@@ -5,7 +5,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.types.*; 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.List;
import java.util.Map; import java.util.Map;
@@ -176,6 +176,6 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
@Override @Override
public String toString() { public String toString() {
return DescriptorUtil.renderPresentableText(this) + "[" + getClass().getCanonicalName() + "@" + System.identityHashCode(this) + "]"; return DescriptorRenderer.TEXT.render(this) + "[" + getClass().getCanonicalName() + "@" + System.identityHashCode(this) + "]";
} }
} }
@@ -13,7 +13,7 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.resolve.DescriptorUtil; import org.jetbrains.jet.resolve.DescriptorRenderer;
import java.util.*; import java.util.*;
@@ -245,7 +245,7 @@ public class JetTypeInferrer {
case SINGLE_FUNCTION_ARGUMENT_MISMATCH: case SINGLE_FUNCTION_ARGUMENT_MISMATCH:
if (argumentList != null) { if (argumentList != null) {
// TODO : More helpful message. NOTE: there's a separate handling for this for constructors // 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 { else {
trace.getErrorHandler().unresolvedReference(referenceExpression); trace.getErrorHandler().unresolvedReference(referenceExpression);
@@ -9,7 +9,7 @@ import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetReferenceExpression; import org.jetbrains.jet.lang.psi.JetReferenceExpression;
import org.jetbrains.jet.lang.resolve.AnalyzingUtils; import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
import org.jetbrains.jet.lang.resolve.BindingContext; 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.Collections;
import java.util.List; import java.util.List;
@@ -49,9 +49,7 @@ public class JetQuickDocumentationProvider implements DocumentationProvider {
} }
private String render(DeclarationDescriptor declarationDescriptor) { private String render(DeclarationDescriptor declarationDescriptor) {
String text = DescriptorUtil.renderPresentableText(declarationDescriptor); return DescriptorRenderer.HTML.render(declarationDescriptor);
text = text.replaceAll("<", "&lt;");
return text;
} }
@Override @Override
@@ -10,22 +10,7 @@ import java.util.List;
/** /**
* @author abreslav * @author abreslav
*/ */
public class DescriptorUtil { public class DescriptorRenderer {
private static final DeclarationDescriptorVisitor<Void, StringBuilder> rootVisitor = new RenderDeclarationDescriptorVisitor();
private static final DeclarationDescriptorVisitor<Void, StringBuilder> 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 "<null>";
StringBuilder stringBuilder = new StringBuilder();
declarationDescriptor.accept(rootVisitor, stringBuilder);
return stringBuilder.toString();
}
public static String getFQName(DeclarationDescriptor descriptor) { public static String getFQName(DeclarationDescriptor descriptor) {
DeclarationDescriptor container = descriptor.getContainingDeclaration(); DeclarationDescriptor container = descriptor.getContainingDeclaration();
@@ -37,12 +22,57 @@ public class DescriptorUtil {
return descriptor.getName(); return descriptor.getName();
} }
private DescriptorUtil() {} public static final DescriptorRenderer TEXT = new DescriptorRenderer();
public static final DescriptorRenderer HTML = new DescriptorRenderer() {
private static class RenderDeclarationDescriptorVisitor extends DeclarationDescriptorVisitor<Void, StringBuilder> { @Override
protected String escape(String s) {
return s.replaceAll("<", "&lt;");
}
@Override
public String renderKeyword(String keyword) {
return "<b>" + keyword + "</b>";
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private final DeclarationDescriptorVisitor<Void, StringBuilder> rootVisitor = new RenderDeclarationDescriptorVisitor();
private final DeclarationDescriptorVisitor<Void, StringBuilder> subVisitor = new RenderDeclarationDescriptorVisitor() {
@Override
protected void renderName(DeclarationDescriptor descriptor, StringBuilder stringBuilder) {
stringBuilder.append(descriptor.getName());
}
};
private DescriptorRenderer() {}
protected String renderKeyword(String keyword) {
return keyword;
}
protected String escape(String s) {
return s;
}
private String lt() {
return escape("<");
}
public String render(DeclarationDescriptor declarationDescriptor) {
if (declarationDescriptor == null) return lt() + "null>";
StringBuilder stringBuilder = new StringBuilder();
declarationDescriptor.accept(rootVisitor, stringBuilder);
return stringBuilder.toString();
}
private class RenderDeclarationDescriptorVisitor extends DeclarationDescriptorVisitor<Void, StringBuilder> {
@Override @Override
public Void visitValueParameterDescriptor(ValueParameterDescriptor descriptor, StringBuilder builder) { public Void visitValueParameterDescriptor(ValueParameterDescriptor descriptor, StringBuilder builder) {
builder.append("value-parameter "); builder.append(renderKeyword("value-parameter")).append(" ");
return super.visitValueParameterDescriptor(descriptor, builder); return super.visitValueParameterDescriptor(descriptor, builder);
} }
@@ -50,32 +80,32 @@ public class DescriptorUtil {
public Void visitVariableDescriptor(VariableDescriptor descriptor, StringBuilder builder) { public Void visitVariableDescriptor(VariableDescriptor descriptor, StringBuilder builder) {
JetType outType = descriptor.getOutType(); JetType outType = descriptor.getOutType();
JetType inType = descriptor.getInType(); JetType inType = descriptor.getInType();
String typeString = "<no type>"; String typeString = lt() + "no type>";
if (inType != null && outType != null) { if (inType != null && outType != null) {
builder.append("var "); builder.append(renderKeyword("var")).append(" ");
if (inType.equals(outType)) { if (inType.equals(outType)) {
typeString = outType.toString(); typeString = outType.toString();
} }
else { else {
typeString = "<in " + inType + " out " + outType + ">"; typeString = "<" + renderKeyword("in") + ": " + inType + " " + renderKeyword("out") + ": " + outType + ">";
} }
} }
else if (outType != null) { else if (outType != null) {
builder.append("val "); builder.append(renderKeyword("val")).append(" ");
typeString = outType.toString(); typeString = outType.toString();
} }
else if (inType != null) { else if (inType != null) {
builder.append("<write-only> "); builder.append(lt()).append("write-only> ");
typeString = inType.toString(); typeString = inType.toString();
} }
renderName(descriptor, builder); renderName(descriptor, builder);
builder.append(" : ").append(typeString); builder.append(" : ").append(escape(typeString));
return super.visitVariableDescriptor(descriptor, builder); return super.visitVariableDescriptor(descriptor, builder);
} }
@Override @Override
public Void visitFunctionDescriptor(FunctionDescriptor descriptor, StringBuilder builder) { public Void visitFunctionDescriptor(FunctionDescriptor descriptor, StringBuilder builder) {
builder.append("fun "); builder.append(renderKeyword("fun")).append(" ");
renderName(descriptor, builder); renderName(descriptor, builder);
List<TypeParameterDescriptor> typeParameters = descriptor.getTypeParameters(); List<TypeParameterDescriptor> typeParameters = descriptor.getTypeParameters();
renderTypeParameters(typeParameters, builder); renderTypeParameters(typeParameters, builder);
@@ -87,13 +117,13 @@ public class DescriptorUtil {
builder.append(", "); builder.append(", ");
} }
} }
builder.append(") : ").append(descriptor.getUnsubstitutedReturnType()); builder.append(") : ").append(escape(descriptor.getUnsubstitutedReturnType().toString()));
return super.visitFunctionDescriptor(descriptor, builder); return super.visitFunctionDescriptor(descriptor, builder);
} }
private void renderTypeParameters(List<TypeParameterDescriptor> typeParameters, StringBuilder builder) { private void renderTypeParameters(List<TypeParameterDescriptor> typeParameters, StringBuilder builder) {
if (!typeParameters.isEmpty()) { if (!typeParameters.isEmpty()) {
builder.append("<"); builder.append(lt());
for (Iterator<TypeParameterDescriptor> iterator = typeParameters.iterator(); iterator.hasNext(); ) { for (Iterator<TypeParameterDescriptor> iterator = typeParameters.iterator(); iterator.hasNext(); ) {
TypeParameterDescriptor typeParameterDescriptor = iterator.next(); TypeParameterDescriptor typeParameterDescriptor = iterator.next();
typeParameterDescriptor.accept(subVisitor, builder); typeParameterDescriptor.accept(subVisitor, builder);
@@ -107,7 +137,7 @@ public class DescriptorUtil {
@Override @Override
public Void visitTypeParameterDescriptor(TypeParameterDescriptor descriptor, StringBuilder builder) { public Void visitTypeParameterDescriptor(TypeParameterDescriptor descriptor, StringBuilder builder) {
builder.append("<"); builder.append(lt());
renderTypeParameter(descriptor, builder); renderTypeParameter(descriptor, builder);
builder.append(">"); builder.append(">");
return super.visitTypeParameterDescriptor(descriptor, builder); return super.visitTypeParameterDescriptor(descriptor, builder);
@@ -115,14 +145,14 @@ public class DescriptorUtil {
@Override @Override
public Void visitNamespaceDescriptor(NamespaceDescriptor namespaceDescriptor, StringBuilder builder) { public Void visitNamespaceDescriptor(NamespaceDescriptor namespaceDescriptor, StringBuilder builder) {
builder.append("namespace "); builder.append(renderKeyword("namespace")).append(" ");
renderName(namespaceDescriptor, builder); renderName(namespaceDescriptor, builder);
return super.visitNamespaceDescriptor(namespaceDescriptor, builder); return super.visitNamespaceDescriptor(namespaceDescriptor, builder);
} }
@Override @Override
public Void visitClassDescriptor(ClassDescriptor descriptor, StringBuilder builder) { public Void visitClassDescriptor(ClassDescriptor descriptor, StringBuilder builder) {
builder.append("class "); builder.append(renderKeyword("class")).append(" ");
renderName(descriptor, builder); renderName(descriptor, builder);
renderTypeParameters(descriptor.getTypeConstructor().getParameters(), builder); renderTypeParameters(descriptor.getTypeConstructor().getParameters(), builder);
Collection<? extends JetType> supertypes = descriptor.getTypeConstructor().getSupertypes(); Collection<? extends JetType> supertypes = descriptor.getTypeConstructor().getSupertypes();
@@ -145,7 +175,7 @@ public class DescriptorUtil {
renderName(containingDeclaration, stringBuilder); renderName(containingDeclaration, stringBuilder);
stringBuilder.append("::"); stringBuilder.append("::");
} }
stringBuilder.append(descriptor.getName()); stringBuilder.append(escape(descriptor.getName()));
} }
private void renderTypeParameter(TypeParameterDescriptor descriptor, StringBuilder builder) { private void renderTypeParameter(TypeParameterDescriptor descriptor, StringBuilder builder) {
@@ -120,7 +120,7 @@ public class ExpectedResolveData {
assertTrue( assertTrue(
"Must have been unresolved: " + "Must have been unresolved: " +
renderReferenceInContext(referenceExpression) + renderReferenceInContext(referenceExpression) +
" but was resolved to " + DescriptorUtil.renderPresentableText(bindingContext.resolveReferenceExpression(referenceExpression)), " but was resolved to " + DescriptorRenderer.TEXT.render(bindingContext.resolveReferenceExpression(referenceExpression)),
unresolvedReferences.contains(referenceExpression)); unresolvedReferences.contains(referenceExpression));
continue; continue;
} }