Skip to content

Commit aaa4110

Browse files
committed
[Lexer] Factor out diagnostics for single-quoted string literal
For readability.
1 parent 7b701d5 commit aaa4110

File tree

1 file changed

+46
-38
lines changed

1 file changed

+46
-38
lines changed

lib/Parse/Lexer.cpp

Lines changed: 46 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1737,6 +1737,51 @@ static void validateMultilineIndents(const Token &Str,
17371737
commonIndentation);
17381738
}
17391739

1740+
/// Emit diagnostics for single-quote string and suggest replacement
1741+
/// with double-quoted equivalent.
1742+
static void diagnoseSingleQuoteStringLiteral(const char *TokStart,
1743+
const char *TokEnd,
1744+
DiagnosticEngine *D) {
1745+
assert(*TokStart == '\'' && TokEnd[-1] == '\'');
1746+
if (!D)
1747+
return;
1748+
1749+
SmallString<32> replacement;
1750+
replacement.push_back('"');
1751+
const char *Ptr = TokStart + 1;
1752+
const char *OutputPtr = Ptr;
1753+
1754+
while (*Ptr++ != '\'' && Ptr < TokEnd) {
1755+
if (Ptr[-1] == '\\') {
1756+
if (*Ptr == '\'') {
1757+
replacement.append(OutputPtr, Ptr - 1);
1758+
OutputPtr = Ptr + 1;
1759+
// Un-escape single quotes.
1760+
replacement.push_back('\'');
1761+
} else if (*Ptr == '(') {
1762+
// Preserve the contents of interpolation.
1763+
Ptr = skipToEndOfInterpolatedExpression(Ptr + 1, replacement.end(),
1764+
/*IsMultiline=*/false);
1765+
assert(*Ptr == ')');
1766+
}
1767+
// Skip over escaped characters.
1768+
++Ptr;
1769+
} else if (Ptr[-1] == '"') {
1770+
replacement.append(OutputPtr, Ptr - 1);
1771+
OutputPtr = Ptr;
1772+
// Escape double quotes.
1773+
replacement.append("\\\"");
1774+
}
1775+
}
1776+
assert(Ptr == TokEnd && Ptr[-1] == '\'');
1777+
replacement.append(OutputPtr, Ptr - 1);
1778+
replacement.push_back('"');
1779+
1780+
D->diagnose(Lexer::getSourceLoc(TokStart), diag::lex_single_quote_string)
1781+
.fixItReplaceChars(Lexer::getSourceLoc(TokStart),
1782+
Lexer::getSourceLoc(TokEnd), replacement);
1783+
}
1784+
17401785
/// lexStringLiteral:
17411786
/// string_literal ::= ["]([^"\\\n\r]|character_escape)*["]
17421787
/// string_literal ::= ["]["]["].*["]["]["] - approximately
@@ -1793,46 +1838,9 @@ void Lexer::lexStringLiteral(unsigned CustomDelimiterLen) {
17931838
}
17941839

17951840
if (QuoteChar == '\'') {
1796-
// Emit diagnostics for single-quote string and suggest replacement
1797-
// with double-quoted equivalent.
17981841
assert(!IsMultilineString && CustomDelimiterLen == 0 &&
17991842
"Single quoted string cannot have custom delimitor, nor multiline");
1800-
assert(*TokStart == '\'' && CurPtr[-1] == '\'');
1801-
1802-
SmallString<32> replacement;
1803-
replacement.push_back('"');
1804-
const char *Ptr = TokStart + 1;
1805-
const char *OutputPtr = Ptr;
1806-
1807-
while (*Ptr++ != '\'') {
1808-
if (Ptr[-1] == '\\') {
1809-
if (*Ptr == '\'') {
1810-
replacement.append(OutputPtr, Ptr - 1);
1811-
OutputPtr = Ptr + 1;
1812-
// Un-escape single quotes.
1813-
replacement.push_back('\'');
1814-
} else if (*Ptr == '(') {
1815-
// Preserve the contents of interpolation.
1816-
Ptr = skipToEndOfInterpolatedExpression(Ptr + 1, replacement.end(),
1817-
/*IsMultiline=*/false);
1818-
assert(*Ptr == ')');
1819-
}
1820-
// Skip over escaped characters.
1821-
++Ptr;
1822-
} else if (Ptr[-1] == '"') {
1823-
replacement.append(OutputPtr, Ptr - 1);
1824-
OutputPtr = Ptr;
1825-
// Escape double quotes.
1826-
replacement.append("\\\"");
1827-
}
1828-
}
1829-
assert(Ptr == CurPtr);
1830-
replacement.append(OutputPtr, Ptr - 1);
1831-
replacement.push_back('"');
1832-
1833-
diagnose(TokStart, diag::lex_single_quote_string)
1834-
.fixItReplaceChars(getSourceLoc(TokStart), getSourceLoc(CurPtr),
1835-
replacement);
1843+
diagnoseSingleQuoteStringLiteral(TokStart, CurPtr, Diags);
18361844
}
18371845

18381846
if (wasErroneous)

0 commit comments

Comments
 (0)