/
StringValueParsing.java
152 lines (144 loc) · 4.82 KB
/
StringValueParsing.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package graphql.parser;
import graphql.Assert;
import graphql.Internal;
import graphql.i18n.I18n;
import graphql.language.SourceLocation;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Contains parsing code for the StringValue types in the grammar
*/
@Internal
public class StringValueParsing {
private final static String ESCAPED_TRIPLE_QUOTES = "\\\\\"\"\""; // ahh Java + Regex
private final static String THREE_QUOTES = "\"\"\"";
public static String parseTripleQuotedString(String strText) {
int end = strText.length() - 3;
String s = strText.substring(3, end);
s = s.replaceAll(ESCAPED_TRIPLE_QUOTES, THREE_QUOTES);
return removeIndentation(s);
}
/*
See https://github.com/facebook/graphql/pull/327/files#diff-fe406b08746616e2f5f00909488cce66R758
*/
public static String removeIndentation(String rawValue) {
String[] lines = rawValue.split("\\n");
Integer commonIndent = null;
for (int i = 0; i < lines.length; i++) {
if (i == 0) {
continue;
}
String line = lines[i];
int length = line.length();
int indent = leadingWhitespace(line);
if (indent < length) {
if (commonIndent == null || indent < commonIndent) {
commonIndent = indent;
}
}
}
List<String> lineList = new ArrayList<>(Arrays.asList(lines));
if (commonIndent != null) {
for (int i = 0; i < lineList.size(); i++) {
String line = lineList.get(i);
if (i == 0) {
continue;
}
if (line.length() > commonIndent) {
line = line.substring(commonIndent);
lineList.set(i, line);
}
}
}
while (!lineList.isEmpty()) {
String line = lineList.get(0);
if (containsOnlyWhiteSpace(line)) {
lineList.remove(0);
} else {
break;
}
}
while (!lineList.isEmpty()) {
int endIndex = lineList.size() - 1;
String line = lineList.get(endIndex);
if (containsOnlyWhiteSpace(line)) {
lineList.remove(endIndex);
} else {
break;
}
}
StringBuilder formatted = new StringBuilder();
for (int i = 0; i < lineList.size(); i++) {
String line = lineList.get(i);
if (i == 0) {
formatted.append(line);
} else {
formatted.append("\n");
formatted.append(line);
}
}
return formatted.toString();
}
private static int leadingWhitespace(String str) {
int count = 0;
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if (ch != ' ' && ch != '\t') {
break;
}
count++;
}
return count;
}
private static boolean containsOnlyWhiteSpace(String str) {
// according to graphql spec and graphql-js - this is the definition
return leadingWhitespace(str) == str.length();
}
public static String parseSingleQuotedString(I18n i18n, String string, SourceLocation sourceLocation) {
StringWriter writer = new StringWriter(string.length() - 2);
int end = string.length() - 1;
for (int i = 1; i < end; i++) {
char c = string.charAt(i);
if (c != '\\') {
writer.write(c);
continue;
}
char escaped = string.charAt(i + 1);
i += 1;
switch (escaped) {
case '"':
writer.write('"');
continue;
case '/':
writer.write('/');
continue;
case '\\':
writer.write('\\');
continue;
case 'b':
writer.write('\b');
continue;
case 'f':
writer.write('\f');
continue;
case 'n':
writer.write('\n');
continue;
case 'r':
writer.write('\r');
continue;
case 't':
writer.write('\t');
continue;
case 'u':
i = UnicodeUtil.parseAndWriteUnicode(i18n, writer, string, i, sourceLocation);
continue;
default:
Assert.assertShouldNeverHappen();
}
}
return writer.toString();
}
}