mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-154578 Unable to save settings (please restart IntelliJ Idea)
This commit is contained in:
+6
-3
@@ -33,6 +33,7 @@ import com.intellij.openapi.fileEditor.impl.text.CodeFoldingState;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
@@ -67,7 +68,8 @@ class DocumentFoldingInfo implements JDOMExternalizable, CodeFoldingState {
|
||||
@NonNls private static final String EXPANDED_ATT = "expanded";
|
||||
@NonNls private static final String MARKER_TAG = "marker";
|
||||
@NonNls private static final String DATE_ATT = "date";
|
||||
@NonNls private static final String PLACEHOLDER_ATT = "placeholder";
|
||||
@NonNls private static final String PLACEHOLDER_OLD_ATT = "placeholder";
|
||||
@NonNls private static final String PLACEHOLDER_ATT = "ph";
|
||||
|
||||
DocumentFoldingInfo(@NotNull Project project, @NotNull Document document) {
|
||||
myProject = project;
|
||||
@@ -274,7 +276,7 @@ class DocumentFoldingInfo implements JDOMExternalizable, CodeFoldingState {
|
||||
String signature = Integer.valueOf(marker.getStartOffset()) + ":" + Integer.valueOf(marker.getEndOffset());
|
||||
e.setAttribute(SIGNATURE_ATT, signature);
|
||||
String placeHolderText = fi == null ? DEFAULT_PLACEHOLDER : fi.placeHolder;
|
||||
e.setAttribute(PLACEHOLDER_ATT, placeHolderText);
|
||||
e.setAttribute(PLACEHOLDER_ATT, StringUtil.escapeIllegalXmlChars(placeHolderText));
|
||||
element.addContent(e);
|
||||
}
|
||||
}
|
||||
@@ -331,7 +333,8 @@ class DocumentFoldingInfo implements JDOMExternalizable, CodeFoldingState {
|
||||
if (start < 0 || end >= document.getTextLength() || start > end) continue;
|
||||
RangeMarker marker = document.createRangeMarker(start, end);
|
||||
myRangeMarkers.add(marker);
|
||||
String placeHolderText = e.getAttributeValue(PLACEHOLDER_ATT);
|
||||
String placeHolderText = StringUtil.unescapeIllegalXmlChars(e.getAttributeValue(PLACEHOLDER_ATT));
|
||||
if (placeHolderText == null) e.getAttributeValue(PLACEHOLDER_OLD_ATT);
|
||||
if (placeHolderText == null) placeHolderText = DEFAULT_PLACEHOLDER;
|
||||
FoldingInfo fi = new FoldingInfo(placeHolderText, expanded);
|
||||
marker.putUserData(FOLDING_INFO_KEY, fi);
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.text.CharArrayUtil;
|
||||
import com.intellij.util.text.CharSequenceSubSequence;
|
||||
import com.intellij.util.text.StringFactory;
|
||||
import org.jdom.Verifier;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -2194,6 +2195,64 @@ public class StringUtil extends StringUtilRt {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Some characters are illegal in XML even as numerical character references. This method performs escaping of them
|
||||
* in a custom format, which is supposed to be unescaped on retrieving from XML using {@link #unescapeIllegalXmlChars(String)}.
|
||||
* Resulting text can be part of XML version 1.0 document.
|
||||
*
|
||||
* @see <a href="https://www.w3.org/International/questions/qa-controls">https://www.w3.org/International/questions/qa-controls</a>
|
||||
* @see Verifier#isXMLCharacter(int)
|
||||
*/
|
||||
public static String escapeIllegalXmlChars(@NotNull String text) {
|
||||
StringBuilder b = null;
|
||||
int lastPos = 0;
|
||||
for (int i = 0; i < text.length(); i++) {
|
||||
int c = text.codePointAt(i);
|
||||
if (Character.isSupplementaryCodePoint(c)) {
|
||||
//noinspection AssignmentToForLoopParameter
|
||||
i++;
|
||||
}
|
||||
if (c == '#' || !Verifier.isXMLCharacter(c)) {
|
||||
if (b == null) b = new StringBuilder(text.length() + 5); // assuming there's one 'large' char (e.g. 0xFFFF) to escape numerically
|
||||
b.append(text, lastPos, i).append('#');
|
||||
if (c != '#') b.append(Integer.toHexString(c));
|
||||
b.append('#');
|
||||
lastPos = i + 1;
|
||||
}
|
||||
}
|
||||
return b == null ? text : b.append(text, lastPos, text.length()).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #escapeIllegalXmlChars(String)
|
||||
*/
|
||||
public static String unescapeIllegalXmlChars(@NotNull String text) {
|
||||
StringBuilder b = null;
|
||||
int lastPos = 0;
|
||||
for (int i = 0; i < text.length(); i++) {
|
||||
int c = text.charAt(i);
|
||||
if (c == '#') {
|
||||
int numberEnd = text.indexOf('#', i + 1);
|
||||
if (numberEnd > 0) {
|
||||
int charCode;
|
||||
try {
|
||||
charCode = numberEnd == (i + 1) ? '#' : Integer.parseInt(text.substring(i + 1, numberEnd), 16);
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
continue;
|
||||
}
|
||||
if (b == null) b = new StringBuilder(text.length());
|
||||
b.append(text, lastPos, i);
|
||||
b.append((char) charCode);
|
||||
//noinspection AssignmentToForLoopParameter
|
||||
i = numberEnd;
|
||||
lastPos = i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return b == null ? text : b.append(text, lastPos, text.length()).toString();
|
||||
}
|
||||
|
||||
public static void quote(@NotNull final StringBuilder builder) {
|
||||
quote(builder, '\"');
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.LineSeparator;
|
||||
import com.intellij.xml.util.XmlStringUtil;
|
||||
import org.jdom.Verifier;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.nio.CharBuffer;
|
||||
@@ -492,4 +493,13 @@ public class StringUtilTest {
|
||||
assertEquals(3, StringUtil.lastIndexOf("axaxa", 'x', 0, 5));
|
||||
assertEquals(2, StringUtil.lastIndexOf("abcd", 'c', -42, 99)); // #IDEA-144968
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEscapingIllegalXmlChars() {
|
||||
for (String s : new String[]{"ab\n\0\r\tde", "\\abc\1\2\3\uFFFFdef"}) {
|
||||
String escapedText = StringUtil.escapeIllegalXmlChars(s);
|
||||
assertNull(Verifier.checkCharacterData(escapedText));
|
||||
assertEquals(s, StringUtil.unescapeIllegalXmlChars(escapedText));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user