Files
kotlin-fork/idea/src/org/jetbrains/kotlin/idea/JetQuickDocumentationProvider.java
T
2015-01-20 19:20:59 +01:00

125 lines
5.3 KiB
Java

/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea;
import com.google.common.base.Predicate;
import com.intellij.lang.documentation.AbstractDocumentationProvider;
import com.intellij.lang.java.JavaDocumentationProvider;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.asJava.KotlinLightMethod;
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage;
import org.jetbrains.kotlin.kdoc.KdocPackage;
import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag;
import org.jetbrains.kotlin.psi.JetDeclaration;
import org.jetbrains.kotlin.psi.JetPackageDirective;
import org.jetbrains.kotlin.psi.JetReferenceExpression;
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
import org.jetbrains.kotlin.resolve.BindingContext;
public class JetQuickDocumentationProvider extends AbstractDocumentationProvider {
private static final Predicate<PsiElement> SKIP_WHITESPACE_AND_EMPTY_PACKAGE = new Predicate<PsiElement>() {
@Override
public boolean apply(PsiElement input) {
// Skip empty package because there can be comments before it
// Skip whitespaces
return (input instanceof JetPackageDirective && input.getChildren().length == 0) || input instanceof PsiWhiteSpace;
}
};
@Override
public String getQuickNavigateInfo(PsiElement element, PsiElement originalElement) {
return getText(element, originalElement, true);
}
@Override
public String generateDoc(PsiElement element, PsiElement originalElement) {
return getText(element, originalElement, false);
}
private static String getText(PsiElement element, PsiElement originalElement, boolean quickNavigation) {
if (element instanceof JetDeclaration) {
return renderKotlinDeclaration((JetDeclaration) element, quickNavigation);
}
else if (element instanceof KotlinLightMethod) {
return renderKotlinDeclaration(((KotlinLightMethod) element).getOrigin(), quickNavigation);
}
if (quickNavigation) {
JetReferenceExpression referenceExpression = PsiTreeUtil.getParentOfType(originalElement, JetReferenceExpression.class, false);
if (referenceExpression != null) {
BindingContext context = ResolvePackage.analyze(referenceExpression);
DeclarationDescriptor declarationDescriptor = context.get(BindingContext.REFERENCE_TARGET, referenceExpression);
if (declarationDescriptor != null) {
return mixKotlinToJava(declarationDescriptor, element, originalElement);
}
}
}
else {
// This element was resolved to non-kotlin element, it will be rendered with own provider
}
return null;
}
private static String renderKotlinDeclaration(JetDeclaration declaration, boolean quickNavigation) {
BindingContext context = ResolvePackage.analyze(declaration);
DeclarationDescriptor declarationDescriptor = context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration);
assert declarationDescriptor != null;
String renderedDecl = DescriptorRenderer.HTML_NAMES_WITH_SHORT_TYPES.render(declarationDescriptor);
if (!quickNavigation) {
renderedDecl = "<pre>" + DescriptorRenderer.HTML_NAMES_WITH_SHORT_TYPES.render(declarationDescriptor) + "</pre>";
}
KDocTag comment = KdocPackage.findKDoc(declarationDescriptor);
if (comment != null) {
renderedDecl = renderedDecl + "<br/>" + kDocToHtml(comment);
}
return renderedDecl;
}
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_NAMES_WITH_SHORT_TYPES.render(declarationDescriptor);
return renderedDecl + "<br/>Java declaration:<br/>" + originalInfo;
}
return null;
}
private static String kDocToHtml(@NotNull KDocTag comment) {
// TODO: Parse and show markdown comments as html
String content = comment.getContentWithTags();
String htmlContent = StringUtil.replace(content, "\n", "<br/>")
.replaceAll("(@param)\\s+(\\w+)", "@param - <i>$2</i>")
.replaceAll("(@\\w+)", "<b>$1</b>");
return "<p>" + htmlContent + "</p>";
}
}