KT-337 Can't break a line before a dot
This commit is contained in:
@@ -178,7 +178,10 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final TokenSet ALLOW_NEWLINE_OPERATIONS = TokenSet.create(DOT, SAFE_ACCESS);
|
||||||
|
|
||||||
public static final TokenSet ALL_OPERATIONS;
|
public static final TokenSet ALL_OPERATIONS;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
Set<IElementType> operations = new HashSet<IElementType>();
|
Set<IElementType> operations = new HashSet<IElementType>();
|
||||||
Precedence[] values = Precedence.values();
|
Precedence[] values = Precedence.values();
|
||||||
@@ -272,7 +275,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
|||||||
|
|
||||||
precedence.parseHigherPrecedence(this);
|
precedence.parseHigherPrecedence(this);
|
||||||
|
|
||||||
while (!myBuilder.newlineBeforeCurrentToken() && atSet(precedence.getOperations())) {
|
while (!breakedWithNewLine() && atSet(precedence.getOperations())) {
|
||||||
IElementType operation = tt();
|
IElementType operation = tt();
|
||||||
|
|
||||||
parseOperationReference();
|
parseOperationReference();
|
||||||
@@ -328,7 +331,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
|||||||
PsiBuilder.Marker expression = mark();
|
PsiBuilder.Marker expression = mark();
|
||||||
parseAtomicExpression();
|
parseAtomicExpression();
|
||||||
while (true) {
|
while (true) {
|
||||||
if (myBuilder.newlineBeforeCurrentToken()) {
|
if (breakedWithNewLine()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (at(LBRACKET)) {
|
else if (at(LBRACKET)) {
|
||||||
@@ -1704,4 +1707,8 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
|||||||
protected JetParsing create(SemanticWhitespaceAwarePsiBuilder builder) {
|
protected JetParsing create(SemanticWhitespaceAwarePsiBuilder builder) {
|
||||||
return myJetParsing.create(builder);
|
return myJetParsing.create(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean breakedWithNewLine() {
|
||||||
|
return !ALLOW_NEWLINE_OPERATIONS.contains(tt()) && myBuilder.newlineBeforeCurrentToken();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,9 +124,11 @@ public class JetParsing extends AbstractJetParsing {
|
|||||||
parseNamespaceName();
|
parseNamespaceName();
|
||||||
|
|
||||||
if (at(LBRACE)) {
|
if (at(LBRACE)) {
|
||||||
|
// Because it's blocked namespace and it will be parsed as one of top level objects
|
||||||
firstEntry.rollbackTo();
|
firstEntry.rollbackTo();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
firstEntry.drop();
|
firstEntry.drop();
|
||||||
|
|
||||||
consumeIf(SEMICOLON);
|
consumeIf(SEMICOLON);
|
||||||
@@ -134,6 +136,7 @@ public class JetParsing extends AbstractJetParsing {
|
|||||||
firstEntry.rollbackTo();
|
firstEntry.rollbackTo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Duplicate with parsing imports in parseToplevelDeclarations
|
||||||
while (at(IMPORT_KEYWORD)) {
|
while (at(IMPORT_KEYWORD)) {
|
||||||
parseImportDirective();
|
parseImportDirective();
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-2
@@ -25,27 +25,37 @@ public class SemanticWhitespaceAwarePsiBuilderImpl extends PsiBuilderAdapter imp
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean newlineBeforeCurrentToken() {
|
public boolean newlineBeforeCurrentToken() {
|
||||||
|
|
||||||
if (!newlinesEnabled.peek()) return false;
|
if (!newlinesEnabled.peek()) return false;
|
||||||
|
|
||||||
if (eof()) return true;
|
if (eof()) return true;
|
||||||
// TODO: maybe, memoize this somehow?
|
|
||||||
|
// TODO: maybe, memorize this somehow?
|
||||||
for (int i = 1; i <= getCurrentOffset(); i++) {
|
for (int i = 1; i <= getCurrentOffset(); i++) {
|
||||||
IElementType previousToken = rawLookup(-i);
|
IElementType previousToken = rawLookup(-i);
|
||||||
|
|
||||||
if (previousToken == JetTokens.BLOCK_COMMENT
|
if (previousToken == JetTokens.BLOCK_COMMENT
|
||||||
|| previousToken == JetTokens.DOC_COMMENT
|
|| previousToken == JetTokens.DOC_COMMENT
|
||||||
|| previousToken == JetTokens.EOL_COMMENT) {
|
|| previousToken == JetTokens.EOL_COMMENT) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (previousToken != TokenType.WHITE_SPACE) {
|
if (previousToken != TokenType.WHITE_SPACE) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
int previousTokenStart = rawTokenTypeStart(-i);
|
int previousTokenStart = rawTokenTypeStart(-i);
|
||||||
int previousTokenEnd = rawTokenTypeStart(-i + 1);
|
int previousTokenEnd = rawTokenTypeStart(-i + 1);
|
||||||
|
|
||||||
assert previousTokenStart >= 0;
|
assert previousTokenStart >= 0;
|
||||||
assert previousTokenEnd < getOriginalText().length();
|
assert previousTokenEnd < getOriginalText().length();
|
||||||
|
|
||||||
for (int j = previousTokenStart; j < previousTokenEnd; j++) {
|
for (int j = previousTokenStart; j < previousTokenEnd; j++) {
|
||||||
if (getOriginalText().charAt(j) == '\n') return true;
|
if (getOriginalText().charAt(j) == '\n')
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
//KT-337 Can't break a line before a dot
|
||||||
|
|
||||||
|
class A() {
|
||||||
|
fun foo() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
val a = A()
|
||||||
|
|
||||||
|
a
|
||||||
|
|
||||||
|
.foo() // Should be a valid expression
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fun test() {
|
||||||
|
val str = ""
|
||||||
|
|
||||||
|
str
|
||||||
|
|
||||||
|
.length
|
||||||
|
|
||||||
|
str
|
||||||
|
|
||||||
|
?.length
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
JetFile: NewLinesValidOperations.jet
|
||||||
|
NAMESPACE
|
||||||
|
FUN
|
||||||
|
PsiElement(fun)('fun')
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
|
PsiElement(IDENTIFIER)('test')
|
||||||
|
VALUE_PARAMETER_LIST
|
||||||
|
PsiElement(LPAR)('(')
|
||||||
|
PsiElement(RPAR)(')')
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
|
BLOCK
|
||||||
|
PsiElement(LBRACE)('{')
|
||||||
|
PsiWhiteSpace('\n ')
|
||||||
|
PROPERTY
|
||||||
|
PsiElement(val)('val')
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
|
PsiElement(IDENTIFIER)('str')
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
|
PsiElement(EQ)('=')
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
|
STRING_TEMPLATE
|
||||||
|
PsiElement(OPEN_QUOTE)('"')
|
||||||
|
PsiElement(CLOSING_QUOTE)('"')
|
||||||
|
PsiWhiteSpace('\n\n ')
|
||||||
|
DOT_QUALIFIED_EXPRESSION
|
||||||
|
REFERENCE_EXPRESSION
|
||||||
|
PsiElement(IDENTIFIER)('str')
|
||||||
|
PsiWhiteSpace('\n\n ')
|
||||||
|
PsiElement(DOT)('.')
|
||||||
|
REFERENCE_EXPRESSION
|
||||||
|
PsiElement(IDENTIFIER)('length')
|
||||||
|
PsiWhiteSpace('\n\n ')
|
||||||
|
SAFE_ACCESS_EXPRESSION
|
||||||
|
REFERENCE_EXPRESSION
|
||||||
|
PsiElement(IDENTIFIER)('str')
|
||||||
|
PsiWhiteSpace('\n\n ')
|
||||||
|
PsiElement(SAFE_ACCESS)('?.')
|
||||||
|
REFERENCE_EXPRESSION
|
||||||
|
PsiElement(IDENTIFIER)('length')
|
||||||
|
PsiWhiteSpace('\n')
|
||||||
|
PsiElement(RBRACE)('}')
|
||||||
Reference in New Issue
Block a user