diff --git a/topics/tutorials/custom_language_support/documentation_provider.md b/topics/tutorials/custom_language_support/documentation_provider.md index 3a81e3ef4..42423824e 100644 --- a/topics/tutorials/custom_language_support/documentation_provider.md +++ b/topics/tutorials/custom_language_support/documentation_provider.md @@ -6,19 +6,17 @@ A [`DocumentationProvider`](upsource:///platform/analysis-api/src/com/intellij/lang/documentation/DocumentationProvider.java) helps users by showing documentation for symbols like method calls inside the editor. -For the custom language tutorial, we’re implementing a version of this EP for the Simple Language that shows the key/value, +For the custom language tutorial, we're implementing a version of this extension point (EP) for the Simple Language that shows the key/value, the file where it is defined, and any related documentation comment. **Reference:** [](documentation.md) - ## Implement DocumentationProvider and Register the EP In the first step, we create an empty class that extends [`AbstractDocumentationProvider`](upsource:///platform/analysis-api/src/com/intellij/lang/documentation/AbstractDocumentationProvider.java) and registers it in the plugin.xml. - ```java public class SimpleDocumentationProvider extends AbstractDocumentationProvider { } ``` @@ -29,11 +27,10 @@ Make sure the class is registered in the plugin.xml between the `ex + implementationClass="org.intellij.sdk.language.SimpleDocumentationProvider"/> ``` - ## Ensure That the Correct PSI Element Is Used For the Simple Language, we consider two use-cases: @@ -47,8 +44,9 @@ we create a dummy implementation of `generateDoc()`: ```java @Override -public @Nullable String generateDoc(PsiElement element, @Nullable PsiElement originalElement) { - return super.generateDoc(element, originalElement); +public @Nullable String generateDoc(PsiElement element, + @Nullable PsiElement originalElement) { + return super.generateDoc(element, originalElement); } ``` @@ -65,7 +63,6 @@ Inside a Simple file, the situation is similar, and calling View | Qui Please refer to the Addendum below, which explains how to improve on this situation by additionally overriding `getCustomDocumentationElement()` method. - ## Extract Documentation Comments from Key/Value Definitions While `SimpleProperty` elements will provide us with their key and value, we have no direct access to a possible comment that is preceding the key/value definition. @@ -73,14 +70,14 @@ Since we would like to show this comment in the documentation as well, we need a This function will reside in the `SimpleUtil` class and will find for instance the comment preceding `apikey` in the following short example: ```text -#An application programming interface key (API key) is a unique identifier used -#to authenticate a user, developer, or calling program to an API. +#An application programming interface key (API key) is a unique identifier +#used to authenticate a user, developer, or calling program to an API. apikey=ph342m91337h4xX0r5k!11Zz! ``` The following implementation will check if there is any comment preceding a `SimpleProperty`, and if there is, it will collect all comment lines until it reaches either the previous key/value definition or the beginning of the file. -One caveat is that since we’re collecting the comment lines backwards, we need to reverse the list before joining them into a single string. +One caveat is that since we're collecting the comment lines backwards, we need to reverse the list before joining them into a single string. A simple regex is used to remove the leading hash characters and whitespaces from each line. ```java @@ -120,7 +117,7 @@ After implementing all the steps above, the IDE will show the rendered documenta We can provide implementations for additional functionality that comes with a `DocumentationProvider`. For instance, when simply hovering the mouse over the code, it also shows documentation after a short delay. -It’s not necessary that this popup show the exact same information as when calling _Quick Documentation_, but for the purpose of this tutorial, we’ll do just that. +It's not necessary that this popup show the exact same information as when calling _Quick Documentation_, but for the purpose of this tutorial, we'll do just that. ```java ``` @@ -141,7 +138,6 @@ In that case, language developers need to ensure that the correct PSI element fo In the case of Simple Language, the lookup element is already a `SimpleProperty` and no additional work needs to be done. In other circumstances, you can override `getDocumentationElementForLookupItem() `and return the correct PSI element. - ## Addendum: Choosing a Better Target Element To be able to call View | Quick Documentation for Simple properties in all places of a Java string literal, two steps are required: @@ -156,29 +152,37 @@ This allows getting documentation for a Simple property no matter where it was c ```java @Override -public @Nullable PsiElement getCustomDocumentationElement(@NotNull Editor editor, @NotNull PsiFile file, @Nullable PsiElement contextElement, int targetOffset) { - if (contextElement != null) { - // In this part the SimpleProperty element is extracted from inside a Java string - if (contextElement instanceof PsiJavaToken && ((PsiJavaToken) contextElement).getTokenType().equals(JavaTokenType.STRING_LITERAL)) { - final PsiElement parent = contextElement.getParent(); - final PsiReference[] references = parent.getReferences(); - for (PsiReference ref : references) { - if (ref instanceof SimpleReference) { - final PsiElement property = ref.resolve(); - if (property instanceof SimpleProperty) { - return property; - } - } - } - } - // In this part the SimpleProperty element is extracted when inside a .simple file - else if (contextElement.getLanguage() == SimpleLanguage.INSTANCE) { - final PsiElement property = PsiTreeUtil.getParentOfType(contextElement, SimpleProperty.class); - if (property != null) { - return property; - } - } - } - return super.getCustomDocumentationElement(editor, file, contextElement, targetOffset); +public @Nullable PsiElement getCustomDocumentationElement(@NotNull Editor editor, + @NotNull PsiFile file, + @Nullable PsiElement context, + int targetOffset) { + if (context != null) { + // In this part the SimpleProperty element + // is extracted from inside a Java string + if (context instanceof PsiJavaToken && + ((PsiJavaToken) context).getTokenType().equals(JavaTokenType.STRING_LITERAL)) { + PsiElement parent = context.getParent(); + PsiReference[] references = parent.getReferences(); + for (PsiReference ref : references) { + if (ref instanceof SimpleReference) { + PsiElement property = ref.resolve(); + if (property instanceof SimpleProperty) { + return property; + } + } + } + } + // In this part the SimpleProperty element is extracted + // when inside of a .simple file + else if (context.getLanguage() == SimpleLanguage.INSTANCE) { + PsiElement property = + PsiTreeUtil.getParentOfType(context, SimpleProperty.class); + if (property != null) { + return property; + } + } + } + return super.getCustomDocumentationElement( + editor, file, context, targetOffset); } ```