IDEA-128176 Good code is red: Unicode supplementary character range

This commit is contained in:
Maxim.Mossienko
2015-06-24 21:27:46 +02:00
parent a5f23f4fd2
commit 29bc79f9f3
2 changed files with 44 additions and 1 deletions
@@ -21,6 +21,7 @@ import com.intellij.lang.ASTNode;
import com.intellij.lang.annotation.Annotation;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.Annotator;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiComment;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
@@ -37,6 +38,7 @@ import java.util.Set;
public final class RegExpAnnotator extends RegExpElementVisitor implements Annotator {
private static final Set<String> POSIX_CHARACTER_CLASSES = ContainerUtil.newHashSet(
"alnum", "alpha", "ascii", "blank", "cntrl", "digit", "graph", "lower", "print", "punct", "space", "upper", "word", "xdigit");
private static final String ILLEGAL_CHARACTER_RANGE_TO_FROM = "Illegal character range (to < from)";
private AnnotationHolder myHolder;
private final RegExpLanguageHosts myLanguageHosts;
@@ -65,7 +67,8 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
final Character f = ((RegExpChar)from).getValue();
if (t != null && f != null) {
if (t < f) {
myHolder.createErrorAnnotation(range, "Illegal character range (to < from)");
if (handleSurrogates(range, f, t)) return;
myHolder.createErrorAnnotation(range, ILLEGAL_CHARACTER_RANGE_TO_FROM);
}
else if (t == f) {
myHolder.createWarningAnnotation(range, "Redundant character range");
@@ -80,6 +83,30 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
}
}
private boolean handleSurrogates(RegExpCharRange range, Character f, Character t) {
// \ud800\udc00-\udbff\udfff
PsiElement prevSibling = range.getPrevSibling();
PsiElement nextSibling = range.getNextSibling();
if (prevSibling instanceof RegExpChar && nextSibling instanceof RegExpChar) {
Character prevSiblingValue = ((RegExpChar)prevSibling).getValue();
Character nextSiblingValue = ((RegExpChar)nextSibling).getValue();
if (prevSiblingValue != null && nextSiblingValue != null) {
if (Character.isSurrogatePair(prevSiblingValue, f) && Character.isSurrogatePair(t, nextSiblingValue)) {
if (Character.toCodePoint(prevSiblingValue, f) > Character.toCodePoint(t, nextSiblingValue)) {
TextRange prevSiblingRange = prevSibling.getTextRange();
TextRange nextSiblingRange = nextSibling.getTextRange();
TextRange errorRange = new TextRange(prevSiblingRange.getStartOffset(), nextSiblingRange.getEndOffset());
myHolder.createErrorAnnotation(errorRange, ILLEGAL_CHARACTER_RANGE_TO_FROM);
}
return true;
}
}
}
return false;
}
@Override
public void visitRegExpClass(RegExpClass regExpClass) {
final HashSet<Character> seen = new HashSet<Character>();
+16
View File
@@ -619,6 +619,22 @@
<pattern>[\x4a-\x3f]</pattern>
<expected>ERR</expected>
</test>
<test>
<pattern><![CDATA[[<error descr="Illegal character range (to < from)">\udbff\udfff-\ud800\udc00</error>]]]></pattern>
<expected>OK</expected>
</test>
<test>
<pattern>[\ud800\udc00-\udbff\udfff]</pattern>
<expected>OK</expected>
</test>
<test>
<pattern><![CDATA[[<error descr="Illegal character range (to < from)">z-a</error>]]]></pattern>
<expected>OK</expected>
</test>
<test>
<pattern>[a-z]</pattern>
<expected>OK</expected>
</test>
<test>
<pattern>a\Qabc?*+.))]][]\Eb</pattern>
<expected>OK</expected>