port regexp to the new Annotator APIDefault

GitOrigin-RevId: 1b23390720da9f36a634303498e1ebfeff5d8d48
This commit is contained in:
Alexey Kudravtsev
2020-01-09 13:38:30 +03:00
committed by intellij-monorepo-bot
parent 096ede200d
commit 517eb36401
2 changed files with 64 additions and 67 deletions

View File

@@ -18,10 +18,7 @@ package org.intellij.lang.regexp.validation;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.lang.ASTNode;
import com.intellij.lang.annotation.Annotation;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.AnnotationSession;
import com.intellij.lang.annotation.Annotator;
import com.intellij.lang.annotation.*;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiComment;
@@ -81,7 +78,7 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
final int c = text.codePointAt(i);
if (!Character.isBmpCodePoint(c) || !myLanguageHosts.supportsInlineOptionFlag((char)c, options)) {
final int offset = options.getTextOffset() + i;
myHolder.createErrorAnnotation(new TextRange(offset, offset + 1), "Unknown inline option flag");
myHolder.newAnnotation(HighlightSeverity.ERROR, "Unknown inline option flag").range(new TextRange(offset, offset + 1)).create();
}
}
}
@@ -90,12 +87,11 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
public void visitRegExpCharRange(RegExpCharRange range) {
final RegExpChar from = range.getFrom();
final RegExpChar to = range.getTo();
if (to != null) {
checkRange(range, from.getValue(), to.getValue());
if (to == null) {
return;
}
}
private void checkRange(RegExpCharRange range, int fromCodePoint, int toCodePoint) {
int fromCodePoint = from.getValue();
int toCodePoint = to.getValue();
if (fromCodePoint == -1 || toCodePoint == -1) {
return;
}
@@ -133,14 +129,14 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
@Override
public void visitRegExpBoundary(RegExpBoundary boundary) {
if (!myLanguageHosts.supportsBoundary(boundary)) {
myHolder.createErrorAnnotation(boundary, "This boundary is not supported in this regex dialect");
myHolder.newAnnotation(HighlightSeverity.ERROR, "This boundary is not supported in this regex dialect").create();
}
}
@Override
public void visitSimpleClass(RegExpSimpleClass simpleClass) {
if (!myLanguageHosts.supportsSimpleClass(simpleClass)) {
myHolder.createErrorAnnotation(simpleClass, "Illegal/unsupported escape sequence");
myHolder.newAnnotation(HighlightSeverity.ERROR, "Illegal/unsupported escape sequence").create();
}
}
@@ -156,15 +152,15 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
final RegExpChar regExpChar = (RegExpChar)element;
final int value = regExpChar.getValue();
if (value != -1 && !seen.add(value)) {
myHolder.createWarningAnnotation(regExpChar, "Duplicate character '" + regExpChar.getText() + "' inside character class");
myHolder.newAnnotation(HighlightSeverity.WARNING, "Duplicate character '" + regExpChar.getText() + "' inside character class").range(regExpChar).create();
}
}
else if (element instanceof RegExpSimpleClass) {
final RegExpSimpleClass regExpSimpleClass = (RegExpSimpleClass)element;
final RegExpSimpleClass.Kind kind = regExpSimpleClass.getKind();
if (!seen.add(kind)) {
myHolder.createWarningAnnotation(regExpSimpleClass, "Duplicate predefined character class '" + regExpSimpleClass.getText() +
"' inside character class");
myHolder.newAnnotation(HighlightSeverity.WARNING, "Duplicate predefined character class '" + regExpSimpleClass.getText() +
"' inside character class").range(regExpSimpleClass).create();
}
}
else if (element instanceof RegExpClass) {
@@ -180,34 +176,34 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
final PsiElement child = ch.getFirstChild();
final IElementType type = child.getNode().getElementType();
if (type == StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN) {
myHolder.createErrorAnnotation(ch, "Illegal/unsupported escape sequence");
myHolder.newAnnotation(HighlightSeverity.ERROR, "Illegal/unsupported escape sequence").create();
return;
}
else if (type == RegExpTT.BAD_HEX_VALUE) {
myHolder.createErrorAnnotation(ch, "Illegal hexadecimal escape sequence");
myHolder.newAnnotation(HighlightSeverity.ERROR, "Illegal hexadecimal escape sequence").create();
return;
}
else if (type == RegExpTT.BAD_OCT_VALUE) {
myHolder.createErrorAnnotation(ch, "Illegal octal escape sequence");
myHolder.newAnnotation(HighlightSeverity.ERROR, "Illegal octal escape sequence").create();
return;
}
else if (type == StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN) {
myHolder.createErrorAnnotation(ch, "Illegal unicode escape sequence");
myHolder.newAnnotation(HighlightSeverity.ERROR, "Illegal unicode escape sequence").create();
return;
}
final String text = ch.getUnescapedText();
if (type == RegExpTT.ESC_CTRL_CHARACTER && text.equals("\\b") && !myLanguageHosts.supportsLiteralBackspace(ch)) {
myHolder.createErrorAnnotation(ch, "Illegal/unsupported escape sequence");
myHolder.newAnnotation(HighlightSeverity.ERROR, "Illegal/unsupported escape sequence").create();
}
final RegExpChar.Type charType = ch.getType();
if (charType == RegExpChar.Type.HEX || charType == RegExpChar.Type.UNICODE) {
if (ch.getValue() == -1) {
myHolder.createErrorAnnotation(ch, "Illegal unicode escape sequence");
myHolder.newAnnotation(HighlightSeverity.ERROR, "Illegal unicode escape sequence").create();
return;
}
if (text.charAt(text.length() - 1) == '}') {
if (!myLanguageHosts.supportsExtendedHexCharacter(ch)) {
myHolder.createErrorAnnotation(ch, "This hex character syntax is not supported in this regex dialect");
myHolder.newAnnotation(HighlightSeverity.ERROR, "This hex character syntax is not supported in this regex dialect").create();
}
}
}
@@ -220,27 +216,27 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
return;
}
if (!myLanguageHosts.supportsPropertySyntax(property)) {
myHolder.createErrorAnnotation(property, "Property escape sequences are not supported in this regex dialect");
myHolder.newAnnotation(HighlightSeverity.ERROR, "Property escape sequences are not supported in this regex dialect").create();
return;
}
final String propertyName = category.getText();
final ASTNode next = category.getTreeNext();
if (next == null || next.getElementType() != RegExpTT.EQ) {
if(!myLanguageHosts.isValidCategory(category.getPsi(), propertyName)) {
final Annotation a = myHolder.createErrorAnnotation(category, "Unknown character category");
a.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
myHolder.newAnnotation(HighlightSeverity.ERROR, "Unknown character category").range(category)
.highlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL).create();
}
}
else {
if(!myLanguageHosts.isValidPropertyName(category.getPsi(), propertyName)) {
final Annotation a = myHolder.createErrorAnnotation(category, "Unknown property name");
a.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
myHolder.newAnnotation(HighlightSeverity.ERROR, "Unknown property name").range(category)
.highlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL).create();
return;
}
final ASTNode valueNode = property.getValueNode();
if (valueNode != null && !myLanguageHosts.isValidPropertyValue(category.getPsi(), propertyName, valueNode.getText())) {
final Annotation a = myHolder.createErrorAnnotation(valueNode, "Unknown property value");
a.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
myHolder.newAnnotation(HighlightSeverity.ERROR, "Unknown property value").range(valueNode)
.highlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL).create();
}
}
}
@@ -248,13 +244,13 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
@Override
public void visitRegExpNamedCharacter(RegExpNamedCharacter namedCharacter) {
if (!myLanguageHosts.supportsNamedCharacters(namedCharacter)) {
myHolder.createErrorAnnotation(namedCharacter, "Named Unicode characters are not allowed in this regex dialect");
myHolder.newAnnotation(HighlightSeverity.ERROR, "Named Unicode characters are not allowed in this regex dialect").create();
}
else if (!myLanguageHosts.isValidNamedCharacter(namedCharacter)) {
final ASTNode node = namedCharacter.getNameNode();
if (node != null) {
final Annotation a = myHolder.createErrorAnnotation(node, "Unknown character name");
a.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
myHolder.newAnnotation(HighlightSeverity.ERROR, "Unknown character name").range(node)
.highlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL).create();
}
}
}
@@ -263,11 +259,11 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
public void visitRegExpBackref(final RegExpBackref backref) {
final RegExpGroup group = backref.resolve();
if (group == null) {
final Annotation a = myHolder.createErrorAnnotation(backref, "Unresolved back reference");
a.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
myHolder.newAnnotation(HighlightSeverity.ERROR, "Unresolved back reference")
.highlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL).create();
}
else if (PsiTreeUtil.isAncestor(group, backref, true)) {
myHolder.createWarningAnnotation(backref, "Back reference is nested into the capturing group it refers to");
myHolder.newAnnotation(HighlightSeverity.WARNING, "Back reference is nested into the capturing group it refers to").create();
}
}
@@ -278,7 +274,7 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
final RegExpBranch[] branches = pattern.getBranches();
if (isEmpty(branches)) {
// catches "()" as well as "(|)"
myHolder.createWarningAnnotation(group, "Empty group");
myHolder.newAnnotation(HighlightSeverity.WARNING, "Empty group").create();
}
else if (branches.length == 1) {
final RegExpAtom[] atoms = branches[0].getAtoms();
@@ -287,7 +283,7 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
if (type == RegExpGroup.Type.CAPTURING_GROUP || type == RegExpGroup.Type.ATOMIC || type == RegExpGroup.Type.NON_CAPTURING) {
final RegExpGroup innerGroup = (RegExpGroup)atoms[0];
if (group.isCapturing() == innerGroup.isCapturing()) {
myHolder.createWarningAnnotation(group, "Redundant group nesting");
myHolder.newAnnotation(HighlightSeverity.WARNING, "Redundant group nesting").create();
}
}
}
@@ -295,29 +291,29 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
}
if (group.isAnyNamedGroup()) {
if (!myLanguageHosts.supportsNamedGroupSyntax(group)) {
myHolder.createErrorAnnotation(group, "This named group syntax is not supported in this regex dialect");
myHolder.newAnnotation(HighlightSeverity.ERROR, "This named group syntax is not supported in this regex dialect").create();
}
}
if (group.getType() == RegExpGroup.Type.ATOMIC && !myLanguageHosts.supportsPossessiveQuantifiers(group)) {
myHolder.createErrorAnnotation(group, "Atomic groups are not supported in this regex dialect");
myHolder.newAnnotation(HighlightSeverity.ERROR, "Atomic groups are not supported in this regex dialect").create();
}
final String name = group.getName();
if (name != null && !myLanguageHosts.isValidGroupName(name, group)) {
final ASTNode node = group.getNode().findChildByType(RegExpTT.NAME);
if (node != null) myHolder.createErrorAnnotation(node, "Invalid group name");
if (node != null) myHolder.newAnnotation(HighlightSeverity.ERROR, "Invalid group name").range(node).create();
}
final AnnotationSession session = myHolder.getCurrentAnnotationSession();
final Map<String, RegExpGroup> namedGroups = NAMED_GROUP_MAP.get(session, new HashMap<>());
if (namedGroups.isEmpty()) session.putUserData(NAMED_GROUP_MAP, namedGroups);
if (namedGroups.put(name, group) != null) {
final ASTNode node = group.getNode().findChildByType(RegExpTT.NAME);
if (node != null) myHolder.createErrorAnnotation(node, "Group with name '" + name + "' already defined");
if (node != null) myHolder.newAnnotation(HighlightSeverity.ERROR, "Group with name '" + name + "' already defined").range(node).create();
}
final RegExpGroup.Type groupType = group.getType();
if (groupType == RegExpGroup.Type.POSITIVE_LOOKBEHIND || groupType == RegExpGroup.Type.NEGATIVE_LOOKBEHIND) {
final RegExpLanguageHost.Lookbehind support = myLanguageHosts.supportsLookbehind(group);
if (support == RegExpLanguageHost.Lookbehind.NOT_SUPPORTED) {
myHolder.createErrorAnnotation(group, "Look-behind groups are not supported in this regex dialect");
myHolder.newAnnotation(HighlightSeverity.ERROR, "Look-behind groups are not supported in this regex dialect").create();
}
else {
group.accept(new LookbehindVisitor(support, myHolder));
@@ -328,7 +324,7 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
@Override
public void visitRegExpNamedGroupRef(RegExpNamedGroupRef groupRef) {
if (!myLanguageHosts.supportsNamedGroupRefSyntax(groupRef)) {
myHolder.createErrorAnnotation(groupRef, "This named group reference syntax is not supported in this regex dialect");
myHolder.newAnnotation(HighlightSeverity.ERROR, "This named group reference syntax is not supported in this regex dialect").create();
return;
}
if (groupRef.getGroupName() == null) {
@@ -338,12 +334,12 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
if (group == null) {
final ASTNode node = groupRef.getNode().findChildByType(RegExpTT.NAME);
if (node != null) {
final Annotation a = myHolder.createErrorAnnotation(node, "Unresolved named group reference");
a.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
myHolder.newAnnotation(HighlightSeverity.ERROR, "Unresolved named group reference").range(node)
.highlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL).create();
}
}
else if (PsiTreeUtil.isAncestor(group, groupRef, true)) {
myHolder.createWarningAnnotation(groupRef, "Group reference is nested into the named group it refers to");
myHolder.newAnnotation(HighlightSeverity.WARNING, "Group reference is nested into the named group it refers to").create();
}
}
@@ -351,7 +347,7 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
public void visitComment(@NotNull PsiComment comment) {
if (comment.getText().startsWith("(?#")) {
if (!myLanguageHosts.supportsPerl5EmbeddedComments(comment)) {
myHolder.createErrorAnnotation(comment, "Embedded comments are not supported in this regex dialect");
myHolder.newAnnotation(HighlightSeverity.ERROR, "Embedded comments are not supported in this regex dialect").create();
}
}
}
@@ -359,7 +355,7 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
@Override
public void visitRegExpPyCondRef(RegExpPyCondRef condRef) {
if (!myLanguageHosts.supportsPythonConditionalRefs(condRef)) {
myHolder.createErrorAnnotation(condRef, "Conditional references are not supported in this regex dialect");
myHolder.newAnnotation(HighlightSeverity.ERROR, "Conditional references are not supported in this regex dialect").create();
}
}
@@ -375,7 +371,7 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
@Override
public void visitRegExpClosure(RegExpClosure closure) {
if (closure.getAtom() instanceof RegExpSetOptions) {
myHolder.createErrorAnnotation(closure.getQuantifier(), "Dangling metacharacter");
myHolder.newAnnotation(HighlightSeverity.ERROR, "Dangling metacharacter").range(closure.getQuantifier()).create();
}
}
@@ -388,50 +384,50 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
final String max = maxElement == null ? "" : maxElement.getText();
if (!max.isEmpty() && max.equals(min)) {
if ("1".equals(max)) {
final Annotation a = myHolder.createWeakWarningAnnotation(quantifier, "Single repetition");
registerFix(a, new SimplifyQuantifierAction(quantifier, null));
myHolder.newAnnotation(HighlightSeverity.WEAK_WARNING, "Single repetition")
.withFix(new SimplifyQuantifierAction(quantifier, null)).create();
}
else {
final ASTNode node = quantifier.getNode();
if (node.findChildByType(RegExpTT.COMMA) != null) {
final Annotation a = myHolder.createWeakWarningAnnotation(quantifier, "Fixed repetition range");
registerFix(a, new SimplifyQuantifierAction(quantifier, "{" + max + "}"));
myHolder.newAnnotation(HighlightSeverity.WEAK_WARNING, "Fixed repetition range")
.withFix(new SimplifyQuantifierAction(quantifier, "{" + max + "}")).create();
}
}
}
else if (("0".equals(min) || min.isEmpty()) && "1".equals(max)) {
final Annotation a = myHolder.createWeakWarningAnnotation(quantifier, "Repetition range replaceable by '?'");
registerFix(a, new SimplifyQuantifierAction(quantifier, "?"));
myHolder.newAnnotation(HighlightSeverity.WEAK_WARNING, "Repetition range replaceable by '?'")
.withFix(new SimplifyQuantifierAction(quantifier, "?")).create();
}
else if (("0".equals(min) || min.isEmpty()) && max.isEmpty()) {
final Annotation a = myHolder.createWeakWarningAnnotation(quantifier, "Repetition range replaceable by '*'");
registerFix(a, new SimplifyQuantifierAction(quantifier, "*"));
myHolder.newAnnotation(HighlightSeverity.WEAK_WARNING, "Repetition range replaceable by '*'")
.withFix(new SimplifyQuantifierAction(quantifier, "*")).create();
}
else if ("1".equals(min) && max.isEmpty()) {
final Annotation a = myHolder.createWeakWarningAnnotation(quantifier, "Repetition range replaceable by '+'");
registerFix(a, new SimplifyQuantifierAction(quantifier, "+"));
myHolder.newAnnotation(HighlightSeverity.WEAK_WARNING, "Repetition range replaceable by '+'")
.withFix(new SimplifyQuantifierAction(quantifier, "+")).create();
}
Number minValue = null;
if (minElement != null) {
minValue = myLanguageHosts.getQuantifierValue(minElement);
if (minValue == null) myHolder.createErrorAnnotation(minElement, "Repetition value too large");
if (minValue == null) myHolder.newAnnotation(HighlightSeverity.ERROR, "Repetition value too large").range(minElement).create();
}
Number maxValue = null;
if (maxElement != null) {
maxValue= myLanguageHosts.getQuantifierValue(maxElement);
if (maxValue == null) myHolder.createErrorAnnotation(maxElement, "Repetition value too large");
if (maxValue == null) myHolder.newAnnotation(HighlightSeverity.ERROR, "Repetition value too large").range(maxElement).create();
}
if (minValue != null && maxValue != null) {
if (minValue.longValue() > maxValue.longValue() || minValue.doubleValue() > maxValue.doubleValue()) {
final TextRange range = new TextRange(minElement.getTextOffset(), maxElement.getTextOffset() + maxElement.getTextLength());
myHolder.createErrorAnnotation(range, "Illegal repetition range (min > max)");
myHolder.newAnnotation(HighlightSeverity.ERROR, "Illegal repetition range (min > max)").range(range).create();
}
}
}
if (quantifier.isPossessive() && !myLanguageHosts.supportsPossessiveQuantifiers(quantifier)) {
final ASTNode modifier = quantifier.getModifier();
assert modifier != null;
myHolder.createErrorAnnotation(modifier, "Nested quantifier in regexp");
myHolder.newAnnotation(HighlightSeverity.ERROR, "Nested quantifier in regexp").range(modifier).create();
}
}
@@ -441,8 +437,8 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
if (!POSIX_CHARACTER_CLASSES.contains(className) && !"<".equals(className) && !">".equals(className)) {
final ASTNode node = posixBracketExpression.getNode().findChildByType(RegExpTT.NAME);
if (node != null) {
final Annotation annotation = myHolder.createErrorAnnotation(node, "Unknown POSIX character class");
annotation.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
myHolder.newAnnotation(HighlightSeverity.ERROR, "Unknown POSIX character class").range(node)
.highlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL).create();
}
}
}
@@ -586,7 +582,7 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
}
public void stopAndReportError(RegExpElement element, @NotNull String message) {
myHolder.createErrorAnnotation(element, message);
myHolder.newAnnotation(HighlightSeverity.ERROR, message).range(element).create();
myStop = true;
}
}

View File

@@ -18,6 +18,7 @@ package org.intellij.plugins.intelliLang.inject.config.ui;
import com.intellij.lang.LanguageAnnotators;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.Annotator;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.util.Key;
import com.intellij.psi.PsiElement;
import org.intellij.lang.regexp.RegExpFile;
@@ -69,7 +70,7 @@ public class ValueRegExpAnnotator implements Annotator {
});
if (count[0] != 1) {
holder.createWarningAnnotation(branch, "The pattern should contain exactly one capturing group");
holder.newAnnotation(HighlightSeverity.WARNING, "The pattern should contain exactly one capturing group").range(branch).create();
}
}
}