import Type
import Generics
import Expr
/** does t depend on dep?
The main challenge with the depends relation is the use of generic types
which may cause reverse dependencies to occur. E.g., a class Foo in
package bar declares a field of type List<Foo>. The paramaterized type
List<Foo> is placed in the same package as List<T>. Therefore we make Foo
not depend on the parameterized type List<Foo> but rather the generic
type List and its argument Foo. Then we can use the definition below
for depends.
A few subtle points: Parameterized and raw types do not depend on
any other types in this predicate as we do not want to include them
in metrics since they introduce false dependencies. The usesType
predicate is used to decompose a parameterized type into
its generic type and its type arguments.
*/
predicate depends(RefType t, RefType dep) {
depends(t, dep, _, _)
}
/** does t use dep in any way? */
predicate usesType(Type t, RefType dep) {
((RefType)t).getSourceDeclaration() = dep
or
((ParameterizedType)t).getATypeArgument() = dep
or
(((Array)t).getElementType() = dep)
}
/** class to explain the reason for a dependency */
class Reason extends Locatable {
Reason() {
exists(RefType t | t = this)
or exists(Field f | f = this)
or exists(Callable c | c = this)
or exists(Call c | c = this)
or exists(FieldAccess f | f = this)
or exists(LocalVariableDeclExpr t | t = this)
or exists(TypeLiteral t | t = this)
or exists(Annotation a | a = this)
or exists(InstanceOfExpr a | a = this)
}
string toString() {
result = ((RefType)this).toString()
or result = ((Field)this).toString()
or result = ((Callable)this).toString()
or result = ((Call)this).toString()
or result = ((FieldAccess)this).toString()
or result = ((LocalVariableDeclExpr)this).toString()
or result = ((TypeLiteral)this).toString()
or result = ((Annotation)this).toString()
or result = ((InstanceOfExpr)this).toString()
}
}
/** dependencies with reasons as strings and locatable to click on */
predicate depends(RefType t, RefType dep, string reason, Reason click) {
not isParameterized(t) and not isRaw(t) and
(
(usesType(t.getASupertype(), dep) and reason = "super type" and click = t)
or
(usesType(((NestedType)t).getEnclosingType(), dep) and reason = "enclosing type" and
click = t)
or
(exists(Field f | t.getAField()=f and
usesType(f.getType(), dep) and
reason = "field "+f.getName() and
click = f))
or
(exists(Method m | m.getDeclaringType() = t and
m = m.getSourceDeclaration() and
usesType(m.getType(), dep) and
reason = "return of method "+m.getName() and
click=m))
or
(exists(Callable c | c.getDeclaringType() = t and
c = c.getSourceDeclaration() and
usesType(c.getAParamType(), dep) and
reason = "parameter of callable "+c.toString() and
click=c))
or
(exists(Exception e, Callable c | c=t.getACallable() and
c.getAnException()= e and
usesType(e.getType(), dep) and
reason = c.getName() + " throws "+e.toString() and
click = c))
or
(exists(Call c, Callable n, Callable m |
n = c.getCaller() and
n.getSourceDeclaration().getDeclaringType()=t and
m = c.getCallee() and
usesType(m.getSourceDeclaration().getDeclaringType(), dep) and
reason = "call of "+m.getName()+" by "+n.getName() and
click=c))
)
or
(exists(Field f, FieldRead fr, Callable m |
t.getACallable() = m and m = fr.getSite() and
f = fr.getField() and
usesType(f.getSourceDeclaration().getDeclaringType(),dep) and
reason = "read of "+f.getName()+ " by "+ m.getName() and
click = fr))
or
(exists(Field f, FieldWrite fw, Callable m |
t.getACallable() = m and m = fw.getSite() and
f = fw.getField() and
usesType(f.getSourceDeclaration().getDeclaringType(),dep) and
reason = "write of "+f.getName()+ " by "+ m.getName() and
click = fw))
or
(exists(LocalVariableDeclExpr ts, Callable c |
c = ts.getEnclosingCallable() and
c.getSourceDeclaration().getDeclaringType() = t and
usesType(ts.getType(),dep) and
reason = "local variable in "+c.getName() and
click=ts))
or
(exists(TypeLiteral l |
l.getEnclosingCallable().getSourceDeclaration().getDeclaringType() = t and
usesType(l.getTypeName().getType(),dep) and
reason = "type literal" and
click = l))
or
(exists(Annotation a |
(t = a.getAnnotatedElement() or
t = ((Member)a.getAnnotatedElement()).getDeclaringType()) and
(usesType(a.getType(),dep) or
usesType(a.getAValue().getType(),dep)) and
reason = "annotation" and
click = a))
or
(exists(InstanceOfExpr ioe |
t = ioe.getEnclosingCallable().getSourceDeclaration().getDeclaringType() and
usesType(ioe.getTypeName().getType(),dep) and
reason = "instanceof" and
click = ioe))
}
|