Skip to content
Snippets Groups Projects
Commit 68b25042 authored by Johannes Mey's avatar Johannes Mey
Browse files

extract analysis code and create line marker for nonterminal usages

parent f8d10017
No related branches found
No related tags found
No related merge requests found
......@@ -6,63 +6,31 @@ import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.Annotator;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.editor.DefaultLanguageHighlighterColors;
import com.intellij.psi.JavaResolveResult;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiJavaCodeReferenceElement;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.javadoc.PsiDocTag;
import org.jastadd.tooling.psi.RelAstGrammarTypeDecl;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import static org.jastadd.tooling.RelAstGrammarUtil.asReferenceToTypeDecl;
public class RelAstGrammarAnnotator implements Annotator {
@Override
public void annotate(@NotNull final PsiElement element, @NotNull AnnotationHolder holder) {
Optional<PsiClass> classOptional = asReferenceToTypeDecl(element);
// Ensure the Psi Element is an reference
if (!(element instanceof PsiJavaCodeReferenceElement)) {
return;
}
// Ensure the Psi element references something with a name
PsiJavaCodeReferenceElement javaCodeReferenceElement = (PsiJavaCodeReferenceElement) element;
String value = javaCodeReferenceElement.getReferenceName();
if (value == null) {
if (classOptional.isEmpty()) {
return;
}
// Ensure that the reference is valid and accessible
JavaResolveResult result = javaCodeReferenceElement.advancedResolve(true);
if (!result.isValidResult() || !result.isAccessible() || result.getElement() == null) {
return;
}
// Ensure that the reference is a Java class
PsiElement reference = result.getElement();
if (!(reference instanceof PsiClass)) {
return;
}
// Ensure that the class has a doc comment which contains the tag ast with the value node
PsiClass refClass = (PsiClass) reference;
PsiDocComment docComment = refClass.getDocComment();
if (docComment == null) {
return;
}
PsiDocTag astTag = docComment.findTagByName("ast");
if (astTag == null) {
return;
}
if (astTag.getValueElement() == null || !astTag.getValueElement().getText().equals("node")) {
return;
}
PsiDocComment docComment = classOptional.get().getDocComment();
assert docComment != null; // asReferenceToTypeDecl ensures this is not null
PsiDocTag declaredAtTag = docComment.findTagByName("declaredat");
if (declaredAtTag == null) {
......@@ -82,12 +50,6 @@ public class RelAstGrammarAnnotator implements Annotator {
.textAttributes(DefaultLanguageHighlighterColors.HIGHLIGHTED_REFERENCE)
.tooltip("<b>JastAdd Nonterminal</b><br/>Production: <i>" + production + "</i><br/><i>Declared at </i>" + declaredAt)
.create();
// Get the list of typeDecls for given key
List<RelAstGrammarTypeDecl> typeDecls = RelAstGrammarUtil.findTypeDecl(element.getProject(), value);
if (!typeDecls.isEmpty()) {
// TODO decide what to do here
}
}
}
......@@ -3,45 +3,36 @@ package org.jastadd.tooling;
import com.intellij.codeInsight.daemon.RelatedItemLineMarkerInfo;
import com.intellij.codeInsight.daemon.RelatedItemLineMarkerProvider;
import com.intellij.codeInsight.navigation.NavigationGutterIconBuilder;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiLiteralExpression;
import com.intellij.psi.impl.source.tree.java.PsiJavaTokenImpl;
import org.jastadd.tooling.psi.RelAstGrammarTypeDecl;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import static org.jastadd.tooling.RelAstGrammarUtil.asReferenceToTypeDecl;
public class RelAstGrammarLineMarkerProvider extends RelatedItemLineMarkerProvider {
@Override
protected void collectNavigationMarkers(@NotNull PsiElement element,
@NotNull Collection<? super RelatedItemLineMarkerInfo<?>> result) {
// This must be an element with a literal expression as a parent
if (!(element instanceof PsiJavaTokenImpl) || !(element.getParent() instanceof PsiLiteralExpression)) {
return;
}
// The literal expression must start with the Simple language literal expression
PsiLiteralExpression literalExpression = (PsiLiteralExpression) element.getParent();
String value = literalExpression.getValue() instanceof String ? (String) literalExpression.getValue() : null;
if ((value == null) ||
!value.startsWith(SimpleAnnotator.SIMPLE_PREFIX_STR + SimpleAnnotator.SIMPLE_SEPARATOR_STR)) {
Optional<PsiClass> classOptional = asReferenceToTypeDecl(element);
if (classOptional.isEmpty()) {
return;
}
// Get the Simple language property usage
Project project = element.getProject();
String possibleProperties = value.substring(
SimpleAnnotator.SIMPLE_PREFIX_STR.length() + SimpleAnnotator.SIMPLE_SEPARATOR_STR.length()
);
final List<SimpleProperty> properties = SimpleUtil.findProperties(project, possibleProperties);
if (properties.size() > 0) {
// Add the property to a collection of line marker info
// Get the list of typeDecls for given key
List<RelAstGrammarTypeDecl> typeDecls = RelAstGrammarUtil.findTypeDecl(element.getProject(), classOptional.get().getName());
if (!typeDecls.isEmpty()) {
NavigationGutterIconBuilder<PsiElement> builder =
NavigationGutterIconBuilder.create(SimpleIcons.FILE)
.setTargets(properties)
.setTooltipText("Navigate to Simple language property");
NavigationGutterIconBuilder.create(JastAddIcons.FILE)
.setTargets(typeDecls)
.setTooltipText("Navigate to production rule for RelAst nonterminal");
result.add(builder.createLineMarkerInfo(element));
}
}
......
package org.jastadd.tooling;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.editor.DefaultLanguageHighlighterColors;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.*;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.javadoc.PsiDocTag;
import com.intellij.psi.search.FileTypeIndex;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;
import org.jastadd.tooling.psi.RelAstGrammarFile;
import org.jastadd.tooling.psi.RelAstGrammarTypeDecl;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
public class RelAstGrammarUtil {
......@@ -71,4 +76,47 @@ public class RelAstGrammarUtil {
return result;
}
public static Optional<PsiClass> asReferenceToTypeDecl(@NotNull final PsiElement element) {
// Ensure the Psi Element is an reference
if (!(element instanceof PsiJavaCodeReferenceElement)) {
return Optional.empty();
}
// Ensure the Psi element references something with a name
PsiJavaCodeReferenceElement javaCodeReferenceElement = (PsiJavaCodeReferenceElement) element;
String value = javaCodeReferenceElement.getReferenceName();
if (value == null) {
return Optional.empty();
}
// Ensure that the reference is valid and accessible
JavaResolveResult result = javaCodeReferenceElement.advancedResolve(true);
if (!result.isValidResult() || !result.isAccessible() || result.getElement() == null) {
return Optional.empty();
}
// Ensure that the reference is a Java class
PsiElement reference = result.getElement();
if (!(reference instanceof PsiClass)) {
return Optional.empty();
}
// Ensure that the class has a doc comment which contains the tag ast with the value node
PsiClass refClass = (PsiClass) reference;
PsiDocComment docComment = refClass.getDocComment();
if (docComment == null) {
return Optional.empty();
}
PsiDocTag astTag = docComment.findTagByName("ast");
if (astTag == null) {
return Optional.empty();
}
if (astTag.getValueElement() == null || !astTag.getValueElement().getText().equals("node")) {
return Optional.empty();
}
return Optional.of(refClass);
}
}
......@@ -24,6 +24,9 @@
<colorSettingsPage implementation="org.jastadd.tooling.RelAstGrammarColorSettingsPage"/>
<annotator language="JAVA" implementationClass="org.jastadd.tooling.RelAstGrammarAnnotator"/>
<codeInsight.lineMarkerProvider language="JAVA"
implementationClass="org.jastadd.tooling.RelAstGrammarLineMarkerProvider"/>
</extensions>
<actions>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment