|
| 1 | +/** |
| 2 | + * Finds overriding methods which seem to have parameters switched by accident, |
| 3 | + * compared to the overridden method. |
| 4 | + * |
| 5 | + * For example: |
| 6 | + * ```java |
| 7 | + * void addUser(String firstName, String lastName); |
| 8 | + * |
| 9 | + * ... |
| 10 | + * |
| 11 | + * // Accidentally has "lastName" as first parameter |
| 12 | + * @Override |
| 13 | + * void addUser(String lastName, String firstName) { |
| 14 | + * ... |
| 15 | + * } |
| 16 | + * ``` |
| 17 | + * |
| 18 | + * @id TODO |
| 19 | + * @kind problem |
| 20 | + */ |
| 21 | + |
| 22 | +// TODO: Could make this more precise (at the risk of more false negatives) by checking that parameters |
| 23 | +// are really switched, i.e. the other expected param also has the overriding param switched |
| 24 | +// (currently the query just checks if the param is at the wrong index) |
| 25 | +import java |
| 26 | + |
| 27 | +// CodeQL seems to generate param names in the form p0, p1, ... for external classes |
| 28 | +predicate areParamNamesKnown(Method m) { |
| 29 | + m.fromSource() |
| 30 | + or |
| 31 | + // Or there is a param name which is not `p<N>` |
| 32 | + exists(string paramName | paramName = m.getAParameter().getName() | |
| 33 | + not paramName.regexpMatch("p\\d+") |
| 34 | + ) |
| 35 | +} |
| 36 | + |
| 37 | +from |
| 38 | + Method m, int pIndex, Parameter p, Method overridden, int pOverriddenIndex, Parameter pOverridden |
| 39 | +where |
| 40 | + m.fromSource() and |
| 41 | + p = m.getParameter(pIndex) and |
| 42 | + overridden = m.getAnOverride() and |
| 43 | + // TODO: Maybe also check that both parameters have same type, or common (non-Object) supertype |
| 44 | + pOverridden = overridden.getParameter(pOverriddenIndex) and |
| 45 | + pOverridden.getName() = p.getName() and |
| 46 | + pOverriddenIndex != pIndex and |
| 47 | + areParamNamesKnown(overridden) |
| 48 | +select p, "Has different position than $@ parameter in overridden method", pOverridden, "this" |
0 commit comments