diff --git a/python/src/com/jetbrains/python/lexer/PyStringLiteralLexer.java b/python/src/com/jetbrains/python/lexer/PyStringLiteralLexer.java
index 6cfeac5af1cb..10c8c9be41cb 100644
--- a/python/src/com/jetbrains/python/lexer/PyStringLiteralLexer.java
+++ b/python/src/com/jetbrains/python/lexer/PyStringLiteralLexer.java
@@ -221,6 +221,7 @@ public class PyStringLiteralLexer extends LexerBase {
if (myBuffer.charAt(i) == '\\') {
LOG.assertTrue(myState == AFTER_FIRST_QUOTE);
i++;
+ if (myIsRaw) return i;
if (i == myBufferEnd) {
myState = AFTER_LAST_QUOTE;
return i;
@@ -282,7 +283,7 @@ public class PyStringLiteralLexer extends LexerBase {
final int quote_limit = myIsTriple ? 3 : 1;
int qcnt = 0; // count consequent quotes
while (i < myBufferEnd) { // scan to next \something
- if (myBuffer.charAt(i) == '\\') {
+ if (myBuffer.charAt(i) == '\\' && !myIsRaw) {
return i;
}
if (myState == BEFORE_FIRST_QUOTE && myBuffer.charAt(i) == myQuoteChar) {
@@ -292,7 +293,7 @@ public class PyStringLiteralLexer extends LexerBase {
qcnt = 0; // for last quote detection in the same pass
}
}
- else if (myState == AFTER_FIRST_QUOTE && myBuffer.charAt(i) == myQuoteChar) { // done?
+ else if (myState == AFTER_FIRST_QUOTE && myBuffer.charAt(i) == myQuoteChar && (!myIsRaw || myBuffer.charAt(i-1) != '\\')) { // done?
qcnt += 1;
if (qcnt == quote_limit) {
myState = AFTER_LAST_QUOTE;
diff --git a/python/testData/selectWord/escapeSequenceRaw/after1.py b/python/testData/selectWord/escapeSequenceRaw/after1.py
new file mode 100644
index 000000000000..cc34c2e72f4e
--- /dev/null
+++ b/python/testData/selectWord/escapeSequenceRaw/after1.py
@@ -0,0 +1 @@
+s = r'Hello\nWorld!'
\ No newline at end of file
diff --git a/python/testData/selectWord/escapeSequenceRaw/before.py b/python/testData/selectWord/escapeSequenceRaw/before.py
new file mode 100644
index 000000000000..7de388ad5996
--- /dev/null
+++ b/python/testData/selectWord/escapeSequenceRaw/before.py
@@ -0,0 +1 @@
+s = r'Hello\nWorld!'
\ No newline at end of file
diff --git a/python/testSrc/com/jetbrains/python/PySelectWordTest.java b/python/testSrc/com/jetbrains/python/PySelectWordTest.java
index 9321d576a925..0d043332488b 100644
--- a/python/testSrc/com/jetbrains/python/PySelectWordTest.java
+++ b/python/testSrc/com/jetbrains/python/PySelectWordTest.java
@@ -46,6 +46,10 @@ public class PySelectWordTest extends PyTestCase {
doTest();
}
+ public void testEscapeSequenceRaw() { // PY-10322
+ doTest();
+ }
+
private void doTest() {
CodeInsightTestUtil.doWordSelectionTestOnDirectory(myFixture, "selectWord/" + getTestName(true), "py");
}
diff --git a/python/testSrc/com/jetbrains/python/PyStringLiteralLexerTest.java b/python/testSrc/com/jetbrains/python/PyStringLiteralLexerTest.java
index 037eef11427e..100f84988709 100644
--- a/python/testSrc/com/jetbrains/python/PyStringLiteralLexerTest.java
+++ b/python/testSrc/com/jetbrains/python/PyStringLiteralLexerTest.java
@@ -26,4 +26,9 @@ public class PyStringLiteralLexerTest extends PyLexerTestCase {
PyLexerTestCase.doLexerTest("u\"\\N{LATIN SMALL LETTER B}\"", new PyStringLiteralLexer(PyTokenTypes.SINGLE_QUOTED_UNICODE),
"Py:SINGLE_QUOTED_UNICODE", "VALID_STRING_ESCAPE_TOKEN", "Py:SINGLE_QUOTED_UNICODE");
}
+
+ public void testRawBackslashN() {
+ PyLexerTestCase.doLexerTest("r'[\\w\\']'", new PyStringLiteralLexer(PyTokenTypes.SINGLE_QUOTED_STRING), true,
+ "r'[\\w\\']'");
+ }
}
diff --git a/python/testSrc/com/jetbrains/python/fixtures/PyLexerTestCase.java b/python/testSrc/com/jetbrains/python/fixtures/PyLexerTestCase.java
index 4ce5e3516364..aa6fc8af0ab4 100644
--- a/python/testSrc/com/jetbrains/python/fixtures/PyLexerTestCase.java
+++ b/python/testSrc/com/jetbrains/python/fixtures/PyLexerTestCase.java
@@ -35,6 +35,13 @@ public abstract class PyLexerTestCase extends PlatformLiteFixture {
}
public static void doLexerTest(String text, Lexer lexer, String... expectedTokens) {
+ doLexerTest(text, lexer, false, expectedTokens);
+ }
+
+ public static void doLexerTest(String text,
+ Lexer lexer,
+ boolean checkTokenText,
+ String... expectedTokens) {
lexer.start(text);
int idx = 0;
int tokenPos = 0;
@@ -44,13 +51,13 @@ public abstract class PyLexerTestCase extends PlatformLiteFixture {
lexer.advance();
while (lexer.getTokenType() != null) {
remainingTokens.append(",");
- remainingTokens.append(" \"").append(lexer.getTokenType().toString()).append("\"");
+ remainingTokens.append(" \"").append(checkTokenText ? lexer.getTokenText() : lexer.getTokenType().toString()).append("\"");
lexer.advance();
}
fail("Too many tokens. Following tokens: " + remainingTokens.toString());
}
assertEquals("Token offset mismatch at position " + idx, tokenPos, lexer.getTokenStart());
- String tokenName = lexer.getTokenType().toString();
+ String tokenName = checkTokenText ? lexer.getTokenText() : lexer.getTokenType().toString();
assertEquals("Token mismatch at position " + idx, expectedTokens[idx], tokenName);
idx++;
tokenPos = lexer.getTokenEnd();