Set up rendering for structure elements

This commit is contained in:
Nikolay Krasko
2014-05-23 22:03:15 +04:00
parent 2d6dc5db68
commit 58d9375a25
9 changed files with 278 additions and 106 deletions
@@ -56,9 +56,12 @@ public interface DescriptorRenderer extends Renderer<DeclarationDescriptor> {
DescriptorRenderer STARTS_FROM_NAME_WITH_SHORT_TYPES = new DescriptorRendererBuilder() DescriptorRenderer STARTS_FROM_NAME_WITH_SHORT_TYPES = new DescriptorRendererBuilder()
.setWithDefinedIn(false) .setWithDefinedIn(false)
.setUnitReturnType(false)
.setModifiers() .setModifiers()
.setShortNames(true) .setShortNames(true)
.setWithoutTypeParameters(true)
.setWithoutFunctionParameterNames(true)
.setReceiverAfterName(true)
.setRenderClassObjectName(true)
.setStartFromName(true).build(); .setStartFromName(true).build();
DescriptorRenderer FQ_NAMES_IN_TYPES = new DescriptorRendererBuilder().build(); DescriptorRenderer FQ_NAMES_IN_TYPES = new DescriptorRendererBuilder().build();
@@ -1,5 +1,5 @@
/* /*
* Copyright 2010-2013 JetBrains s.r.o. * Copyright 2010-2014 JetBrains s.r.o.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -39,6 +39,9 @@ public class DescriptorRendererBuilder {
private boolean uninferredTypeParameterAsName = false; private boolean uninferredTypeParameterAsName = false;
private boolean includePropertyConstant = false; private boolean includePropertyConstant = false;
private boolean includeSynthesizedParameterNames = true; private boolean includeSynthesizedParameterNames = true;
private boolean withoutFunctionParameterNames = false;
private boolean withoutTypeParameters = false;
@NotNull @NotNull
private DescriptorRenderer.OverrideRenderingPolicy overrideRenderingPolicy = DescriptorRenderer.OverrideRenderingPolicy.RENDER_OPEN; private DescriptorRenderer.OverrideRenderingPolicy overrideRenderingPolicy = DescriptorRenderer.OverrideRenderingPolicy.RENDER_OPEN;
@NotNull @NotNull
@@ -47,6 +50,8 @@ public class DescriptorRendererBuilder {
private DescriptorRenderer.TextFormat textFormat = DescriptorRenderer.TextFormat.PLAIN; private DescriptorRenderer.TextFormat textFormat = DescriptorRenderer.TextFormat.PLAIN;
@NotNull @NotNull
private Collection<FqName> excludedAnnotationClasses = Collections.emptyList(); private Collection<FqName> excludedAnnotationClasses = Collections.emptyList();
private boolean receiverAfterName = false;
private boolean renderClassObjectName = false;
public DescriptorRendererBuilder() { public DescriptorRendererBuilder() {
} }
@@ -162,13 +167,34 @@ public class DescriptorRendererBuilder {
return this; return this;
} }
public DescriptorRendererBuilder setWithoutTypeParameters(boolean withoutTypeParameters) {
this.withoutTypeParameters = withoutTypeParameters;
return this;
}
public DescriptorRendererBuilder setWithoutFunctionParameterNames(boolean withoutFunctionParameterNames) {
this.withoutFunctionParameterNames = withoutFunctionParameterNames;
return this;
}
public DescriptorRendererBuilder setReceiverAfterName(boolean receiverAfterName) {
this.receiverAfterName = receiverAfterName;
return this;
}
public DescriptorRendererBuilder setRenderClassObjectName(boolean renderClassObjectName) {
this.renderClassObjectName = renderClassObjectName;
return this;
}
@NotNull @NotNull
public DescriptorRenderer build() { public DescriptorRenderer build() {
return new DescriptorRendererImpl( return new DescriptorRendererImpl(
shortNames, withDefinedIn, modifiers, startFromName, debugMode, classWithPrimaryConstructor, verbose, unitReturnType, shortNames, withDefinedIn, modifiers, startFromName, debugMode, classWithPrimaryConstructor, verbose, unitReturnType,
normalizedVisibilities, showInternalKeyword, prettyFunctionTypes, uninferredTypeParameterAsName, normalizedVisibilities, showInternalKeyword, prettyFunctionTypes, uninferredTypeParameterAsName,
overrideRenderingPolicy, valueParametersHandler, textFormat, excludedAnnotationClasses, includePropertyConstant, overrideRenderingPolicy, valueParametersHandler, textFormat, excludedAnnotationClasses, includePropertyConstant,
includeSynthesizedParameterNames); includeSynthesizedParameterNames, withoutFunctionParameterNames, withoutTypeParameters, receiverAfterName,
renderClassObjectName);
} }
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright 2010-2013 JetBrains s.r.o. * Copyright 2010-2014 JetBrains s.r.o.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -58,7 +58,11 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
private final boolean prettyFunctionTypes; private final boolean prettyFunctionTypes;
private final boolean uninferredTypeParameterAsName; private final boolean uninferredTypeParameterAsName;
private final boolean includeSynthesizedParameterNames; private final boolean includeSynthesizedParameterNames;
private final boolean withoutFunctionParameterNames;
private final boolean withoutTypeParameters;
private final boolean renderClassObjectName;
private final boolean receiverAfterName;
@NotNull @NotNull
private final OverrideRenderingPolicy overrideRenderingPolicy; private final OverrideRenderingPolicy overrideRenderingPolicy;
@NotNull @NotNull
@@ -87,7 +91,11 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
@NotNull TextFormat textFormat, @NotNull TextFormat textFormat,
@NotNull Collection<FqName> excludedAnnotationClasses, @NotNull Collection<FqName> excludedAnnotationClasses,
boolean includePropertyConstant, boolean includePropertyConstant,
boolean includeSynthesizedParameterNames boolean includeSynthesizedParameterNames,
boolean withoutFunctionParameterNames,
boolean withoutTypeParameters,
boolean receiverAfterName,
boolean renderClassObjectName
) { ) {
this.shortNames = shortNames; this.shortNames = shortNames;
this.withDefinedIn = withDefinedIn; this.withDefinedIn = withDefinedIn;
@@ -107,6 +115,10 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
this.prettyFunctionTypes = prettyFunctionTypes; this.prettyFunctionTypes = prettyFunctionTypes;
this.uninferredTypeParameterAsName = uninferredTypeParameterAsName; this.uninferredTypeParameterAsName = uninferredTypeParameterAsName;
this.includeSynthesizedParameterNames = includeSynthesizedParameterNames; this.includeSynthesizedParameterNames = includeSynthesizedParameterNames;
this.withoutFunctionParameterNames = withoutFunctionParameterNames;
this.withoutTypeParameters = withoutTypeParameters;
this.receiverAfterName = receiverAfterName;
this.renderClassObjectName = renderClassObjectName;
} }
/* FORMATTING */ /* FORMATTING */
@@ -187,6 +199,15 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
builder.append(renderName(descriptor.getName())); builder.append(renderName(descriptor.getName()));
} }
private void renderClassObjectName(@NotNull DeclarationDescriptor descriptor, @NotNull StringBuilder builder) {
if (renderClassObjectName) {
builder.append("<class object>");
}
if (verbose) {
builder.append(renderName(descriptor.getName()));
}
}
@NotNull @NotNull
private String renderFqName(@NotNull FqNameBase fqName) { private String renderFqName(@NotNull FqNameBase fqName) {
return renderFqName(fqName.pathSegments()); return renderFqName(fqName.pathSegments());
@@ -553,6 +574,8 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
@NotNull StringBuilder builder, @NotNull StringBuilder builder,
boolean withSpace boolean withSpace
) { ) {
if (withoutTypeParameters) return;
if (!typeParameters.isEmpty()) { if (!typeParameters.isEmpty()) {
builder.append(lt()); builder.append(lt());
for (Iterator<TypeParameterDescriptor> iterator = typeParameters.iterator(); iterator.hasNext(); ) { for (Iterator<TypeParameterDescriptor> iterator = typeParameters.iterator(); iterator.hasNext(); ) {
@@ -580,24 +603,39 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
builder.append(renderKeyword("fun")).append(" "); builder.append(renderKeyword("fun")).append(" ");
renderTypeParameters(function.getTypeParameters(), builder, true); renderTypeParameters(function.getTypeParameters(), builder, true);
renderReceiver(function, builder);
ReceiverParameterDescriptor receiver = function.getReceiverParameter();
if (receiver != null) {
builder.append(escape(renderType(receiver.getType()))).append(".");
}
} }
renderName(function, builder); renderName(function, builder);
renderValueParameters(function, builder); renderValueParameters(function, builder);
renderReceiverAfterName(function, builder);
JetType returnType = function.getReturnType(); JetType returnType = function.getReturnType();
if (unitReturnType || !KotlinBuiltIns.getInstance().isUnit(returnType)) { if (unitReturnType || (returnType == null || !KotlinBuiltIns.getInstance().isUnit(returnType))) {
builder.append(": ").append(returnType == null ? "[NULL]" : escape(renderType(returnType))); builder.append(": ").append(returnType == null ? "[NULL]" : escape(renderType(returnType)));
} }
renderWhereSuffix(function.getTypeParameters(), builder); renderWhereSuffix(function.getTypeParameters(), builder);
} }
private void renderReceiverAfterName(CallableDescriptor callableDescriptor, StringBuilder builder) {
if (!receiverAfterName) return;
ReceiverParameterDescriptor receiver = callableDescriptor.getReceiverParameter();
if (receiver != null) {
builder.append(" on ").append(escape(renderType(receiver.getType())));
}
}
private void renderReceiver(CallableDescriptor callableDescriptor, StringBuilder builder) {
ReceiverParameterDescriptor receiver = callableDescriptor.getReceiverParameter();
if (receiver != null) {
builder.append(escape(renderType(receiver.getType()))).append(".");
}
}
private void renderConstructor(@NotNull ConstructorDescriptor constructor, @NotNull StringBuilder builder) { private void renderConstructor(@NotNull ConstructorDescriptor constructor, @NotNull StringBuilder builder) {
renderAnnotations(constructor, builder); renderAnnotations(constructor, builder);
renderVisibility(constructor.getVisibility(), builder); renderVisibility(constructor.getVisibility(), builder);
@@ -614,6 +652,8 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
} }
private void renderWhereSuffix(@NotNull List<TypeParameterDescriptor> typeParameters, @NotNull StringBuilder builder) { private void renderWhereSuffix(@NotNull List<TypeParameterDescriptor> typeParameters, @NotNull StringBuilder builder) {
if (withoutTypeParameters) return;
List<String> upperBoundStrings = Lists.newArrayList(); List<String> upperBoundStrings = Lists.newArrayList();
for (TypeParameterDescriptor typeParameter : typeParameters) { for (TypeParameterDescriptor typeParameter : typeParameters) {
@@ -643,7 +683,8 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
} }
private void renderValueParameters(@NotNull FunctionDescriptor function, @NotNull StringBuilder builder) { private void renderValueParameters(@NotNull FunctionDescriptor function, @NotNull StringBuilder builder) {
boolean includeNames = includeSynthesizedParameterNames || !function.hasSynthesizedParameterNames(); boolean includeNames = !withoutFunctionParameterNames &&
(includeSynthesizedParameterNames || !function.hasSynthesizedParameterNames());
handler.appendBeforeValueParameters(function, builder); handler.appendBeforeValueParameters(function, builder);
for (ValueParameterDescriptor parameter : function.getValueParameters()) { for (ValueParameterDescriptor parameter : function.getValueParameters()) {
handler.appendBeforeValueParameter(parameter, builder); handler.appendBeforeValueParameter(parameter, builder);
@@ -711,19 +752,16 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
renderModalityForCallable(property, builder); renderModalityForCallable(property, builder);
renderOverride(property, builder); renderOverride(property, builder);
renderMemberKind(property, builder); renderMemberKind(property, builder);
renderValVarPrefix(property, builder); renderValVarPrefix(property, builder);
renderTypeParameters(property.getTypeParameters(), builder, true);
renderReceiver(property, builder);
} }
renderTypeParameters(property.getTypeParameters(), builder, true);
ReceiverParameterDescriptor receiver = property.getReceiverParameter();
if (receiver != null) {
builder.append(escape(renderType(receiver.getType()))).append(".");
}
renderName(property, builder); renderName(property, builder);
builder.append(": ").append(escape(renderType(property.getType()))); builder.append(": ").append(escape(renderType(property.getType())));
renderReceiverAfterName(property, builder);
renderInitializer(property, builder); renderInitializer(property, builder);
renderWhereSuffix(property.getTypeParameters(), builder); renderWhereSuffix(property.getTypeParameters(), builder);
@@ -748,13 +786,16 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
renderModality(klass.getModality(), builder); renderModality(klass.getModality(), builder);
} }
renderInner(klass.isInner(), builder); renderInner(klass.isInner(), builder);
builder.append(renderKeyword(getClassKindPrefix(klass))); renderClassKindPrefix(klass, builder);
builder.append(" ");
} }
if (klass.getKind() != ClassKind.CLASS_OBJECT || verbose) { if (klass.getKind() != ClassKind.CLASS_OBJECT) {
builder.append(" ");
renderName(klass, builder); renderName(klass, builder);
} }
else {
renderClassObjectName(klass, builder);
}
List<TypeParameterDescriptor> typeParameters = klass.getTypeConstructor().getParameters(); List<TypeParameterDescriptor> typeParameters = klass.getTypeConstructor().getParameters();
renderTypeParameters(typeParameters, builder, false); renderTypeParameters(typeParameters, builder, false);
@@ -786,6 +827,10 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
renderWhereSuffix(typeParameters, builder); renderWhereSuffix(typeParameters, builder);
} }
private void renderClassKindPrefix(ClassDescriptor klass, StringBuilder builder) {
builder.append(renderKeyword(getClassKindPrefix(klass)));
}
@NotNull @NotNull
private static String getClassKindPrefix(@NotNull ClassDescriptor klass) { private static String getClassKindPrefix(@NotNull ClassDescriptor klass) {
switch (klass.getKind()) { switch (klass.getKind()) {
@@ -46,8 +46,9 @@ public class JetStructureViewElement implements StructureViewTreeElement, Colore
private final NavigatablePsiElement element; private final NavigatablePsiElement element;
private String elementText; private String elementText;
private Icon icon;
public JetStructureViewElement(NavigatablePsiElement element) { public JetStructureViewElement(@NotNull NavigatablePsiElement element) {
this.element = element; this.element = element;
} }
@@ -55,10 +56,6 @@ public class JetStructureViewElement implements StructureViewTreeElement, Colore
element = fileElement; element = fileElement;
} }
private static DeclarationDescriptor getDescriptor(JetDeclaration declaration) {
return declaration.isValid() ? ResolvePackage.getLazyResolveSession(declaration).resolveToDescriptor(declaration) : null;
}
@NotNull @NotNull
public NavigatablePsiElement getElement() { public NavigatablePsiElement getElement() {
return element; return element;
@@ -102,6 +99,55 @@ public class JetStructureViewElement implements StructureViewTreeElement, Colore
}), TreeElement.class); }), TreeElement.class);
} }
@Nullable
@Override
public TextAttributesKey getTextAttributesKey() {
if (element instanceof JetModifierListOwner && JetPsiUtil.isDeprecated((JetModifierListOwner) element)) {
return CodeInsightColors.DEPRECATED_ATTRIBUTES;
}
return null;
}
@Nullable
@Override
public String getPresentableText() {
if (elementText == null) {
elementText = getElementText(element, getDescriptor());
}
return elementText;
}
@Nullable
@Override
public String getLocationString() {
return null;
}
@Nullable
@Override
public Icon getIcon(boolean unused) {
if (icon == null) {
icon = getElementIcon(element, getDescriptor());
}
return icon;
}
@Nullable
private DeclarationDescriptor getDescriptor() {
if (!(element.isValid() && element instanceof JetDeclaration)) {
return null;
}
JetDeclaration declaration = (JetDeclaration) element;
if (declaration instanceof JetClassInitializer) {
return null;
}
return ResolvePackage.getLazyResolveSession(declaration).resolveToDescriptor(declaration);
}
private List<JetDeclaration> getChildrenDeclarations() { private List<JetDeclaration> getChildrenDeclarations() {
if (element instanceof JetFile) { if (element instanceof JetFile) {
JetFile jetFile = (JetFile) element; JetFile jetFile = (JetFile) element;
@@ -129,74 +175,29 @@ public class JetStructureViewElement implements StructureViewTreeElement, Colore
return Collections.emptyList(); return Collections.emptyList();
} }
@Nullable private static Icon getElementIcon(@NotNull NavigatablePsiElement navigatablePsiElement, @Nullable DeclarationDescriptor descriptor) {
@Override if (descriptor != null) {
public TextAttributesKey getTextAttributesKey() { return JetDescriptorIconProvider.getIcon(descriptor, navigatablePsiElement, Iconable.ICON_FLAG_VISIBILITY);
if (element instanceof JetModifierListOwner && JetPsiUtil.isDeprecated((JetModifierListOwner) element)) {
return CodeInsightColors.DEPRECATED_ATTRIBUTES;
} }
return PsiIconUtil.getProvidersIcon(navigatablePsiElement, Iconable.ICON_FLAG_VISIBILITY);
}
@Nullable
private static String getElementText(@NotNull NavigatablePsiElement navigatablePsiElement, @Nullable DeclarationDescriptor descriptor) {
if (descriptor != null) {
return DescriptorRenderer.STARTS_FROM_NAME_WITH_SHORT_TYPES.render(descriptor);
}
String text = navigatablePsiElement.getName();
if (!StringUtil.isEmpty(text)) {
return text;
}
if (navigatablePsiElement instanceof JetClassInitializer) {
return "<class initializer>";
}
return null; return null;
} }
@Nullable
@Override
public String getPresentableText() {
if (elementText == null) {
elementText = getElementText();
}
return elementText;
}
@Nullable
@Override
public String getLocationString() {
return null;
}
@Nullable
@Override
public Icon getIcon(boolean unused) {
if (!element.isValid()) return null;
if (element instanceof JetDeclaration) {
DeclarationDescriptor descriptor = getDescriptor((JetDeclaration) element);
if (descriptor != null) {
JetDescriptorIconProvider.getIcon(descriptor, element, Iconable.ICON_FLAG_VISIBILITY);
}
}
return PsiIconUtil.getProvidersIcon(element, Iconable.ICON_FLAG_VISIBILITY);
}
private String getElementText() {
String text = "";
// Try to find text in correspondent descriptor
if (element instanceof JetDeclaration) {
JetDeclaration declaration = (JetDeclaration) element;
DeclarationDescriptor descriptor = getDescriptor(declaration);
if (descriptor != null) {
//text = getDescriptorTreeText(descriptor);
text = DescriptorRenderer.STARTS_FROM_NAME_WITH_SHORT_TYPES.render(descriptor);
}
}
if (StringUtil.isEmpty(text)) {
text = element.getName();
}
if (StringUtil.isEmpty(text)) {
if (element instanceof JetClassInitializer) {
return "<class initializer>";
}
if (element instanceof JetClassObject) {
return "<class object>";
}
}
return text;
}
} }
@@ -0,0 +1,40 @@
-Render.kt
test1(): Unit
test2(String?): Unit
test3(T, U): Unit
test4(T): Unit
test5(): String
test6(): Comparable<String>
extension1() on String: Unit
extension2() on Comparable<T>: Unit
a: Int
a: String on Comparable<T>
b: Any
A1
-A2
a: Int
b: [ERROR : Annotation is absent]
-A3
a: Int
b: String
-A4
t: T?
-A5
Inner1
Inner2
-A6
-<class object>
test(): Unit
-A7
a: Int
<class initializer>
-Enum1 : Enum<Enum1>
FIRST : Enum1
SECOND : Enum1
Trait
Trait1 : Trait
TestWithWhere
testWithWhere(): Unit
-WithDefaultArgs
a: Int
withDefaulArgs(Int = ..., String = ...): Unit
@@ -0,0 +1,54 @@
//package test.render
fun test1() {}
fun test2(a: String?) {}
fun <T, U> test3(t: T, u: U) {}
fun <T: String> test4(t: T) {}
fun test5(): String = "some"
fun test6(): Comparable<String> = "some"
fun String.extension1() {}
fun <T> Comparable<T>.extension2() {}
val a: Int = 1
val <T> Comparable<T>.a = "String"
val b = object {}
class A1
class A2(val a: Int, var b = "some")
class A3(val a: Int) {
var b = "some"
}
class A4<T: Any>(val t: T?)
class A5 {
class Inner1
inner class Inner2
}
class A6 {
class object {
fun test() {}
}
}
class A7 {
val a: Int
{
a = 1
}
}
enum class Enum1 {
FIRST
SECOND
}
trait Trait
trait Trait1: Trait
class TestWithWhere<T> where T: Any?
fun <T> testWithWhere() where T: String {}
class WithDefaultArgs(val a: Int = 1, b: String = "str")
fun withDefaulArgs(a: Int = 1, b: String = "str") {}
@@ -1,5 +1,5 @@
-SeveralClasses.kt -SeveralClasses.kt
A (<root>) A
B (<root>) B
Some (<root>) Some : B, A
Other (<root>) Other : A
@@ -1,6 +1,6 @@
-Simple.kt -Simple.kt
-Test (<root>) -Test
str:kotlin.String str: String
some:kotlin.Int some: Int
foo():kotlin.Int foo(): Int
other():kotlin.Unit other(): Unit
@@ -33,9 +33,7 @@ import org.jetbrains.jet.plugin.structureView.AbstractKotlinFileStructureTest;
@TestMetadata("idea/testData/structureView/fileStructure") @TestMetadata("idea/testData/structureView/fileStructure")
public class KotlinFileStructureTestGenerated extends AbstractKotlinFileStructureTest { public class KotlinFileStructureTestGenerated extends AbstractKotlinFileStructureTest {
public void testAllFilesPresentInFileStructure() throws Exception { public void testAllFilesPresentInFileStructure() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/structureView/fileStructure"), Pattern.compile("^(.+)\\.kt$"), true);
new File("idea/testData/structureView/fileStructure"), Pattern.compile("^(.+)\\.kt$"),
true);
} }
@TestMetadata("EmptyFile.kt") @TestMetadata("EmptyFile.kt")
@@ -48,6 +46,11 @@ public class KotlinFileStructureTestGenerated extends AbstractKotlinFileStructur
doTest("idea/testData/structureView/fileStructure/InheritedMembers.kt"); doTest("idea/testData/structureView/fileStructure/InheritedMembers.kt");
} }
@TestMetadata("Render.kt")
public void testRender() throws Exception {
doTest("idea/testData/structureView/fileStructure/Render.kt");
}
@TestMetadata("SeveralClasses.kt") @TestMetadata("SeveralClasses.kt")
public void testSeveralClasses() throws Exception { public void testSeveralClasses() throws Exception {
doTest("idea/testData/structureView/fileStructure/SeveralClasses.kt"); doTest("idea/testData/structureView/fileStructure/SeveralClasses.kt");