Add article and tutorial about Documentation Provider (#413)

* Initial version of a simple DocumentationProvider
* Correct usage of DocumentationMarkup, fix quick navigation
* Include Yann's suggestions. Not finished yet.
* Fix issues Yann pointed out
This commit is contained in:
Patrick Scheibe 2021-06-14 23:52:13 +02:00 committed by GitHub
parent fd1fc38585
commit 516ca8f264
3 changed files with 120 additions and 4 deletions

View File

@ -0,0 +1,96 @@
package org.intellij.sdk.language;
import com.intellij.lang.documentation.AbstractDocumentationProvider;
import com.intellij.lang.documentation.DocumentationMarkup;
import com.intellij.psi.PsiElement;
import com.intellij.psi.presentation.java.SymbolPresentationUtil;
import org.intellij.sdk.language.psi.SimpleProperty;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class SimpleDocumentationProvider extends AbstractDocumentationProvider {
/**
* For the Simple Language, we don't have online documentation. However, if your language provides
* references pages online, URLs for the element can be returned here.
*/
@Override
public @Nullable List<String> getUrlFor(PsiElement element, PsiElement originalElement) {
return null;
}
/**
* Extracts the key, value, file and documentation comment of a Simple key/value entry and returns
* a formatted representation of the information.
*/
@Override
public @Nullable String generateDoc(PsiElement element, @Nullable PsiElement originalElement) {
if (element instanceof SimpleProperty) {
final String key = ((SimpleProperty) element).getKey();
final String value = ((SimpleProperty) element).getValue();
final String file = SymbolPresentationUtil.getFilePathPresentation(element.getContainingFile());
final String docComment = SimpleUtil.findDocumentationComment((SimpleProperty) element);
return renderFullDoc(key, value, file, docComment);
}
return null;
}
/**
* Provides the information in which file the Simple language key/value is defined.
*/
@Override
public @Nullable String getQuickNavigateInfo(PsiElement element, PsiElement originalElement) {
if (element instanceof SimpleProperty) {
final String key = ((SimpleProperty) element).getKey();
final String file = SymbolPresentationUtil.getFilePathPresentation(element.getContainingFile());
return "\"" + key + "\" in " + file;
}
return null;
}
/**
* Provides documentation when a Simple Language element is hovered with the mouse.
*/
@Override
public @Nullable String generateHoverDoc(@NotNull PsiElement element, @Nullable PsiElement originalElement) {
return generateDoc(element, originalElement);
}
/**
* Creates a key/value row for the rendered documentation.
*/
private void addKeyValueSection(String key, String value, StringBuilder sb) {
sb.append(DocumentationMarkup.SECTION_HEADER_START);
sb.append(key);
sb.append(DocumentationMarkup.SECTION_SEPARATOR);
sb.append("<p>");
sb.append(value);
sb.append(DocumentationMarkup.SECTION_END);
}
/**
* Creates the formatted documentation using {@link DocumentationMarkup}. See the Java doc of
* {@link com.intellij.lang.documentation.DocumentationProvider#generateDoc(PsiElement, PsiElement)} for more
* information about building the layout.
*/
private String renderFullDoc(String key, String value, String file, String docComment) {
StringBuilder sb = new StringBuilder();
sb.append(DocumentationMarkup.DEFINITION_START);
sb.append("Simple Property");
sb.append(DocumentationMarkup.DEFINITION_END);
sb.append(DocumentationMarkup.CONTENT_START);
sb.append(value);
sb.append(DocumentationMarkup.CONTENT_END);
sb.append(DocumentationMarkup.SECTIONS_START);
addKeyValueSection("Key:", key, sb);
addKeyValueSection("Value:", value, sb);
addKeyValueSection("File:", file, sb);
addKeyValueSection("Comment:", docComment, sb);
sb.append(DocumentationMarkup.SECTIONS_END);
return sb.toString();
}
}

View File

@ -2,19 +2,22 @@
package org.intellij.sdk.language; package org.intellij.sdk.language;
import com.google.common.collect.Lists;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiComment;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiManager; import com.intellij.psi.PsiManager;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.search.FileTypeIndex; import com.intellij.psi.search.FileTypeIndex;
import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTreeUtil;
import org.intellij.sdk.language.psi.SimpleFile; import org.intellij.sdk.language.psi.SimpleFile;
import org.intellij.sdk.language.psi.SimpleProperty; import org.intellij.sdk.language.psi.SimpleProperty;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList; import java.util.*;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class SimpleUtil { public class SimpleUtil {
@ -61,4 +64,20 @@ public class SimpleUtil {
return result; return result;
} }
/**
* Attempts to collect any comment elements above the Simple key/value pair.
*/
public static @NotNull String findDocumentationComment(SimpleProperty property) {
List<String> result = new LinkedList<>();
PsiElement element = property.getPrevSibling();
while (element instanceof PsiComment || element instanceof PsiWhiteSpace) {
if (element instanceof PsiComment) {
String commentText = element.getText().replaceFirst("[!# ]+", "");
result.add(commentText);
}
element = element.getPrevSibling();
}
return StringUtil.join(Lists.reverse(result),"\n ");
}
} }

View File

@ -66,6 +66,7 @@
<codeStyleSettingsProvider implementation="org.intellij.sdk.language.SimpleCodeStyleSettingsProvider"/> <codeStyleSettingsProvider implementation="org.intellij.sdk.language.SimpleCodeStyleSettingsProvider"/>
<langCodeStyleSettingsProvider implementation="org.intellij.sdk.language.SimpleLanguageCodeStyleSettingsProvider"/> <langCodeStyleSettingsProvider implementation="org.intellij.sdk.language.SimpleLanguageCodeStyleSettingsProvider"/>
<lang.commenter language="Simple" implementationClass="org.intellij.sdk.language.SimpleCommenter"/> <lang.commenter language="Simple" implementationClass="org.intellij.sdk.language.SimpleCommenter"/>
<lang.documentationProvider language="Simple" implementationClass="org.intellij.sdk.language.SimpleDocumentationProvider"/>
</extensions> </extensions>
</idea-plugin> </idea-plugin>