diff --git a/json/src/com/intellij/json/psi/impl/JsonPsiImplUtils.java b/json/src/com/intellij/json/psi/impl/JsonPsiImplUtils.java index 26996a439f7a..59a112103398 100644 --- a/json/src/com/intellij/json/psi/impl/JsonPsiImplUtils.java +++ b/json/src/com/intellij/json/psi/impl/JsonPsiImplUtils.java @@ -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>> STRING_FRAGMENTS = new Key>>("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> getTextFragments(@NotNull JsonStringLiteral literal) { - final List> result = new ArrayList>(); - 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> result = literal.getUserData(STRING_FRAGMENTS); + if (result == null) { + result = new ArrayList>(); + 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; }