From 9486df1cc3dfe2ff2dce616d3d34d1fe2b7c89bb Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 3 Aug 2011 19:56:05 +0200 Subject: [PATCH] fix groovy reparse leaving error elements when changing from multiline string into a normal one after a method with an unfinished method call the newlines should be mNLS, not WHITESPACE --- .../groovy/lang/lexer/_GroovyLexer.java | 288 +++++++++--------- .../plugins/groovy/lang/lexer/groovy.flex | 9 +- .../lang/parser/GroovyReparseTest.groovy | 14 + .../reparse/MultilineToNormalString.txt | 141 +++++++++ .../testdata/reparse/SynchronizedRParen.txt | 4 +- .../groovy/testdata/reparse/WhileRParen.txt | 4 +- 6 files changed, 314 insertions(+), 146 deletions(-) create mode 100644 plugins/groovy/testdata/reparse/MultilineToNormalString.txt diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/_GroovyLexer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/_GroovyLexer.java index d54e47eafbf0..9c24ee6d8655 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/_GroovyLexer.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/_GroovyLexer.java @@ -1,4 +1,4 @@ -/* The following code was generated by JFlex 1.4.3 on 4/27/11 7:30 PM */ +/* The following code was generated by JFlex 1.4.3 on 8/3/11 7:36 PM */ /* * Copyright 2000-2010 JetBrains s.r.o. @@ -27,7 +27,7 @@ import org.jetbrains.annotations.NotNull; /** * This class is a scanner generated by * JFlex 1.4.3 - * on 4/27/11 7:30 PM from the specification file + * on 8/3/11 7:36 PM from the specification file * /home/peter/work/idea/tools/lexer/../../community/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/groovy.flex */ public class _GroovyLexer implements FlexLexer, GroovyTokenTypes { @@ -2035,6 +2035,87 @@ public class _GroovyLexer implements FlexLexer, GroovyTokenTypes { { return( kFINALLY ); } case 225: break; + case 84: + { yybegin(WAIT_FOR_REGEX); + return(mPLUS_ASSIGN); + } + case 226: break; + case 133: + { return( kVOID ); + } + case 227: break; + case 151: + { return( kPUBLIC ); + } + case 228: break; + case 125: + { return( kELSE ); + } + case 229: break; + case 14: + { return mSTRING_LITERAL; + } + case 230: break; + case 7: + { yybegin(WAIT_FOR_REGEX); + return(mLNOT); + } + case 231: break; + case 11: + { yybegin(WAIT_FOR_REGEX); + return(mMINUS); + } + case 232: break; + case 67: + { yypushback(1); + yybegin(WAIT_FOR_REGEX); + } + case 233: break; + case 31: + { yybegin(WAIT_FOR_REGEX); + return(mBAND); + } + case 234: break; + case 169: + { return( kIMPLEMENTS ); + } + case 235: break; + case 6: + { yybegin(WAIT_FOR_REGEX); + return(mSTAR); + } + case 236: break; + case 12: + { yybegin(WAIT_FOR_REGEX); + return(mDOT); + } + case 237: break; + case 9: + { return mNUM_INT; + } + case 238: break; + case 165: + { return( kINTERFACE ); + } + case 239: break; + case 83: + { yybegin(WAIT_FOR_REGEX); + return(mINC); + } + case 240: break; + case 160: + { return( kPACKAGE ); + } + case 241: break; + case 59: + { afterComment = YYINITIAL; + return(mWS); + } + case 242: break; + case 139: + { return( kTHROW ); + } + case 243: break; case 57: { if (!blockStack.isEmpty()) { IElementType br = blockStack.pop(); @@ -2042,92 +2123,14 @@ public class _GroovyLexer implements FlexLexer, GroovyTokenTypes { if (br.equals(mLBRACK)) yybegin(IN_TRIPLE_GSTRING); if (br.equals(mDIV)) yybegin(IN_REGEX); } + while (!braceCount.isEmpty() && mLCURLY != braceCount.peek()) { + braceCount.pop(); + } if (!braceCount.isEmpty() && mLCURLY == braceCount.peek()) { braceCount.pop(); } return mRCURLY; } - case 226: break; - case 84: - { yybegin(WAIT_FOR_REGEX); - return(mPLUS_ASSIGN); - } - case 227: break; - case 133: - { return( kVOID ); - } - case 228: break; - case 151: - { return( kPUBLIC ); - } - case 229: break; - case 125: - { return( kELSE ); - } - case 230: break; - case 14: - { return mSTRING_LITERAL; - } - case 231: break; - case 7: - { yybegin(WAIT_FOR_REGEX); - return(mLNOT); - } - case 232: break; - case 11: - { yybegin(WAIT_FOR_REGEX); - return(mMINUS); - } - case 233: break; - case 67: - { yypushback(1); - yybegin(WAIT_FOR_REGEX); - } - case 234: break; - case 31: - { yybegin(WAIT_FOR_REGEX); - return(mBAND); - } - case 235: break; - case 169: - { return( kIMPLEMENTS ); - } - case 236: break; - case 6: - { yybegin(WAIT_FOR_REGEX); - return(mSTAR); - } - case 237: break; - case 12: - { yybegin(WAIT_FOR_REGEX); - return(mDOT); - } - case 238: break; - case 9: - { return mNUM_INT; - } - case 239: break; - case 165: - { return( kINTERFACE ); - } - case 240: break; - case 83: - { yybegin(WAIT_FOR_REGEX); - return(mINC); - } - case 241: break; - case 160: - { return( kPACKAGE ); - } - case 242: break; - case 59: - { afterComment = YYINITIAL; - return(mWS); - } - case 243: break; - case 139: - { return( kTHROW ); - } case 244: break; case 93: { yybegin(WAIT_FOR_REGEX); @@ -2270,6 +2273,16 @@ public class _GroovyLexer implements FlexLexer, GroovyTokenTypes { { return( kSWITCH ); } case 271: break; + case 16: + { while (!braceCount.isEmpty() && mLCURLY != braceCount.peek()) { + braceCount.pop(); + } + if (!braceCount.isEmpty() && mLCURLY == braceCount.peek()) { + braceCount.pop(); + } + return(mRCURLY); + } + case 272: break; case 5: { if (zzStartRead == 0 || zzBuffer.subSequence(0, zzStartRead).toString().trim().length() == 0) { @@ -2279,56 +2292,56 @@ public class _GroovyLexer implements FlexLexer, GroovyTokenTypes { return(mDIV); } } - case 272: break; + case 273: break; case 90: { return mGSTRING_LITERAL; } - case 273: break; + case 274: break; case 120: { yybegin(WAIT_FOR_REGEX); return(mSL_ASSIGN); } - case 274: break; + case 275: break; case 136: { return( kFLOAT ); } - case 275: break; + case 276: break; case 46: { yypushback(1); yybegin(IN_TRIPLE_IDENT); } - case 276: break; + case 277: break; case 35: { yybegin(IN_SINGLE_DOT); return mIDENT; } - case 277: break; + case 278: break; case 119: { yybegin(WAIT_FOR_REGEX); return(mCOMPARE_TO); } - case 278: break; + case 279: break; case 81: { return( kIF ); } - case 279: break; + case 280: break; case 137: { return( kFINAL ); } - case 280: break; + case 281: break; case 102: { yybegin(WAIT_FOR_REGEX); return(mBAND_ASSIGN); } - case 281: break; + case 282: break; case 150: { return( kTHROWS ); } - case 282: break; + case 283: break; case 78: { return mNUM_FLOAT; } - case 283: break; + case 284: break; case 51: { if (blockStack.isEmpty()){ yybegin(YYINITIAL); @@ -2337,205 +2350,198 @@ public class _GroovyLexer implements FlexLexer, GroovyTokenTypes { } return mREGEX_END; } - case 284: break; + case 285: break; case 39: { blockStack.push(mLBRACK); braceCount.push(mLCURLY); yybegin(NLS_AFTER_LBRACE); return mLCURLY; } - case 285: break; + case 286: break; case 56: { blockStack.push(mLCURLY); braceCount.push(mLCURLY); yybegin(NLS_AFTER_LBRACE); return(mLCURLY); } - case 286: break; + case 287: break; case 111: { return( kINT ); } - case 287: break; + case 288: break; case 163: { return( kSTRICTFP ); } - case 288: break; + case 289: break; case 49: { yypushback(yytext().length()); gStringStack.push(mDIV); // For regexes yybegin(IN_REGEX_DOLLAR); } - case 289: break; + case 290: break; case 10: { yybegin(WAIT_FOR_REGEX); return(mPLUS); } - case 290: break; + case 291: break; case 161: { return( kABSTRACT ); } - case 291: break; + case 292: break; case 138: { return( kFALSE ); } - case 292: break; + case 293: break; case 42: { yybegin(IN_SINGLE_GSTRING_DOLLAR); return mDOLLAR; } - case 293: break; + case 294: break; case 27: { yybegin(WAIT_FOR_REGEX); return(mBNOT); } - case 294: break; + case 295: break; case 13: { yybegin(IN_SINGLE_GSTRING); gStringStack.push(mLPAREN); return mGSTRING_BEGIN; } - case 295: break; + case 296: break; case 91: { return( kAS ); } - case 296: break; + case 297: break; case 74: { yybegin(WAIT_FOR_REGEX); return(mSTAR_ASSIGN); } - case 297: break; + case 298: break; case 162: { return( kCONTINUE ); } - case 298: break; + case 299: break; case 41: { clearStacks(); yybegin(NLS_AFTER_NLS); afterComment = YYINITIAL; return mNLS; } - case 299: break; + case 300: break; case 124: { return( kLONG ); } - case 300: break; + case 301: break; case 79: { return mNUM_LONG; } - case 301: break; + case 302: break; case 140: { return( kBREAK ); } - case 302: break; + case 303: break; case 158: { return( kBOOLEAN ); } - case 303: break; + case 304: break; case 152: { return( kASSERT ); } - case 304: break; + case 305: break; case 97: { yybegin(WAIT_FOR_REGEX); return(mGE); } - case 305: break; + case 306: break; case 24: { yybegin(WAIT_FOR_REGEX); return(mCOMMA); } - case 306: break; + case 307: break; case 94: { yybegin(WAIT_FOR_REGEX); return(mEQUAL); } - case 307: break; + case 308: break; case 129: { return( kTHIS ); } - case 308: break; + case 309: break; case 61: { yybegin(NLS_AFTER_NLS); afterComment = YYINITIAL; clearStacks(); return mNLS; } - case 309: break; + case 310: break; case 159: { return( kPRIVATE ); } - case 310: break; + case 311: break; case 19: { yybegin(WAIT_FOR_REGEX); braceCount.push(mLPAREN); return(mLPAREN); } - case 311: break; + case 312: break; case 105: // lookahead expression with fixed base length zzMarkedPos = zzStartRead + 1; { yybegin(IN_TRIPLE_NLS); return mDOT; } - case 312: break; + case 313: break; case 53: { yypushback(yytext().length()); yybegin(KING_STATE_INNER_CONTENT); } - case 313: break; + case 314: break; case 144: { return( kSHORT ); } - case 314: break; + case 315: break; case 85: { yybegin(WAIT_FOR_REGEX); return(mDEC); } - case 315: break; + case 316: break; case 32: { yybegin(WAIT_FOR_REGEX); return(mSEMI); } - case 316: break; + case 317: break; case 164: { return( kVOLATILE ); } - case 317: break; + case 318: break; case 15: { yybegin(NLS_AFTER_LBRACE); braceCount.push(mLCURLY); return(mLCURLY); } - case 318: break; + case 319: break; case 33: { yybegin(WAIT_FOR_REGEX); return(mAT); } - case 319: break; + case 320: break; case 77: { return mNUM_BIG_INT; } - case 320: break; + case 321: break; case 114: { yybegin(WAIT_FOR_REGEX); return(mRANGE_EXCLUSIVE); } - case 321: break; + case 322: break; case 141: { return( kCLASS ); } - case 322: break; + case 323: break; case 71: { yybegin(WAIT_FOR_REGEX); return(mDIV_ASSIGN); } - case 323: break; - case 16: - { if (!braceCount.isEmpty() && mLCURLY == braceCount.peek()) { - braceCount.pop(); - } - return(mRCURLY); - } case 324: break; case 135: { if (blockStack.isEmpty()){ diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/groovy.flex b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/groovy.flex index 9c75ca82d259..3ab9934c03e3 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/groovy.flex +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/groovy.flex @@ -370,6 +370,9 @@ mGSTRING_LITERAL = \"\" if (br.equals(mLBRACK)) yybegin(IN_TRIPLE_GSTRING); if (br.equals(mDIV)) yybegin(IN_REGEX); } + while (!braceCount.isEmpty() && mLCURLY != braceCount.peek()) { + braceCount.pop(); + } if (!braceCount.isEmpty() && mLCURLY == braceCount.peek()) { braceCount.pop(); } @@ -633,7 +636,11 @@ mGSTRING_LITERAL = \"\" { -"}" { if (!braceCount.isEmpty() && mLCURLY == braceCount.peek()) { +"}" { + while (!braceCount.isEmpty() && mLCURLY != braceCount.peek()) { + braceCount.pop(); + } + if (!braceCount.isEmpty() && mLCURLY == braceCount.peek()) { braceCount.pop(); } return(mRCURLY); } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/GroovyReparseTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/GroovyReparseTest.groovy index 9b5b1ab0fb09..daf5d8691a49 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/GroovyReparseTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/GroovyReparseTest.groovy @@ -171,5 +171,19 @@ def foo() { }""", ";" } + public void testMultilineToNormalString() { + checkReparse ''' +class a { + def foo() { + bar(""aaa") + } + + def bar() { + zoo() + } +} +''', '\b' + } + } diff --git a/plugins/groovy/testdata/reparse/MultilineToNormalString.txt b/plugins/groovy/testdata/reparse/MultilineToNormalString.txt new file mode 100644 index 000000000000..23cf5f3e1182 --- /dev/null +++ b/plugins/groovy/testdata/reparse/MultilineToNormalString.txt @@ -0,0 +1,141 @@ +Groovy script + PsiElement(new line)('\n') + Class definition + Modifiers + + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(identifier)('a') + PsiWhiteSpace(' ') + Type definition body + PsiElement({)('{') + PsiWhiteSpace('\n ') + Method + Modifiers + PsiElement(def)('def') + PsiWhiteSpace(' ') + PsiElement(identifier)('foo') + PsiElement(()('(') + Parameter list + + PsiElement())(')') + PsiWhiteSpace(' ') + Throw clause + + Open block + PsiElement({)('{') + PsiWhiteSpace('\n ') + Method call + Reference expression + PsiElement(identifier)('bar') + Arguments + PsiElement(()('(') + Literal + PsiElement(Gstring)('""') + PsiErrorElement:',' or ')' expected + + Reference expression + PsiElement(identifier)('aaa') + PsiErrorElement:',' or ')' expected + + Compound Gstring + PsiElement(Gstring begin)('"') + PsiElement(Gstring content)(')') + PsiErrorElement:String end expected + + PsiElement(new line)('\n ') + PsiErrorElement:',' or ')' expected + + PsiElement(})('}') + PsiElement(new line)('\n\n ') + Method + Modifiers + PsiElement(def)('def') + PsiWhiteSpace(' ') + PsiElement(identifier)('bar') + PsiElement(()('(') + Parameter list + + PsiElement())(')') + PsiWhiteSpace(' ') + Throw clause + + Open block + PsiElement({)('{') + PsiWhiteSpace('\n ') + Method call + Reference expression + PsiElement(identifier)('zoo') + Arguments + PsiElement(()('(') + PsiElement())(')') + PsiElement(new line)('\n ') + PsiElement(})('}') + PsiElement(new line)('\n') + PsiElement(})('}') + PsiElement(new line)('\n') +--- +Groovy script + PsiElement(new line)('\n') + Class definition + Modifiers + + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(identifier)('a') + PsiWhiteSpace(' ') + Type definition body + PsiElement({)('{') + PsiWhiteSpace('\n ') + Method + Modifiers + PsiElement(def)('def') + PsiWhiteSpace(' ') + PsiElement(identifier)('foo') + PsiElement(()('(') + Parameter list + + PsiElement())(')') + PsiWhiteSpace(' ') + Throw clause + + Open block + PsiElement({)('{') + PsiWhiteSpace('\n ') + Method call + Reference expression + PsiElement(identifier)('bar') + Arguments + PsiElement(()('(') + Literal + PsiElement(Gstring)('"aaa"') + PsiElement())(')') + PsiElement(new line)('\n ') + PsiElement(})('}') + PsiElement(new line)('\n\n ') + Method + Modifiers + PsiElement(def)('def') + PsiWhiteSpace(' ') + PsiElement(identifier)('bar') + PsiElement(()('(') + Parameter list + + PsiElement())(')') + PsiWhiteSpace(' ') + Throw clause + + Open block + PsiElement({)('{') + PsiWhiteSpace('\n ') + Method call + Reference expression + PsiElement(identifier)('zoo') + Arguments + PsiElement(()('(') + PsiElement())(')') + PsiElement(new line)('\n ') + PsiElement(})('}') + PsiElement(new line)('\n') + PsiElement(})('}') + PsiElement(new line)('\n') \ No newline at end of file diff --git a/plugins/groovy/testdata/reparse/SynchronizedRParen.txt b/plugins/groovy/testdata/reparse/SynchronizedRParen.txt index f396c2e55a20..80a5095484a2 100644 --- a/plugins/groovy/testdata/reparse/SynchronizedRParen.txt +++ b/plugins/groovy/testdata/reparse/SynchronizedRParen.txt @@ -51,7 +51,7 @@ Groovy script PsiWhiteSpace('\n ') PsiElement(})('}') - PsiWhiteSpace('\n') + PsiElement(new line)('\n') PsiElement(})('}') --- Groovy script @@ -105,5 +105,5 @@ Groovy script PsiElement(})('}') PsiWhiteSpace('\n ') PsiElement(})('}') - PsiWhiteSpace('\n') + PsiElement(new line)('\n') PsiElement(})('}') \ No newline at end of file diff --git a/plugins/groovy/testdata/reparse/WhileRParen.txt b/plugins/groovy/testdata/reparse/WhileRParen.txt index 8231e4f642ac..5df4d40eda46 100644 --- a/plugins/groovy/testdata/reparse/WhileRParen.txt +++ b/plugins/groovy/testdata/reparse/WhileRParen.txt @@ -51,7 +51,7 @@ Groovy script PsiWhiteSpace('\n ') PsiElement(})('}') - PsiWhiteSpace('\n') + PsiElement(new line)('\n') PsiElement(})('}') --- Groovy script @@ -105,5 +105,5 @@ Groovy script PsiElement(})('}') PsiWhiteSpace('\n ') PsiElement(})('}') - PsiWhiteSpace('\n') + PsiElement(new line)('\n') PsiElement(})('}') \ No newline at end of file