From 2c5c92c728c562f6dab1c2ae4346948aeb91e07c Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Fri, 17 Jun 2011 21:20:05 +0400 Subject: [PATCH] JET-114 Do not allow an anonymous initializer on the same line after 'get' of a property + 'Toggle Error Reporting' Action --- idea/src/META-INF/plugin.xml | 5 ++ .../jet/lang/parsing/JetParsing.java | 42 +++++++++---- .../actions/ToggleErrorReportingAction.java | 15 +++++ .../jet/plugin/annotations/JetPsiChecker.java | 14 ++++- .../psi/PropertiesFollowedByInitializers.jet | 26 ++++++++ idea/testData/psi/Properties_ERR.txt | 60 ++++++++++--------- 6 files changed, 122 insertions(+), 40 deletions(-) create mode 100644 idea/src/org/jetbrains/jet/plugin/actions/ToggleErrorReportingAction.java create mode 100644 idea/testData/psi/PropertiesFollowedByInitializers.jet diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index dfeb5885b21..857f5bb1d13 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -19,6 +19,11 @@ + + + + diff --git a/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java b/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java index 33069e536b2..ac23d35f30a 100644 --- a/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java +++ b/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java @@ -818,20 +818,35 @@ public class JetParsing extends AbstractJetParsing { parseTypeRef(); } - if (at(EQ)) { - advance(); // EQ - myExpressionParsing.parseExpression(); - if (!local) { - consumeIf(SEMICOLON); - } else { + if (local) { + if (at(EQ)) { + advance(); // EQ + myExpressionParsing.parseExpression(); // "val a = 1; b" must not be an infix call of b on "val ...;" } } - if (!local) { + else { + if (at(EQ)) { + advance(); // EQ + myExpressionParsing.parseExpression(); + consumeIf(SEMICOLON); + } + if (parsePropertyGetterOrSetter()) { parsePropertyGetterOrSetter(); } - consumeIf(SEMICOLON); + if (!atSet(EOL_OR_SEMICOLON, RBRACE)) { + int i = -1; + while (-i < myBuilder.getCurrentOffset() && WHITE_SPACE_OR_COMMENT_BIT_SET.contains(myBuilder.rawLookup(i))) { + i--; + } + if (myBuilder.rawLookup(i) != SEMICOLON) { + errorUntil("Property getter or setter expected", TokenSet.create(EOL_OR_SEMICOLON)); + } + } + else { + consumeIf(SEMICOLON); + } } @@ -862,8 +877,15 @@ public class JetParsing extends AbstractJetParsing { advance(); // GET_KEYWORD or SET_KEYWORD if (!at(LPAR)) { - getterOrSetter.done(PROPERTY_ACCESSOR); - return true; + // Account for Jet-114 (val a : int get {...}) + TokenSet ACCESSOR_FIRST_OR_PROPERTY_END = TokenSet.orSet(MODIFIER_KEYWORDS, TokenSet.create(LBRACKET, GET_KEYWORD, SET_KEYWORD, EOL_OR_SEMICOLON, RBRACE)); + if (!atSet(ACCESSOR_FIRST_OR_PROPERTY_END)) { + errorUntil("Accessor body expected", TokenSet.orSet(ACCESSOR_FIRST_OR_PROPERTY_END, TokenSet.create(LBRACE, LPAR, EQ))); + } + else { + getterOrSetter.done(PROPERTY_ACCESSOR); + return true; + } } myBuilder.disableNewlines(); diff --git a/idea/src/org/jetbrains/jet/plugin/actions/ToggleErrorReportingAction.java b/idea/src/org/jetbrains/jet/plugin/actions/ToggleErrorReportingAction.java new file mode 100644 index 00000000000..bb24e3cebc2 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/actions/ToggleErrorReportingAction.java @@ -0,0 +1,15 @@ +package org.jetbrains.jet.plugin.actions; + +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import org.jetbrains.jet.plugin.annotations.JetPsiChecker; + +/** + * @author yole + */ +public class ToggleErrorReportingAction extends AnAction { + @Override + public void actionPerformed(AnActionEvent e) { + JetPsiChecker.setErrorReportingEnabled(!JetPsiChecker.isErrorReportingEnabled()); + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/annotations/JetPsiChecker.java b/idea/src/org/jetbrains/jet/plugin/annotations/JetPsiChecker.java index acffda1badf..ddeb88d09de 100644 --- a/idea/src/org/jetbrains/jet/plugin/annotations/JetPsiChecker.java +++ b/idea/src/org/jetbrains/jet/plugin/annotations/JetPsiChecker.java @@ -28,6 +28,16 @@ import java.util.Set; */ public class JetPsiChecker implements Annotator { + private static volatile boolean errorReportingEnabled = true; + + public static void setErrorReportingEnabled(boolean value) { + errorReportingEnabled = value; + } + + public static boolean isErrorReportingEnabled() { + return errorReportingEnabled; + } + @Override public void annotate(@NotNull PsiElement element, @NotNull final AnnotationHolder holder) { if (element instanceof JetFile) { @@ -85,7 +95,9 @@ public class JetPsiChecker implements Annotator { } }; - AnalyzingUtils.applyHandler(errorHandler, bindingContext); + if (errorReportingEnabled) { + AnalyzingUtils.applyHandler(errorHandler, bindingContext); + } highlightBackingFields(holder, file, bindingContext); diff --git a/idea/testData/psi/PropertiesFollowedByInitializers.jet b/idea/testData/psi/PropertiesFollowedByInitializers.jet new file mode 100644 index 00000000000..eaf68db97b6 --- /dev/null +++ b/idea/testData/psi/PropertiesFollowedByInitializers.jet @@ -0,0 +1,26 @@ +class Foo() { + val a : Int get = 1 + var b : Int get() = 1; set + var b1 : Int get() = 1; set {1} + val b2 : Int get + { + + } + val b3 : Int get { + return 1 + } + val b4 : Int get; { + } + + var b5 : Int get abstract set + var b6 : Int get [a] abstract set + var b7 : Int get [a] abstract {} +} + +class PublicVar() { public var foo = 0; } +class PublicVar() { public var foo = 0; var x : Int } +class PublicVar() { public var foo = 0 } +class PublicVar() { public var foo get set } +class PublicVar() { public var foo get set } + +val now: Long get() = System.currentTimeMillis(); fun foo() = now diff --git a/idea/testData/psi/Properties_ERR.txt b/idea/testData/psi/Properties_ERR.txt index 12fd9ae5008..b99669b22db 100644 --- a/idea/testData/psi/Properties_ERR.txt +++ b/idea/testData/psi/Properties_ERR.txt @@ -5,21 +5,19 @@ JetFile: Properties_ERR.jet PsiWhiteSpace(' ') PsiErrorElement:Expecting property name or receiver type PsiElement(MINUS)('-') - PsiWhiteSpace(' ') - PsiErrorElement:Expecting namespace or top level declaration - PsiElement(LBRACE)('{') - PsiErrorElement:Expecting namespace or top level declaration - PsiElement(RBRACE)('}') + PsiWhiteSpace(' ') + PsiErrorElement:Property getter or setter expected + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') PsiWhiteSpace('\n') PROPERTY PsiElement(var)('var') PsiWhiteSpace(' ') PsiElement(IDENTIFIER)('f') - PsiWhiteSpace(' ') - PsiErrorElement:Expecting namespace or top level declaration - PsiElement(LBRACE)('{') - PsiErrorElement:Expecting namespace or top level declaration - PsiElement(RBRACE)('}') + PsiWhiteSpace(' ') + PsiErrorElement:Property getter or setter expected + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') PsiWhiteSpace('\n') PROPERTY PsiElement(var)('var') @@ -70,8 +68,8 @@ JetFile: Properties_ERR.jet PsiElement(IDENTIFIER)('foo') PsiElement(DOT)('.') PsiElement(IDENTIFIER)('bar') - PsiErrorElement:Expecting namespace or top level declaration - PsiElement(DOT)('.') + PsiErrorElement:Property getter or setter expected + PsiElement(DOT)('.') PsiWhiteSpace('\n') PROPERTY PsiElement(val)('val') @@ -167,13 +165,20 @@ JetFile: Properties_ERR.jet PsiWhiteSpace('\n ') PROPERTY_ACCESSOR PsiElement(set)('set') - PsiErrorElement:Expecting namespace or top level declaration - PsiElement(RPAR)(')') - PsiWhiteSpace(' ') - PsiErrorElement:Expecting namespace or top level declaration - PsiElement(LBRACE)('{') - PsiErrorElement:Expecting namespace or top level declaration - PsiElement(RBRACE)('}') + PsiErrorElement:Accessor body expected + PsiElement(RPAR)(')') + PsiErrorElement:Expecting '(' + + PsiWhiteSpace(' ') + VALUE_PARAMETER_LIST + VALUE_PARAMETER + PsiErrorElement:Expecting parameter name + + PsiErrorElement:Expecting ')' + + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') PsiWhiteSpace('\n ') PsiErrorElement:Expecting namespace or top level declaration PsiElement(IDENTIFIER)('dfget') @@ -266,16 +271,13 @@ JetFile: Properties_ERR.jet PsiElement(IDENTIFIER)('f') PsiElement(DOT)('.') PsiElement(IDENTIFIER)('d') - PsiErrorElement:Expecting namespace or top level declaration - PsiElement(DOT)('.') - PsiErrorElement:Expecting namespace or top level declaration - PsiElement(MINUS)('-') - PsiWhiteSpace(' ') - PsiErrorElement:Expecting namespace or top level declaration - PsiElement(EQ)('=') - PsiWhiteSpace(' ') - PsiErrorElement:Expecting namespace or top level declaration - PsiElement(IDENTIFIER)('f') + PsiErrorElement:Property getter or setter expected + PsiElement(DOT)('.') + PsiElement(MINUS)('-') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('f') PsiWhiteSpace('\n\n') PROPERTY PsiElement(val)('val')