diff --git a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java index 852a414388e..35b528d27c8 100644 --- a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java +++ b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java @@ -16,6 +16,9 @@ package org.jetbrains.jet.resolve; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; @@ -23,8 +26,10 @@ import org.jetbrains.jet.lang.diagnostics.rendering.Renderer; import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe; +import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; +import org.jetbrains.jet.lexer.JetKeywordToken; import org.jetbrains.jet.lexer.JetTokens; import java.util.*; @@ -33,6 +38,14 @@ import java.util.*; * @author abreslav */ public class DescriptorRenderer implements Renderer { + private static final Set KEYWORDS = Sets.newHashSet(); + static { + for (IElementType elementType : JetTokens.KEYWORDS.getTypes()) { + assert elementType instanceof JetKeywordToken; + assert !((JetKeywordToken) elementType).isSoft(); + KEYWORDS.add(((JetKeywordToken) elementType).getValue()); + } + } public static final DescriptorRenderer COMPACT_WITH_MODIFIERS = new DescriptorRenderer() { @Override @@ -112,6 +125,28 @@ public class DescriptorRenderer implements Renderer { return keyword; } + private String renderName(Name identifier) { + String asString = identifier.toString(); + return escape(KEYWORDS.contains(asString) ? '`' + asString + '`' : asString); + } + + @NotNull + private String renderFqName(@NotNull FqNameUnsafe fqName) { + return renderFqName(fqName.pathSegments()); + } + + @NotNull + private String renderFqName(@NotNull List pathSegments) { + StringBuilder buf = new StringBuilder(); + for (Name element : pathSegments) { + if (buf.length() != 0) { + buf.append("."); + } + buf.append(renderName(element)); + } + return buf.toString(); + } + public String renderType(JetType type) { return renderType(type, false); } @@ -156,25 +191,32 @@ public class DescriptorRenderer implements Renderer { return sb.toString(); } - private static String renderTypeName(@NotNull TypeConstructor typeConstructor, boolean shortNamesOnly) { + private String renderTypeName(@NotNull TypeConstructor typeConstructor, boolean shortNamesOnly) { ClassifierDescriptor cd = typeConstructor.getDeclarationDescriptor(); - if (cd == null || cd instanceof TypeParameterDescriptor) { + if (cd == null) { return typeConstructor.toString(); } + else if (cd instanceof TypeParameterDescriptor) { + return renderName(cd.getName()); + } else { if (shortNamesOnly) { - Object typeNameObject; + List qualifiedNameElements = Lists.newArrayList(); + // for nested classes qualified name should be used - typeNameObject = cd.getName(); - DeclarationDescriptor parent = cd.getContainingDeclaration(); - while (parent instanceof ClassDescriptor) { - typeNameObject = parent.getName() + "." + typeNameObject; - parent = parent.getContainingDeclaration(); + DeclarationDescriptor current = cd; + do { + qualifiedNameElements.add(current.getName()); + current = current.getContainingDeclaration(); } - return typeNameObject.toString(); + while (current instanceof ClassDescriptor); + + Collections.reverse(qualifiedNameElements); + + return renderFqName(qualifiedNameElements); } else { - return DescriptorUtils.getFQName(cd).getFqName(); + return renderFqName(DescriptorUtils.getFQName(cd)); } } } @@ -281,7 +323,7 @@ public class DescriptorRenderer implements Renderer { final DeclarationDescriptor containingDeclaration = declarationDescriptor.getContainingDeclaration(); if (containingDeclaration != null) { FqNameUnsafe fqName = DescriptorUtils.getFQName(containingDeclaration); - stringBuilder.append(FqName.ROOT.equalsTo(fqName) ? "root package" : escape(fqName.getFqName())); + stringBuilder.append(FqName.ROOT.equalsTo(fqName) ? "root package" : renderFqName(fqName)); } } @@ -627,7 +669,7 @@ public class DescriptorRenderer implements Renderer { } protected void renderName(DeclarationDescriptor descriptor, StringBuilder stringBuilder) { - stringBuilder.append(escape(descriptor.getName().getName())); + stringBuilder.append(escape(DescriptorRenderer.this.renderName(descriptor.getName()))); } protected void renderTypeParameter(TypeParameterDescriptor descriptor, StringBuilder builder, boolean topLevel) { diff --git a/compiler/testData/renderer/KeywordsInNames.kt b/compiler/testData/renderer/KeywordsInNames.kt new file mode 100644 index 00000000000..9f72fd68c8f --- /dev/null +++ b/compiler/testData/renderer/KeywordsInNames.kt @@ -0,0 +1,23 @@ +val `val` = 5 + +trait `trait` + +class `class`<`in`>(p: `in`?) { + class `class` +} + +val `is` = `class`.`class`() +val `in` = `class`<`trait`>(null) + +fun `trait`.`fun`(`false`: `trait`): `trait` + +//internal final val `val` : jet.Int defined in root package +//internal trait `trait` defined in root package +//internal final class `class`<`in`> defined in root package +//<`in`> defined in `class` +//value-parameter val p : `in`? defined in `class`. +//internal final class `class` defined in `class` +//internal final val `is` : `class`.`class` defined in root package +//internal final val `in` : `class`<`trait`> defined in root package +//internal final fun `trait`.`fun`(`false` : `trait`) : `trait` defined in root package +//value-parameter val `false` : `trait` defined in `fun` \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java index 8f30906d08e..26ae420df59 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java @@ -15,13 +15,16 @@ */ package org.jetbrains.jet.jvm.compiler; +import junit.framework.Assert; import junit.framework.Test; import junit.framework.TestSuite; + +import java.io.File; import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.test.InnerTestClasses; import org.jetbrains.jet.test.TestMetadata; -import java.io.File; +import org.jetbrains.jet.jvm.compiler.AbstractLoadJavaTest; /** This class is generated by {@link org.jetbrains.jet.generators.tests.GenerateTests}. DO NOT MODIFY MANUALLY */ @TestMetadata("compiler/testData/loadJava") diff --git a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveDescriptorRendererTestGenerated.java b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveDescriptorRendererTestGenerated.java index e7e3a46b2b8..0bf4581aaaa 100644 --- a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveDescriptorRendererTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveDescriptorRendererTestGenerated.java @@ -70,6 +70,11 @@ public class LazyResolveDescriptorRendererTestGenerated extends AbstractLazyReso doTest("compiler/testData/renderer/InheritedMembersVisibility.kt"); } + @TestMetadata("KeywordsInNames.kt") + public void testKeywordsInNames() throws Exception { + doTest("compiler/testData/renderer/KeywordsInNames.kt"); + } + @TestMetadata("TupleTypes.kt") public void testTupleTypes() throws Exception { doTest("compiler/testData/renderer/TupleTypes.kt"); diff --git a/compiler/tests/org/jetbrains/jet/resolve/DescriptorRendererTest.java b/compiler/tests/org/jetbrains/jet/resolve/DescriptorRendererTest.java index 10bac3b8065..ad3c5d5345c 100644 --- a/compiler/tests/org/jetbrains/jet/resolve/DescriptorRendererTest.java +++ b/compiler/tests/org/jetbrains/jet/resolve/DescriptorRendererTest.java @@ -80,6 +80,10 @@ public class DescriptorRendererTest extends JetLiteFixture { doTest(); } + public void testKeywordsInNames() throws IOException { + doTest(); + } + @Override protected String getTestDataPath() { return JetTestCaseBuilder.getTestDataPathBase() + "/renderer";