|
| 1 | +/** |
| 2 | + * @name UnusedField |
| 3 | + * @description A field that is not used in the characteristic predicate will contain every value |
| 4 | + * of its type when accessed in other predicates, which is probably not intended. |
| 5 | + * @kind problem |
| 6 | + * @problem.severity warning |
| 7 | + * @id ql/unused-field |
| 8 | + * @precision high |
| 9 | + */ |
| 10 | + |
| 11 | +import ql |
| 12 | + |
| 13 | +from ClassType clz, ClassType implClz, FieldDecl field, string extraMsg |
| 14 | +where |
| 15 | + clz.getDeclaration().getAField() = field and |
| 16 | + implClz.getASuperType*() = clz and |
| 17 | + // The field is not accessed in the charpred (of any of the classes) |
| 18 | + not exists(FieldAccess access | |
| 19 | + access.getEnclosingPredicate() = |
| 20 | + [clz.getDeclaration().getCharPred(), implClz.getDeclaration().getCharPred()] |
| 21 | + ) and |
| 22 | + // The implementation class is not abstract, and the field is not an override |
| 23 | + not implClz.getDeclaration().isAbstract() and |
| 24 | + not field.isOverride() and |
| 25 | + // There doesn't exist a class in between `clz` and `implClz` that binds `field`. |
| 26 | + not exists(ClassType c, CharPred p | |
| 27 | + c.getASuperType*() = clz and |
| 28 | + implClz.getASuperType*() = c and |
| 29 | + p = c.getDeclaration().getCharPred() and |
| 30 | + exists(FieldAccess access | access.getDeclaration() = field | |
| 31 | + access.getEnclosingPredicate() = p |
| 32 | + ) |
| 33 | + ) and |
| 34 | + (if clz = implClz then extraMsg = "." else extraMsg = " of any class between it and $@.") and |
| 35 | + // The `implClz` does not override `field` with a more specific type. |
| 36 | + not exists(FieldDecl override | |
| 37 | + override = implClz.getDeclaration().getAField() and |
| 38 | + override.getName() = field.getName() and |
| 39 | + override.hasAnnotation("override") and |
| 40 | + override.getVarDecl().getType() != field.getVarDecl().getType() |
| 41 | + ) |
| 42 | +select clz, "The field $@ declared in $@ is not used in the characteristic predicate" + extraMsg, |
| 43 | + field, field.getName(), clz, clz.getName(), implClz, implClz.getName() |
0 commit comments