PY-1747: allow non-builtin decorators before @classmethod | @staticmethod

This commit is contained in:
Dmitry Cheryasov
2010-09-05 15:23:23 +03:00
parent a1e52d975b
commit e1ca0a5b0d
2 changed files with 32 additions and 19 deletions
@@ -444,27 +444,30 @@ public class PyUtil {
}
/**
* For cases when a function is decorated many decorators, and the innermost is a built-in decorator:
* When a function is decorated many decorators, finds the deepest builtin decorator:
* <pre>
* &#x40;foo
* &#x40;classmethod <b># &lt;-- that's it</b>
* &#x40;bar
* def moo(cls):
* &nbsp;&nbsp;pass
* </pre>
* @param node the allegedly decorated function
* @return name of the only built-in decorator, or null (even if there are multiple or non-built-in decorators!)
* @return name of the built-in decorator, or null (even if there are non-built-in decorators).
*/
public static
@Nullable
String getImmediateBuiltinDecorator(@NotNull final PyFunction node) {
String getDeepestBuiltinDecorator(@NotNull final PyFunction node) {
PyDecoratorList decolist = node.getDecoratorList();
if (decolist != null) {
PyDecorator[] decos = decolist.getDecorators();
if (decos.length > 0) {
PyDecorator deco = decos[decos.length - 1];
String deconame = deco.getName();
if (deco.isBuiltin()) {
return deconame;
for (int i = decos.length - 1; i >= 0; i -= 1) {
PyDecorator deco = decos[i];
String deconame = deco.getName();
if (deco.isBuiltin()) {
return deconame;
}
}
}
}
@@ -480,7 +483,7 @@ public class PyUtil {
@NotNull
public static Set<PyFunction.Flag> detectDecorationsAndWrappersOf(PyFunction function) {
Set<PyFunction.Flag> flags = EnumSet.noneOf(PyFunction.Flag.class);
String deconame = getImmediateBuiltinDecorator(function);
String deconame = getDeepestBuiltinDecorator(function);
if (PyNames.CLASSMETHOD.equals(deconame)) {
flags.add(CLASSMETHOD);
}
@@ -2,24 +2,19 @@
<problems>
<problem>
<file>first_arg.py</file>
<line>9</line>
<line>13</line>
<description>Usually first parameter of a method is named 'self'</description>
</problem>
<problem>
<file>first_arg.py</file>
<line>12</line>
<line>16</line>
<description>Method must have a first parameter, usually called 'self'</description>
</problem>
<problem>
<file>first_arg.py</file>
<line>15</line>
<line>19</line>
<description>First parameter of a non-static method must not be a tuple</description>
</problem>
<problem>
<file>first_arg.py</file>
<line>21</line>
<description>Usually first parameter of such methods is named 'cls'</description>
</problem>
<problem>
<file>first_arg.py</file>
<line>25</line>
@@ -27,17 +22,32 @@
</problem>
<problem>
<file>first_arg.py</file>
<line>38</line>
<line>29</line>
<description>Usually first parameter of such methods is named 'cls'</description>
</problem>
<problem>
<file>first_arg.py</file>
<line>34</line>
<description>Usually first parameter of such methods is named 'cls'</description>
</problem>
<problem>
<file>first_arg.py</file>
<line>39</line>
<description>Usually first parameter of such methods is named 'cls'</description>
</problem>
<problem>
<file>first_arg.py</file>
<line>62</line>
<description>Usually first parameter of a method is named 'self'</description>
</problem>
<problem>
<file>first_arg.py</file>
<line>41</line>
<line>65</line>
<description>Usually first parameter of such methods is named 'cls'</description>
</problem>
<problem>
<file>first_arg.py</file>
<line>44</line>
<line>68</line>
<description>Usually first parameter of such methods is named 'cls'</description>
</problem>
</problems>