diff --git a/python/src/com/jetbrains/python/formatter/PyBlock.java b/python/src/com/jetbrains/python/formatter/PyBlock.java index 2120bf8fb5a5..a5128b7ae6c5 100644 --- a/python/src/com/jetbrains/python/formatter/PyBlock.java +++ b/python/src/com/jetbrains/python/formatter/PyBlock.java @@ -509,21 +509,15 @@ public class PyBlock implements ASTBlock { private static boolean isWhitespaceWithLineBreaks(@Nullable ASTNode node, int minCount) { if (isWhitespace(node)) { - for (ASTNode prevNode = node.getTreePrev(); isWhitespace(prevNode); prevNode = prevNode.getTreePrev()) { - node = prevNode; - } - while (isWhitespace(node)) { - final String nodeText = node.getText(); - int count = 0; - for (int i = 0; i < nodeText.length(); i++) { - if (nodeText.charAt(i) == '\n') { - count++; - if (count == minCount) { - return true; - } + final String prevNodeText = node.getText(); + int count = 0; + for (int i = 0; i < prevNodeText.length(); i++) { + if (prevNodeText.charAt(i) == '\n') { + count++; + if (count == minCount) { + return true; } } - node = node.getTreeNext(); } } return false; diff --git a/python/src/com/jetbrains/python/lexer/PythonIndentingProcessor.java b/python/src/com/jetbrains/python/lexer/PythonIndentingProcessor.java index 4bad22c7ad76..80818476da58 100644 --- a/python/src/com/jetbrains/python/lexer/PythonIndentingProcessor.java +++ b/python/src/com/jetbrains/python/lexer/PythonIndentingProcessor.java @@ -143,6 +143,9 @@ public class PythonIndentingProcessor extends MergingLexerAdapter { if (text.charAt(i) == ' ') { spaces++; } + else if (text.charAt(i) == '\t') { + spaces += 8; + } } myCurrentNewLineIndent = spaces; } @@ -317,7 +320,8 @@ public class PythonIndentingProcessor extends MergingLexerAdapter { // line break token int end = getBaseTokenEnd(); advanceBase(); - while (getBaseTokenType() == PyTokenTypes.SPACE || (!breakStatementOnLineBreak && getBaseTokenType() == PyTokenTypes.LINE_BREAK)) { + while (getBaseTokenType() == PyTokenTypes.SPACE || getBaseTokenType() == PyTokenTypes.TAB || + (!breakStatementOnLineBreak && getBaseTokenType() == PyTokenTypes.LINE_BREAK)) { end = getBaseTokenEnd(); advanceBase(); } diff --git a/python/testData/psi/TabInsideContinuationIndent.py b/python/testData/psi/TabInsideContinuationIndent.py new file mode 100644 index 000000000000..6090700eb6f6 --- /dev/null +++ b/python/testData/psi/TabInsideContinuationIndent.py @@ -0,0 +1,3 @@ +x = { + 'foo': 42, +} \ No newline at end of file diff --git a/python/testData/psi/TabInsideContinuationIndent.txt b/python/testData/psi/TabInsideContinuationIndent.txt new file mode 100644 index 000000000000..9743c77613ed --- /dev/null +++ b/python/testData/psi/TabInsideContinuationIndent.txt @@ -0,0 +1,20 @@ +PyFile:TabInsideContinuationIndent.py + PyAssignmentStatement + PyTargetExpression: x + PsiElement(Py:IDENTIFIER)('x') + PsiWhiteSpace(' ') + PsiElement(Py:EQ)('=') + PsiWhiteSpace(' ') + PyDictLiteralExpression + PsiElement(Py:LBRACE)('{') + PsiWhiteSpace('\n\t') + PyKeyValueExpression + PyStringLiteralExpression: foo + PsiElement(Py:SINGLE_QUOTED_STRING)(''foo'') + PsiElement(Py:COLON)(':') + PsiWhiteSpace(' ') + PyNumericLiteralExpression + PsiElement(Py:INTEGER_LITERAL)('42') + PsiElement(Py:COMMA)(',') + PsiWhiteSpace('\n') + PsiElement(Py:RBRACE)('}') \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/PythonParsingTest.java b/python/testSrc/com/jetbrains/python/PythonParsingTest.java index d253db77f7c0..9bdc65e52428 100644 --- a/python/testSrc/com/jetbrains/python/PythonParsingTest.java +++ b/python/testSrc/com/jetbrains/python/PythonParsingTest.java @@ -463,6 +463,11 @@ public class PythonParsingTest extends ParsingTestCase { doTest(); } + // PY-14408 + public void testTabInsideContinuationIndent() { + doTest(); + } + public void doTest(LanguageLevel languageLevel) { LanguageLevel prev = myLanguageLevel; myLanguageLevel = languageLevel;