for-in fix
authorMaxim Medvedev <maxim.medvedev@jetbrains.com>
Tue, 10 Nov 2009 14:56:04 +0000 (17:56 +0300)
committerMaxim Medvedev <maxim.medvedev@jetbrains.com>
Wed, 11 Nov 2009 10:50:41 +0000 (13:50 +0300)
plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties
plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/ForStatement.java

index 6999e58898d99bf88a9e486d73860452480c5e55..bb3efddebe0816f347dc46b4080b4fab5ebe540b 100644 (file)
@@ -298,3 +298,5 @@ groovy.like.library.found.text=Do you want to set up Groovy for module ''{0}'' \
 with found library ''{1}'' (Groovy version {2})?
 compile.groovy.files=&Compile Groovy files
 copy.groovy.files.to.output=Copy Groovy files to output as &resources
+in.expected='in' expected
+not.allowed.modifier.in.forin=Modifier ''{0}'' is not allowed here
index 1875d195ef180a98e64bff0bb97fbece780e2c98..508db407449b077c7f30d6f252b16f657b82d2f5 100644 (file)
@@ -61,6 +61,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrBreakStatem
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrContinueStatement;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrFlowInterruptingStatement;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnStatement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrForInClause;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression;
@@ -160,6 +161,9 @@ public class GroovyAnnotator implements Annotator {
     else if (element instanceof GrLiteral) {
       checkLiteral(((GrLiteral)element), holder);
     }
+    else if (element instanceof GrForInClause) {
+      checkForInClause(((GrForInClause)element), holder);
+    }
     else if (element instanceof GroovyFile) {
       final GroovyFile file = (GroovyFile)element;
       if (file.isScript()) {
@@ -181,6 +185,22 @@ public class GroovyAnnotator implements Annotator {
     }
   }
 
+  private static void checkForInClause(GrForInClause forInClause, AnnotationHolder holder) {
+    final GrVariable[] declaredVariables = forInClause.getDeclaredVariables();
+    if (declaredVariables.length < 1) return;
+    final GrVariable variable = declaredVariables[0];
+    final GrModifierList modifierList = ((GrModifierList)variable.getModifierList());
+    if (modifierList == null) return;
+    final PsiElement[] modifiers = modifierList.getModifiers();
+    for (PsiElement modifier : modifiers) {
+      if (modifier instanceof PsiAnnotation) continue;
+      final String modifierText = modifier.getText();
+      if (PsiModifier.FINAL.equals(modifierText)) continue;
+      if ("def".equals(modifierText)) continue;
+      holder.createErrorAnnotation(modifier, GroovyBundle.message("not.allowed.modifier.in.forin", modifierText));
+    }
+  }
+
   private static void checkLiteral(GrLiteral literal, AnnotationHolder holder) {
     String text = literal.getText();
     if (text.startsWith("'''")) {
index de26018560c8475973cfc1d2dcdd209663a6fee0..01dc392c3229bafe83216b5a9d490961d8d433e6 100644 (file)
@@ -22,7 +22,6 @@ import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
 import org.jetbrains.plugins.groovy.lang.parser.GroovyParser;
 import org.jetbrains.plugins.groovy.lang.parser.parsing.auxiliary.modifiers.Modifiers;
 import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.declaration.Declaration;
-import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.declaration.DeclarationStart;
 import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.expressions.StrictContextExpression;
 import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.expressions.arithmetic.ShiftExpression;
 import org.jetbrains.plugins.groovy.lang.parser.parsing.types.TypeSpec;
@@ -42,16 +41,15 @@ public class ForStatement implements GroovyElementTypes {
 
     PsiBuilder.Marker marker = builder.mark();
 
-    if (ParserUtils.getToken(builder, mSEMI) ||
-            (Declaration.parse(builder, false, parser) &&
-                    ParserUtils.getToken(builder, mSEMI))) {
+    if (ParserUtils.getToken(builder, mSEMI) || (Declaration.parse(builder, false, parser) && ParserUtils.getToken(builder, mSEMI))) {
       StrictContextExpression.parse(builder, parser);
       ParserUtils.getToken(builder, mSEMI, GroovyBundle.message("semi.expected"));
       ParserUtils.getToken(builder, mNLS);
       if (!mRPAREN.equals(builder.getTokenType())) {
         controlExpressionListParse(builder, parser);
       }
-    } else {
+    }
+    else {
       marker.rollbackTo();
       marker = builder.mark();
       controlExpressionListParse(builder, parser);
@@ -77,24 +75,23 @@ public class ForStatement implements GroovyElementTypes {
 
     while (mCOMMA.equals(builder.getTokenType())) {
 
-      if (ParserUtils.lookAhead(builder, mCOMMA, mNLS, mRPAREN) ||
-              ParserUtils.lookAhead(builder, mCOMMA, mRPAREN)) {
+      if (ParserUtils.lookAhead(builder, mCOMMA, mNLS, mRPAREN) || ParserUtils.lookAhead(builder, mCOMMA, mRPAREN)) {
         ParserUtils.getToken(builder, mCOMMA);
         builder.error(GroovyBundle.message("expression.expected"));
-      } else {
+      }
+      else {
         ParserUtils.getToken(builder, mCOMMA);
       }
       ParserUtils.getToken(builder, mNLS);
       if (!StrictContextExpression.parse(builder, parser)) {
         ParserUtils.getToken(builder, mNLS);
-        if (!mRPAREN.equals(builder.getTokenType()) &&
-                !mSEMI.equals(builder.getTokenType())) {
+        if (!mRPAREN.equals(builder.getTokenType()) && !mSEMI.equals(builder.getTokenType())) {
           builder.error(GroovyBundle.message("expression.expected"));
         }
         if (!mRPAREN.equals(builder.getTokenType()) &&
-                !mSEMI.equals(builder.getTokenType()) &&
-                !mCOMMA.equals(builder.getTokenType()) &&
-                !mNLS.equals(builder.getTokenType())) {
+            !mSEMI.equals(builder.getTokenType()) &&
+            !mCOMMA.equals(builder.getTokenType()) &&
+            !mNLS.equals(builder.getTokenType())) {
           builder.advanceLexer();
         }
       }
@@ -108,56 +105,27 @@ public class ForStatement implements GroovyElementTypes {
 
     PsiBuilder.Marker marker = builder.mark();
 
-    PsiBuilder.Marker declMarker = builder.mark();
-
-    if (ParserUtils.lookAhead(builder, mIDENT, kIN)) {
-      ParserUtils.eatElement(builder, PARAMETER);
-      declMarker.drop();
-      ParserUtils.getToken(builder, kIN);
-      if (!ShiftExpression.parse(builder, parser)) {
-        builder.error(GroovyBundle.message("expression.expected"));
-      }
-      marker.done(FOR_IN_CLAUSE);
-      return true;
+    PsiBuilder.Marker parameterMarker = builder.mark();
+    Modifiers.parse(builder, parser);
+    if (ParserUtils.lookAhead(builder, mIDENT, kIN) || ParserUtils.lookAhead(builder, mIDENT, mCOLON)) {
+      ParserUtils.getToken(builder, mIDENT);
     }
-
-    if (DeclarationStart.parse(builder, parser)) {
-      if (Modifiers.parse(builder, parser)) {
-        TypeSpec.parse(builder);
-        return singleDeclNoInitParse(builder, marker, declMarker, parser);
-      }
+    else {
+      TypeSpec.parseStrict(builder);
+      ParserUtils.getToken(builder, mIDENT, GroovyBundle.message("identifier.expected"));
     }
+    parameterMarker.done(PARAMETER);
 
-    if (TypeSpec.parse(builder)) {
-      return singleDeclNoInitParse(builder, marker, declMarker, parser);
+    if (!ParserUtils.getToken(builder, kIN) && !ParserUtils.getToken(builder, mCOLON)) {
+      builder.error(GroovyBundle.message("in.expected"));
+      marker.drop();
+      return false;
     }
 
-    declMarker.drop();
-    marker.drop();
-    return false;
-  }
-
-  private static boolean singleDeclNoInitParse(PsiBuilder builder,
-                                                         PsiBuilder.Marker marker,
-                                                         PsiBuilder.Marker declMarker, GroovyParser parser) {
-    if (ParserUtils.getToken(builder, mIDENT)) {
-      if (kIN.equals(builder.getTokenType()) || mCOLON.equals(builder.getTokenType())) {
-        declMarker.done(PARAMETER);
-        builder.advanceLexer();
-        if (!ShiftExpression.parse(builder, parser)) {
-          builder.error(GroovyBundle.message("expression.expected"));
-        }
-        marker.done(FOR_IN_CLAUSE);
-        return true;
-      } else {
-        marker.rollbackTo();
-        return false;
-      }
-    } else {
-      declMarker.drop();
-      marker.rollbackTo();
-      return false;
+    if (!ShiftExpression.parse(builder, parser)) {
+      builder.error(GroovyBundle.message("expression.expected"));
     }
+    marker.done(FOR_IN_CLAUSE);
+    return true;
   }
-
 }