From db217b6f968a1447d020712404066d26cec76887 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 13 Jan 2010 22:17:49 +0300 Subject: [PATCH] correct parsing for 'as' in except clause (part of PY-297) --- .../com/jetbrains/python/parsing/Parsing.java | 24 +--------- .../python/parsing/StatementParsing.java | 38 +++++----------- .../python/psi/impl/PyExceptPartImpl.java | 26 ++--------- .../psi/impl/PyTryExceptStatementImpl.java | 22 +-------- python/testData/psi/TryExceptAs.py | 4 ++ python/testData/psi/TryExceptAs.txt | 45 +++++++++++++++++++ .../jetbrains/python/PythonParsingTest.java | 6 +++ 7 files changed, 73 insertions(+), 92 deletions(-) create mode 100644 python/testData/psi/TryExceptAs.py create mode 100644 python/testData/psi/TryExceptAs.txt diff --git a/python/src/com/jetbrains/python/parsing/Parsing.java b/python/src/com/jetbrains/python/parsing/Parsing.java index 8daea27a6807..900cd989b4cb 100644 --- a/python/src/com/jetbrains/python/parsing/Parsing.java +++ b/python/src/com/jetbrains/python/parsing/Parsing.java @@ -1,33 +1,13 @@ -/* - * Copyright 2005 Pythonid Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS"; BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.jetbrains.python.parsing; import com.intellij.lang.PsiBuilder; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; -import com.intellij.openapi.diagnostic.Logger; import com.jetbrains.python.psi.PyElementType; /** - * Created by IntelliJ IDEA. - * User: yole - * Date: 29.05.2005 - * Time: 11:49:33 - * To change this template use File | Settings | File Templates. + * @author yole */ public class Parsing { protected ParsingContext myContext; diff --git a/python/src/com/jetbrains/python/parsing/StatementParsing.java b/python/src/com/jetbrains/python/parsing/StatementParsing.java index 035b48a38f61..3057d7e4f574 100644 --- a/python/src/com/jetbrains/python/parsing/StatementParsing.java +++ b/python/src/com/jetbrains/python/parsing/StatementParsing.java @@ -1,19 +1,3 @@ -/* - * Copyright 2005 Pythonid Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS"; BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.jetbrains.python.parsing; import com.intellij.lang.ITokenTypeRemapper; @@ -23,8 +7,8 @@ import com.intellij.psi.tree.IElementType; import com.intellij.util.text.CharArrayUtil; import com.jetbrains.python.PyElementTypes; import com.jetbrains.python.PyTokenTypes; -import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.Nullable; import java.util.EnumSet; import java.util.Set; @@ -43,9 +27,10 @@ public class StatementParsing @NonNls protected static final String TOK_NESTED_SCOPES = "nested_scopes"; @NonNls protected static final String TOK_WITH = "with"; @NonNls protected static final String TOK_AS = "as"; + protected enum FIPH {NONE, FROM, FUTURE, IMPORT} // 'from __future__ import' phase private FIPH _from_import_phase = FIPH.NONE; - private boolean _expect_AS_kwd = false; + private boolean myExpectAsKeyword = false; protected enum FUTURE {ABSOLUTE_IMPORT, DIVISION, GENERATORS, NESTED_SCOPES, WITH_STATEMENT} protected Set myFutureFlags = EnumSet.noneOf(FUTURE.class); @@ -394,14 +379,14 @@ public class StatementParsing } } } - _expect_AS_kwd = true; // possible 'as' comes as an ident; reparse it as keyword if found + myExpectAsKeyword = true; // possible 'as' comes as an ident; reparse it as keyword if found if (builder.getTokenType() == PyTokenTypes.AS_KEYWORD) { builder.advanceLexer(); - _expect_AS_kwd = false; + myExpectAsKeyword = false; parseIdentifier(PyElementTypes.TARGET_EXPRESSION); } asMarker.done(PyElementTypes.IMPORT_ELEMENT); - _expect_AS_kwd = false; + myExpectAsKeyword = false; if (builder.getTokenType() == PyTokenTypes.COMMA) { builder.advanceLexer(); if (in_parens && builder.getTokenType() == PyTokenTypes.RPAR) { @@ -442,15 +427,15 @@ public class StatementParsing PsiBuilder.Marker marker = myBuilder.mark(); myBuilder.advanceLexer(); marker.done(PyElementTypes.REFERENCE_EXPRESSION); - boolean old_expect_AS_kwd = _expect_AS_kwd; - _expect_AS_kwd = expect_as; + boolean old_expect_AS_kwd = myExpectAsKeyword; + myExpectAsKeyword = expect_as; while (myBuilder.getTokenType() == PyTokenTypes.DOT) { marker = marker.precede(); myBuilder.advanceLexer(); checkMatches(PyTokenTypes.IDENTIFIER, "identifier expected"); marker.done(PyElementTypes.REFERENCE_EXPRESSION); } - _expect_AS_kwd = old_expect_AS_kwd; + myExpectAsKeyword = old_expect_AS_kwd; return true; } @@ -574,7 +559,8 @@ public class StatementParsing if (!getExpressionParser().parseSingleExpression(false)) { myBuilder.error("expression expected"); } - if (myBuilder.getTokenType() == PyTokenTypes.COMMA) { + myExpectAsKeyword = true; + if (myBuilder.getTokenType() == PyTokenTypes.COMMA || myBuilder.getTokenType() == PyTokenTypes.AS_KEYWORD) { myBuilder.advanceLexer(); if (!getExpressionParser().parseSingleExpression(true)) { myBuilder.error("expression expected"); @@ -689,7 +675,7 @@ public class StatementParsing } public IElementType filter(final IElementType source, final int start, final int end, final CharSequence text) { if ( - (myFutureFlags.contains(FUTURE.WITH_STATEMENT) || _expect_AS_kwd) && + (myFutureFlags.contains(FUTURE.WITH_STATEMENT) || myExpectAsKeyword) && source == PyTokenTypes.IDENTIFIER && CharArrayUtil.regionMatches(text, start, end, TOK_AS) ) { diff --git a/python/src/com/jetbrains/python/psi/impl/PyExceptPartImpl.java b/python/src/com/jetbrains/python/psi/impl/PyExceptPartImpl.java index b6398464d567..8e8403062e4c 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyExceptPartImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyExceptPartImpl.java @@ -1,34 +1,14 @@ -/* - * Copyright 2005 Pythonid Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS"; BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.jetbrains.python.psi.impl; import com.intellij.lang.ASTNode; +import com.jetbrains.python.PyElementTypes; +import com.jetbrains.python.psi.*; import com.jetbrains.python.toolbox.SingleIterable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import com.jetbrains.python.PyElementTypes; -import com.jetbrains.python.psi.*; /** - * Created by IntelliJ IDEA. - * User: yole - * Date: 02.06.2005 - * Time: 23:37:49 - * To change this template use File | Settings | File Templates. + * @author dcheryasov */ public class PyExceptPartImpl extends PyElementImpl implements PyExceptPart { public PyExceptPartImpl(ASTNode astNode) { diff --git a/python/src/com/jetbrains/python/psi/impl/PyTryExceptStatementImpl.java b/python/src/com/jetbrains/python/psi/impl/PyTryExceptStatementImpl.java index 6f87156b764d..f49827a82aba 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyTryExceptStatementImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyTryExceptStatementImpl.java @@ -1,19 +1,3 @@ -/* - * Copyright 2005 Pythonid Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS"; BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.jetbrains.python.psi.impl; import com.intellij.lang.ASTNode; @@ -26,11 +10,7 @@ import com.jetbrains.python.psi.*; import org.jetbrains.annotations.NotNull; /** - * Created by IntelliJ IDEA. - * User: yole - * Date: 02.06.2005 - * Time: 23:14:57 - * To change this template use File | Settings | File Templates. + * @author yole */ public class PyTryExceptStatementImpl extends PyPartitionedElementImpl implements PyTryExceptStatement { private static final TokenSet EXCEPT_BLOCKS = TokenSet.create(PyElementTypes.EXCEPT_PART); diff --git a/python/testData/psi/TryExceptAs.py b/python/testData/psi/TryExceptAs.py new file mode 100644 index 000000000000..1ce2dcdb5d72 --- /dev/null +++ b/python/testData/psi/TryExceptAs.py @@ -0,0 +1,4 @@ +try: + f = open('myfile.txt') +except IOError as (errno, strerror): + pass diff --git a/python/testData/psi/TryExceptAs.txt b/python/testData/psi/TryExceptAs.txt new file mode 100644 index 000000000000..4dd4d25cd7d2 --- /dev/null +++ b/python/testData/psi/TryExceptAs.txt @@ -0,0 +1,45 @@ +PyFile:TryExceptAs.py + PyTryExceptStatement + PyTryPart + PsiElement(Py:TRY_KEYWORD)('try') + PsiElement(Py:COLON)(':') + PsiWhiteSpace('\n ') + PyStatementList + PyAssignmentStatement + PyTargetExpression: f + PsiElement(Py:IDENTIFIER)('f') + PsiWhiteSpace(' ') + PsiElement(Py:EQ)('=') + PsiWhiteSpace(' ') + PyCallExpression: open + PyReferenceExpression: open + PsiElement(Py:IDENTIFIER)('open') + PyArgumentList + PsiElement(Py:LPAR)('(') + PyStringLiteralExpression: myfile.txt + PsiElement(Py:STRING_LITERAL)(''myfile.txt'') + PsiElement(Py:RPAR)(')') + PsiWhiteSpace('\n') + PyExceptPart + PsiElement(Py:EXCEPT_KEYWORD)('except') + PsiWhiteSpace(' ') + PyReferenceExpression: IOError + PsiElement(Py:IDENTIFIER)('IOError') + PsiWhiteSpace(' ') + PsiElement(Py:AS_KEYWORD)('as') + PsiWhiteSpace(' ') + PyParenthesizedExpression + PsiElement(Py:LPAR)('(') + PyTupleExpression + PyTargetExpression: errno + PsiElement(Py:IDENTIFIER)('errno') + PsiElement(Py:COMMA)(',') + PsiWhiteSpace(' ') + PyTargetExpression: strerror + PsiElement(Py:IDENTIFIER)('strerror') + PsiElement(Py:RPAR)(')') + PsiElement(Py:COLON)(':') + PsiWhiteSpace('\n ') + PyStatementList + PyPassStatement + PsiElement(Py:PASS_KEYWORD)('pass') \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/PythonParsingTest.java b/python/testSrc/com/jetbrains/python/PythonParsingTest.java index 7bfe9abdafe6..2c46f70a2a5c 100644 --- a/python/testSrc/com/jetbrains/python/PythonParsingTest.java +++ b/python/testSrc/com/jetbrains/python/PythonParsingTest.java @@ -1,6 +1,7 @@ package com.jetbrains.python; import com.intellij.testFramework.ParsingTestCase; +import com.jetbrains.python.fixtures.PyLightFixtureTestCase; /** * @author yole @@ -8,6 +9,7 @@ import com.intellij.testFramework.ParsingTestCase; public class PythonParsingTest extends ParsingTestCase { public PythonParsingTest() { super("", "py"); + PyLightFixtureTestCase.initPlatformPrefix(); } protected String getTestDataPath() { @@ -87,4 +89,8 @@ public class PythonParsingTest extends ParsingTestCase { public void testDecoratedFunction() throws Exception { doTest(true); } + + public void testTryExceptAs() throws Exception { // PY-293 + doTest(true); + } }