KT-337 Can't break a line before a dot

This commit is contained in:
Nikolay Krasko
2011-11-28 12:59:16 +04:00
parent 5ad627fab9
commit 09de9bef20
6 changed files with 90 additions and 4 deletions
@@ -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;
static {
Set<IElementType> operations = new HashSet<IElementType>();
Precedence[] values = Precedence.values();
@@ -272,7 +275,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
precedence.parseHigherPrecedence(this);
while (!myBuilder.newlineBeforeCurrentToken() && atSet(precedence.getOperations())) {
while (!breakedWithNewLine() && atSet(precedence.getOperations())) {
IElementType operation = tt();
parseOperationReference();
@@ -328,7 +331,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
PsiBuilder.Marker expression = mark();
parseAtomicExpression();
while (true) {
if (myBuilder.newlineBeforeCurrentToken()) {
if (breakedWithNewLine()) {
break;
}
else if (at(LBRACKET)) {
@@ -1704,4 +1707,8 @@ public class JetExpressionParsing extends AbstractJetParsing {
protected JetParsing create(SemanticWhitespaceAwarePsiBuilder 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();
if (at(LBRACE)) {
// Because it's blocked namespace and it will be parsed as one of top level objects
firstEntry.rollbackTo();
return;
}
firstEntry.drop();
consumeIf(SEMICOLON);
@@ -134,6 +136,7 @@ public class JetParsing extends AbstractJetParsing {
firstEntry.rollbackTo();
}
// TODO: Duplicate with parsing imports in parseToplevelDeclarations
while (at(IMPORT_KEYWORD)) {
parseImportDirective();
}
@@ -25,27 +25,37 @@ public class SemanticWhitespaceAwarePsiBuilderImpl extends PsiBuilderAdapter imp
@Override
public boolean newlineBeforeCurrentToken() {
if (!newlinesEnabled.peek()) return false;
if (eof()) return true;
// TODO: maybe, memoize this somehow?
// TODO: maybe, memorize this somehow?
for (int i = 1; i <= getCurrentOffset(); i++) {
IElementType previousToken = rawLookup(-i);
if (previousToken == JetTokens.BLOCK_COMMENT
|| previousToken == JetTokens.DOC_COMMENT
|| previousToken == JetTokens.EOL_COMMENT) {
continue;
}
if (previousToken != TokenType.WHITE_SPACE) {
break;
}
int previousTokenStart = rawTokenTypeStart(-i);
int previousTokenEnd = rawTokenTypeStart(-i + 1);
assert previousTokenStart >= 0;
assert previousTokenEnd < getOriginalText().length();
for (int j = previousTokenStart; j < previousTokenEnd; j++) {
if (getOriginalText().charAt(j) == '\n') return true;
if (getOriginalText().charAt(j) == '\n')
return true;
}
}
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)('}')