Render short type names in quick documentation and navigation

This commit is contained in:
Nikolay Krasko
2014-06-04 21:08:21 +04:00
parent 57fc2c8301
commit 2d72b5afc7
13 changed files with 46 additions and 30 deletions
@@ -75,6 +75,11 @@ public interface DescriptorRenderer extends Renderer<DeclarationDescriptor> {
.setWithDefinedIn(false)
.setTextFormat(TextFormat.HTML).build();
DescriptorRenderer HTML_NAMES_WITH_SHORT_TYPES = new DescriptorRendererBuilder()
.setWithDefinedIn(false)
.setShortNames(true)
.setTextFormat(TextFormat.HTML).build();
DescriptorRenderer HTML = new DescriptorRendererBuilder().setTextFormat(TextFormat.HTML).build();
DescriptorRenderer HTML_FOR_UNINFERRED_TYPE_PARAMS = new DescriptorRendererBuilder()
@@ -55,15 +55,15 @@ public class JetQuickDocumentationProvider extends AbstractDocumentationProvider
return getText(element, originalElement, false);
}
private static String getText(PsiElement element, PsiElement originalElement, boolean mergeKotlinAndJava) {
private static String getText(PsiElement element, PsiElement originalElement, boolean quickNavigation) {
if (element instanceof JetDeclaration) {
return renderKotlinDeclaration((JetDeclaration) element);
return renderKotlinDeclaration((JetDeclaration) element, quickNavigation);
}
else if (element instanceof KotlinLightMethod) {
return renderKotlinDeclaration(((KotlinLightMethod) element).getOrigin());
return renderKotlinDeclaration(((KotlinLightMethod) element).getOrigin(), quickNavigation);
}
if (mergeKotlinAndJava) {
if (quickNavigation) {
JetReferenceExpression referenceExpression = PsiTreeUtil.getParentOfType(originalElement, JetReferenceExpression.class, false);
if (referenceExpression != null) {
BindingContext context = AnalyzerFacadeWithCache.getContextForElement(referenceExpression);
@@ -80,13 +80,17 @@ public class JetQuickDocumentationProvider extends AbstractDocumentationProvider
return null;
}
private static String renderKotlinDeclaration(JetDeclaration declaration) {
private static String renderKotlinDeclaration(JetDeclaration declaration, boolean quickNavigation) {
BindingContext context = AnalyzerFacadeWithCache.getContextForElement(declaration);
DeclarationDescriptor declarationDescriptor = context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration);
assert declarationDescriptor != null;
String renderedDecl = DescriptorRenderer.HTML.render(declarationDescriptor);
String renderedDecl = DescriptorRenderer.HTML_NAMES_WITH_SHORT_TYPES.render(declarationDescriptor);
if (!quickNavigation) {
renderedDecl = "<pre>" + DescriptorRenderer.HTML_NAMES_WITH_SHORT_TYPES.render(declarationDescriptor) + "</pre>";
}
KDoc comment = findElementKDoc(declaration);
if (comment != null) {
renderedDecl = renderedDecl + "<br/>" + kDocToHtml(comment);
@@ -95,12 +99,13 @@ public class JetQuickDocumentationProvider extends AbstractDocumentationProvider
return renderedDecl;
}
private static String mixKotlinToJava(@NotNull DeclarationDescriptor declarationDescriptor,
private static String mixKotlinToJava(
@NotNull DeclarationDescriptor declarationDescriptor,
PsiElement element, PsiElement originalElement
) {
String originalInfo = new JavaDocumentationProvider().getQuickNavigateInfo(element, originalElement);
if (originalInfo != null) {
String renderedDecl = DescriptorRenderer.HTML.render(declarationDescriptor);
String renderedDecl = DescriptorRenderer.HTML_NAMES_WITH_SHORT_TYPES.render(declarationDescriptor);
return renderedDecl + "<br/>Java declaration:<br/>" + originalInfo;
}
@@ -1,3 +1,3 @@
fun some(<caret>f: (Int) -> String) : String? = null
//INFO: <b>value-parameter</b> <b>val</b> f: (kotlin.Int) &rarr; kotlin.String <i>defined in</i> some
// INFO: <b>value-parameter</b> <b>val</b> f: (Int) &rarr; String
@@ -2,4 +2,4 @@ trait Base
class Some<<caret>T: Base>
//INFO: &lt;T : Base&gt; <i>defined in</i> Some
// INFO: &lt;T : Base&gt;
@@ -5,4 +5,4 @@ fun test() {
}
//INFO: <b>val</b> test: kotlin.String? <i>defined in</i> test
// INFO: <b>val</b> test: String?
@@ -2,4 +2,4 @@ fun testing() {
<caret>SomeClass<List<String>>()
}
// INFO: <b>public</b> <b>constructor</b> SomeClass&lt;T : kotlin.List&lt;kotlin.Any?&gt;?&gt;() <i>defined in</i> SomeClass<br/>Java declaration:<br/>[light_idea_test_case] public class SomeClass&lt;T extends java.util.List&gt; extends Object
// INFO: <b>public</b> <b>constructor</b> SomeClass&lt;T : List&lt;Any?&gt;?&gt;()<br/>Java declaration:<br/>[light_idea_test_case] public class SomeClass&lt;T extends java.util.List&gt; extends Object
@@ -2,4 +2,4 @@ fun ktTest() {
Test.<caret>foo("SomeTest")
}
//INFO: <b>public</b> <b>open</b> <b>fun</b> foo(param: kotlin.String): kotlin.Array&lt;out kotlin.Any&gt; <i>defined in</i> Test<br/>Java declaration:<br/>Test...
// INFO: <b>public</b> <b>open</b> <b>fun</b> foo(param: String): Array&lt;out Any&gt;<br/>Java declaration:<br/>Test...
@@ -2,4 +2,4 @@ fun test() {
listOf(1, 2, 4).<caret>filter { it > 0 }
}
// INFO: kotlin.inline <b>public</b> <b>fun</b> &lt;T&gt; kotlin.Iterable&lt;T&gt;.filter(predicate: (T) &rarr; kotlin.Boolean): kotlin.List&lt;T&gt; <i>defined in</i> kotlin<br/><p>Returns a list containing all elements matching the given *predicate*<br/></p>
// INFO: inline <b>public</b> <b>fun</b> &lt;T&gt; Iterable&lt;T&gt;.filter(predicate: (T) &rarr; Boolean): List&lt;T&gt;<br/><p>Returns a list containing all elements matching the given *predicate*<br/></p>
@@ -3,4 +3,4 @@
*/
class <caret>Some
// INFO: <b>internal</b> <b>final</b> <b>class</b> Some <i>defined in</i> root package<br/><p>Usefull comment<br/></p>
// INFO: <b>internal</b> <b>final</b> <b>class</b> Some<br/><p>Usefull comment<br/></p>
@@ -12,4 +12,4 @@ package test
*/
fun <caret>testFun(first: String, second: Int) = 12
// INFO: <b>internal</b> <b>fun</b> testFun(first: kotlin.String, second: kotlin.Int): kotlin.Int <i>defined in</i> test<br/><p>Test function<br/><br/><br/><b>@param</b> - <i>first</i> - Some<br/><b>@param</b> - <i>second</i> - Other<br/></p>
// INFO: <b>internal</b> <b>fun</b> testFun(first: String, second: Int): Int<br/><p>Test function<br/><br/><br/><b>@param</b> - <i>first</i> - Some<br/><b>@param</b> - <i>second</i> - Other<br/></p>
@@ -12,4 +12,4 @@ fun test() {
<caret>testMethod(1, "value")
}
// INFO: <b>internal</b> <b>fun</b> testMethod(a: kotlin.Int, b: kotlin.String): kotlin.Unit <i>defined in</i> root package<br/><p>Some documentation<br/><br/><b>@param</b> - <i>a</i> - Some int<br/><b>@param</b> - <i>b</i>: String<br/></p>
// INFO: <b>internal</b> <b>fun</b> testMethod(a: Int, b: String): Unit<br/><p>Some documentation<br/><br/><b>@param</b> - <i>a</i> - Some int<br/><b>@param</b> - <i>b</i>: String<br/></p>
@@ -8,4 +8,4 @@ class Testing {
}
}
// INFO: <b>internal</b> <b>fun</b> foo(bar: kotlin.Int): kotlin.Unit <i>defined in</i> some<br/><p>KDoc foo<br/></p>
// INFO: <b>internal</b> <b>fun</b> foo(bar: Int): Unit<br/><p>KDoc foo<br/></p>
@@ -16,9 +16,6 @@
package org.jetbrains.jet.editor.quickDoc;
import com.google.common.base.Predicates;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.intellij.codeInsight.documentation.DocumentationManager;
import com.intellij.codeInsight.navigation.CtrlMouseHandler;
import com.intellij.openapi.util.io.FileUtil;
@@ -27,17 +24,13 @@ import com.intellij.psi.PsiElement;
import com.intellij.rt.execution.junit.FileComparisonFailure;
import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import com.intellij.util.ArrayUtil;
import junit.framework.Assert;
import junit.framework.ComparisonFailure;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.InTextDirectivesUtils;
import org.jetbrains.jet.plugin.ProjectDescriptorWithStdlibSources;
import org.jetbrains.jet.test.util.UtilPackage;
import org.junit.Assert;
import java.io.File;
import java.util.Collection;
import java.util.List;
public abstract class AbstractJetQuickDocProviderTest extends LightCodeInsightFixtureTestCase {
@@ -64,16 +57,18 @@ public abstract class AbstractJetQuickDocProviderTest extends LightCodeInsightFi
testDataFile.getAbsolutePath());
}
else if (directives.size() == 1) {
assertNotNull(info);
String expectedInfo = directives.get(0);
// We can avoid testing for too long comments with \n character by placing '...' in test data
if (info != null && expectedInfo.endsWith("...")) {
if (expectedInfo.endsWith("...")) {
if (!info.startsWith(StringUtil.trimEnd(expectedInfo, "..."))) {
throw new ComparisonFailure(null, expectedInfo, info);
wrapToFileComparisonFailure(info, path, textData);
}
}
else {
Assert.assertEquals(expectedInfo, info);
else if (!expectedInfo.equals(info)) {
wrapToFileComparisonFailure(info, path, textData);
}
}
else {
@@ -81,6 +76,17 @@ public abstract class AbstractJetQuickDocProviderTest extends LightCodeInsightFi
}
}
private static void wrapToFileComparisonFailure(String info, String filePath, String fileData) {
int newLineIndex = info.indexOf('\n');
if (newLineIndex != -1) {
info = info.substring(0, newLineIndex) + "...";
}
String correctedFileText = fileData.replaceFirst("//\\s?INFO: .*", "// INFO: " + info);
throw new FileComparisonFailure("Unexpected info", fileData, correctedFileText, new File(filePath).getAbsolutePath());
}
@NotNull
@Override
protected LightProjectDescriptor getProjectDescriptor() {