WEB-14036 Cache text fragments for JSON strings in user data

This commit is contained in:
Mikhail Golubev
2014-12-10 20:47:08 +03:00
parent 5aaea9dcf8
commit 8fcea99aa2
@@ -7,6 +7,7 @@ import com.intellij.json.codeinsight.JsonStandardComplianceInspection;
import com.intellij.json.psi.*;
import com.intellij.lang.ASTNode;
import com.intellij.navigation.ItemPresentation;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
@@ -19,9 +20,12 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class JsonPsiImplUtils {
private static final Key<List<Pair<TextRange, String>>> STRING_FRAGMENTS = new Key<List<Pair<TextRange, String>>>("JSON string fragments");
@NotNull
public static String getName(@NotNull JsonProperty property) {
return StringUtil.stripQuotesAroundValue(property.getNameElement().getText());
@@ -129,56 +133,61 @@ public class JsonPsiImplUtils {
@NotNull
public static List<Pair<TextRange, String>> getTextFragments(@NotNull JsonStringLiteral literal) {
final List<Pair<TextRange, String>> result = new ArrayList<Pair<TextRange, String>>();
final String text = literal.getText();
final int length = text.length();
int pos = 1, unescapedSequenceStart = 1;
while (pos < length) {
if (text.charAt(pos) == '\\') {
if (unescapedSequenceStart != pos) {
result.add(Pair.create(new TextRange(unescapedSequenceStart, pos), text.substring(unescapedSequenceStart, pos)));
}
if (pos == length - 1) {
result.add(Pair.create(new TextRange(pos, pos + 1), "\\"));
break;
}
final char next = text.charAt(pos + 1);
switch (next) {
case '"':
case '\\':
case '/':
case 'b':
case 'f':
case 'n':
case 'r':
case 't':
final int idx = ourEscapesTable.indexOf(next);
result.add(Pair.create(new TextRange(pos, pos + 2), ourEscapesTable.substring(idx + 1, idx + 2)));
pos += 2;
List<Pair<TextRange, String>> result = literal.getUserData(STRING_FRAGMENTS);
if (result == null) {
result = new ArrayList<Pair<TextRange, String>>();
final String text = literal.getText();
final int length = text.length();
int pos = 1, unescapedSequenceStart = 1;
while (pos < length) {
if (text.charAt(pos) == '\\') {
if (unescapedSequenceStart != pos) {
result.add(Pair.create(new TextRange(unescapedSequenceStart, pos), text.substring(unescapedSequenceStart, pos)));
}
if (pos == length - 1) {
result.add(Pair.create(new TextRange(pos, pos + 1), "\\"));
break;
case 'u':
int i = pos + 2;
for (; i < pos + 6; i++) {
if (i == length || !StringUtil.isHexDigit(text.charAt(i))) {
break;
}
final char next = text.charAt(pos + 1);
switch (next) {
case '"':
case '\\':
case '/':
case 'b':
case 'f':
case 'n':
case 'r':
case 't':
final int idx = ourEscapesTable.indexOf(next);
result.add(Pair.create(new TextRange(pos, pos + 2), ourEscapesTable.substring(idx + 1, idx + 2)));
pos += 2;
break;
case 'u':
int i = pos + 2;
for (; i < pos + 6; i++) {
if (i == length || !StringUtil.isHexDigit(text.charAt(i))) {
break;
}
}
}
result.add(Pair.create(new TextRange(pos, i), text.substring(pos, i)));
pos = i;
break;
default:
result.add(Pair.create(new TextRange(pos, pos + 2), text.substring(pos, pos + 2)));
pos += 2;
result.add(Pair.create(new TextRange(pos, i), text.substring(pos, i)));
pos = i;
break;
default:
result.add(Pair.create(new TextRange(pos, pos + 2), text.substring(pos, pos + 2)));
pos += 2;
}
unescapedSequenceStart = pos;
}
else {
pos++;
}
unescapedSequenceStart = pos;
}
else {
pos++;
final int contentEnd = text.charAt(0) == text.charAt(length - 1) ? length - 1 : length;
if (unescapedSequenceStart < contentEnd) {
result.add(Pair.create(new TextRange(unescapedSequenceStart, length), text.substring(unescapedSequenceStart, contentEnd)));
}
}
final int contentEnd = text.charAt(0) == text.charAt(length - 1) ? length - 1 : length;
if (unescapedSequenceStart < contentEnd) {
result.add(Pair.create(new TextRange(unescapedSequenceStart, length), text.substring(unescapedSequenceStart, contentEnd)));
result = Collections.unmodifiableList(result);
literal.putUserData(STRING_FRAGMENTS, result);
}
return result;
}