diff --git a/python/src/com/jetbrains/python/psi/ComprhForComponent.java b/python/src/com/jetbrains/python/psi/ComprhForComponent.java new file mode 100644 index 000000000000..d2c7caba3995 --- /dev/null +++ b/python/src/com/jetbrains/python/psi/ComprhForComponent.java @@ -0,0 +1,11 @@ +package com.jetbrains.python.psi; + +/** + * The "for" part of list comprehensions and generators. + * User: dcheryasov + * Date: Jul 31, 2008 + */ +public interface ComprhForComponent { + PyExpression getIteratorVariable(); + PyExpression getIteratedList(); +} diff --git a/python/src/com/jetbrains/python/psi/ComprhIfComponent.java b/python/src/com/jetbrains/python/psi/ComprhIfComponent.java new file mode 100644 index 000000000000..80136be2bdde --- /dev/null +++ b/python/src/com/jetbrains/python/psi/ComprhIfComponent.java @@ -0,0 +1,10 @@ +package com.jetbrains.python.psi; + +/** + * The "if" part of list comprehensions and generators. + * User: dcheryasov + * Date: Jul 31, 2008 + */ +public interface ComprhIfComponent { + PyExpression getTest(); +} diff --git a/python/src/com/jetbrains/python/psi/NameDefiner.java b/python/src/com/jetbrains/python/psi/NameDefiner.java index d330bbbc373b..9fd618fb9005 100644 --- a/python/src/com/jetbrains/python/psi/NameDefiner.java +++ b/python/src/com/jetbrains/python/psi/NameDefiner.java @@ -50,6 +50,10 @@ public interface NameDefiner extends PsiElement { } } + /** + * Helper iterator-over-array class. + * @param array element type + */ class ArrayIter implements Iterator { protected int my_index; @@ -78,6 +82,10 @@ public interface NameDefiner extends PsiElement { } } + /** + * Iterable that can only have one element. + * @param element type + */ class SingleIterable implements Iterable { T content; diff --git a/python/src/com/jetbrains/python/psi/PyGeneratorExpression.java b/python/src/com/jetbrains/python/psi/PyGeneratorExpression.java index c73441cd6555..04dce9b5d41a 100644 --- a/python/src/com/jetbrains/python/psi/PyGeneratorExpression.java +++ b/python/src/com/jetbrains/python/psi/PyGeneratorExpression.java @@ -16,12 +16,15 @@ package com.jetbrains.python.psi; +import java.util.List; + /** - * Created by IntelliJ IDEA. + * Generator expression PSI. * User: yole * Date: 05.06.2005 - * Time: 10:15:46 - * To change this template use File | Settings | File Templates. */ -public interface PyGeneratorExpression extends PyExpression { +public interface PyGeneratorExpression extends PyExpression, NameDefiner { + PyExpression getResultExpression(); + List getForComponents(); + List getIfComponents(); } diff --git a/python/src/com/jetbrains/python/psi/PyListCompExpression.java b/python/src/com/jetbrains/python/psi/PyListCompExpression.java index 456ae1c0a19a..07f44cb468aa 100644 --- a/python/src/com/jetbrains/python/psi/PyListCompExpression.java +++ b/python/src/com/jetbrains/python/psi/PyListCompExpression.java @@ -19,25 +19,13 @@ package com.jetbrains.python.psi; import java.util.List; /** - * Created by IntelliJ IDEA. + * List comprehension PSI. * User: yole * Date: 31.05.2005 - * Time: 23:32:57 - * To change this template use File | Settings | File Templates. */ -public interface PyListCompExpression extends PyExpression { - PyExpression getResultExpression(); - List getComponents(); +public interface PyListCompExpression extends PyExpression, NameDefiner { + PyExpression getResultExpression(); + List getForComponents(); + List getIfComponents(); - interface ListCompComponent { - } - - interface IfComponent extends ListCompComponent { - PyExpression getTest(); - } - - interface ForComponent extends ListCompComponent { - PyExpression getIteratorVariable(); - PyExpression getIteratedList(); - } } diff --git a/python/src/com/jetbrains/python/psi/PyUtil.java b/python/src/com/jetbrains/python/psi/PyUtil.java index 0096165a94b3..e47546e49ee4 100644 --- a/python/src/com/jetbrains/python/psi/PyUtil.java +++ b/python/src/com/jetbrains/python/psi/PyUtil.java @@ -27,6 +27,7 @@ import com.intellij.psi.TokenType; import com.intellij.util.IncorrectOperationException; import com.jetbrains.python.PythonLanguage; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Comparator; @@ -192,4 +193,45 @@ public class PyUtil { private static boolean isWhitespace(ASTNode node) { return node != null && node.getElementType().equals(TokenType.WHITE_SPACE); } + + + protected static List _unfoldParenExprs(T[] targets, List receiver) { + // NOTE: this proliferation of instanceofs is not very beautiful. Maybe rewrite using a visitor. + for (T exp : targets) { + if (exp instanceof PyParenthesizedExpression) { + final PyParenthesizedExpression parex = (PyParenthesizedExpression)exp; + PyExpression cont = parex.getContainedExpression(); + if (cont instanceof PyTupleExpression) { + final PyTupleExpression tupex = (PyTupleExpression)cont; + _unfoldParenExprs((T[])tupex.getElements(), receiver); + } + else receiver.add(exp); + } + else receiver.add(exp); + } + return receiver; + } + + // Poor man's catamorhpism :) + /** + * Flattens the representation of every element in targets, and puts all results together. + * Elements of every tuple nested in target item are brought to the top level: (a, (b, (c, d))) -> (a, b, c, d) + * Typical usage: flattenedParens(some_tuple.getExpressions()). + * @param targets target elements. + * @return the list of flattened expressions. + */ + @NotNull + public static List flattenedParens(T[] targets) { + return _unfoldParenExprs(targets, new ArrayList(targets.length)); + } + + // Poor man's filter + // TODO: move to a saner place + public static boolean instanceOf(Object obj, Class... possibleClasses) { + for (Class cls : possibleClasses) { + if (cls.isInstance(obj)) return true; + } + return false; + } + } diff --git a/python/src/com/jetbrains/python/psi/impl/PyAssignmentStatementImpl.java b/python/src/com/jetbrains/python/psi/impl/PyAssignmentStatementImpl.java index 4aec75047b69..effccff332b8 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyAssignmentStatementImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyAssignmentStatementImpl.java @@ -27,9 +27,6 @@ import com.jetbrains.python.psi.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.List; - /** * Created by IntelliJ IDEA. * User: yole @@ -101,27 +98,11 @@ public class PyAssignmentStatementImpl extends PyElementImpl implements PyAssign return true; } - protected static List _unfoldParenExprs(PyElement[] targets, List receiver) { - // NOTE: this proliferation of instanceofs is not very beautiful. Maybe rewrite using a visitor. - for (PyElement exp : targets) { - if (exp instanceof PyParenthesizedExpression) { - final PyParenthesizedExpression parex = (PyParenthesizedExpression)exp; - PyExpression cont = parex.getContainedExpression(); - if (cont instanceof PyTupleExpression) { - final PyTupleExpression tupex = (PyTupleExpression)cont; - _unfoldParenExprs(tupex.getElements(), receiver); - } - else receiver.add(exp); - } - else receiver.add(exp); - } - return receiver; - } - @NotNull public Iterable iterateNames() { - PyExpression[] targets = getTargets(); - return _unfoldParenExprs(targets, new ArrayList(targets.length)); + PyElement[] targets = getTargets(); + // return _unfoldParenExprs(targets, new ArrayList(targets.length)); + return PyUtil.flattenedParens(targets); } public PyElement getElementNamed(final String the_name) { diff --git a/python/src/com/jetbrains/python/psi/impl/PyComprehensionElementImpl.java b/python/src/com/jetbrains/python/psi/impl/PyComprehensionElementImpl.java new file mode 100644 index 000000000000..3fd605a8f915 --- /dev/null +++ b/python/src/com/jetbrains/python/psi/impl/PyComprehensionElementImpl.java @@ -0,0 +1,118 @@ +package com.jetbrains.python.psi.impl; + +import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; +import com.intellij.psi.tree.IElementType; +import com.jetbrains.python.PyElementTypes; +import com.jetbrains.python.PyTokenTypes; +import com.jetbrains.python.psi.*; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +/** + * Comprehension-like element base, for list comps ang generators. + * User: dcheryasov + * Date: Jul 31, 2008 + */ +public class PyComprehensionElementImpl extends PyElementImpl implements NameDefiner { + public PyComprehensionElementImpl(ASTNode astNode) { + super(astNode); + } + + /** + * In "[x+1 for x in (1,2,3)]" result expression is "x+1". + * @return result expression. + */ + public PyExpression getResultExpression() { + ASTNode[] exprs = getNode().getChildren(PyElementTypes.EXPRESSIONS); + return exprs.length == 0 ? null : (PyExpression)exprs[0].getPsi(); + } + + /** + * In "[x+1 for x in (1,2,3)]" a "for component" is "x". + * @return all "for components" + */ + public List getForComponents() { + ASTNode node = getNode().getFirstChildNode(); + List list = new ArrayList(5); + while (node != null) { + IElementType type = node.getElementType(); + ASTNode next = getNextExpression(node); + if (next == null) break; + if (type == PyTokenTypes.FOR_KEYWORD) { + ASTNode next2 = getNextExpression(next); + if (next2 == null) break; + final PyExpression variable = (PyExpression)next.getPsi(); + final PyExpression iterated = (PyExpression)next2.getPsi(); + list.add(new ComprhForComponent() { + public PyExpression getIteratorVariable() { + return variable; + } + + public PyExpression getIteratedList() { + return iterated; + } + }); + } + node = node.getTreeNext(); + } + return list; + } + + public List getIfComponents() { + ASTNode node = getNode().getFirstChildNode(); + List list = new ArrayList(5); + while (node != null) { + IElementType type = node.getElementType(); + ASTNode next = getNextExpression(node); + if (next == null) break; + if (type == PyTokenTypes.IF_KEYWORD) { + final PyExpression test = (PyExpression)next.getPsi(); + list.add(new ComprhIfComponent() { + public PyExpression getTest() { + return test; + } + }); + } + node = node.getTreeNext(); + } + return list; + } + + private static ASTNode getNextExpression(ASTNode after) { + ASTNode node = after; + do { + node = node.getTreeNext(); + } + while (node != null && !PyElementTypes.EXPRESSIONS.contains(node.getElementType())); + return node; + } + + /** + * In "[x+1 for x in (1,2,3) if x > 2]" an "if component" is "x > 2". + * @return all "if components" + */ + @NotNull + public Iterable iterateNames() { + // extract whatever names are defined in "for" components + List fors = getForComponents(); + PyElement[] for_targets = new PyElement[fors.size()]; + int i = 0; + for (ComprhForComponent for_comp : fors) { + for_targets[i] = for_comp.getIteratorVariable(); + i += 1; + } + List name_refs = PyUtil.flattenedParens(for_targets); + return name_refs; + } + + public PsiElement getElementNamed(final String the_name) { + return IterHelper.findName(iterateNames(), the_name); + } + + public boolean mustResolveOutside() { + return false; + } +} diff --git a/python/src/com/jetbrains/python/psi/impl/PyGeneratorExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyGeneratorExpressionImpl.java index 00bcfe147e03..0e6e416a51cb 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyGeneratorExpressionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyGeneratorExpressionImpl.java @@ -17,9 +17,12 @@ package com.jetbrains.python.psi.impl; import com.intellij.lang.ASTNode; -import com.jetbrains.python.psi.PyElementVisitor; -import com.jetbrains.python.psi.PyGeneratorExpression; +import com.intellij.psi.PsiElement; +import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.types.PyType; +import org.jetbrains.annotations.NotNull; + +import java.util.List; /** * Created by IntelliJ IDEA. @@ -28,7 +31,7 @@ import com.jetbrains.python.psi.types.PyType; * Time: 10:16:07 * To change this template use File | Settings | File Templates. */ -public class PyGeneratorExpressionImpl extends PyElementImpl implements PyGeneratorExpression { +public class PyGeneratorExpressionImpl extends PyComprehensionElementImpl implements PyGeneratorExpression { public PyGeneratorExpressionImpl(ASTNode astNode) { super(astNode); } @@ -41,4 +44,27 @@ public class PyGeneratorExpressionImpl extends PyElementImpl implements PyGenera public PyType getType() { return null; } + + @NotNull + public Iterable iterateNames() { + // extract whatever names are defined in "for" components + List fors = getForComponents(); + PyElement[] for_targets = new PyElement[fors.size()]; + int i = 0; + for (ComprhForComponent for_comp : fors) { + for_targets[i] = for_comp.getIteratorVariable(); + i += 1; + } + List name_refs = PyUtil.flattenedParens(for_targets); + return name_refs; + } + + public PsiElement getElementNamed(final String the_name) { + return IterHelper.findName(iterateNames(), the_name); + } + + public boolean mustResolveOutside() { + return false; + } + } diff --git a/python/src/com/jetbrains/python/psi/impl/PyImportElementImpl.java b/python/src/com/jetbrains/python/psi/impl/PyImportElementImpl.java index 5e5721e60620..72eed060384e 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyImportElementImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyImportElementImpl.java @@ -29,11 +29,9 @@ import org.jetbrains.annotations.Nullable; import java.util.List; /** - * Created by IntelliJ IDEA. + * The "import foo" or "import foo as bar" parts. * User: yole * Date: 02.06.2005 - * Time: 22:22:35 - * To change this template use File | Settings | File Templates. */ public class PyImportElementImpl extends PyElementImpl implements PyImportElement { public PyImportElementImpl(ASTNode astNode) { @@ -104,23 +102,11 @@ public class PyImportElementImpl extends PyElementImpl implements PyImportElemen public PsiElement getElementNamed(final String the_name) { PyElement named_elt = IterHelper.findName(iterateNames(), the_name); if (named_elt != null) { - PsiElement from_elt = null; - PyReferenceExpression import_ref = getImportReference(); // import what? - if (import_ref == null) return null; - String import_ref_name = import_ref.getName(); - if (import_ref_name == null) return null; // no imported name - /* - PyFromImportStatement import_from_stmt = PsiTreeUtil.getParentOfType(this, PyFromImportStatement.class); - if (import_from_stmt != null) { - PyReferenceExpression from_src = import_from_stmt.getImportSource(); - if (from_src != null) { - //return ResolveImportUtil.resolvePythonImport2(from_src, import_ref_name); - return ResolveImportUtil.resolveImportReference(import_ref); - } + PyReferenceExpression import_ref = getImportReference(); // = most qualified import name: "z" for "import x.y.z" + if (getAsName() == null) { // the match was not by target expr of "import ... as foo" + if (named_elt instanceof PyReferenceExpression) import_ref = (PyReferenceExpression)named_elt; // [part of] import ref matched + else return null; // I wonder what could have matched there? } - // else return ResolveImportUtil.resolvePythonImport2(import_ref, null); - else return ResolveImportUtil.resolveImportReference(import_ref); - */ return ResolveImportUtil.resolveImportReference(import_ref); } // no element of this name diff --git a/python/src/com/jetbrains/python/psi/impl/PyListCompExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyListCompExpressionImpl.java index eeb7dec87506..6e5a95b31751 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyListCompExpressionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyListCompExpressionImpl.java @@ -20,18 +20,11 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; import com.intellij.psi.ResolveState; import com.intellij.psi.scope.PsiScopeProcessor; -import com.intellij.psi.tree.IElementType; -import org.jetbrains.annotations.NotNull; -import com.jetbrains.python.PyElementTypes; -import com.jetbrains.python.PyTokenTypes; -import com.jetbrains.python.psi.PsiCached; +import com.jetbrains.python.psi.ComprhForComponent; import com.jetbrains.python.psi.PyElementVisitor; -import com.jetbrains.python.psi.PyExpression; import com.jetbrains.python.psi.PyListCompExpression; import com.jetbrains.python.psi.types.PyType; - -import java.util.ArrayList; -import java.util.List; +import org.jetbrains.annotations.NotNull; /** * Created by IntelliJ IDEA. @@ -40,7 +33,7 @@ import java.util.List; * Time: 23:33:16 * To change this template use File | Settings | File Templates. */ -public class PyListCompExpressionImpl extends PyElementImpl implements PyListCompExpression { +public class PyListCompExpressionImpl extends PyComprehensionElementImpl implements PyListCompExpression { public PyListCompExpressionImpl(ASTNode astNode) { super(astNode); } @@ -50,68 +43,16 @@ public class PyListCompExpressionImpl extends PyElementImpl implements PyListCom pyVisitor.visitPyListCompExpression(this); } - @PsiCached - public PyExpression getResultExpression() { - ASTNode[] exprs = getNode().getChildren(PyElementTypes.EXPRESSIONS); - return exprs.length == 0 ? null : (PyExpression)exprs[0].getPsi(); - } - - @PsiCached - public List getComponents() { - ASTNode node = getNode().getFirstChildNode(); - List list = new ArrayList(5); - while (node != null) { - IElementType type = node.getElementType(); - ASTNode next = getNextExpression(node); - if (next == null) break; - if (type == PyTokenTypes.IF_KEYWORD) { - final PyExpression test = (PyExpression)next.getPsi(); - list.add(new IfComponent() { - public PyExpression getTest() { - return test; - } - }); - } - else if (type == PyTokenTypes.FOR_KEYWORD) { - ASTNode next2 = getNextExpression(next); - if (next2 == null) break; - final PyExpression variable = (PyExpression)next.getPsi(); - final PyExpression iterated = (PyExpression)next2.getPsi(); - list.add(new ForComponent() { - public PyExpression getIteratorVariable() { - return variable; - } - - public PyExpression getIteratedList() { - return iterated; - } - }); - } - node = node.getTreeNext(); - } - return list; - } - - private static ASTNode getNextExpression(ASTNode after) { - ASTNode node = after; - do { - node = node.getTreeNext(); - } - while (node != null && !PyElementTypes.EXPRESSIONS.contains(node.getElementType())); - return node; - } - public boolean processDeclarations(@NotNull PsiScopeProcessor processor, @NotNull ResolveState substitutor, PsiElement lastParent, @NotNull PsiElement place) { - for (ListCompComponent component : getComponents()) { - if (component instanceof ForComponent) { + for (ComprhForComponent component : getForComponents()) { + if (component != null) { //TODO: this needs to restrict resolution based on nesting // for example, this is not valid (the i in the first for should not resolve): // x for x in i for i in y - ForComponent forComponent = (ForComponent)component; - if (!forComponent.getIteratorVariable().processDeclarations(processor, substitutor, null, place)) return false; + if (!component.getIteratorVariable().processDeclarations(processor, substitutor, null, place)) return false; } } return true; @@ -120,4 +61,5 @@ public class PyListCompExpressionImpl extends PyElementImpl implements PyListCom public PyType getType() { return null; } + } diff --git a/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java index 5e732bf8241e..9f77cd12afbf 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java @@ -144,8 +144,14 @@ public class PyReferenceExpressionImpl extends PyElementImpl implements PyRefere // here we have an unqualified expr. it may be defined: // ...in current file - //PsiElement ret = PyResolveUtil.treeWalkUp(new PyResolveUtil.ResolveProcessor(referencedName), this, this, null); PsiElement ret = PyResolveUtil.treeCrawlUp(new PyResolveUtil.ResolveProcessor(referencedName), this); + if ((ret != null) && (ret instanceof PyClass)) { + // is it a case of the bizarre "class Foo(Foo)" construct? + PyClass cls = (PyClass)ret; + for (PyExpression base_expr : cls.getSuperClassExpressions()){ + if (base_expr == this) return null; // cannot resolve us, the base class ref, to the class being defined + } + } if (ret == null) { // ...as a part of current module PyType otype = PyBuiltinCache.getInstance(this.getProject()).getObjectType(); // "object" as a closest kin to "module" diff --git a/python/src/com/jetbrains/python/validation/AddImportAction.java b/python/src/com/jetbrains/python/validation/AddImportAction.java index 2d74ad66a629..7950b8f16085 100644 --- a/python/src/com/jetbrains/python/validation/AddImportAction.java +++ b/python/src/com/jetbrains/python/validation/AddImportAction.java @@ -12,20 +12,13 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiComment; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiReference; +import com.intellij.psi.*; import com.intellij.psi.search.FilenameIndex; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; import com.jetbrains.python.PythonLanguage; -import com.jetbrains.python.psi.PyExpression; -import com.jetbrains.python.psi.PyFromImportStatement; -import com.jetbrains.python.psi.PyImportStatement; -import com.jetbrains.python.psi.PyReferenceExpression; -import com.jetbrains.python.psi.types.PyModuleType; +import com.jetbrains.python.psi.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -64,7 +57,7 @@ public class AddImportAction implements HintAction, QuestionAction { final PsiElement element = myReference.getElement(); if (myReference instanceof PyReferenceExpression) { final PyExpression qual = ((PyReferenceExpression)myReference).getQualifier(); - if ((qual != null) && (qual.getType() instanceof PyModuleType)) return false; // don't propose to import unknown fields, etc + if ((qual != null) /*&& (qual.getType() instanceof PyModuleType)*/) return false; // don't propose to import unknown fields, etc } if (PsiTreeUtil.getParentOfType(element, PyImportStatement.class) != null) return false; if (PsiTreeUtil.getParentOfType(element, PyFromImportStatement.class) != null) return false; @@ -83,9 +76,11 @@ public class AddImportAction implements HintAction, QuestionAction { final String referenceName = getRefName(); final PsiFile[] files = getRefFiles(referenceName); if (files.length == 1) { - final PyImportStatement importNodeToInsert = PythonLanguage.getInstance().getElementGenerator().createImportStatementFromText(myProject, "import " + referenceName); + final PyImportStatement importNodeToInsert = PythonLanguage.getInstance().getElementGenerator().createImportStatementFromText( + myProject, "import " + referenceName + "\n\n" + ); try { - file.addBefore(importNodeToInsert, getFirstNonComment(file)); + file.addAfter(importNodeToInsert, getInsertPosition(file)); } catch (IncorrectOperationException e) { LOG.error(e); @@ -95,11 +90,20 @@ public class AddImportAction implements HintAction, QuestionAction { }); } - private static PsiElement getFirstNonComment(final PsiFile file) { - final PsiElement firstChild = file.getFirstChild(); - LOG.assertTrue(firstChild != null); - final PsiElement element = PsiTreeUtil.skipSiblingsForward(firstChild, PsiComment.class); - return element != null ? element : firstChild; + private static PsiElement getInsertPosition(final PsiFile file) { + PsiElement feeler = file.getFirstChild(); + LOG.assertTrue(feeler != null); + // skip initial comments and whitespace and try to get just below the last import stmt + PsiElement seeker = feeler; + do { + if (PyUtil.instanceOf(feeler, PyImportStatement.class, PyFromImportStatement.class)) { + seeker = feeler; + feeler = feeler.getNextSibling(); + } + else if (PyUtil.instanceOf(feeler, PsiWhiteSpace.class, PsiComment.class)) feeler = feeler.getNextSibling(); + else break; // some other statement, stop + } while (feeler != null); + return seeker; } public boolean startInWriteAction() { diff --git a/python/src/com/jetbrains/python/validation/ParameterListAnnotator.java b/python/src/com/jetbrains/python/validation/ParameterListAnnotator.java index 8b89d1a10b46..2a375eba4baf 100644 --- a/python/src/com/jetbrains/python/validation/ParameterListAnnotator.java +++ b/python/src/com/jetbrains/python/validation/ParameterListAnnotator.java @@ -21,11 +21,9 @@ import com.jetbrains.python.psi.PyParameter; import com.jetbrains.python.psi.PyParameterList; /** - * Created by IntelliJ IDEA. + * Checks for anomalies in parameter lists of function declarations. * User: yole * Date: 12.06.2005 - * Time: 11:05:22 - * To change this template use File | Settings | File Templates. */ public class ParameterListAnnotator extends PyAnnotator { @Override public void visitPyParameterList(final PyParameterList node) {