CodeInsightUtilCore#mapBackStringRange extracted; octal escapes supported

Review ID: IDEA-CR-32724
This commit is contained in:
Tagir Valeev
2018-05-21 13:42:02 +07:00
parent cdff6032f2
commit a457452110
3 changed files with 67 additions and 43 deletions
@@ -8,7 +8,7 @@ class Foo {
@Contract("!null -> !null; <warning descr="Contract clause '!null -> null' is never satisfied as its conditions are covered by previous contracts">!null -> null</warning>")
public native String repeating(String x);
@Contract("true, false, _ -> !null; true, true, _\u0020-> null; <warning descr="Contract clause 'true, _, _ -> fail' is never satisfied as its conditions are covered by previous contracts">true, _, _ -> fail</warning>")
@Contract("true, false, _ ->\40!null; true, true,\040_\u0020-> null; <warning descr="Contract clause 'true, _, _ -> fail' is never satisfied as its conditions are covered by previous contracts">true, _, _ -> fail</warning>")
public native String booleanProblem(boolean x, boolean y, String z);
@Contract("true, false, _ -> !null; true, true, _ -> null; false, _, _ -> fail")
@@ -18,6 +18,7 @@ package com.intellij.codeInsight;
import com.intellij.lang.Language;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
@@ -212,9 +213,71 @@ public abstract class CodeInsightUtilCore extends FileModificationService {
}
}
if (sourceOffsets != null) {
sourceOffsets[outChars.length()-outOffset] = index;
sourceOffsets[outChars.length() - outOffset] = index;
}
}
return true;
}
/**
* Maps the substring range inside Java String literal value back into the source code range.
*
* @param text string literal as present in source code (including quotes)
* @param from start offset inside the represented string
* @param to end offset inside the represented string
* @return the range which represents the corresponding substring inside source representation,
* or null if from/to values are out of bounds.
*/
@Nullable
public static TextRange mapBackStringRange(@NotNull String text, int from, int to) {
if (from > to || to < 0) return null;
if (text.startsWith("`")) {
// raw string
return new TextRange(from + 1, to + 1);
}
if (!text.startsWith("\"")) {
return null;
}
if (text.indexOf('\\') == -1) {
return new TextRange(from + 1, to + 1);
}
int curOffset = 0;
int mappedFrom = -1, mappedTo = -1;
int end = text.length() - 1;
int i = 1;
while (i <= end) {
if (curOffset == from) {
mappedFrom = i;
}
if (curOffset == to) {
mappedTo = i;
break;
}
if (i == end) break;
char c = text.charAt(i++);
if (c == '\\') {
if (i == end) return null;
// like \u0020
char c1 = text.charAt(i++);
if (c1 == 'u') {
while (i < end && text.charAt(i) == 'u') i++;
i += 4;
} else if (c1 >= '0' && c1 <= '7') { // octal escape
char c2 = i < end ? text.charAt(i) : 0;
if (c2 >= '0' && c2 <= '7') {
i++;
char c3 = i < end ? text.charAt(i) : 0;
if (c3 >= '0' && c3 <= '7' && c1 <= '3') {
i++;
}
}
}
}
curOffset++;
}
if (mappedFrom >= 0 && mappedTo >= 0) {
return new TextRange(mappedFrom, mappedTo);
}
return null;
}
}
@@ -15,10 +15,7 @@
*/
package com.siyeh.ig.psiutils;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.ExpressionUtil;
import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.codeInsight.PsiEquivalenceUtil;
import com.intellij.codeInsight.*;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
@@ -1258,43 +1255,7 @@ public class ExpressionUtils {
if (expression instanceof PsiLiteralExpression) {
String value = tryCast(((PsiLiteralExpression)expression).getValue(), String.class);
if (value == null || value.length() < from || value.length() < to) return null;
String text = expression.getText();
if (text.startsWith("`")) {
// raw-string
return new TextRange(1 + from, 1 + to);
}
if (text.startsWith("\"")) {
int curOffset = 0;
int mappedFrom = -1, mappedTo = -1;
int end = text.length() - 1;
int i = 1;
while (i <= end) {
if (curOffset == from) {
mappedFrom = i;
}
if (curOffset == to) {
mappedTo = i;
break;
}
if (i == end) break;
char c = text.charAt(i);
if (c == '\\') {
i++;
if (i == end) return null;
// like \u0020
if (text.charAt(i) == 'u') {
while (i < end && text.charAt(i) == 'u') i++;
i += 3;
}
}
curOffset++;
i++;
}
if (mappedFrom >= 0 && mappedTo >= 0) {
return new TextRange(mappedFrom, mappedTo);
}
}
return null;
return CodeInsightUtilCore.mapBackStringRange(expression.getText(), from, to);
}
if (expression instanceof PsiParenthesizedExpression) {
PsiExpression operand = ((PsiParenthesizedExpression)expression).getExpression();