regexp: check if group name is valid

This commit is contained in:
Bas Leijdekkers
2016-08-24 19:22:47 +02:00
parent b7435455ed
commit 25b24b59df
5 changed files with 46 additions and 14 deletions
@@ -32,6 +32,16 @@ public interface RegExpLanguageHost {
boolean supportsNamedGroupRefSyntax(RegExpNamedGroupRef ref);
boolean supportsExtendedHexCharacter(RegExpChar regExpChar);
default boolean isValidGroupName(String name, @NotNull PsiElement context) {
for (int i = 0, length = name.length(); i < length; i++) {
int c = name.codePointAt(i);
if (!(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || c == '_')) {
return false;
}
}
return true;
}
default boolean supportsSimpleClass(RegExpSimpleClass simpleClass) {
return true;
}
@@ -22,6 +22,7 @@ import com.intellij.psi.PsiComment;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiLanguageInjectionHost;
import org.intellij.lang.regexp.psi.*;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
@@ -48,6 +49,7 @@ public final class RegExpLanguageHosts extends ClassExtension<RegExpLanguageHost
myHost = host;
}
@Contract("null -> null")
@Nullable
private static RegExpLanguageHost findRegExpHost(@Nullable final PsiElement element) {
if (ApplicationManager.getApplication().isUnitTestMode() && myHost != null) {
@@ -115,6 +117,11 @@ public final class RegExpLanguageHosts extends ClassExtension<RegExpLanguageHost
}
}
public boolean isValidGroupName(String name, @Nullable final PsiElement context) {
final RegExpLanguageHost host = findRegExpHost(context);
return host != null && host.isValidGroupName(name, context);
}
public boolean supportsPerl5EmbeddedComments(@Nullable final PsiComment comment) {
final RegExpLanguageHost host = findRegExpHost(comment);
return host != null && host.supportsPerl5EmbeddedComments();
@@ -222,10 +222,7 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
}
if(!myLanguageHosts.isValidCategory(category.getPsi(), category.getText())) {
final Annotation a = myHolder.createErrorAnnotation(category, "Unknown character category");
if (a != null) {
// IDEA-9381
a.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
}
a.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
}
}
@@ -234,10 +231,7 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
final RegExpGroup group = backref.resolve();
if (group == null) {
final Annotation a = myHolder.createErrorAnnotation(backref, "Unresolved back reference");
if (a != null) {
// IDEA-9381
a.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
}
a.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
}
else if (PsiTreeUtil.isAncestor(group, backref, true)) {
myHolder.createWarningAnnotation(backref, "Back reference is nested into the capturing group it refers to");
@@ -277,6 +271,11 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
myHolder.createErrorAnnotation(group, "This named group syntax is not supported");
}
}
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");
}
}
@Override
@@ -291,9 +290,8 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
final RegExpGroup group = groupRef.resolve();
if (group == null) {
final ASTNode node = groupRef.getNode().findChildByType(RegExpTT.NAME);
final Annotation a = myHolder.createErrorAnnotation(node, "Unresolved named group reference");
if (a != null) {
// IDEA-9381
if (node != null) {
final Annotation a = myHolder.createErrorAnnotation(node, "Unresolved named group reference");
a.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
}
}
@@ -383,9 +381,7 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
final String className = posixBracketExpression.getClassName();
if (!POSIX_CHARACTER_CLASSES.contains(className)) {
final Annotation annotation = myHolder.createErrorAnnotation(posixBracketExpression, "Unknown POSIX character class");
if (annotation != null) {
annotation.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
}
annotation.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
}
}
+8
View File
@@ -79,6 +79,14 @@
<pattern><![CDATA[\k<<error descr="Unresolved named group reference">adsf</error>>]]></pattern>
<expected>OK</expected>
</test>
<test host="com.intellij.psi.impl.JavaRegExpHost" varify="false">
<pattern>(?&lt;important_value1&gt;\d\d)</pattern>
<expected>ERR</expected>
</test>
<test host="com.intellij.psi.impl.JavaRegExpHost" varify="false">
<pattern>(?&lt;importantValue1&gt;\d\d)</pattern>
<expected>OK</expected>
</test>
</groups>
<escapes>
<test verify="false">
@@ -164,6 +164,17 @@ public class JavaRegExpHost implements RegExpLanguageHost {
return ref.isNamedGroupRef() && hasAtLeastJdkVersion(ref, JavaSdkVersion.JDK_1_7);
}
@Override
public boolean isValidGroupName(String name, @NotNull PsiElement context) {
for (int i = 0, length = name.length(); i < length; i++) {
int c = name.codePointAt(i);
if (!(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9')) {
return false;
}
}
return true;
}
@Override
public boolean supportsExtendedHexCharacter(RegExpChar regExpChar) {
return hasAtLeastJdkVersion(regExpChar, JavaSdkVersion.JDK_1_7);