Java: Autoformat most of semmle.code.java.

This commit is contained in:
Anders Schack-Mulligen
2018-10-11 16:33:01 +02:00
parent bc7ea93608
commit 2f0b983335
32 changed files with 1747 additions and 1863 deletions

View File

@@ -38,14 +38,10 @@ class Annotation extends @annotation, Expr {
Expr getAValue() { filteredAnnotValue(this, _, result) }
/** Gets the value of the annotation element with the specified `name`. */
Expr getValue(string name) {
filteredAnnotValue(this, this.getAnnotationElement(name), result)
}
Expr getValue(string name) { filteredAnnotValue(this, this.getAnnotationElement(name), result) }
/** Gets the element being annotated. */
Element getTarget() {
exprs(this, _, _, result, _)
}
Element getTarget() { exprs(this, _, _, result, _) }
override string toString() { result = this.getType().getName() }
@@ -63,35 +59,28 @@ class Annotation extends @annotation, Expr {
Expr getAValue(string name) {
getType().getAnnotationElement(name).getType() instanceof Array and
exists(Expr value | value = getValue(name) |
if value instanceof ArrayInit then
result = value.(ArrayInit).getAnInit()
else
result = value
if value instanceof ArrayInit then result = value.(ArrayInit).getAnInit() else result = value
)
}
}
/** An `Annotation` that applies to a declaration. */
class DeclAnnotation extends @declannotation, Annotation {
}
class DeclAnnotation extends @declannotation, Annotation { }
/** An `Annotation` that applies to a type. */
class TypeAnnotation extends @typeannotation, Annotation {
}
class TypeAnnotation extends @typeannotation, Annotation { }
/**
* There may be duplicate entries in annotValue(...) - one entry for
* information populated from bytecode, and one for information populated
* from source. This removes the duplication.
*/
private
predicate filteredAnnotValue(Annotation a, Method m, Expr val) {
private predicate filteredAnnotValue(Annotation a, Method m, Expr val) {
annotValue(a, m, val) and
(sourceAnnotValue(a, m, val) or not sourceAnnotValue(a, m, _))
}
private
predicate sourceAnnotValue(Annotation a, Method m, Expr val) {
private predicate sourceAnnotValue(Annotation a, Method m, Expr val) {
annotValue(a, m, val) and
val.getFile().getExtension() = "java"
}
@@ -103,7 +92,9 @@ class Annotatable extends Element {
/** Holds if this element has the specified annotation. */
predicate hasAnnotation(string package, string name) {
exists(AnnotationType at | at = getAnAnnotation().getType() | at.nestedName() = name and at.getPackage().getName() = package)
exists(AnnotationType at | at = getAnAnnotation().getType() |
at.nestedName() = name and at.getPackage().getName() = package
)
}
/** Gets an annotation that applies to this element. */
@@ -114,14 +105,20 @@ class Annotatable extends Element {
* annotation attached to it for the specified `category`.
*/
predicate suppressesWarningsAbout(string category) {
exists(string withQuotes
| withQuotes = ((SuppressWarningsAnnotation) getAnAnnotation()).getASuppressedWarning()
| category = withQuotes.substring(1, withQuotes.length() - 1)
) or
this.(Member).getDeclaringType().suppressesWarningsAbout(category) or
this.(Expr).getEnclosingCallable().suppressesWarningsAbout(category) or
this.(Stmt).getEnclosingCallable().suppressesWarningsAbout(category) or
this.(NestedClass).getEnclosingType().suppressesWarningsAbout(category) or
exists(string withQuotes |
withQuotes = (getAnAnnotation().(SuppressWarningsAnnotation)).getASuppressedWarning()
|
category = withQuotes.substring(1, withQuotes.length() - 1)
)
or
this.(Member).getDeclaringType().suppressesWarningsAbout(category)
or
this.(Expr).getEnclosingCallable().suppressesWarningsAbout(category)
or
this.(Stmt).getEnclosingCallable().suppressesWarningsAbout(category)
or
this.(NestedClass).getEnclosingType().suppressesWarningsAbout(category)
or
this.(LocalVariableDecl).getCallable().suppressesWarningsAbout(category)
}
}
@@ -132,13 +129,11 @@ class AnnotationType extends Interface {
/** Gets the annotation element with the specified `name`. */
AnnotationElement getAnnotationElement(string name) {
methods(result,_,_,_,this,_) and result.hasName(name)
methods(result, _, _, _, this, _) and result.hasName(name)
}
/** Gets an annotation element that is a member of this annotation type. */
AnnotationElement getAnAnnotationElement() {
methods(result,_,_,_,this,_)
}
AnnotationElement getAnAnnotationElement() { methods(result, _, _, _, this, _) }
/** Holds if this annotation type is annotated with the meta-annotation `@Inherited`. */
predicate isInherited() {
@@ -154,5 +149,5 @@ class AnnotationElement extends Member {
AnnotationElement() { isAnnotElem(this) }
/** Gets the type of this annotation element. */
Type getType() { methods(this,_,_,result,_,_) }
Type getType() { methods(this, _, _, result, _, _) }
}

View File

@@ -9,9 +9,11 @@ import java
* `List<T>`, instantiating the type parameter to `Object`.
*/
predicate instantiates(RefType t, GenericType g, int i, RefType arg) {
t = g.getAParameterizedType() and exists(g.getTypeParameter(i)) and
t = g.getAParameterizedType() and
exists(g.getTypeParameter(i)) and
(
arg = t.(ParameterizedType).getTypeArgument(i) or
arg = t.(ParameterizedType).getTypeArgument(i)
or
t instanceof RawType and arg instanceof TypeObject
)
}
@@ -40,7 +42,7 @@ predicate indirectlyInstantiates(RefType t, GenericType g, int i, RefType arg) {
(extendsReftype(tsrc, sup) or implInterface(tsrc, sup)) and
// check whether the subtype instantiates `g`
indirectlyInstantiates(sup, g, i, suparg)
|
|
// if `t` is itself an instantiation of `tsrc` and `sup` instantiates
// `g` to one of the type parameters of `tsrc`, we return the corresponding
// instantiation in `t`
@@ -63,7 +65,7 @@ class CollectionType extends RefType {
CollectionType() {
exists(ParameterizedInterface coll |
coll.getSourceDeclaration().hasQualifiedName("java.util", "Collection")
|
|
this.hasSupertype*(coll)
)
}
@@ -78,9 +80,7 @@ class CollectionType extends RefType {
/** A method declared in a collection type. */
class CollectionMethod extends Method {
CollectionMethod() {
this.getDeclaringType() instanceof CollectionType
}
CollectionMethod() { this.getDeclaringType() instanceof CollectionType }
/** Gets the type of elements of the collection to which this method belongs. */
RefType getReceiverElementType() {
@@ -90,34 +90,24 @@ class CollectionMethod extends Method {
/** The `size` method on `java.util.Collection`. */
class CollectionSizeMethod extends CollectionMethod {
CollectionSizeMethod() {
this.hasName("size") and this.hasNoParameters()
}
CollectionSizeMethod() { this.hasName("size") and this.hasNoParameters() }
}
/** A method that mutates the collection it belongs to. */
class CollectionMutator extends CollectionMethod {
CollectionMutator() {
this.getName().regexpMatch("add.*|remove.*|push|pop|clear")
}
CollectionMutator() { this.getName().regexpMatch("add.*|remove.*|push|pop|clear") }
}
/** A method call that mutates a collection. */
class CollectionMutation extends MethodAccess {
CollectionMutation() {
this.getMethod() instanceof CollectionMutator
}
CollectionMutation() { this.getMethod() instanceof CollectionMutator }
predicate resultIsChecked() {
not this.getParent() instanceof ExprStmt
}
predicate resultIsChecked() { not this.getParent() instanceof ExprStmt }
}
/** A method that queries the contents of a collection without mutating it. */
class CollectionQueryMethod extends CollectionMethod {
CollectionQueryMethod() {
this.getName().regexpMatch("contains|containsAll|get|size|peek")
}
CollectionQueryMethod() { this.getName().regexpMatch("contains|containsAll|get|size|peek") }
}
/** A `new` expression that allocates a fresh, empty collection. */

View File

@@ -10,29 +10,21 @@ import semmle.code.FileSystem
* A compilation unit is a `.java` or `.class` file.
*/
class CompilationUnit extends Element, File {
CompilationUnit() {
cupackage(this,_)
}
CompilationUnit() { cupackage(this, _) }
/** Gets the name of the compilation unit (not including its extension). */
override string getName() {
result = Element.super.getName()
}
override string getName() { result = Element.super.getName() }
/**
* Holds if this compilation unit has the specified `name`,
* which must not include the file extension.
*/
override predicate hasName(string name) {
Element.super.hasName(name)
}
override predicate hasName(string name) { Element.super.hasName(name) }
override string toString() {
result = Element.super.toString()
}
override string toString() { result = Element.super.toString() }
/** Gets the declared package of this compilation unit. */
Package getPackage() { cupackage(this,result) }
Package getPackage() { cupackage(this, result) }
/**
* Gets the module associated with this compilation unit, if any.

View File

@@ -24,12 +24,12 @@ import java
*/
newtype Label = MkLabel(string l) { exists(LabeledStmt lbl | l = lbl.getLabel()) }
/**
* Either a `Label` or nothing.
*/
newtype MaybeLabel = JustLabel(Label l) or NoLabel()
newtype MaybeLabel =
JustLabel(Label l) or
NoLabel()
/**
* A completion of a statement or an expression.
@@ -48,7 +48,8 @@ newtype Completion =
* flow node having value `innerValue`.
*/
BooleanCompletion(boolean outerValue, boolean innerValue) {
(outerValue = true or outerValue = false) and (innerValue = true or innerValue = false)
(outerValue = true or outerValue = false) and
(innerValue = true or innerValue = false)
} or
/**
* The expression or statement completes via a `break` statement.
@@ -63,25 +64,13 @@ newtype Completion =
*/
ThrowCompletion(ThrowableType tt)
ContinueCompletion anonymousContinueCompletion() { result = ContinueCompletion(NoLabel()) }
ContinueCompletion anonymousContinueCompletion() {
result = ContinueCompletion(NoLabel())
}
ContinueCompletion labelledContinueCompletion(Label l) { result = ContinueCompletion(JustLabel(l)) }
ContinueCompletion labelledContinueCompletion(Label l) {
result = ContinueCompletion(JustLabel(l))
}
BreakCompletion anonymousBreakCompletion() { result = BreakCompletion(NoLabel()) }
BreakCompletion anonymousBreakCompletion() {
result = BreakCompletion(NoLabel())
}
BreakCompletion labelledBreakCompletion(Label l) {
result = BreakCompletion(JustLabel(l))
}
BreakCompletion labelledBreakCompletion(Label l) { result = BreakCompletion(JustLabel(l)) }
/** Gets the completion `booleanCompletion(value, value)`. */
Completion basicBooleanCompletion(boolean value) {
result = BooleanCompletion(value, value)
}
Completion basicBooleanCompletion(boolean value) { result = BooleanCompletion(value, value) }

View File

@@ -1,4 +1,3 @@
import java
/**

File diff suppressed because it is too large Load Diff

View File

@@ -4,6 +4,7 @@
*
* See the Java Language Specification, Section 5, for details.
*/
import java
import semmle.code.java.arithmetic.Overflow
@@ -21,23 +22,17 @@ abstract class ConversionSite extends Expr {
/**
* Gets the type that is converted from.
*/
Type getConversionSource() {
result = this.getType()
}
Type getConversionSource() { result = this.getType() }
/**
* Whether this conversion site actually induces a conversion.
*/
predicate isTrivial() {
getConversionTarget() = getConversionSource()
}
predicate isTrivial() { getConversionTarget() = getConversionSource() }
/**
* Whether this conversion is implicit.
*/
predicate isImplicit() {
any()
}
predicate isImplicit() { any() }
abstract string kind();
}
@@ -50,18 +45,16 @@ abstract class ConversionSite extends Expr {
*/
class AssignmentConversionContext extends ConversionSite {
Variable v;
AssignmentConversionContext() {
this = v.getAnAssignedValue() or
this = v.getAnAssignedValue()
or
exists(Assignment a | a.getDest().getProperExpr() = v.getAnAccess() and this = a.getSource())
}
override Type getConversionTarget() {
result = v.getType()
}
override Type getConversionTarget() { result = v.getType() }
override string kind() {
result = "assignment context"
}
override string kind() { result = "assignment context" }
}
/**
@@ -73,16 +66,12 @@ class AssignmentConversionContext extends ConversionSite {
*/
class ReturnConversionSite extends ConversionSite {
ReturnStmt r;
ReturnConversionSite() {
this = r.getResult()
}
override Type getConversionTarget() {
result = r.getEnclosingCallable().getReturnType()
}
override string kind() {
result = "return context"
}
ReturnConversionSite() { this = r.getResult() }
override Type getConversionTarget() { result = r.getEnclosingCallable().getReturnType() }
override string kind() { result = "return context" }
}
/**
@@ -93,18 +82,14 @@ class ReturnConversionSite extends ConversionSite {
*/
class InvocationConversionContext extends ConversionSite {
Call c;
int index;
InvocationConversionContext() {
this = c.getArgument(index)
}
override Type getConversionTarget() {
result = c.getCallee().getParameter(index).getType()
}
InvocationConversionContext() { this = c.getArgument(index) }
override string kind() {
result = "invocation context"
}
override Type getConversionTarget() { result = c.getCallee().getParameter(index).getType() }
override string kind() { result = "invocation context" }
}
/**
@@ -115,38 +100,28 @@ class InvocationConversionContext extends ConversionSite {
*/
class StringConversionContext extends ConversionSite {
AddExpr a;
StringConversionContext() {
a.getAnOperand() = this and
not this.getType() instanceof TypeString and
a.getAnOperand().getType() instanceof TypeString
}
override Type getConversionTarget() {
result instanceof TypeString
}
override Type getConversionTarget() { result instanceof TypeString }
override string kind() {
result = "string context"
}
override string kind() { result = "string context" }
}
class CastConversionContext extends ConversionSite {
CastExpr c;
CastConversionContext() {
this = c.getExpr()
}
override Type getConversionTarget() {
result = c.getType()
}
CastConversionContext() { this = c.getExpr() }
override predicate isImplicit() {
none()
}
override Type getConversionTarget() { result = c.getType() }
override string kind() {
result = "cast context"
}
override predicate isImplicit() { none() }
override string kind() { result = "cast context" }
}
/**
@@ -157,16 +132,10 @@ class CastConversionContext extends ConversionSite {
*/
class NumericConversionContext extends ConversionSite {
ArithExpr e;
NumericConversionContext() {
this = e.getAnOperand()
}
override Type getConversionTarget() {
result = e.getType()
}
NumericConversionContext() { this = e.getAnOperand() }
override string kind() {
result = "numeric context"
}
override Type getConversionTarget() { result = e.getType() }
override string kind() { result = "numeric context" }
}

View File

@@ -34,57 +34,48 @@ predicate depends(RefType t, RefType dep) {
usesType(t.(NestedType).getEnclosingType(), dep)
or
// the type of any field declared in `t`,
exists(Field f | f.getDeclaringType() = t |
usesType(f.getType(), dep)
) or
exists(Field f | f.getDeclaringType() = t | usesType(f.getType(), dep))
or
// the return type of any method declared in `t`,
exists(Method m | m.getDeclaringType() = t |
usesType(m.getReturnType(), dep)
) or
exists(Method m | m.getDeclaringType() = t | usesType(m.getReturnType(), dep))
or
// the type of any parameter of a callable in `t`,
exists(Callable c | c.getDeclaringType() = t |
usesType(c.getAParamType(), dep)
) or
exists(Callable c | c.getDeclaringType() = t | usesType(c.getAParamType(), dep))
or
// the type of any exception in the `throws` clause of a callable declared in `t`,
exists(Exception e | e.getCallable().getDeclaringType() = t |
usesType(e.getType(), dep)
) or
exists(Exception e | e.getCallable().getDeclaringType() = t | usesType(e.getType(), dep))
or
// the declaring type of a callable accessed in `t`,
exists(Callable c |
c.getAReference().getEnclosingCallable().getDeclaringType() = t
|
exists(Callable c | c.getAReference().getEnclosingCallable().getDeclaringType() = t |
usesType(c.getSourceDeclaration().getDeclaringType(), dep)
) or
)
or
// the declaring type of a field accessed in `t`,
exists(Field f |
f.getAnAccess().getEnclosingCallable().getDeclaringType() = t
|
exists(Field f | f.getAnAccess().getEnclosingCallable().getDeclaringType() = t |
usesType(f.getSourceDeclaration().getDeclaringType(), dep)
) or
)
or
// the type of a local variable declared in `t`,
exists(LocalVariableDeclExpr decl |
decl.getEnclosingCallable().getDeclaringType() = t
|
exists(LocalVariableDeclExpr decl | decl.getEnclosingCallable().getDeclaringType() = t |
usesType(decl.getType(), dep)
) or
)
or
// the type of a type literal accessed in `t`,
exists(TypeLiteral l |
l.getEnclosingCallable().getDeclaringType() = t
|
exists(TypeLiteral l | l.getEnclosingCallable().getDeclaringType() = t |
usesType(l.getTypeName().getType(), dep)
) or
)
or
// the type of an annotation (or one of its element values) that annotates `t` or one of its members,
exists(Annotation a |
a.getAnnotatedElement() = t or
a.getAnnotatedElement().(Member).getDeclaringType() = t
|
|
usesType(a.getType(), dep) or
usesType(a.getAValue().getType(), dep)
) or
)
or
// the type accessed in an `instanceof` expression in `t`.
exists(InstanceOfExpr ioe |
t = ioe.getEnclosingCallable().getDeclaringType()
|
exists(InstanceOfExpr ioe | t = ioe.getEnclosingCallable().getDeclaringType() |
usesType(ioe.getTypeName().getType(), dep)
)
)
@@ -108,8 +99,7 @@ predicate usesType(Type t, RefType dep) {
* the element type of an array type, or
* a bound of a type variable or wildcard.
*/
private
RefType inside(Type t) {
private RefType inside(Type t) {
result = t.(TypeVariable).getATypeBound().getType() or
result = t.(Wildcard).getATypeBound().getType() or
result = t.(ParameterizedType).getATypeArgument() or

View File

@@ -28,89 +28,98 @@ predicate numDepends(RefType t, RefType dep, int value) {
not t = dep and
// Type `t` depends on:
value = strictcount(Element elem |
// its supertypes,
exists(RefType s | elem = s and t.hasSupertype(s) |
usesType(s, dep)
) or
// its enclosing types,
exists(RefType s | elem = s and t.getEnclosingType() = s |
usesType(s, dep)
) or
// the type of any field declared in `t`,
exists(Field f | elem = f and f.getDeclaringType() = t |
usesType(f.getType(), dep)
) or
// the return type of any method declared in `t`,
exists(Method m | elem = m and m.getDeclaringType() = t |
usesType(m.getReturnType(), dep)
) or
// the type of any parameter of a callable in `t`,
exists(Parameter p | elem = p and p.getCallable().getDeclaringType() = t |
usesType(p.getType(), dep)
) or
// the type of any exception in the `throws` clause of a callable declared in `t`,
exists(Exception e | elem = e and e.getCallable().getDeclaringType() = t |
usesType(e.getType(), dep)
) or
// the declaring type of a callable accessed in `t`,
exists(Call c | elem = c and
c.getEnclosingCallable().getDeclaringType() = t
// its supertypes,
exists(RefType s | elem = s and t.hasSupertype(s) | usesType(s, dep))
or
// its enclosing types,
exists(RefType s | elem = s and t.getEnclosingType() = s | usesType(s, dep))
or
// the type of any field declared in `t`,
exists(Field f | elem = f and f.getDeclaringType() = t | usesType(f.getType(), dep))
or
// the return type of any method declared in `t`,
exists(Method m | elem = m and m.getDeclaringType() = t | usesType(m.getReturnType(), dep))
or
// the type of any parameter of a callable in `t`,
exists(Parameter p | elem = p and p.getCallable().getDeclaringType() = t |
usesType(p.getType(), dep)
)
or
// the type of any exception in the `throws` clause of a callable declared in `t`,
exists(Exception e | elem = e and e.getCallable().getDeclaringType() = t |
usesType(e.getType(), dep)
)
or
// the declaring type of a callable accessed in `t`,
exists(Call c |
elem = c and
c.getEnclosingCallable().getDeclaringType() = t
|
usesType(c.getCallee().getSourceDeclaration().getDeclaringType(), dep)
) or
// the declaring type of a field accessed in `t`,
exists(FieldAccess fa | elem = fa and
fa.getEnclosingCallable().getDeclaringType() = t
usesType(c.getCallee().getSourceDeclaration().getDeclaringType(), dep)
)
or
// the declaring type of a field accessed in `t`,
exists(FieldAccess fa |
elem = fa and
fa.getEnclosingCallable().getDeclaringType() = t
|
usesType(fa.getField().getSourceDeclaration().getDeclaringType(), dep)
) or
// the type of a local variable declared in `t`,
exists(LocalVariableDeclExpr decl | elem = decl and
decl.getEnclosingCallable().getDeclaringType() = t
usesType(fa.getField().getSourceDeclaration().getDeclaringType(), dep)
)
or
// the type of a local variable declared in `t`,
exists(LocalVariableDeclExpr decl |
elem = decl and
decl.getEnclosingCallable().getDeclaringType() = t
|
usesType(decl.getType(), dep)
) or
// the type of a type literal accessed in `t`,
exists(TypeLiteral l | elem = l and
l.getEnclosingCallable().getDeclaringType() = t
usesType(decl.getType(), dep)
)
or
// the type of a type literal accessed in `t`,
exists(TypeLiteral l |
elem = l and
l.getEnclosingCallable().getDeclaringType() = t
|
usesType(l.getTypeName().getType(), dep)
) or
// the type of an annotation (or one of its element values) that annotates `t` or one of its members,
exists(Annotation a |
a.getAnnotatedElement() = t or
a.getAnnotatedElement().(Member).getDeclaringType() = t
usesType(l.getTypeName().getType(), dep)
)
or
// the type of an annotation (or one of its element values) that annotates `t` or one of its members,
exists(Annotation a |
a.getAnnotatedElement() = t or
a.getAnnotatedElement().(Member).getDeclaringType() = t
|
elem = a and usesType(a.getType(), dep) or
elem = a.getAValue() and elem.getFile().getExtension() = "java" and usesType(elem.(Expr).getType(), dep)
) or
// the type accessed in an `instanceof` expression in `t`.
exists(InstanceOfExpr ioe | elem = ioe and
t = ioe.getEnclosingCallable().getDeclaringType()
elem = a and usesType(a.getType(), dep)
or
elem = a.getAValue() and
elem.getFile().getExtension() = "java" and
usesType(elem.(Expr).getType(), dep)
)
or
// the type accessed in an `instanceof` expression in `t`.
exists(InstanceOfExpr ioe |
elem = ioe and
t = ioe.getEnclosingCallable().getDeclaringType()
|
usesType(ioe.getTypeName().getType(), dep)
usesType(ioe.getTypeName().getType(), dep)
)
)
)
}
predicate filePackageDependencyCount(File sourceFile, int total, string entity) {
exists(Package targetPackage |
total = strictsum(RefType sourceType, RefType targetType, int num |
sourceType.getFile() = sourceFile and
sourceType.fromSource() and
sourceType.getPackage() != targetPackage and
targetType.getPackage() = targetPackage and
numDepends(sourceType, targetType, num)
sourceType.getFile() = sourceFile and
sourceType.fromSource() and
sourceType.getPackage() != targetPackage and
targetType.getPackage() = targetPackage and
numDepends(sourceType, targetType, num)
|
num)
and
num
) and
entity = "/" + sourceFile.getRelativePath() + "<|>" + targetPackage + "<|>N/A"
)
}
private string nameVersionRegex() {
result = "([_.A-Za-z0-9-]*)-([0-9][A-Za-z0-9.+_-]*)"
}
private string nameVersionRegex() { result = "([_.A-Za-z0-9-]*)-([0-9][A-Za-z0-9.+_-]*)" }
/**
* Given a JAR filename, try to split it into a name and version.
@@ -122,7 +131,8 @@ bindingset[target]
predicate hasDashedVersion(string target, string name, string version) {
exists(string regex | regex = nameVersionRegex() |
name = target.regexpCapture(regex, 1) and
version = target.regexpCapture(regex, 2))
version = target.regexpCapture(regex, 2)
)
}
predicate fileJarDependencyCount(File sourceFile, int total, string entity) {
@@ -130,20 +140,22 @@ predicate fileJarDependencyCount(File sourceFile, int total, string entity) {
jarStem = targetJar.getStem() and
targetJar.(File).getExtension() = "jar" and
jarStem != "rt"
|
|
total = strictsum(RefType r, RefType dep, int num |
r.getFile() = sourceFile and
r.fromSource() and
dep.getFile().getParentContainer*() = targetJar and
numDepends(r, dep, num)
r.getFile() = sourceFile and
r.fromSource() and
dep.getFile().getParentContainer*() = targetJar and
numDepends(r, dep, num)
|
num) and
num
) and
exists(string name, string version |
if hasDashedVersion(jarStem, _, _) then
hasDashedVersion(jarStem, name, version)
else
(name = jarStem and version = "unknown")
|
if hasDashedVersion(jarStem, _, _)
then hasDashedVersion(jarStem, name, version)
else (
name = jarStem and version = "unknown"
)
|
entity = "/" + sourceFile.getRelativePath() + "<|>" + name + "<|>" + version
)
)

View File

@@ -9,7 +9,7 @@ import Javadoc
/** A program element that has a name. */
class Element extends @element, Top {
/** Holds if this element has the specified `name`. */
predicate hasName(string name) { hasName(this,name) }
predicate hasName(string name) { hasName(this, name) }
/** Gets the name of this element. */
string getName() { this.hasName(result) }
@@ -34,9 +34,7 @@ class Element extends @element, Top {
* Elements pertaining to source files may include generated elements
* not visible in source code, such as implicit default constructors.
*/
predicate fromSource() {
getCompilationUnit().getExtension() = "java"
}
predicate fromSource() { getCompilationUnit().getExtension() = "java" }
/** Gets the compilation unit that this element belongs to. */
CompilationUnit getCompilationUnit() { result = getFile() }
@@ -49,13 +47,27 @@ class Element extends @element, Top {
* Holds if element `parent` is immediately above element `e` in the syntax tree.
*/
private predicate hasChildElement(Element parent, Element e) {
cupackage(e,parent) or
enclInReftype(e,parent) or
(not(enclInReftype(e,_)) and e.(Class).getCompilationUnit() = parent) or
(not(enclInReftype(e,_)) and e.(Interface).getCompilationUnit() = parent) or
methods(e,_,_,_,parent,_) or
constrs(e,_,_,_,parent,_) or
params(e,_,_,parent,_) or
fields(e,_,_,parent,_) or
typeVars(e,_,_,_,parent)
cupackage(e, parent)
or
enclInReftype(e, parent)
or
(
not (enclInReftype(e, _)) and
e.(Class).getCompilationUnit() = parent
)
or
(
not (enclInReftype(e, _)) and
e.(Interface).getCompilationUnit() = parent
)
or
methods(e, _, _, _, parent, _)
or
constrs(e, _, _, _, parent, _)
or
params(e, _, _, parent, _)
or
fields(e, _, _, parent, _)
or
typeVars(e, _, _, _, parent)
}

View File

@@ -15,10 +15,10 @@ import Type
*/
class Exception extends Element, @exception {
/** Gets the type of this exception. */
RefType getType() { exceptions(this,result,_) }
RefType getType() { exceptions(this, result, _) }
/** Gets the callable whose `throws` clause contains this exception. */
Callable getCallable() { exceptions(this,_,result) }
Callable getCallable() { exceptions(this, _, result) }
/** Gets the name of this exception, that is, the name of its type. */
override string getName() { result = this.getType().getName() }

File diff suppressed because it is too large Load Diff

View File

@@ -6,17 +6,13 @@ import Type
private import semmle.code.java.frameworks.JavaxAnnotations
/** A Java class that is detected as having been generated. */
abstract class GeneratedClass extends Class {
}
abstract class GeneratedClass extends Class { }
/**
* A Java class annotated with a `@Generated` annotation.
*/
class AnnotatedGeneratedClass extends GeneratedClass {
AnnotatedGeneratedClass() {
this.getAnAnnotation() instanceof GeneratedAnnotation
}
AnnotatedGeneratedClass() { this.getAnAnnotation() instanceof GeneratedAnnotation }
}
/** A Java class generated by an ANTLR scanner or parser class. */
@@ -28,38 +24,36 @@ class AntlrGenerated extends GeneratedClass {
t.hasQualifiedName("org.antlr.runtime", "Parser") or
t.hasQualifiedName("org.antlr.runtime.tree", "TreeParser") or
// ANTLR v2
t.hasQualifiedName("antlr","TreeParser") or
t.hasQualifiedName("antlr","CharScanner") or
t.hasQualifiedName("antlr","LLkParser")
t.hasQualifiedName("antlr", "TreeParser") or
t.hasQualifiedName("antlr", "CharScanner") or
t.hasQualifiedName("antlr", "LLkParser")
)
}
}
/** A generated callable is a callable declared in a generated class. */
class GeneratedCallable extends Callable {
GeneratedCallable() {
this.getDeclaringType() instanceof GeneratedClass
}
GeneratedCallable() { this.getDeclaringType() instanceof GeneratedClass }
}
/**
* A file that is detected as having been generated.
*/
abstract class GeneratedFile extends File {
}
abstract class GeneratedFile extends File { }
/**
* A file detected as generated based on commonly-used marker comments.
*/
library
class MarkerCommentGeneratedFile extends GeneratedFile {
library class MarkerCommentGeneratedFile extends GeneratedFile {
MarkerCommentGeneratedFile() {
exists(JavadocElement t | t.getFile() = this |
exists(string msg | msg = t.getText() |
msg.regexpMatch("(?i).*\\bGenerated By\\b.*\\bDo not edit\\b.*") or
msg.regexpMatch("(?i).*\\bThis (file|class|interface|art[ei]fact) (was|is|(has been)) (?:auto[ -]?)?gener(e?)ated.*") or
msg
.regexpMatch("(?i).*\\bThis (file|class|interface|art[ei]fact) (was|is|(has been)) (?:auto[ -]?)?gener(e?)ated.*") or
msg.regexpMatch("(?i).*\\bAny modifications to this file will be lost\\b.*") or
msg.regexpMatch("(?i).*\\bThis (file|class|interface|art[ei]fact) (was|is) (?:mechanically|automatically) generated\\b.*") or
msg
.regexpMatch("(?i).*\\bThis (file|class|interface|art[ei]fact) (was|is) (?:mechanically|automatically) generated\\b.*") or
msg.regexpMatch("(?i).*\\bThe following code was (?:auto[ -]?)?generated (?:by|from)\\b.*") or
msg.regexpMatch("(?i).*\\bAutogenerated by Thrift.*") or
msg.regexpMatch("(?i).*\\bGenerated By.*JavaCC.*") or

View File

@@ -39,7 +39,7 @@ import Type
* For example, `X` in `class X<T> { }`.
*/
class GenericType extends RefType {
GenericType() { typeVars(_,_,_,_,this) }
GenericType() { typeVars(_, _, _, _, this) }
/**
* Gets a parameterization of this generic type, where each use of
@@ -78,12 +78,10 @@ class GenericType extends RefType {
}
/** A generic type that is a class. */
class GenericClass extends GenericType, Class {
}
class GenericClass extends GenericType, Class { }
/** A generic type that is an interface. */
class GenericInterface extends GenericType, Interface {
}
class GenericInterface extends GenericType, Interface { }
/**
* A common super-class for Java types that may have a type bound.
@@ -113,7 +111,8 @@ abstract class BoundedType extends RefType, @boundedtype {
/** Gets a transitive upper bound for this type that is not itself a bounded type. */
RefType getAnUltimateUpperBoundType() {
result = getUpperBoundType() and not result instanceof BoundedType or
result = getUpperBoundType() and not result instanceof BoundedType
or
result = getUpperBoundType().(BoundedType).getAnUltimateUpperBoundType()
}
}
@@ -126,10 +125,10 @@ abstract class BoundedType extends RefType, @boundedtype {
*/
class TypeVariable extends BoundedType, @typevariable {
/** Gets the generic type that is parameterized by this type parameter, if any. */
RefType getGenericType() { typeVars(this,_,_,_,result) }
RefType getGenericType() { typeVars(this, _, _, _, result) }
/** Gets the generic callable that is parameterized by this type parameter, if any. */
GenericCallable getGenericCallable() { typeVars(this,_,_,_,result) }
GenericCallable getGenericCallable() { typeVars(this, _, _, _, result) }
/**
* Gets an upper bound of this type parameter, or `Object`
@@ -137,10 +136,9 @@ class TypeVariable extends BoundedType, @typevariable {
*/
pragma[nomagic]
override RefType getUpperBoundType() {
if this.hasTypeBound() then
result = this.getATypeBound().getType()
else
result instanceof TypeObject
if this.hasTypeBound()
then result = this.getATypeBound().getType()
else result instanceof TypeObject
}
/**
@@ -149,10 +147,9 @@ class TypeVariable extends BoundedType, @typevariable {
*/
pragma[nomagic]
override RefType getFirstUpperBoundType() {
if this.hasTypeBound() then
result = this.getFirstTypeBound().getType()
else
result instanceof TypeObject
if this.hasTypeBound()
then result = this.getFirstTypeBound().getType()
else result instanceof TypeObject
}
/** Gets the lexically enclosing package of this type parameter, if any. */
@@ -167,19 +164,20 @@ class TypeVariable extends BoundedType, @typevariable {
exists(GenericType gen, int pos |
this = gen.getTypeParameter(pos) and
typearg = gen.getAParameterizedType().getTypeArgument(pos)
) or
)
or
typearg = any(GenericCall call).getATypeArgument(this)
|
if typearg.(Wildcard).isUnconstrained() and this.hasTypeBound() then
result.(Wildcard).getUpperBound().getType() = this.getUpperBoundType()
else
result = typearg
|
if typearg.(Wildcard).isUnconstrained() and this.hasTypeBound()
then result.(Wildcard).getUpperBound().getType() = this.getUpperBoundType()
else result = typearg
)
}
/** Finds a non-typevariable type that was transitively supplied for this parameter. */
RefType getAnUltimatelySuppliedType() {
result = getASuppliedType() and not result instanceof TypeVariable or
result = getASuppliedType() and not result instanceof TypeVariable
or
result = getASuppliedType().(TypeVariable).getAnUltimatelySuppliedType()
}
}
@@ -197,29 +195,22 @@ class TypeVariable extends BoundedType, @typevariable {
*/
class Wildcard extends BoundedType, @wildcard {
/** Holds if this wildcard has an upper bound. */
predicate hasUpperBound() {
wildcards(this, _, 1)
}
predicate hasUpperBound() { wildcards(this, _, 1) }
/** Holds if this wildcard has a lower bound. */
predicate hasLowerBound() {
wildcards(this, _, 2)
}
predicate hasLowerBound() { wildcards(this, _, 2) }
/** Gets the upper bound for this wildcard, if any. */
TypeBound getUpperBound() {
this.hasUpperBound() and result = this.getATypeBound()
}
TypeBound getUpperBound() { this.hasUpperBound() and result = this.getATypeBound() }
/**
* Gets an upper bound type of this wildcard, or `Object`
* if no explicit type bound is present.
*/
override RefType getUpperBoundType() {
if this.hasUpperBound() then
result = this.getUpperBound().getType()
else
result instanceof TypeObject
if this.hasUpperBound()
then result = this.getUpperBound().getType()
else result instanceof TypeObject
}
/**
@@ -227,24 +218,19 @@ class Wildcard extends BoundedType, @wildcard {
* if no explicit type bound is present.
*/
override RefType getFirstUpperBoundType() {
if this.hasUpperBound() then
result = this.getFirstTypeBound().getType()
else
result instanceof TypeObject
if this.hasUpperBound()
then result = this.getFirstTypeBound().getType()
else result instanceof TypeObject
}
/** Gets the lower bound of this wildcard, if any. */
TypeBound getLowerBound() {
this.hasLowerBound() and result = this.getATypeBound()
}
TypeBound getLowerBound() { this.hasLowerBound() and result = this.getATypeBound() }
/**
* Gets the lower bound type for this wildcard,
* if an explicit lower bound is present.
*/
Type getLowerBoundType() {
result = this.getLowerBound().getType()
}
Type getLowerBoundType() { result = this.getLowerBound().getType() }
/**
* Holds if this is the unconstrained wildcard `?`.
@@ -273,7 +259,7 @@ class TypeBound extends @typebound {
* For example, `T` is the type variable bounded by the
* type `Number` in `T extends Number`.
*/
BoundedType getBoundedType() { typeBounds(this,_,_,result) }
BoundedType getBoundedType() { typeBounds(this, _, _, result) }
/**
* Gets the type of this bound.
@@ -281,7 +267,7 @@ class TypeBound extends @typebound {
* For example, `Number` is the type of the bound (of
* the type variable `T`) in `T extends Number`.
*/
RefType getType() { typeBounds(this,result,_,_) }
RefType getType() { typeBounds(this, result, _, _) }
/**
* Gets the (zero-indexed) position of this bound.
@@ -294,14 +280,13 @@ class TypeBound extends @typebound {
* the position of the bound `Runnable` is 0 and
* the position of the bound `Cloneable` is 1.
*/
int getPosition() { typeBounds(this,_,result,_) }
int getPosition() { typeBounds(this, _, result, _) }
/** Gets a textual representation of this type bound. */
string toString() { result = this.getType().getName() }
}
// -------- Parameterizations of generic types --------
/**
* A parameterized type is an instantiation of a generic type, where
* each formal type variable has been replaced with a type argument.
@@ -311,8 +296,8 @@ class TypeBound extends @typebound {
*/
class ParameterizedType extends RefType {
ParameterizedType() {
typeArgs(_,_,this) or
typeVars(_,_,_,_,this)
typeArgs(_, _, this) or
typeVars(_, _, _, _, this)
}
/**
@@ -320,7 +305,7 @@ class ParameterizedType extends RefType {
*
* For example, the erasure of both `X<Number>` and `X<Integer>` is `X<T>`.
*/
override RefType getErasure() { erasure(this,result) or this.(GenericType) = result }
override RefType getErasure() { erasure(this, result) or this.(GenericType) = result }
/**
* Gets the generic type corresponding to this parameterized type.
@@ -335,35 +320,33 @@ class ParameterizedType extends RefType {
* For example, `Number` in `List<Number>`.
*/
RefType getATypeArgument() {
typeArgs(result,_,this) or
typeVars(result,_,_,_,this)
typeArgs(result, _, this) or
typeVars(result, _, _, _, this)
}
/** Gets the type argument of this parameterized type at the specified position. */
RefType getTypeArgument(int pos) {
typeArgs(result,pos,this) or
typeVars(result,_,pos,_,this)
typeArgs(result, pos, this) or
typeVars(result, _, pos, _, this)
}
/** Gets the number of type arguments of this parameterized type. */
int getNumberOfTypeArguments() {
result = count(int pos |
typeArgs(_,pos,this) or
typeVars(_,_,pos,_,this)
)
typeArgs(_, pos, this) or
typeVars(_, _, pos, _, this)
)
}
/** Holds if this type originates from source code. */
override predicate fromSource() { typeVars(_,_,_,_,this) and RefType.super.fromSource() }
override predicate fromSource() { typeVars(_, _, _, _, this) and RefType.super.fromSource() }
}
/** A parameterized type that is a class. */
class ParameterizedClass extends Class, ParameterizedType {
}
class ParameterizedClass extends Class, ParameterizedType { }
/** A parameterized type that is an interface. */
class ParameterizedInterface extends Interface, ParameterizedType {
}
class ParameterizedInterface extends Interface, ParameterizedType { }
/**
* The raw version of a generic type is the type that is formed by
@@ -383,31 +366,28 @@ class RawType extends RefType {
*
* For example, the erasure of `List` is `List<E>`.
*/
override RefType getErasure() { erasure(this,result) }
override RefType getErasure() { erasure(this, result) }
/** Holds if this type originates from source code. */
override predicate fromSource() { not any() }
}
/** A raw type that is a class. */
class RawClass extends Class, RawType {
}
class RawClass extends Class, RawType { }
/** A raw type that is an interface. */
class RawInterface extends Interface, RawType {
}
class RawInterface extends Interface, RawType { }
// -------- Generic callables --------
/**
* A generic callable is a callable with a type parameter.
*/
class GenericCallable extends Callable {
GenericCallable() {
exists(Callable srcDecl |
methods(this,_,_,_,_,srcDecl) or constrs(this,_,_,_,_,srcDecl)
|
typeVars(_,_,_,_,srcDecl)
methods(this, _, _, _, _, srcDecl) or constrs(this, _, _, _, _, srcDecl)
|
typeVars(_, _, _, _, srcDecl)
)
}
@@ -431,9 +411,7 @@ class GenericCallable extends Callable {
* A call where the callee is a generic callable.
*/
class GenericCall extends Call {
GenericCall() {
this.getCallee() instanceof GenericCallable
}
GenericCall() { this.getCallee() instanceof GenericCallable }
private RefType getAnInferredTypeArgument(TypeVariable v) {
typevarArg(this, v, result)
@@ -454,7 +432,8 @@ class GenericCall extends Call {
/** Gets a type argument of the call for the given `TypeVariable`. */
RefType getATypeArgument(TypeVariable v) {
result = getAnExplicitTypeArgument(v) or
result = getAnExplicitTypeArgument(v)
or
not exists(getAnExplicitTypeArgument(v)) and
result = getAnInferredTypeArgument(v)
}
@@ -465,36 +444,38 @@ private predicate typevarArg(Call call, TypeVariable v, RefType typearg) {
exists(GenericCallable gen |
gen = call.getCallee() and
v = gen.getATypeParameter()
|
hasSubstitution(gen.getReturnType(), call.(Expr).getType(), v, typearg)
or
exists(int n | hasSubtypedSubstitution(gen.getParameterType(n), call.getArgument(n).getType(), v, typearg))
|
hasSubstitution(gen.getReturnType(), call.(Expr).getType(), v, typearg) or
exists(int n |
hasSubtypedSubstitution(gen.getParameterType(n), call.getArgument(n).getType(), v, typearg)
)
)
}
/**
* The reflexive transitive closure of `RefType.extendsOrImplements` including reflexivity on `Type`s.
*/
private Type getShallowSupertype(Type t) {
result = t or t.(RefType).extendsOrImplements+(result)
}
private Type getShallowSupertype(Type t) { result = t or t.(RefType).extendsOrImplements+(result) }
/**
* Manual magic sets optimization for the "inputs" of `hasSubstitution` and
* `hasParameterSubstitution`.
*/
private predicate unificationTargets(RefType t1, Type t2) {
exists(GenericCallable gen, Call call |
gen = call.getCallee()
|
t1 = gen.getReturnType() and t2 = call.(Expr).getType() or
exists(int n | t1 = gen.getParameterType(n) and t2 = getShallowSupertype(call.getArgument(n).getType()))
) or
exists(GenericCallable gen, Call call | gen = call.getCallee() |
t1 = gen.getReturnType() and t2 = call.(Expr).getType()
or
exists(int n |
t1 = gen.getParameterType(n) and t2 = getShallowSupertype(call.getArgument(n).getType())
)
)
or
exists(Array a1, Array a2 |
unificationTargets(a1, a2) and
t1 = a1.getComponentType() and
t2 = a2.getComponentType()
) or
)
or
exists(ParameterizedType pt1, ParameterizedType pt2, int pos |
unificationTargets(pt1, pt2) and
t1 = pt1.getTypeArgument(pos) and
@@ -526,17 +507,21 @@ private predicate hasSubtypedSubstitution(RefType t1, Type t2, TypeVariable v, R
private predicate hasSubstitution(RefType t1, Type t2, TypeVariable v, RefType subst) {
unificationTargets(t1, t2) and
(
t1 = v and (t2 = subst or t2.(PrimitiveType).getBoxedType() = subst) or
hasSubstitution(t1.(Array).getComponentType(), t2.(Array).getComponentType(), v, subst) or
t1 = v and
(t2 = subst or t2.(PrimitiveType).getBoxedType() = subst)
or
hasSubstitution(t1.(Array).getComponentType(), t2.(Array).getComponentType(), v, subst)
or
exists(GenericType g | hasParameterSubstitution(g, t1, g, t2, v, subst))
)
}
private predicate hasParameterSubstitution(GenericType g1, ParameterizedType pt1, GenericType g2, ParameterizedType pt2, TypeVariable v, RefType subst) {
private predicate hasParameterSubstitution(
GenericType g1, ParameterizedType pt1, GenericType g2, ParameterizedType pt2, TypeVariable v,
RefType subst
) {
unificationTargets(pt1, pt2) and
exists(int pos |
hasSubstitution(pt1.getTypeArgument(pos), pt2.getTypeArgument(pos), v, subst)
) and
exists(int pos | hasSubstitution(pt1.getTypeArgument(pos), pt2.getTypeArgument(pos), v, subst)) and
g1 = pt1.getGenericType() and
g2 = pt2.getGenericType()
}
@@ -547,7 +532,10 @@ private predicate hasParameterSubstitution(GenericType g1, ParameterizedType pt1
* For example, `<T> C(T t) { }` is a generic constructor for type `C`.
*/
class GenericConstructor extends Constructor, GenericCallable {
override GenericConstructor getSourceDeclaration() { result = Constructor.super.getSourceDeclaration() }
override GenericConstructor getSourceDeclaration() {
result = Constructor.super.getSourceDeclaration()
}
override ConstructorCall getAReference() { result = Constructor.super.getAReference() }
}
@@ -561,5 +549,4 @@ class GenericMethod extends Method, GenericCallable {
}
/** A generic method that is the same as its source declaration. */
class GenericSrcMethod extends SrcMethod, GenericMethod {
}
class GenericSrcMethod extends SrcMethod, GenericMethod { }

View File

@@ -22,10 +22,10 @@ class Import extends Element, @import {
* For example, `import java.util.Set;`.
*/
class ImportType extends Import {
ImportType() { imports(this,_,_,1) }
ImportType() { imports(this, _, _, 1) }
/** Gets the imported type. */
RefType getImportedType() { imports(this,result,_,_) }
RefType getImportedType() { imports(this, result, _, _) }
override string toString() { result = "import " + this.getImportedType().toString() }
}
@@ -39,17 +39,15 @@ class ImportType extends Import {
* `java.util.Map`.
*/
class ImportOnDemandFromType extends Import {
ImportOnDemandFromType() { imports(this,_,_,2) }
ImportOnDemandFromType() { imports(this, _, _, 2) }
/** Gets the type from which accessible nested types are imported. */
RefType getTypeHoldingImport() { imports(this,result,_,_) }
RefType getTypeHoldingImport() { imports(this, result, _, _) }
/** Gets an imported type. */
NestedType getAnImport() { result.getEnclosingType() = this.getTypeHoldingImport() }
override string toString() {
result = "import " + this.getTypeHoldingImport().toString() + ".*"
}
override string toString() { result = "import " + this.getTypeHoldingImport().toString() + ".*" }
}
/**
@@ -59,10 +57,10 @@ class ImportOnDemandFromType extends Import {
* For example, `import java.util.*;`.
*/
class ImportOnDemandFromPackage extends Import {
ImportOnDemandFromPackage() { imports(this,_,_,3) }
ImportOnDemandFromPackage() { imports(this, _, _, 3) }
/** Gets the package from which accessible types are imported. */
Package getPackageHoldingImport() { imports(this,result,_,_) }
Package getPackageHoldingImport() { imports(this, result, _, _) }
/** Gets an imported type. */
RefType getAnImport() { result.getPackage() = this.getPackageHoldingImport() }
@@ -80,10 +78,10 @@ class ImportOnDemandFromPackage extends Import {
* For example, `import static java.lang.System.*;`.
*/
class ImportStaticOnDemand extends Import {
ImportStaticOnDemand() { imports(this,_,_,4) }
ImportStaticOnDemand() { imports(this, _, _, 4) }
/** Gets the type from which accessible static members are imported. */
RefType getTypeHoldingImport() { imports(this,result,_,_) }
RefType getTypeHoldingImport() { imports(this, result, _, _) }
/** Gets an imported type. */
NestedType getATypeImport() { result.getEnclosingType() = this.getTypeHoldingImport() }
@@ -109,18 +107,19 @@ class ImportStaticOnDemand extends Import {
* class `java.util.Collections`.
*/
class ImportStaticTypeMember extends Import {
ImportStaticTypeMember() { imports(this,_,_,5) }
ImportStaticTypeMember() { imports(this, _, _, 5) }
/** Gets the type from which static members with a given name are imported. */
RefType getTypeHoldingImport() { imports(this,result,_,_) }
RefType getTypeHoldingImport() { imports(this, result, _, _) }
/** Gets the name of the imported member(s). */
override string getName() { imports(this,_,result,_) }
override string getName() { imports(this, _, result, _) }
/** Gets an imported member. */
Member getAMemberImport() {
this.getTypeHoldingImport().getAMember() = result and
result.getName() = this.getName() and result.isStatic()
result.getName() = this.getName() and
result.isStatic()
}
/** Gets an imported type. */
@@ -134,7 +133,6 @@ class ImportStaticTypeMember extends Import {
/** Gets a printable representation of this import declaration. */
override string toString() {
result = "import static " + this.getTypeHoldingImport().toString()
+ "." + this.getName()
result = "import static " + this.getTypeHoldingImport().toString() + "." + this.getName()
}
}

View File

@@ -7,61 +7,49 @@ import Type
/** An entity bean. */
class EntityBean extends Class {
EntityBean() {
exists(Interface i | i.hasQualifiedName("javax.ejb","EntityBean") |
this.hasSupertype+(i)
)
exists(Interface i | i.hasQualifiedName("javax.ejb", "EntityBean") | this.hasSupertype+(i))
}
}
/** An enterprise bean. */
class EnterpriseBean extends RefType {
EnterpriseBean() {
exists(Interface i | i.hasQualifiedName("javax.ejb","EnterpriseBean") |
this.hasSupertype+(i)
)
exists(Interface i | i.hasQualifiedName("javax.ejb", "EnterpriseBean") | this.hasSupertype+(i))
}
}
/** A local EJB home interface. */
class LocalEJBHomeInterface extends Interface {
LocalEJBHomeInterface() {
exists(Interface i | i.hasQualifiedName("javax.ejb","EJBLocalHome") |
this.hasSupertype+(i)
)
exists(Interface i | i.hasQualifiedName("javax.ejb", "EJBLocalHome") | this.hasSupertype+(i))
}
}
/** A remote EJB home interface. */
class RemoteEJBHomeInterface extends Interface {
RemoteEJBHomeInterface() {
exists(Interface i | i.hasQualifiedName("javax.ejb","EJBHome") |
this.hasSupertype+(i)
)
exists(Interface i | i.hasQualifiedName("javax.ejb", "EJBHome") | this.hasSupertype+(i))
}
}
/** A local EJB interface. */
class LocalEJBInterface extends Interface {
LocalEJBInterface() {
exists(Interface i | i.hasQualifiedName("javax.ejb","EJBLocalObject") |
this.hasSupertype+(i)
)
exists(Interface i | i.hasQualifiedName("javax.ejb", "EJBLocalObject") | this.hasSupertype+(i))
}
}
/** A remote EJB interface. */
class RemoteEJBInterface extends Interface {
RemoteEJBInterface() {
exists(Interface i | i.hasQualifiedName("javax.ejb","EJBObject") |
this.hasSupertype+(i)
)
exists(Interface i | i.hasQualifiedName("javax.ejb", "EJBObject") | this.hasSupertype+(i))
}
}
/** A message bean. */
class MessageBean extends Class {
MessageBean() {
exists(Interface i | i.hasQualifiedName("javax.ejb","MessageDrivenBean") |
exists(Interface i | i.hasQualifiedName("javax.ejb", "MessageDrivenBean") |
this.hasSupertype+(i)
)
}
@@ -70,8 +58,6 @@ class MessageBean extends Class {
/** A session bean. */
class SessionBean extends Class {
SessionBean() {
exists(Interface i | i.hasQualifiedName("javax.ejb","SessionBean") |
this.hasSupertype+(i)
)
exists(Interface i | i.hasQualifiedName("javax.ejb", "SessionBean") | this.hasSupertype+(i))
}
}

View File

@@ -5,104 +5,67 @@
import Member
// --- Standard types ---
/** The class `java.lang.Object`. */
class TypeObject extends Class {
pragma[noinline]
TypeObject() {
this.hasQualifiedName("java.lang", "Object")
}
TypeObject() { this.hasQualifiedName("java.lang", "Object") }
}
/** The interface `java.lang.Cloneable`. */
class TypeCloneable extends Interface {
TypeCloneable() {
this.hasQualifiedName("java.lang", "Cloneable")
}
TypeCloneable() { this.hasQualifiedName("java.lang", "Cloneable") }
}
/** The class `java.lang.ProcessBuilder`. */
class TypeProcessBuilder extends Class {
TypeProcessBuilder() {
hasQualifiedName("java.lang", "ProcessBuilder")
}
TypeProcessBuilder() { hasQualifiedName("java.lang", "ProcessBuilder") }
}
/** The class `java.lang.Runtime`. */
class TypeRuntime extends Class {
TypeRuntime() {
hasQualifiedName("java.lang", "Runtime")
}
}
class TypeRuntime extends Class { TypeRuntime() { hasQualifiedName("java.lang", "Runtime") } }
/** The class `java.lang.String`. */
class TypeString extends Class {
TypeString() {
this.hasQualifiedName("java.lang", "String")
}
}
class TypeString extends Class { TypeString() { this.hasQualifiedName("java.lang", "String") } }
/** The `length()` method of the class `java.lang.String`. */
class StringLengthMethod extends Method {
StringLengthMethod() {
this.hasName("length") and this.getDeclaringType() instanceof TypeString
}
StringLengthMethod() { this.hasName("length") and this.getDeclaringType() instanceof TypeString }
}
/** The class `java.lang.StringBuffer`. */
class TypeStringBuffer extends Class {
TypeStringBuffer() {
this.hasQualifiedName("java.lang", "StringBuffer")
}
TypeStringBuffer() { this.hasQualifiedName("java.lang", "StringBuffer") }
}
/** The class `java.lang.StringBuilder`. */
class TypeStringBuilder extends Class {
TypeStringBuilder() {
this.hasQualifiedName("java.lang", "StringBuilder")
}
TypeStringBuilder() { this.hasQualifiedName("java.lang", "StringBuilder") }
}
/** The class `java.lang.System`. */
class TypeSystem extends Class {
TypeSystem() {
this.hasQualifiedName("java.lang", "System")
}
}
class TypeSystem extends Class { TypeSystem() { this.hasQualifiedName("java.lang", "System") } }
/** The class `java.lang.Throwable`. */
class TypeThrowable extends Class {
TypeThrowable() {
this.hasQualifiedName("java.lang", "Throwable")
}
TypeThrowable() { this.hasQualifiedName("java.lang", "Throwable") }
}
/** The class `java.lang.Exception`. */
class TypeException extends Class {
TypeException() {
this.hasQualifiedName("java.lang", "Exception")
}
TypeException() { this.hasQualifiedName("java.lang", "Exception") }
}
/** The class `java.lang.Error`. */
class TypeError extends Class {
TypeError() {
this.hasQualifiedName("java.lang", "Error")
}
}
class TypeError extends Class { TypeError() { this.hasQualifiedName("java.lang", "Error") } }
/** The class `java.lang.RuntimeException`. */
class TypeRuntimeException extends Class {
TypeRuntimeException() {
this.hasQualifiedName("java.lang", "RuntimeException")
}
TypeRuntimeException() { this.hasQualifiedName("java.lang", "RuntimeException") }
}
/** The class `java.lang.ClassCastException`. */
class TypeClassCastException extends Class {
TypeClassCastException() {
this.hasQualifiedName("java.lang", "ClassCastException")
}
TypeClassCastException() { this.hasQualifiedName("java.lang", "ClassCastException") }
}
/**
@@ -111,9 +74,7 @@ class TypeClassCastException extends Class {
* This includes the generic source declaration, any parameterized instances and the raw type.
*/
class TypeClass extends Class {
TypeClass() {
this.getSourceDeclaration().hasQualifiedName("java.lang", "Class")
}
TypeClass() { this.getSourceDeclaration().hasQualifiedName("java.lang", "Class") }
}
/**
@@ -128,11 +89,7 @@ class TypeConstructor extends Class {
}
/** The class `java.lang.Math`. */
class TypeMath extends Class {
TypeMath() {
this.hasQualifiedName("java.lang", "Math")
}
}
class TypeMath extends Class { TypeMath() { this.hasQualifiedName("java.lang", "Math") } }
/** A numeric type, including both primitive and boxed types. */
class NumericType extends Type {
@@ -140,7 +97,7 @@ class NumericType extends Type {
exists(string name |
name = this.(PrimitiveType).getName() or
name = this.(BoxedType).getPrimitiveType().getName()
|
|
name.regexpMatch("byte|short|int|long|double|float")
)
}
@@ -158,58 +115,36 @@ class ImmutableType extends Type {
}
// --- Java IO ---
/** The interface `java.io.Serializable`. */
class TypeSerializable extends Interface {
TypeSerializable() {
hasQualifiedName("java.io", "Serializable")
}
TypeSerializable() { hasQualifiedName("java.io", "Serializable") }
}
/** The interface `java.io.ObjectOutput`. */
class TypeObjectOutput extends Interface {
TypeObjectOutput() {
hasQualifiedName("java.io", "ObjectOutput")
}
TypeObjectOutput() { hasQualifiedName("java.io", "ObjectOutput") }
}
/** The type `java.io.ObjectOutputStream`. */
class TypeObjectOutputStream extends RefType {
TypeObjectOutputStream() {
hasQualifiedName("java.io", "ObjectOutputStream")
}
TypeObjectOutputStream() { hasQualifiedName("java.io", "ObjectOutputStream") }
}
/** The class `java.nio.file.Paths`. */
class TypePaths extends Class {
TypePaths() {
this.hasQualifiedName("java.nio.file", "Paths")
}
}
class TypePaths extends Class { TypePaths() { this.hasQualifiedName("java.nio.file", "Paths") } }
/** The class `java.nio.file.Path`. */
class TypePath extends Class {
TypePath() {
this.hasQualifiedName("java.nio.file", "Path")
}
}
class TypePath extends Class { TypePath() { this.hasQualifiedName("java.nio.file", "Path") } }
/** The class `java.nio.file.FileSystem`. */
class TypeFileSystem extends Class {
TypeFileSystem() {
this.hasQualifiedName("java.nio.file", "FileSystem")
}
TypeFileSystem() { this.hasQualifiedName("java.nio.file", "FileSystem") }
}
/** The class `java.io.File`. */
class TypeFile extends Class {
TypeFile() {
this.hasQualifiedName("java.io", "File")
}
}
class TypeFile extends Class { TypeFile() { this.hasQualifiedName("java.io", "File") } }
// --- Standard methods ---
/**
* Any of the methods named `command` on class `java.lang.ProcessBuilder`.
*/
@@ -315,7 +250,6 @@ class MethodAbs extends Method {
}
// --- Standard fields ---
/** The field `System.in`. */
class SystemIn extends Field {
SystemIn() {
@@ -341,7 +275,6 @@ class SystemErr extends Field {
}
// --- User-defined methods with a particular meaning ---
/** A method with the same signature as `java.lang.Object.equals`. */
class EqualsMethod extends Method {
EqualsMethod() {
@@ -351,9 +284,7 @@ class EqualsMethod extends Method {
}
/** Gets the single parameter of this method. */
Parameter getParameter() {
result = this.getAParameter()
}
Parameter getParameter() { result = this.getAParameter() }
}
/** A method with the same signature as `java.lang.Object.hashCode`. */
@@ -399,8 +330,7 @@ class PreMainMethod extends Method {
this.getReturnType().hasName("void") and
this.getNumberOfParameters() < 3 and
this.getParameter(0).getType() instanceof TypeString and
(exists(this.getParameter(1)) implies
this.getParameter(1).getType().hasName("Instrumentation"))
(exists(this.getParameter(1)) implies this.getParameter(1).getType().hasName("Instrumentation"))
}
}
@@ -414,9 +344,7 @@ class ArrayLengthField extends Field {
/** A (reflexive, transitive) subtype of `java.lang.Throwable`. */
class ThrowableType extends RefType {
ThrowableType() {
exists(TypeThrowable throwable | hasSubtype*(throwable, this))
}
ThrowableType() { exists(TypeThrowable throwable | hasSubtype*(throwable, this)) }
}
/** An unchecked exception. That is, a (reflexive, transitive) subtype of `java.lang.Error` or `java.lang.RuntimeException`. */

View File

@@ -6,23 +6,17 @@ import java
/** A `@Deprecated` annotation. */
class DeprecatedAnnotation extends Annotation {
DeprecatedAnnotation() {
this.getType().hasQualifiedName("java.lang", "Deprecated")
}
DeprecatedAnnotation() { this.getType().hasQualifiedName("java.lang", "Deprecated") }
}
/** An `@Override` annotation. */
class OverrideAnnotation extends Annotation {
OverrideAnnotation() {
this.getType().hasQualifiedName("java.lang", "Override")
}
OverrideAnnotation() { this.getType().hasQualifiedName("java.lang", "Override") }
}
/** A `@SuppressWarnings` annotation. */
class SuppressWarningsAnnotation extends Annotation {
SuppressWarningsAnnotation() {
this.getType().hasQualifiedName("java.lang", "SuppressWarnings")
}
SuppressWarningsAnnotation() { this.getType().hasQualifiedName("java.lang", "SuppressWarnings") }
/** Gets the name of a warning suppressed by this annotation. */
string getASuppressedWarning() {
@@ -33,9 +27,7 @@ class SuppressWarningsAnnotation extends Annotation {
/** A `@Target` annotation. */
class TargetAnnotation extends Annotation {
TargetAnnotation() {
this.getType().hasQualifiedName("java.lang.annotation", "Target")
}
TargetAnnotation() { this.getType().hasQualifiedName("java.lang.annotation", "Target") }
/**
* Gets a target expression within this annotation.
@@ -61,16 +53,15 @@ class TargetAnnotation extends Annotation {
exists(EnumConstant ec |
ec = this.getATargetExpression().(VarAccess).getVariable() and
ec.getDeclaringType().hasQualifiedName("java.lang.annotation", "ElementType")
|
result = ec.getName())
|
result = ec.getName()
)
}
}
/** A `@Retention` annotation. */
class RetentionAnnotation extends Annotation {
RetentionAnnotation() {
this.getType().hasQualifiedName("java.lang.annotation", "Retention")
}
RetentionAnnotation() { this.getType().hasQualifiedName("java.lang.annotation", "Retention") }
/**
* Gets the retention policy expression within this annotation.
@@ -78,9 +69,7 @@ class RetentionAnnotation extends Annotation {
* For example, the field access `RetentionPolicy.RUNTIME` is the
* retention policy expression in `@Retention(RetentionPolicy.RUNTIME)`.
*/
Expr getRetentionPolicyExpression() {
result = this.getValue("value")
}
Expr getRetentionPolicyExpression() { result = this.getValue("value") }
/**
* Gets the name of the retention policy of this annotation.
@@ -92,8 +81,9 @@ class RetentionAnnotation extends Annotation {
exists(EnumConstant ec |
ec = this.getRetentionPolicyExpression().(VarAccess).getVariable() and
ec.getDeclaringType().hasQualifiedName("java.lang.annotation", "RetentionPolicy")
|
result = ec.getName())
|
result = ec.getName()
)
}
}
@@ -122,7 +112,7 @@ class ReflectiveAccessAnnotation extends Annotation {
* Any annotation that is not a subclass of `NonReflectiveAnnotation` is assumed to
* allow for reflective access.
*/
abstract class NonReflectiveAnnotation extends Annotation {}
abstract class NonReflectiveAnnotation extends Annotation { }
library class StandardNonReflectiveAnnotation extends NonReflectiveAnnotation {
StandardNonReflectiveAnnotation() {

View File

@@ -5,15 +5,10 @@
import Type
/** A managed bean. */
abstract class ManagedBean extends Interface {
}
abstract class ManagedBean extends Interface { }
/** An `MBean`. */
class MBean extends ManagedBean {
MBean() {
this.getQualifiedName().matches("%MBean%")
}
}
class MBean extends ManagedBean { MBean() { this.getQualifiedName().matches("%MBean%") } }
/** An `MXBean`. */
class MXBean extends ManagedBean {
@@ -30,26 +25,20 @@ class MXBean extends ManagedBean {
class RegisteredManagedBeanImpl extends Class {
RegisteredManagedBeanImpl() {
getAnAncestor() instanceof ManagedBean and
exists(JMXRegistrationCall registerCall |
registerCall.getObjectArgument().getType() = this
)
exists(JMXRegistrationCall registerCall | registerCall.getObjectArgument().getType() = this)
}
/**
* Gets a managed bean that this registered bean class implements.
*/
ManagedBean getAnImplementedManagedBean() {
result = getAnAncestor()
}
ManagedBean getAnImplementedManagedBean() { result = getAnAncestor() }
}
/**
* A call that registers an object with the `MBeanServer`, directly or indirectly.
*/
class JMXRegistrationCall extends MethodAccess {
JMXRegistrationCall() {
getCallee() instanceof JMXRegistrationMethod
}
JMXRegistrationCall() { getCallee() instanceof JMXRegistrationMethod }
/**
* Gets the argument that represents the object in the registration call.
@@ -71,16 +60,19 @@ class JMXRegistrationMethod extends Method {
// A direct registration with the `MBeanServer`.
getDeclaringType().hasQualifiedName("javax.management", "MBeanServer") and
getName() = "registerMBean"
) or
)
or
/*
* The `MBeanServer` is often wrapped by an application specific management class, so identify
* methods that wrap a call to another `JMXRegistrationMethod`.
*/
exists(JMXRegistrationCall c |
/*
* This must be a call to another JMX registration method, where the object argument is an access
* of one of the parameters of this method.
*/
c.getObjectArgument().(VarAccess).getVariable() = getAParameter()
)
}
@@ -94,7 +86,8 @@ class JMXRegistrationMethod extends Method {
getDeclaringType().hasQualifiedName("javax.management", "MBeanServer") and
getName() = "registerMBean" and
result = 0
) or
)
or
// Identify the position in this method where the object parameter should be passed.
exists(JMXRegistrationCall c |
c.getObjectArgument().(VarAccess).getVariable() = getParameter(result)

View File

@@ -11,64 +11,43 @@ class JavadocParent extends @javadocParent, Top {
JavadocElement getAChild() { result.getParent() = this }
/** Gets the child documentation element at the specified (zero-based) position. */
JavadocElement getChild(int index) {
result = this.getAChild() and result.getIndex() = index
}
JavadocElement getChild(int index) { result = this.getAChild() and result.getIndex() = index }
/** Gets the number of documentation elements attached to this parent. */
int getNumChild() {
result = count(getAChild())
}
int getNumChild() { result = count(getAChild()) }
/** Gets a documentation element with the specified Javadoc tag name. */
JavadocTag getATag(string name) {
result = this.getAChild() and result.getTagName() = name
}
JavadocTag getATag(string name) { result = this.getAChild() and result.getTagName() = name }
/*abstract*/ override string toString() { result = "Javadoc" }
}
/** A Javadoc comment. */
class Javadoc extends JavadocParent, @javadoc {
/** Gets the number of lines in this Javadoc comment. */
int getNumberOfLines() {
result = this.getLocation().getNumberOfCommentLines()
}
int getNumberOfLines() { result = this.getLocation().getNumberOfCommentLines() }
/** Gets the value of the `@version` tag, if any. */
string getVersion() {
result = this.getATag("@version").getChild(0).toString()
}
string getVersion() { result = this.getATag("@version").getChild(0).toString() }
/** Gets the value of the `@author` tag, if any. */
string getAuthor() {
result = this.getATag("@author").getChild(0).toString()
}
string getAuthor() { result = this.getATag("@author").getChild(0).toString() }
override string toString() {
result = toStringPrefix() + getChild(0) + toStringPostfix()
}
override string toString() { result = toStringPrefix() + getChild(0) + toStringPostfix() }
private string toStringPrefix() {
if isEolComment(this) then
result = "//"
if isEolComment(this)
then result = "//"
else (
if isNormalComment(this) then
result = "/* "
else
result = "/** "
if isNormalComment(this) then result = "/* " else result = "/** "
)
}
private string toStringPostfix() {
if isEolComment(this) then
result = ""
if isEolComment(this)
then result = ""
else (
if strictcount(getAChild()) = 1 then
result = " */"
else
result = " ... */"
if strictcount(getAChild()) = 1 then result = " */" else result = " ... */"
)
}
@@ -79,25 +58,19 @@ class Javadoc extends JavadocParent, @javadoc {
/** A documentable element that can have an attached Javadoc comment. */
class Documentable extends Element, @member {
/** Gets the Javadoc comment attached to this element. */
Javadoc getJavadoc() { hasJavadoc(this,result) and not isNormalComment(result) }
Javadoc getJavadoc() { hasJavadoc(this, result) and not isNormalComment(result) }
/** Gets the name of the author(s) of this element, if any. */
string getAuthor() {
result = this.getJavadoc().getAuthor()
}
string getAuthor() { result = this.getJavadoc().getAuthor() }
}
/** A common super-class for Javadoc elements, which may be either tags or text. */
abstract class JavadocElement extends @javadocElement, Top {
/** Gets the parent of this Javadoc element. */
JavadocParent getParent() {
javadocTag(this,_,result,_) or javadocText(this,_,result,_)
}
JavadocParent getParent() { javadocTag(this, _, result, _) or javadocText(this, _, result, _) }
/** Gets the index of this child element relative to its parent. */
int getIndex() {
javadocTag(this,_,_,result) or javadocText(this,_,_,result)
}
int getIndex() { javadocTag(this, _, _, result) or javadocText(this, _, _, result) }
/** Gets a printable representation of this Javadoc element. */
/*abstract*/ override string toString() { result = "Javadoc element" }
@@ -109,7 +82,7 @@ abstract class JavadocElement extends @javadocElement, Top {
/** A Javadoc tag. */
class JavadocTag extends JavadocElement, JavadocParent, @javadocTag {
/** Gets the name of this Javadoc tag. */
string getTagName() { javadocTag(this,result,_,_) }
string getTagName() { javadocTag(this, result, _, _) }
/** Gets a printable representation of this Javadoc tag. */
override string toString() { result = this.getTagName() }
@@ -158,12 +131,11 @@ class AuthorTag extends JavadocTag {
/** A piece of Javadoc text. */
class JavadocText extends JavadocElement, @javadocText {
/** Gets the Javadoc comment that contains this piece of text. */
Javadoc getJavadoc() { result.getAChild+() = this }
/** Gets the text itself. */
override string getText() { javadocText(this,result,_,_) }
override string getText() { javadocText(this, result, _, _) }
/** Gets a printable representation of this Javadoc element. */
override string toString() { result = this.getText() }

View File

@@ -6,7 +6,7 @@ class MapType extends RefType {
MapType() {
exists(ParameterizedInterface coll |
coll.getSourceDeclaration().hasQualifiedName("java.util", "Map")
|
|
this.hasSupertype*(coll)
)
}
@@ -28,44 +28,30 @@ class MapType extends RefType {
/** A method declared in a map type. */
class MapMethod extends Method {
MapMethod() {
this.getDeclaringType() instanceof MapType
}
MapMethod() { this.getDeclaringType() instanceof MapType }
/** Gets the type of keys of the map to which this method belongs. */
RefType getReceiverKeyType() {
result = this.getDeclaringType().(MapType).getKeyType()
}
RefType getReceiverKeyType() { result = this.getDeclaringType().(MapType).getKeyType() }
/** Gets the type of values of the map to which this method belongs. */
RefType getReceiverValueType() {
result = this.getDeclaringType().(MapType).getValueType()
}
RefType getReceiverValueType() { result = this.getDeclaringType().(MapType).getValueType() }
}
/** A method that mutates the map it belongs to. */
class MapMutator extends MapMethod {
MapMutator() {
this.getName().regexpMatch("(put.*|remove|clear)")
}
MapMutator() { this.getName().regexpMatch("(put.*|remove|clear)") }
}
/** The `size` method of `java.util.Map`. */
class MapSizeMethod extends MapMethod {
MapSizeMethod() {
this.hasName("size") and this.hasNoParameters()
}
MapSizeMethod() { this.hasName("size") and this.hasNoParameters() }
}
/** A method call that mutates a map. */
class MapMutation extends MethodAccess {
MapMutation() {
this.getMethod() instanceof MapMutator
}
MapMutation() { this.getMethod() instanceof MapMutator }
predicate resultIsChecked() {
not this.getParent() instanceof ExprStmt
}
predicate resultIsChecked() { not this.getParent() instanceof ExprStmt }
}
/** A method that queries the contents of the map it belongs to without mutating it. */
@@ -88,15 +74,9 @@ class FreshMap extends ClassInstanceExpr {
* A call to `Map.put(key, value)`.
*/
class MapPutCall extends MethodAccess {
MapPutCall() {
getCallee().(MapMethod).hasName("put")
}
MapPutCall() { getCallee().(MapMethod).hasName("put") }
Expr getKey() {
result = getArgument(0)
}
Expr getKey() { result = getArgument(0) }
Expr getValue() {
result = getArgument(1)
}
Expr getValue() { result = getArgument(1) }
}

View File

@@ -14,17 +14,13 @@ import metrics.MetricField
* including methods, constructors, fields, and nested types.
*/
class Member extends Element, Annotatable, Modifiable, @member {
Member() {
declaresMember(_,this)
}
Member() { declaresMember(_, this) }
/** Gets the type in which this member is declared. */
RefType getDeclaringType() { declaresMember(result, this) }
/** Gets the qualified name of this member. */
string getQualifiedName() {
result = getDeclaringType().getName() + "." + getName()
}
string getQualifiedName() { result = getDeclaringType().getName() + "." + getName() }
/** Holds if this member is package protected, that is, neither public nor private nor protected. */
predicate isPackageProtected() {
@@ -78,16 +74,15 @@ class Callable extends StmtParent, Member, @callable {
}
private string descriptorUpTo(int n) {
(n = 0 and result = "") or
exists(Parameter p | p = this.getParameter(n-1) |
result = descriptorUpTo(n-1) + p.getType().getTypeDescriptor()
(n = 0 and result = "")
or
exists(Parameter p | p = this.getParameter(n - 1) |
result = descriptorUpTo(n - 1) + p.getType().getTypeDescriptor()
)
}
/** Holds if this callable calls `target`. */
predicate calls(Callable target) {
exists(getACallSite(target))
}
predicate calls(Callable target) { exists(getACallSite(target)) }
/**
* Holds if this callable calls `target`
@@ -109,28 +104,23 @@ class Callable extends StmtParent, Member, @callable {
* Holds if this callable calls `target`
* using a `super` method call.
*/
predicate callsSuper(Method target) {
getACallSite(target) instanceof SuperMethodAccess
}
predicate callsSuper(Method target) { getACallSite(target) instanceof SuperMethodAccess }
/**
* Holds if this callable calls `c` using
* either a `super(...)` constructor call
* or a `this(...)` constructor call.
*/
predicate callsConstructor(Constructor c) {
this.callsSuperConstructor(c) or this.callsThis(c)
}
predicate callsConstructor(Constructor c) { this.callsSuperConstructor(c) or this.callsThis(c) }
/**
* Holds if this callable may call the specified callable,
* taking overriding into account.
*/
predicate polyCalls(Callable m) {
this.calls(m) or
exists(Method mSuper, VirtualMethodAccess c |
c.getCaller() = this and c.getMethod() = mSuper
|
this.calls(m)
or
exists(Method mSuper, VirtualMethodAccess c | c.getCaller() = this and c.getMethod() = mSuper |
m.(Method).overrides(mSuper)
)
}
@@ -139,17 +129,13 @@ class Callable extends StmtParent, Member, @callable {
* Holds if field `f` may be assigned a value
* within the body of this callable.
*/
predicate writes(Field f) {
f.getAnAccess().(LValue).getEnclosingCallable() = this
}
predicate writes(Field f) { f.getAnAccess().(LValue).getEnclosingCallable() = this }
/**
* Holds if field `f` may be read
* within the body of this callable.
*/
predicate reads(Field f) {
f.getAnAccess().(RValue).getEnclosingCallable() = this
}
predicate reads(Field f) { f.getAnAccess().(RValue).getEnclosingCallable() = this }
/**
* Holds if field `f` may be either read or written
@@ -169,9 +155,7 @@ class Callable extends StmtParent, Member, @callable {
predicate hasNoParameters() { not exists(getAParameter()) }
/** Gets the number of formal parameters of this callable. */
int getNumberOfParameters() {
result = count(getAParameter())
}
int getNumberOfParameters() { result = count(getAParameter()) }
/** Gets a formal parameter of this callable. */
Parameter getAParameter() { result.getCallable() = this }
@@ -188,9 +172,7 @@ class Callable extends StmtParent, Member, @callable {
*
* Use `getSignature` to obtain a signature including fully qualified type names.
*/
string getStringSignature() {
result = this.getName() + this.paramsString()
}
string getStringSignature() { result = this.getName() + this.paramsString() }
/** Gets a parenthesized string containing all parameter types of this callable, separated by a comma. */
pragma[nomagic]
@@ -198,7 +180,7 @@ class Callable extends StmtParent, Member, @callable {
exists(int n | n = getNumberOfParameters() |
n = 0 and result = "()"
or
n > 0 and result = "(" + this.paramUpTo(n-1) + ")"
n > 0 and result = "(" + this.paramUpTo(n - 1) + ")"
)
}
@@ -209,24 +191,20 @@ class Callable extends StmtParent, Member, @callable {
private string paramUpTo(int n) {
n = 0 and result = getParameterType(0).toString()
or
n > 0 and result = paramUpTo(n-1) + ", " + getParameterType(n)
n > 0 and result = paramUpTo(n - 1) + ", " + getParameterType(n)
}
/** Holds if this callable has the specified string signature. */
predicate hasStringSignature(string sig) {
sig = this.getStringSignature()
}
predicate hasStringSignature(string sig) { sig = this.getStringSignature() }
/** Gets an exception that occurs in the `throws` clause of this callable. */
Exception getAnException() { exceptions(result,_,this) }
Exception getAnException() { exceptions(result, _, this) }
/** Gets an exception type that occurs in the `throws` clause of this callable. */
RefType getAThrownExceptionType() { result = getAnException().getType() }
/** Gets a call site that references this callable. */
Call getAReference() {
result.getCallee() = this
}
Call getAReference() { result.getCallee() = this }
/** Gets the body of this callable, if any. */
Block getBody() { result.getParent() = this }
@@ -266,11 +244,12 @@ class Callable extends StmtParent, Member, @callable {
}
/** Holds if method `m1` overrides method `m2`. */
private
predicate overrides(Method m1, Method m2) {
private predicate overrides(Method m1, Method m2) {
exists(RefType t1, RefType t2 | overridesIgnoringAccess(m1, t1, m2, t2) |
m2.isPublic() or
m2.isProtected() or
m2.isPublic()
or
m2.isProtected()
or
m2.isPackageProtected() and t1.getPackage() = t2.getPackage()
)
}
@@ -290,7 +269,7 @@ predicate overridesIgnoringAccess(Method m1, RefType t1, Method m2, RefType t2)
}
private predicate virtualMethodWithSignature(string sig, RefType t, Method m) {
methods(m,_,_,_,t,_) and
methods(m, _, _, _, t, _) and
sig = m.getSignature() and
m.isVirtual()
}
@@ -326,21 +305,20 @@ class Method extends Callable, @method {
* source declaration of this method (and not equal to it).
*/
predicate overridesOrInstantiates(Method m) {
this.overrides(m) or
this.overrides(m)
or
this.getSourceDeclaration() = m and this != m
}
/** Gets a method (directly or transitively) overridden by this method. */
Method getAnOverride() {
this.overrides+(result)
}
Method getAnOverride() { this.overrides+(result) }
/** Gets the source declaration of a method overridden by this method. */
SrcMethod getASourceOverriddenMethod() {
exists(Method m | this.overrides(m) and result = m.getSourceDeclaration())
}
override string getSignature() { methods(this,_,result,_,_,_) }
override string getSignature() { methods(this, _, result, _, _, _) }
/**
* Holds if this method and method `m` are declared in the same type
@@ -357,7 +335,7 @@ class Method extends Callable, @method {
not exists(int n | this.getParameterType(n) != m.getParameterType(n))
}
override SrcMethod getSourceDeclaration() { methods(this,_,_,_,_,result) }
override SrcMethod getSourceDeclaration() { methods(this, _, _, _, _, result) }
/**
* All the methods that could possibly be called when this method
@@ -372,9 +350,7 @@ class Method extends Callable, @method {
this.getSourceDeclaration().getAPossibleImplementationOfSrcMethod() = result
}
override MethodAccess getAReference() {
result = Callable.super.getAReference()
}
override MethodAccess getAReference() { result = Callable.super.getAReference() }
override predicate isPublic() {
Callable.super.isPublic() or
@@ -413,9 +389,7 @@ class Method extends Callable, @method {
* Holds if this method is neither private nor static, and hence
* uses dynamic dispatch.
*/
predicate isVirtual() {
not isPrivate() and not isStatic()
}
predicate isVirtual() { not isPrivate() and not isStatic() }
/** Holds if this method can be overridden. */
predicate isOverridable() {
@@ -427,7 +401,7 @@ class Method extends Callable, @method {
/** A method that is the same as its source declaration. */
class SrcMethod extends Method {
SrcMethod() { methods(_,_,_,_,_,this) }
SrcMethod() { methods(_, _, _, _, _, this) }
/**
* All the methods that could possibly be called when this method
@@ -440,10 +414,9 @@ class SrcMethod extends Method {
*/
SrcMethod getAPossibleImplementationOfSrcMethod() {
(
if this.getDeclaringType() instanceof Interface and this.isVirtual() then
implementsInterfaceMethod(result, this)
else
result.getASourceOverriddenMethod*() = this
if this.getDeclaringType() instanceof Interface and this.isVirtual()
then implementsInterfaceMethod(result, this)
else result.getASourceOverriddenMethod*() = this
) and
(exists(result.getBody()) or result.hasModifier("native"))
}
@@ -462,7 +435,7 @@ class SetterMethod extends Method {
this.getNumberOfParameters() = 1 and
exists(ExprStmt s, Assignment a |
s = this.getBody().(SingletonBlock).getStmt() and a = s.getExpr()
|
|
exists(Field f | f.getDeclaringType() = this.getDeclaringType() |
a.getDest() = f.getAnAccess() and
a.getSource() = this.getAParameter().getAnAccess()
@@ -472,9 +445,7 @@ class SetterMethod extends Method {
/** Gets the field assigned by this setter method. */
Field getField() {
exists(Assignment a | a.getEnclosingCallable() = this |
a.getDest() = result.getAnAccess()
)
exists(Assignment a | a.getEnclosingCallable() = this | a.getDest() = result.getAnAccess())
}
}
@@ -495,9 +466,7 @@ class GetterMethod extends Method {
/** Gets the field whose value is returned by this getter method. */
Field getField() {
exists(ReturnStmt r | r.getEnclosingCallable() = this |
r.getResult() = result.getAnAccess()
)
exists(ReturnStmt r | r.getEnclosingCallable() = this | r.getResult() = result.getAnAccess())
}
}
@@ -518,9 +487,9 @@ class Constructor extends Callable, @constructor {
/** Holds if this is a default constructor, not explicitly declared in source code. */
predicate isDefaultConstructor() { isDefConstr(this) }
override Constructor getSourceDeclaration() { constrs(this,_,_,_,_,result) }
override Constructor getSourceDeclaration() { constrs(this, _, _, _, _, result) }
override string getSignature() { constrs(this,_,result,_,_,_) }
override string getSignature() { constrs(this, _, result, _, _, _) }
}
/**
@@ -528,26 +497,20 @@ class Constructor extends Callable, @constructor {
* non-static), which is used to hold (static or non-static) field
* initializers, as well as explicit initializer blocks.
*/
abstract class InitializerMethod extends Method {}
abstract class InitializerMethod extends Method { }
/**
* A static initializer is a method that contains all static
* field initializations and static initializer blocks.
*/
class StaticInitializer extends InitializerMethod {
StaticInitializer() {
hasName("<clinit>")
}
}
class StaticInitializer extends InitializerMethod { StaticInitializer() { hasName("<clinit>") } }
/**
* An instance initializer is a method that contains field initializations
* and explicit instance initializer blocks.
*/
class InstanceInitializer extends InitializerMethod {
InstanceInitializer() {
this.hasName("<obinit>")
}
InstanceInitializer() { this.hasName("<obinit>") }
}
/** A field declaration that declares one or more class or instance fields. */
@@ -565,10 +528,9 @@ class FieldDeclaration extends ExprParent, @fielddecl, Annotatable {
int getNumField() { result = max(int idx | fieldDeclaredIn(_, this, idx) | idx) + 1 }
override string toString() {
if this.getNumField() = 0 then
result = this.getTypeAccess() + " " + this.getField(0) + ";"
else
result = this.getTypeAccess() + " " + this.getField(0) + ", ...;"
if this.getNumField() = 0
then result = this.getTypeAccess() + " " + this.getField(0) + ";"
else result = this.getTypeAccess() + " " + this.getField(0) + ", ...;"
}
}
@@ -607,7 +569,7 @@ class Field extends Member, ExprParent, @field, Variable {
*
* For all other fields, the source declaration is the field itself.
*/
Field getSourceDeclaration() { fields(this,_,_,_,result) }
Field getSourceDeclaration() { fields(this, _, _, _, result) }
/** Holds if this field is the same as its source declaration. */
predicate isSourceDeclaration() { this.getSourceDeclaration() = this }
@@ -638,8 +600,4 @@ class Field extends Member, ExprParent, @field, Variable {
}
/** An instance field. */
class InstanceField extends Field {
InstanceField() {
not this.isStatic()
}
}
class InstanceField extends Field { InstanceField() { not this.isStatic() } }

View File

@@ -7,7 +7,7 @@ import Element
/** A modifier such as `private`, `static` or `abstract`. */
class Modifier extends Element, @modifier {
/** Gets the element to which this modifier applies. */
Element getElement() { hasModifier(result,this) }
Element getElement() { hasModifier(result, this) }
}
/** An element of the Java syntax tree that may have a modifier. */
@@ -21,12 +21,10 @@ abstract class Modifiable extends Element {
* abstract, so `isAbstract()` will hold for them even if `hasModifier("abstract")`
* does not.
*/
predicate hasModifier(string m) {
modifiers(getAModifier(), m)
}
predicate hasModifier(string m) { modifiers(getAModifier(), m) }
/** Holds if this element has no modifier. */
predicate hasNoModifier() { not hasModifier(this,_) }
predicate hasNoModifier() { not hasModifier(this, _) }
/** Gets a modifier of this element. */
Modifier getAModifier() { this = result.getElement() }

View File

@@ -8,9 +8,7 @@ import CompilationUnit
* A module.
*/
class Module extends @module {
Module() {
modules(this, _)
}
Module() { modules(this, _) }
/**
* Gets the name of this module.
@@ -50,9 +48,7 @@ abstract class Directive extends @directive {
* A `requires` directive in a module declaration.
*/
class RequiresDirective extends Directive, @requires {
RequiresDirective() {
requires(this,_)
}
RequiresDirective() { requires(this, _) }
/**
* Holds if this `requires` directive is `transitive`,
@@ -75,12 +71,11 @@ class RequiresDirective extends Directive, @requires {
*/
Module getTargetModule() { requires(this, result) }
override
string toString() {
override string toString() {
exists(string transitive, string static |
(if isTransitive() then transitive = "transitive " else transitive = "") and
(if isStatic() then static = "static " else static = "")
|
|
result = "requires " + transitive + static + getTargetModule() + ";"
)
}
@@ -90,9 +85,7 @@ class RequiresDirective extends Directive, @requires {
* An `exports` directive in a module declaration.
*/
class ExportsDirective extends Directive, @exports {
ExportsDirective() {
exports(this,_)
}
ExportsDirective() { exports(this, _) }
/**
* Gets the package exported by this `exports` directive.
@@ -116,11 +109,12 @@ class ExportsDirective extends Directive, @exports {
*/
Module getATargetModule() { exportsTo(this, result) }
override
string toString() {
override string toString() {
exists(string toClause |
if isQualified() then toClause = (" to " + concat(getATargetModule().getName(), ", ")) else toClause = ""
|
if isQualified()
then toClause = (" to " + concat(getATargetModule().getName(), ", "))
else toClause = ""
|
result = "exports " + getExportedPackage() + toClause + ";"
)
}
@@ -130,9 +124,7 @@ class ExportsDirective extends Directive, @exports {
* An `opens` directive in a module declaration.
*/
class OpensDirective extends Directive, @opens {
OpensDirective() {
opens(this,_)
}
OpensDirective() { opens(this, _) }
/**
* Gets the package opened by this `opens` directive.
@@ -156,11 +148,12 @@ class OpensDirective extends Directive, @opens {
*/
Module getATargetModule() { opensTo(this, result) }
override
string toString() {
override string toString() {
exists(string toClause |
if isQualified() then toClause = (" to " + concat(getATargetModule().getName(), ", ")) else toClause = ""
|
if isQualified()
then toClause = (" to " + concat(getATargetModule().getName(), ", "))
else toClause = ""
|
result = "opens " + getOpenedPackage() + toClause + ";"
)
}
@@ -170,28 +163,21 @@ class OpensDirective extends Directive, @opens {
* A `uses` directive in a module declaration.
*/
class UsesDirective extends Directive, @uses {
UsesDirective() {
uses(this,_)
}
UsesDirective() { uses(this, _) }
/**
* Gets the qualified name of the service interface specified in this `uses` directive.
*/
string getServiceInterfaceName() { uses(this, result) }
override
string toString() {
result = "uses " + getServiceInterfaceName() + ";"
}
override string toString() { result = "uses " + getServiceInterfaceName() + ";" }
}
/**
* A `provides` directive in a module declaration.
*/
class ProvidesDirective extends Directive, @provides {
ProvidesDirective() {
provides(this,_)
}
ProvidesDirective() { provides(this, _) }
/**
* Gets the qualified name of the service interface specified in this `provides` directive.
@@ -203,9 +189,8 @@ class ProvidesDirective extends Directive, @provides {
*/
string getServiceImplementationName() { providesWith(this, result) }
override
string toString() {
result = "provides " + getServiceInterfaceName() + " with " + concat(getServiceImplementationName(), ", ") + ";"
override string toString() {
result = "provides " + getServiceInterfaceName() + " with " +
concat(getServiceImplementationName(), ", ") + ";"
}
}

View File

@@ -15,9 +15,7 @@ class Package extends Element, Annotatable, @package {
TopLevelType getATopLevelType() { result.getPackage() = this }
/** Holds if at least one reference type in this package originates from source code. */
override predicate fromSource() {
exists(RefType t | t.fromSource() and t.getPackage() = this)
}
override predicate fromSource() { exists(RefType t | t.fromSource() and t.getPackage() = this) }
/** Cast this package to a class that provides access to metrics information. */
MetricPackage getMetrics() { result = this }

View File

@@ -7,13 +7,13 @@ import JDKAnnotations
import Serializability
import semmle.code.java.dataflow.DefUse
predicate reflectivelyRead(Field f){
predicate reflectivelyRead(Field f) {
f instanceof SerializableField or
f.getAnAnnotation() instanceof ReflectiveAccessAnnotation or
referencedInXmlFile(f)
}
predicate reflectivelyWritten(Field f){
predicate reflectivelyWritten(Field f) {
f instanceof DeserializableField or
f.getAnAnnotation() instanceof ReflectiveAccessAnnotation or
referencedInXmlFile(f)
@@ -44,7 +44,7 @@ private XMLElement elementReferencingType(RefType rt) {
result.getAnAttribute().getValue() = rt.getSourceDeclaration().getQualifiedName()
}
private abstract class ReflectiveClassIdentifier extends Expr {
abstract private class ReflectiveClassIdentifier extends Expr {
abstract RefType getReflectivelyIdentifiedClass();
}
@@ -60,17 +60,17 @@ private class ReflectiveClassIdentifierLiteral extends ReflectiveClassIdentifier
library class ReflectiveClassIdentifierMethodAccess extends ReflectiveClassIdentifier, MethodAccess {
ReflectiveClassIdentifierMethodAccess() {
// A call to `Class.forName(...)`, from which we can infer `T` in the returned type `Class<T>`.
getCallee().getDeclaringType() instanceof TypeClass and getCallee().hasName("forName") or
getCallee().getDeclaringType() instanceof TypeClass and getCallee().hasName("forName")
or
// A call to `ClassLoader.loadClass(...)`, from which we can infer `T` in the returned type `Class<T>`.
getCallee().getDeclaringType().hasQualifiedName("java.lang", "ClassLoader") and getCallee().hasName("loadClass")
getCallee().getDeclaringType().hasQualifiedName("java.lang", "ClassLoader") and
getCallee().hasName("loadClass")
}
/**
* If the argument to this call is a `StringLiteral`, then return that string.
*/
string getTypeName() {
result = getArgument(0).(StringLiteral).getRepresentedString()
}
string getTypeName() { result = getArgument(0).(StringLiteral).getRepresentedString() }
override RefType getReflectivelyIdentifiedClass() {
// We only handle cases where the class is specified as a string literal to this call.
@@ -82,16 +82,17 @@ library class ReflectiveClassIdentifierMethodAccess extends ReflectiveClassIdent
* Gets a `ReflectiveClassIdentifier` that we believe may represent the value of `expr`.
*/
private ReflectiveClassIdentifier pointsToReflectiveClassIdentifier(Expr expr) {
// If this is an expression creating a `Class<T>`, return the inferred `T` from the creation expression.
result = expr or
// Or if this is an access of a variable which was defined as an expression creating a `Class<T>`,
// return the inferred `T` from the definition expression.
exists(RValue use, VariableAssign assign |
use = expr and
defUsePair(assign, use) and
// The source of the assignment must be a `ReflectiveClassIdentifier`.
result = assign.getSource()
)
// If this is an expression creating a `Class<T>`, return the inferred `T` from the creation expression.
result = expr
or
// Or if this is an access of a variable which was defined as an expression creating a `Class<T>`,
// return the inferred `T` from the definition expression.
exists(RValue use, VariableAssign assign |
use = expr and
defUsePair(assign, use) and
// The source of the assignment must be a `ReflectiveClassIdentifier`.
result = assign.getSource()
)
}
/**
@@ -107,11 +108,7 @@ private predicate overlyGenericType(Type type) {
* `? extends Object` and `? extends Serializable`.
*/
private predicate catchallType(BoundedType type) {
exists(Type upperBound |
upperBound = type.getUpperBoundType()
|
overlyGenericType(upperBound)
)
exists(Type upperBound | upperBound = type.getUpperBoundType() | overlyGenericType(upperBound))
}
/**
@@ -123,9 +120,7 @@ private predicate catchallType(BoundedType type) {
*/
pragma[nomagic]
private Type parameterForSubTypes(ParameterizedType type) {
(
type instanceof TypeClass or type instanceof TypeConstructor
) and
(type instanceof TypeClass or type instanceof TypeConstructor) and
// Only report "real" types.
not result instanceof TypeVariable and
// Identify which types the type argument `arg` could represent.
@@ -133,27 +128,31 @@ private Type parameterForSubTypes(ParameterizedType type) {
arg = type.getTypeArgument(0) and
// Must not be a catch-all.
not catchallType(arg)
|
|
(
// Simple case - this type is not a bounded type, so must represent exactly the `arg` class.
not arg instanceof BoundedType and result = arg
) or
)
or
exists(RefType upperBound |
// Upper bound case
upperBound = arg.(BoundedType).getUpperBoundType()
|
|
/*
* `T extends Foo` implies that `Foo`, or any sub-type of `Foo`, may be represented.
*/
result.(RefType).getAnAncestor() = upperBound
) or
)
or
exists(RefType lowerBound |
// Lower bound case
lowerBound = arg.(Wildcard).getLowerBoundType()
|
|
/*
* `T super Foo` implies that `Foo`, or any super-type of `Foo`, may be represented.
*/
lowerBound.(RefType).getAnAncestor() = result
)
)
@@ -170,21 +169,23 @@ Type inferClassParameterType(Expr expr) {
* If this `expr` is a `VarAccess` of a final or effectively final parameter, then look at the
* arguments to calls to this method, to see if we can infer anything from that case.
*/
exists(Parameter p |
p = expr.(VarAccess).getVariable() and
p.isEffectivelyFinal()
|
|
result = inferClassParameterType(p.getAnArgument())
)
or
if exists(pointsToReflectiveClassIdentifier(expr).getReflectivelyIdentifiedClass()) then
if exists(pointsToReflectiveClassIdentifier(expr).getReflectivelyIdentifiedClass())
then
/*
* We've been able to identify where this `Class` instance was created, and identified the
* particular class that was loaded.
*/
result = pointsToReflectiveClassIdentifier(expr).getReflectivelyIdentifiedClass()
else
(
else (
/*
* If we haven't been able to find where the value for this expression was defined, then we
* resort to the type `T` in `Class<T>`.
@@ -195,6 +196,7 @@ Type inferClassParameterType(Expr expr) {
* A "catch-all" type is something like `? extends Object` or `? extends Serialization`, which
* would return too many sub-types.
*/
result = parameterForSubTypes(expr.getType())
)
)
@@ -224,7 +226,10 @@ private predicate expectsEnclosingInstance(RefType r) {
*/
class NewInstance extends MethodAccess {
NewInstance() {
(getCallee().getDeclaringType() instanceof TypeClass or getCallee().getDeclaringType() instanceof TypeConstructor) and
(
getCallee().getDeclaringType() instanceof TypeClass or
getCallee().getDeclaringType() instanceof TypeConstructor
) and
getCallee().hasName("newInstance")
}
@@ -234,25 +239,31 @@ class NewInstance extends MethodAccess {
*/
Constructor getInferredConstructor() {
result = getInferredConstructedType().getAConstructor() and
if getCallee().getDeclaringType() instanceof TypeClass then
result.getNumberOfParameters() = 0
else if getNumArgument() = 1 and getArgument(0).getType() instanceof Array then
/*
* This is a var-args array argument. If array argument is initialized inline, then identify
* the number of arguments specified in the array.
*/
if exists(getArgument(0).(ArrayCreationExpr).getInit()) then
// Count the number of elements in the initializer, and find the matching constructors.
matchConstructorArguments(result, count(getArgument(0).(ArrayCreationExpr).getInit().getAnInit()))
else
// Could be any of the constructors on this class.
any()
if getCallee().getDeclaringType() instanceof TypeClass
then result.getNumberOfParameters() = 0
else
/*
* No var-args in play, just use the number of arguments to the `newInstance(..)` to determine
* which constructors may be called.
*/
matchConstructorArguments(result, getNumArgument())
if getNumArgument() = 1 and getArgument(0).getType() instanceof Array
then
/*
* This is a var-args array argument. If array argument is initialized inline, then identify
* the number of arguments specified in the array.
*/
if exists(getArgument(0).(ArrayCreationExpr).getInit())
then
// Count the number of elements in the initializer, and find the matching constructors.
matchConstructorArguments(result,
count(getArgument(0).(ArrayCreationExpr).getInit().getAnInit()))
else
// Could be any of the constructors on this class.
any()
else
/*
* No var-args in play, just use the number of arguments to the `newInstance(..)` to determine
* which constructors may be called.
*/
matchConstructorArguments(result, getNumArgument())
}
/**
@@ -263,10 +274,9 @@ class NewInstance extends MethodAccess {
* provided for the enclosing instance.
*/
private predicate matchConstructorArguments(Constructor c, int numArguments) {
if expectsEnclosingInstance(c.getDeclaringType()) then
c.getNumberOfParameters() = numArguments - 1
else
c.getNumberOfParameters() = numArguments
if expectsEnclosingInstance(c.getDeclaringType())
then c.getNumberOfParameters() = numArguments - 1
else c.getNumberOfParameters() = numArguments
}
/**
@@ -296,15 +306,15 @@ class NewInstance extends MethodAccess {
* cast.
*/
private Type getCastInferredConstructedTypes() {
exists(CastExpr cast |
cast.getExpr() = this or cast.getExpr().(ParExpr).getExpr() = this
|
result = cast.getType() or
exists(CastExpr cast | cast.getExpr() = this or cast.getExpr().(ParExpr).getExpr() = this |
result = cast.getType()
or
(
/*
* If we cast the result of this method, then this is either the type specified, or a
* sub-type of that type. Make sure we exclude overly generic types such as `Object`.
*/
not overlyGenericType(cast.getType()) and
hasSubtype*(cast.getType(), result)
)
@@ -316,9 +326,7 @@ class NewInstance extends MethodAccess {
* A `MethodAccess` on a `Class` element.
*/
class ClassMethodAccess extends MethodAccess {
ClassMethodAccess() {
this.getCallee().getDeclaringType() instanceof TypeClass
}
ClassMethodAccess() { this.getCallee().getDeclaringType() instanceof TypeClass }
/**
* Gets an inferred type for the `Class` represented by this expression.
@@ -345,14 +353,14 @@ class ReflectiveMethodAccess extends ClassMethodAccess {
*/
Method inferAccessedMethod() {
(
if this.getCallee().hasName("getDeclaredMethod") then
if this.getCallee().hasName("getDeclaredMethod")
then
// The method must be declared on the type itself.
result.getDeclaringType() = getInferredClassType()
else
// The method may be declared on an inferred type or a super-type.
getInferredClassType().inherits(result)
)
and
) and
// Only consider instances where the method name is provided as a `StringLiteral`.
result.hasName(getArgument(0).(StringLiteral).getRepresentedString())
}
@@ -362,16 +370,12 @@ class ReflectiveMethodAccess extends ClassMethodAccess {
* A call to `Class.getAnnotation(..)`.
*/
class ReflectiveAnnotationAccess extends ClassMethodAccess {
ReflectiveAnnotationAccess() {
this.getCallee().hasName("getAnnotation")
}
ReflectiveAnnotationAccess() { this.getCallee().hasName("getAnnotation") }
/**
* Gets a possible annotation type for this reflective annotation access.
*/
AnnotationType getAPossibleAnnotationType() {
result = inferClassParameterType(getArgument(0))
}
AnnotationType getAPossibleAnnotationType() { result = inferClassParameterType(getArgument(0)) }
}
/**
@@ -385,15 +389,15 @@ class ReflectiveFieldAccess extends ClassMethodAccess {
Field inferAccessedField() {
(
if this.getCallee().hasName("getDeclaredField") then
if this.getCallee().hasName("getDeclaredField")
then
// Declared fields must be on the type itself.
result.getDeclaringType() = getInferredClassType()
else
(
// This field must be public, and be inherited by one of the inferred class types.
result.isPublic() and
getInferredClassType().inherits(result)
)
else (
// This field must be public, and be inherited by one of the inferred class types.
result.isPublic() and
getInferredClassType().inherits(result)
)
) and
result.hasName(getArgument(0).(StringLiteral).getRepresentedString())
}

View File

@@ -10,16 +10,13 @@ private import frameworks.google.GoogleHttpClientApi
* A serializable field may be read without code referencing it,
* due to the use of serialization.
*/
abstract class SerializableField extends Field {
abstract class SerializableField extends Field { }
}
/**
* A deserializable field may be written without code referencing it,
* due to the use of serialization.
*/
abstract class DeserializableField extends Field {
}
abstract class DeserializableField extends Field { }
/**
* A non-`transient` field in a type that (directly or indirectly) implements the `Serializable` interface

View File

@@ -16,13 +16,13 @@ class Stmt extends StmtParent, ExprParent, @stmt {
* Gets the immediately enclosing callable (method or constructor)
* whose body contains this statement.
*/
Callable getEnclosingCallable() { stmts(this,_,_,_,result) }
Callable getEnclosingCallable() { stmts(this, _, _, _, result) }
/** Gets the index of this statement as a child of its parent. */
int getIndex() { stmts(this,_,_,result,_) }
int getIndex() { stmts(this, _, _, result, _) }
/** Gets the parent of this statement. */
StmtParent getParent() { stmts(this,_,result,_,_) }
StmtParent getParent() { stmts(this, _, result, _, _) }
/** Holds if this statement is the child of the specified parent at the specified (zero-based) position. */
predicate isNthChildOf(StmtParent parent, int index) {
@@ -49,11 +49,10 @@ class Stmt extends StmtParent, ExprParent, @stmt {
}
/** A statement parent is any element that can have a statement as its child. */
class StmtParent extends @stmtparent, Top {
}
class StmtParent extends @stmtparent, Top { }
/** A block of statements. */
class Block extends Stmt,@block {
class Block extends Stmt, @block {
/** Gets a statement that is an immediate child of this block. */
Stmt getAStmt() { result.getParent() = this }
@@ -64,7 +63,7 @@ class Block extends Stmt,@block {
int getNumStmt() { result = count(this.getAStmt()) }
/** Gets the last statement in this block. */
Stmt getLastStmt() { result = getStmt(getNumStmt()-1) }
Stmt getLastStmt() { result = getStmt(getNumStmt() - 1) }
/** Gets a printable representation of this statement. May include more detail than `toString()`. */
override string pp() { result = "{ ... }" }
@@ -95,11 +94,11 @@ abstract class ConditionalStmt extends Stmt {
*
* DEPRECATED: use `ConditionNode.getATrueSuccessor()` instead.
*/
deprecated abstract Stmt getTrueSuccessor();
abstract deprecated Stmt getTrueSuccessor();
}
/** An `if` statement. */
class IfStmt extends ConditionalStmt,@ifstmt {
class IfStmt extends ConditionalStmt, @ifstmt {
/** Gets the boolean condition of this `if` statement. */
override Expr getCondition() { result.isNthChildOf(this, 0) }
@@ -127,16 +126,14 @@ class IfStmt extends ConditionalStmt,@ifstmt {
}
/** A `for` loop. */
class ForStmt extends ConditionalStmt,@forstmt {
class ForStmt extends ConditionalStmt, @forstmt {
/**
* Gets an initializer expression of the loop.
*
* This may be an assignment expression or a
* local variable declaration expression.
*/
Expr getAnInit() {
exists(int index | result.isNthChildOf(this, index) | index <= -1)
}
Expr getAnInit() { exists(int index | result.isNthChildOf(this, index) | index <= -1) }
/** Gets the initializer expression of the loop at the specified (zero-based) position. */
Expr getInit(int index) {
@@ -148,9 +145,7 @@ class ForStmt extends ConditionalStmt,@forstmt {
override Expr getCondition() { result.isNthChildOf(this, 1) }
/** Gets an update expression of this `for` loop. */
Expr getAnUpdate() {
exists(int index | result.isNthChildOf(this, index) | index >= 3)
}
Expr getAnUpdate() { exists(int index | result.isNthChildOf(this, index) | index >= 3) }
/** Gets the update expression of this loop at the specified (zero-based) position. */
Expr getUpdate(int index) {
@@ -189,16 +184,14 @@ class ForStmt extends ConditionalStmt,@forstmt {
}
/** Gets a printable representation of this statement. May include more detail than `toString()`. */
override string pp() {
result = "for (...;...;...) " + this.getStmt().pp()
}
override string pp() { result = "for (...;...;...) " + this.getStmt().pp() }
/** This statement's Halstead ID (used to compute Halstead metrics). */
override string getHalsteadID() { result = "ForStmt" }
}
/** An enhanced `for` loop. (Introduced in Java 5.) */
class EnhancedForStmt extends Stmt,@enhancedforstmt {
class EnhancedForStmt extends Stmt, @enhancedforstmt {
/** Gets the local variable declaration expression of this enhanced `for` loop. */
LocalVariableDeclExpr getVariable() { result.getParent() = this }
@@ -209,16 +202,14 @@ class EnhancedForStmt extends Stmt,@enhancedforstmt {
Stmt getStmt() { result.getParent() = this }
/** Gets a printable representation of this statement. May include more detail than `toString()`. */
override string pp() {
result = "for (...) " + this.getStmt().pp()
}
override string pp() { result = "for (...) " + this.getStmt().pp() }
/** This statement's Halstead ID (used to compute Halstead metrics). */
override string getHalsteadID() { result = "EnhancedForStmt" }
}
/** A `while` loop. */
class WhileStmt extends ConditionalStmt,@whilestmt {
class WhileStmt extends ConditionalStmt, @whilestmt {
/** Gets the boolean condition of this `while` loop. */
override Expr getCondition() { result.getParent() = this }
@@ -232,16 +223,14 @@ class WhileStmt extends ConditionalStmt,@whilestmt {
override Stmt getTrueSuccessor() { result = getStmt() }
/** Gets a printable representation of this statement. May include more detail than `toString()`. */
override string pp() {
result = "while (...) " + this.getStmt().pp()
}
override string pp() { result = "while (...) " + this.getStmt().pp() }
/** This statement's Halstead ID (used to compute Halstead metrics). */
override string getHalsteadID() { result = "WhileStmt" }
}
/** A `do` loop. */
class DoStmt extends ConditionalStmt,@dostmt {
class DoStmt extends ConditionalStmt, @dostmt {
/** Gets the condition of this `do` loop. */
override Expr getCondition() { result.getParent() = this }
@@ -255,9 +244,7 @@ class DoStmt extends ConditionalStmt,@dostmt {
override Stmt getTrueSuccessor() { result = getStmt() }
/** Gets a printable representation of this statement. May include more detail than `toString()`. */
override string pp() {
result = "do " + this.getStmt().pp() + " while (...)"
}
override string pp() { result = "do " + this.getStmt().pp() + " while (...)" }
/** This statement's Halstead ID (used to compute Halstead metrics). */
override string getHalsteadID() { result = "DoStmt" }
@@ -292,7 +279,7 @@ class LoopStmt extends Stmt {
}
/** A `try` statement. */
class TryStmt extends Stmt,@trystmt {
class TryStmt extends Stmt, @trystmt {
/** Gets the block of the `try` statement. */
Stmt getBlock() { result.isNthChildOf(this, -1) }
@@ -312,9 +299,7 @@ class TryStmt extends Stmt,@trystmt {
Block getFinally() { result.isNthChildOf(this, -2) }
/** Gets a resource variable declaration, if any. */
LocalVariableDeclStmt getAResourceDecl() {
result.getParent() = this and result.getIndex() <= -3
}
LocalVariableDeclStmt getAResourceDecl() { result.getParent() = this and result.getIndex() <= -3 }
/** Gets the resource variable declaration at the specified position in this `try` statement. */
LocalVariableDeclStmt getResourceDecl(int index) {
@@ -323,9 +308,7 @@ class TryStmt extends Stmt,@trystmt {
}
/** Gets a resource expression, if any. */
VarAccess getAResourceExpr() {
result.getParent() = this and result.getIndex() <= -3
}
VarAccess getAResourceExpr() { result.getParent() = this and result.getIndex() <= -3 }
/** Gets the resource expression at the specified position in this `try` statement. */
VarAccess getResourceExpr(int index) {
@@ -334,9 +317,7 @@ class TryStmt extends Stmt,@trystmt {
}
/** Gets a resource in this `try` statement, if any. */
ExprParent getAResource() {
result = getAResourceDecl() or result = getAResourceExpr()
}
ExprParent getAResource() { result = getAResourceDecl() or result = getAResourceExpr() }
/** Gets the resource at the specified position in this `try` statement. */
ExprParent getResource(int index) {
@@ -350,16 +331,14 @@ class TryStmt extends Stmt,@trystmt {
}
/** Gets a printable representation of this statement. May include more detail than `toString()`. */
override string pp() {
result = "try " + this.getBlock().pp() + " catch (...)"
}
override string pp() { result = "try " + this.getBlock().pp() + " catch (...)" }
/** This statement's Halstead ID (used to compute Halstead metrics). */
override string getHalsteadID() { result = "TryStmt" }
}
/** A `catch` clause in a `try` statement. */
class CatchClause extends Stmt,@catchclause {
class CatchClause extends Stmt, @catchclause {
/** Gets the block of this `catch` clause. */
Block getBlock() { result.getParent() = this }
@@ -370,9 +349,7 @@ class CatchClause extends Stmt,@catchclause {
LocalVariableDeclExpr getVariable() { result.getParent() = this }
/** Holds if this `catch` clause is a _multi_-`catch` clause. */
predicate isMultiCatch() {
this.getVariable().getTypeAccess() instanceof UnionTypeAccess
}
predicate isMultiCatch() { this.getVariable().getTypeAccess() instanceof UnionTypeAccess }
/** Gets a type caught by this `catch` clause. */
RefType getACaughtType() {
@@ -383,16 +360,14 @@ class CatchClause extends Stmt,@catchclause {
}
/** Gets a printable representation of this statement. May include more detail than `toString()`. */
override string pp() {
result = "catch (...) " + this.getBlock().pp()
}
override string pp() { result = "catch (...) " + this.getBlock().pp() }
/** This statement's Halstead ID (used to compute Halstead metrics). */
override string getHalsteadID() { result = "CatchClause" }
}
/** A `switch` statement. */
class SwitchStmt extends Stmt,@switchstmt {
class SwitchStmt extends Stmt, @switchstmt {
/** Gets an immediate child statement of this `switch` statement. */
Stmt getAStmt() { result.getParent() = this }
@@ -418,9 +393,7 @@ class SwitchStmt extends Stmt,@switchstmt {
Expr getExpr() { result.getParent() = this }
/** Gets a printable representation of this statement. May include more detail than `toString()`. */
override string pp() {
result = "switch (...)"
}
override string pp() { result = "switch (...)" }
/** This statement's Halstead ID (used to compute Halstead metrics). */
override string getHalsteadID() { result = "SwitchStmt" }
@@ -431,9 +404,7 @@ class SwitchStmt extends Stmt,@switchstmt {
*
* This includes both normal `case`s and the `default` case.
*/
class SwitchCase extends Stmt, @case {
SwitchStmt getSwitch() { result.getACase() = this }
}
class SwitchCase extends Stmt, @case { SwitchStmt getSwitch() { result.getACase() = this } }
/** A constant `case` of a switch statement. */
class ConstCase extends SwitchCase {
@@ -443,9 +414,7 @@ class ConstCase extends SwitchCase {
Expr getValue() { result.getParent() = this }
/** Gets a printable representation of this statement. May include more detail than `toString()`. */
override string pp() {
result = "case ...:"
}
override string pp() { result = "case ...:" }
/** This statement's Halstead ID (used to compute Halstead metrics). */
override string getHalsteadID() { result = "ConstCase" }
@@ -456,16 +425,14 @@ class DefaultCase extends SwitchCase {
DefaultCase() { not exists(Expr e | e.getParent() = this) }
/** Gets a printable representation of this statement. May include more detail than `toString()`. */
override string pp() {
result = "default"
}
override string pp() { result = "default" }
/** This statement's Halstead ID (used to compute Halstead metrics). */
override string getHalsteadID() { result = "DefaultCase" }
}
/** A `synchronized` statement. */
class SynchronizedStmt extends Stmt,@synchronizedstmt {
class SynchronizedStmt extends Stmt, @synchronizedstmt {
/** Gets the expression on which this `synchronized` statement synchronizes. */
Expr getExpr() { result.getParent() = this }
@@ -473,37 +440,31 @@ class SynchronizedStmt extends Stmt,@synchronizedstmt {
Stmt getBlock() { result.getParent() = this }
/** Gets a printable representation of this statement. May include more detail than `toString()`. */
override string pp() {
result = "synchronized (...) " + this.getBlock().pp()
}
override string pp() { result = "synchronized (...) " + this.getBlock().pp() }
/** This statement's Halstead ID (used to compute Halstead metrics). */
override string getHalsteadID() { result = "SynchronizedStmt" }
}
/** A `return` statement. */
class ReturnStmt extends Stmt,@returnstmt {
class ReturnStmt extends Stmt, @returnstmt {
/** Gets the expression returned by this `return` statement, if any. */
Expr getResult() { result.getParent() = this }
/** Gets a printable representation of this statement. May include more detail than `toString()`. */
override string pp() {
result = "return ..."
}
override string pp() { result = "return ..." }
/** This statement's Halstead ID (used to compute Halstead metrics). */
override string getHalsteadID() { result = "ReturnStmt" }
}
/** A `throw` statement. */
class ThrowStmt extends Stmt,@throwstmt {
class ThrowStmt extends Stmt, @throwstmt {
/** Gets the expression thrown by this `throw` statement. */
Expr getExpr() { result.getParent() = this }
/** Gets a printable representation of this statement. May include more detail than `toString()`. */
override string pp() {
result = "throw ..."
}
override string pp() { result = "throw ..." }
/** This statement's Halstead ID (used to compute Halstead metrics). */
override string getHalsteadID() { result = "ThrowStmt" }
@@ -522,10 +483,11 @@ class ThrowStmt extends Stmt,@throwstmt {
}
private Stmt findEnclosing() {
result = getParent() or
result = getParent()
or
exists(Stmt mid |
mid = findEnclosing() and
not exists(this.catchClauseForThis((TryStmt)mid)) and
not exists(this.catchClauseForThis(mid.(TryStmt))) and
result = mid.getParent()
)
}
@@ -533,7 +495,7 @@ class ThrowStmt extends Stmt,@throwstmt {
private CatchClause catchClauseForThis(TryStmt try) {
result = try.getACatchClause() and
result.getEnclosingCallable() = this.getEnclosingCallable() and
((RefType)getExpr().getType()).hasSupertype*((RefType)result.getVariable().getType()) and
(getExpr().getType().(RefType)).hasSupertype*(result.getVariable().getType().(RefType)) and
not this.getParent+() = result
}
}
@@ -554,14 +516,13 @@ class JumpStmt extends Stmt {
namestrings(result.getLabel(), _, this)
}
private Stmt getLabelTarget() {
result = getTargetLabel().getStmt()
}
private Stmt getLabelTarget() { result = getTargetLabel().getStmt() }
private Stmt getAPotentialTarget() {
this.getParent+() = result and
(
result instanceof LoopStmt or
result instanceof LoopStmt
or
this instanceof BreakStmt and result instanceof SwitchStmt
)
}
@@ -575,25 +536,23 @@ class JumpStmt extends Stmt {
* Gets the statement that this `break` or `continue` jumps to.
*/
Stmt getTarget() {
result = getLabelTarget() or
result = getLabelTarget()
or
(not exists(getLabelTarget()) and result = getEnclosingTarget())
}
}
/** A `break` statement. */
class BreakStmt extends Stmt,@breakstmt {
class BreakStmt extends Stmt, @breakstmt {
/** Gets the label targeted by this `break` statement, if any. */
string getLabel() { namestrings(result,_,this) }
string getLabel() { namestrings(result, _, this) }
/** Holds if this `break` statement has an explicit label. */
predicate hasLabel() { exists(string s | s = this.getLabel()) }
/** Gets a printable representation of this statement. May include more detail than `toString()`. */
override string pp() {
if this.hasLabel() then
result = "break " + this.getLabel()
else
result = "break"
if this.hasLabel() then result = "break " + this.getLabel() else result = "break"
}
/** This statement's Halstead ID (used to compute Halstead metrics). */
@@ -601,19 +560,16 @@ class BreakStmt extends Stmt,@breakstmt {
}
/** A `continue` statement. */
class ContinueStmt extends Stmt,@continuestmt {
class ContinueStmt extends Stmt, @continuestmt {
/** Gets the label targeted by this `continue` statement, if any. */
string getLabel() { namestrings(result,_,this) }
string getLabel() { namestrings(result, _, this) }
/** Holds if this `continue` statement has an explicit label. */
predicate hasLabel() { exists(string s | s = this.getLabel()) }
/** Gets a printable representation of this statement. May include more detail than `toString()`. */
override string pp() {
if this.hasLabel() then
result = "continue " + this.getLabel()
else
result = "continue"
if this.hasLabel() then result = "continue " + this.getLabel() else result = "continue"
}
/** This statement's Halstead ID (used to compute Halstead metrics). */
@@ -621,11 +577,9 @@ class ContinueStmt extends Stmt,@continuestmt {
}
/** The empty statement. */
class EmptyStmt extends Stmt,@emptystmt {
class EmptyStmt extends Stmt, @emptystmt {
/** Gets a printable representation of this statement. May include more detail than `toString()`. */
override string pp() {
result = ";"
}
override string pp() { result = ";" }
/** This statement's Halstead ID (used to compute Halstead metrics). */
override string getHalsteadID() { result = "EmptyStmt" }
@@ -636,14 +590,12 @@ class EmptyStmt extends Stmt,@emptystmt {
*
* Certain kinds of expressions may be used as statements by appending a semicolon.
*/
class ExprStmt extends Stmt,@exprstmt {
class ExprStmt extends Stmt, @exprstmt {
/** Gets the expression of this expression statement. */
Expr getExpr() { result.getParent() = this }
/** Gets a printable representation of this statement. May include more detail than `toString()`. */
override string pp() {
result = "...;"
}
override string pp() { result = "...;" }
/** This statement's Halstead ID (used to compute Halstead metrics). */
override string getHalsteadID() { result = "ExprStmt" }
@@ -653,7 +605,7 @@ class ExprStmt extends Stmt,@exprstmt {
getEnclosingCallable() instanceof InitializerMethod and
exists(FieldDeclaration fd, Location fdl, Location sl |
fdl = fd.getLocation() and sl = getLocation()
|
|
fdl.getFile() = sl.getFile() and
fdl.getStartLine() = sl.getStartLine() and
fdl.getStartColumn() = sl.getStartColumn()
@@ -662,36 +614,31 @@ class ExprStmt extends Stmt,@exprstmt {
}
/** A labeled statement. */
class LabeledStmt extends Stmt,@labeledstmt {
class LabeledStmt extends Stmt, @labeledstmt {
/** Gets the statement of this labeled statement. */
Stmt getStmt() { result.getParent() = this }
/** Gets the label of this labeled statement. */
string getLabel() { namestrings(result,_,this) }
string getLabel() { namestrings(result, _, this) }
/** Gets a printable representation of this statement. May include more detail than `toString()`. */
override string pp() {
result = this.getLabel() + ": " + this.getStmt().pp()
}
override string pp() { result = this.getLabel() + ": " + this.getStmt().pp() }
/** This statement's Halstead ID (used to compute Halstead metrics). */
override string getHalsteadID() { result = this.getLabel() + ":" }
}
/** An `assert` statement. */
class AssertStmt extends Stmt,@assertstmt {
class AssertStmt extends Stmt, @assertstmt {
/** Gets the boolean expression of this `assert` statement. */
Expr getExpr() { exprs(result,_,_,this,_) and result.getIndex() = 0 }
Expr getExpr() { exprs(result, _, _, this, _) and result.getIndex() = 0 }
/** Gets the assertion message expression, if any. */
Expr getMessage() { exprs(result,_,_,this,_) and result.getIndex() = 1 }
Expr getMessage() { exprs(result, _, _, this, _) and result.getIndex() = 1 }
/** Gets a printable representation of this statement. May include more detail than `toString()`. */
override string pp() {
if exists(this.getMessage()) then
result = "assert ... : ..."
else
result = "assert ..."
if exists(this.getMessage()) then result = "assert ... : ..." else result = "assert ..."
}
/** This statement's Halstead ID (used to compute Halstead metrics). */
@@ -699,7 +646,7 @@ class AssertStmt extends Stmt,@assertstmt {
}
/** A statement that declares one or more local variables. */
class LocalVariableDeclStmt extends Stmt,@localvariabledeclstmt {
class LocalVariableDeclStmt extends Stmt, @localvariabledeclstmt {
/** Gets a declared variable. */
LocalVariableDeclExpr getAVariable() { result.getParent() = this }
@@ -710,28 +657,22 @@ class LocalVariableDeclStmt extends Stmt,@localvariabledeclstmt {
}
/** Gets an index of a variable declared in this local variable declaration statement. */
int getAVariableIndex() {
exists(getVariable(result))
}
int getAVariableIndex() { exists(getVariable(result)) }
/** Gets a printable representation of this statement. May include more detail than `toString()`. */
override string pp() {
result = "local variable declaration"
}
override string pp() { result = "local variable declaration" }
/** This statement's Halstead ID (used to compute Halstead metrics). */
override string getHalsteadID() { result = "LocalVariableDeclStmt" }
}
/** A statement that declares a local class. */
class LocalClassDeclStmt extends Stmt,@localclassdeclstmt {
class LocalClassDeclStmt extends Stmt, @localclassdeclstmt {
/** Gets the local class declared by this statement. */
LocalClass getLocalClass() { isLocalClass(result,this) }
LocalClass getLocalClass() { isLocalClass(result, this) }
/** Gets a printable representation of this statement. May include more detail than `toString()`. */
override string pp() {
result = "local class declaration: " + this.getLocalClass().toString()
}
override string pp() { result = "local class declaration: " + this.getLocalClass().toString() }
/** This statement's Halstead ID (used to compute Halstead metrics). */
override string getHalsteadID() { result = "LocalClassDeclStmt" }
@@ -758,7 +699,7 @@ class ThisConstructorInvocationStmt extends Stmt, ConstructorCall, @constructori
}
/** Gets the constructor invoked by this constructor invocation. */
override Constructor getConstructor() { callableBinding(this,result) }
override Constructor getConstructor() { callableBinding(this, result) }
override Expr getQualifier() { none() }
@@ -769,9 +710,7 @@ class ThisConstructorInvocationStmt extends Stmt, ConstructorCall, @constructori
override Stmt getEnclosingStmt() { result = this }
/** Gets a printable representation of this statement. May include more detail than `toString()`. */
override string pp() {
result = "this(...)"
}
override string pp() { result = "this(...)" }
/** Gets a printable representation of this statement. */
override string toString() { result = pp() }
@@ -801,7 +740,7 @@ class SuperConstructorInvocationStmt extends Stmt, ConstructorCall, @superconstr
}
/** Gets the constructor invoked by this constructor invocation. */
override Constructor getConstructor() { callableBinding(this,result) }
override Constructor getConstructor() { callableBinding(this, result) }
/** Gets the qualifier expression of this `super(...)` constructor invocation, if any. */
override Expr getQualifier() { result.isNthChildOf(this, -1) }
@@ -813,9 +752,7 @@ class SuperConstructorInvocationStmt extends Stmt, ConstructorCall, @superconstr
override Stmt getEnclosingStmt() { result = this }
/** Gets a printable representation of this statement. May include more detail than `toString()`. */
override string pp() {
result = "super(...)"
}
override string pp() { result = "super(...)" }
/** Gets a printable representation of this statement. */
override string toString() { result = pp() }

View File

@@ -20,33 +20,32 @@ import JDK
cached
predicate hasSubtype(RefType t, Type sub) {
// Direct subtype.
(extendsReftype(sub, t) and t != sub) or
implInterface(sub, t) or
(extendsReftype(sub, t) and t != sub)
or
implInterface(sub, t)
or
// A parameterized type `T<A>` is a subtype of the corresponding raw type `T<>`.
(parSubtypeRaw(t, sub) and t != sub) or
(parSubtypeRaw(t, sub) and t != sub)
or
// Array subtyping is covariant.
(arraySubtype(t, sub) and t != sub) or
(arraySubtype(t, sub) and t != sub)
or
// Type parameter containment for parameterized types.
(parContainmentSubtype(t, sub) and t != sub) or
(parContainmentSubtype(t, sub) and t != sub)
or
// Type variables are subtypes of their upper bounds.
(typeVarSubtypeBound(t, sub) and t != sub)
}
private
predicate typeVarSubtypeBound(RefType t, TypeVariable tv) {
if tv.hasTypeBound() then
t = tv.getATypeBound().getType()
else
t instanceof TypeObject
private predicate typeVarSubtypeBound(RefType t, TypeVariable tv) {
if tv.hasTypeBound() then t = tv.getATypeBound().getType() else t instanceof TypeObject
}
private
predicate parSubtypeRaw(RefType t, ParameterizedType sub) {
private predicate parSubtypeRaw(RefType t, ParameterizedType sub) {
t = sub.getErasure().(GenericType).getRawType()
}
private
predicate arraySubtype(Array sup, Array sub) {
private predicate arraySubtype(Array sup, Array sub) {
hasSubtype(sup.getComponentType(), sub.getComponentType())
}
@@ -67,10 +66,10 @@ predicate arraySubtype(Array sup, Array sub) {
* base case for `typeArgumentsContain` is therefore `n=1` and this allows an
* improved join order implemented by `contains01`.
*/
private
predicate parContainmentSubtype(ParameterizedType pt, ParameterizedType psub) {
private predicate parContainmentSubtype(ParameterizedType pt, ParameterizedType psub) {
pt != psub and
typeArgumentsContain(_, pt, psub, pt.getNumberOfTypeArguments()-1)
typeArgumentsContain(_, pt, psub, pt.getNumberOfTypeArguments() - 1)
or
typeArgumentsContain0(_, pt, psub)
}
@@ -78,8 +77,7 @@ predicate parContainmentSubtype(ParameterizedType pt, ParameterizedType psub) {
/**
* Gets the `index`-th type parameter of `t`, which is a parameterization of `g`.
*/
private
RefType parameterisationTypeArgument(GenericType g, ParameterizedType t, int index) {
private RefType parameterisationTypeArgument(GenericType g, ParameterizedType t, int index) {
g = t.getGenericType() and
result = t.getTypeArgument(index)
}
@@ -89,7 +87,9 @@ private predicate varianceCandidate(ParameterizedType pt) {
}
pragma[noinline]
private RefType parameterisationTypeArgumentVarianceCand(GenericType g, ParameterizedType t, int index) {
private RefType parameterisationTypeArgumentVarianceCand(
GenericType g, ParameterizedType t, int index
) {
result = parameterisationTypeArgument(g, t, index) and
varianceCandidate(t)
}
@@ -100,15 +100,18 @@ private RefType parameterisationTypeArgumentVarianceCand(GenericType g, Paramete
* being parameterizations of `g`.
*/
pragma[nomagic]
private
predicate typeArgumentsContain(GenericType g, ParameterizedType s, ParameterizedType t, int n) {
private predicate typeArgumentsContain(
GenericType g, ParameterizedType s, ParameterizedType t, int n
) {
contains01(g, s, t) and n = 1
or
contains(g, s, t, n) and
typeArgumentsContain(g, s, t, n-1)
typeArgumentsContain(g, s, t, n - 1)
}
private predicate typeArgumentsContain0(GenericType g, ParameterizedType sParm, ParameterizedType tParm) {
private predicate typeArgumentsContain0(
GenericType g, ParameterizedType sParm, ParameterizedType tParm
) {
exists(RefType s, RefType t |
containsAux0(g, tParm, s, t) and
s = parameterisationTypeArgument(g, sParm, 0) and
@@ -136,14 +139,18 @@ private predicate contains01(GenericType g, ParameterizedType sParm, Parameteriz
}
pragma[nomagic]
private predicate contains01Aux0(GenericType g, ParameterizedType tParm, RefType s0, RefType t0, RefType t1) {
private predicate contains01Aux0(
GenericType g, ParameterizedType tParm, RefType s0, RefType t0, RefType t1
) {
typeArgumentContains(g, s0, t0, 0) and
t0 = parameterisationTypeArgument(g, tParm, 0) and
t1 = parameterisationTypeArgument(g, tParm, 1)
}
pragma[nomagic]
private predicate contains01Aux1(GenericType g, ParameterizedType sParm, RefType s0, RefType s1, RefType t1) {
private predicate contains01Aux1(
GenericType g, ParameterizedType sParm, RefType s0, RefType s1, RefType t1
) {
typeArgumentContains(g, s1, t1, 1) and
s0 = parameterisationTypeArgumentVarianceCand(g, sParm, 0) and
s1 = parameterisationTypeArgumentVarianceCand(g, sParm, 1)
@@ -164,8 +171,7 @@ private predicate containsAux0(GenericType g, ParameterizedType tParm, RefType s
*
* See JLS 4.5.1, Type Arguments of Parameterized Types.
*/
private
predicate contains(GenericType g, ParameterizedType sParm, ParameterizedType tParm, int n) {
private predicate contains(GenericType g, ParameterizedType sParm, ParameterizedType tParm, int n) {
exists(RefType s, RefType t |
containsAux(g, tParm, n, s, t) and
s = parameterisationTypeArgumentVarianceCand(g, sParm, n)
@@ -201,19 +207,20 @@ private predicate typeArgumentContainsAux2(GenericType g, RefType s, RefType t,
*
* See JLS 4.5.1, Type Arguments of Parameterized Types.
*/
private
predicate typeArgumentContainsAux1(RefType s, RefType t, int n) {
private predicate typeArgumentContainsAux1(RefType s, RefType t, int n) {
exists(int i |
s = parameterisationTypeArgumentVarianceCand(_, _, i) and
t = parameterisationTypeArgument(_, _, n) and
i <= n and n <= i
|
i <= n and
n <= i
|
exists(RefType tUpperBound | tUpperBound = t.(Wildcard).getUpperBound().getType() |
// ? extends T <= ? extends S if T <: S
hasSubtypeStar0(s.(Wildcard).getUpperBound().getType(), tUpperBound) or
// ? extends T <= ?
s.(Wildcard).isUnconstrained()
) or
)
or
exists(RefType tLowerBound | tLowerBound = t.(Wildcard).getLowerBound().getType() |
// ? super T <= ? super S if s <: T
hasSubtypeStar0(tLowerBound, s.(Wildcard).getLowerBound().getType()) or
@@ -221,11 +228,14 @@ predicate typeArgumentContainsAux1(RefType s, RefType t, int n) {
s.(Wildcard).isUnconstrained() or
// ? super T <= ? extends Object
wildcardExtendsObject(s)
) or
)
or
// T <= T
s = t or
s = t
or
// T <= ? extends T
hasSubtypeStar0(s.(Wildcard).getUpperBound().getType(), t) or
hasSubtypeStar0(s.(Wildcard).getUpperBound().getType(), t)
or
// T <= ? super T
hasSubtypeStar0(t, s.(Wildcard).getLowerBound().getType())
)
@@ -239,9 +249,7 @@ private predicate wildcardExtendsObject(Wildcard wc) {
/**
* DEPRECATED: Use `hasSubtype*` instead.
*/
deprecated predicate hasSubtypeStar(RefType t, RefType sub) {
hasSubtype*(t, sub)
}
deprecated predicate hasSubtypeStar(RefType t, RefType sub) { hasSubtype*(t, sub) }
private predicate hasSubtypeStar0(RefType t, RefType sub) {
sub = t
@@ -253,13 +261,13 @@ private predicate hasSubtypeStar0(RefType t, RefType sub) {
/** Holds if type `t` declares member `m`. */
predicate declaresMember(Type t, @member m) {
methods(m,_,_,_,t,_)
methods(m, _, _, _, t, _)
or
constrs(m,_,_,_,t,_)
constrs(m, _, _, _, t, _)
or
fields(m,_,_,t,_)
fields(m, _, _, t, _)
or
enclInReftype(m,t) and
enclInReftype(m, t) and
// Since the type `@member` in the dbscheme includes all `@reftype`s,
// anonymous and local classes need to be excluded here.
not m instanceof AnonymousClass and
@@ -311,9 +319,7 @@ class Array extends RefType, @array {
/**
* Gets the JVM descriptor for this type, as used in bytecode.
*/
override string getTypeDescriptor() {
result = "[" + this.getComponentType().getTypeDescriptor()
}
override string getTypeDescriptor() { result = "[" + this.getComponentType().getTypeDescriptor() }
}
/**
@@ -323,29 +329,27 @@ class Array extends RefType, @array {
class RefType extends Type, Annotatable, Modifiable, @reftype {
/** Gets the package in which this type is declared. */
Package getPackage() {
classes(this,_,result,_) or
interfaces(this,_,result,_)
classes(this, _, result, _) or
interfaces(this, _, result, _)
}
/** Gets the type in which this reference type is enclosed, if any. */
RefType getEnclosingType() {
enclInReftype(this, result)
}
RefType getEnclosingType() { enclInReftype(this, result) }
/** Gets the compilation unit in which this type is declared. */
override CompilationUnit getCompilationUnit() { result = this.getFile() }
/** Holds if `t` is an immediate supertype of this type. */
predicate hasSupertype(RefType t) { hasSubtype(t,this) }
predicate hasSupertype(RefType t) { hasSubtype(t, this) }
/** Holds if `t` is an immediate subtype of this type. */
predicate hasSubtype(RefType t) { hasSubtype(this,t) }
predicate hasSubtype(RefType t) { hasSubtype(this, t) }
/** Gets a direct subtype of this type. */
RefType getASubtype() { hasSubtype(this,result) }
RefType getASubtype() { hasSubtype(this, result) }
/** Gets a direct supertype of this type. */
RefType getASupertype() { hasSubtype(result,this) }
RefType getASupertype() { hasSubtype(result, this) }
/** Gets a direct or indirect supertype of this type, including itself. */
RefType getAnAncestor() { hasSubtype*(result, this) }
@@ -413,9 +417,7 @@ class RefType extends Type, Annotatable, Modifiable, @reftype {
* Holds if this type declares or inherits method `m`, which is declared
* in `declaringType`.
*/
predicate hasMethod(Method m, RefType declaringType) {
hasMethod(m, declaringType, false)
}
predicate hasMethod(Method m, RefType declaringType) { hasMethod(m, declaringType, false) }
/**
* Holds if this type declares or inherits method `m`, which is declared
@@ -425,13 +427,14 @@ class RefType extends Type, Annotatable, Modifiable, @reftype {
*/
cached
predicate hasMethod(Method m, RefType declaringType, boolean hidden) {
hasNonInterfaceMethod(m, declaringType, hidden) or
hasNonInterfaceMethod(m, declaringType, hidden)
or
hasInterfaceMethod(m, declaringType) and hidden = false
}
private predicate noMethodExtraction() {
not methods(_,_,_,_,this,_) and
exists(Method m | methods(m,_,_,_,getSourceDeclaration(),_) and m.isInheritable())
not methods(_, _, _, _, this, _) and
exists(Method m | methods(m, _, _, _, getSourceDeclaration(), _) and m.isInheritable())
}
private predicate canInheritFromSupertype(RefType sup) {
@@ -446,25 +449,42 @@ class RefType extends Type, Annotatable, Modifiable, @reftype {
}
private predicate hasNonInterfaceMethod(Method m, RefType declaringType, boolean hidden) {
m = getAMethod() and this = declaringType and not declaringType instanceof Interface and hidden = false or
m = getAMethod() and
this = declaringType and
not declaringType instanceof Interface and
hidden = false
or
exists(RefType sup, boolean h1, boolean h2 |
(if m.isPackageProtected() and sup.getPackage() != this.getPackage() then h1 = true else h1 = false) and
(
if m.isPackageProtected() and sup.getPackage() != this.getPackage()
then h1 = true
else h1 = false
) and
(not sup instanceof Interface or this instanceof Interface) and
canInheritFromSupertype(sup) and
sup.hasNonInterfaceMethod(m, declaringType, h2) and
hidden = h1.booleanOr(h2) and
exists(string signature | methods(m,_,signature,_,_,_) and not methods(_,_,signature,_,this,_)) and
exists(string signature |
methods(m, _, signature, _, _, _) and not methods(_, _, signature, _, this, _)
) and
m.isInheritable()
)
}
private predicate cannotInheritInterfaceMethod(string signature) {
methods(_,_,signature,_,this,_) or
exists(Method m | hasNonInterfaceMethod(m, _, false) and methods(m,_,signature,_,_,_))
methods(_, _, signature, _, this, _)
or
exists(Method m | hasNonInterfaceMethod(m, _, false) and methods(m, _, signature, _, _, _))
}
private predicate interfaceMethodCandidateWithSignature(Method m, string signature, RefType declaringType) {
m = getAMethod() and this = declaringType and declaringType instanceof Interface and methods(m,_,signature,_,_,_) or
private predicate interfaceMethodCandidateWithSignature(
Method m, string signature, RefType declaringType
) {
m = getAMethod() and
this = declaringType and
declaringType instanceof Interface and
methods(m, _, signature, _, _, _)
or
exists(RefType sup |
sup.interfaceMethodCandidateWithSignature(m, signature, declaringType) and
not cannotInheritInterfaceMethod(signature) and
@@ -500,12 +520,14 @@ class RefType extends Type, Annotatable, Modifiable, @reftype {
/** Holds if this type declares or inherits the specified member. */
predicate inherits(Member m) {
exists(Field f | f = m |
f = getAField() or
not f.isPrivate() and not declaresField(f.getName()) and getASupertype().inherits(f) or
f = getAField()
or
not f.isPrivate() and not declaresField(f.getName()) and getASupertype().inherits(f)
or
getSourceDeclaration().inherits(f)
)
or
hasMethod((Method)m, _)
hasMethod(m.(Method), _)
}
/** Holds if this is a top-level type, which is not nested inside any other types. */
@@ -521,7 +543,7 @@ class RefType extends Type, Annotatable, Modifiable, @reftype {
*/
override string getTypeDescriptor() {
result = "L" + this.getPackage().getName().replaceAll(".", "/") + "/" +
this.getSourceDeclaration().nestedName() + ";"
this.getSourceDeclaration().nestedName() + ";"
}
/**
@@ -529,10 +551,7 @@ class RefType extends Type, Annotatable, Modifiable, @reftype {
*/
string getQualifiedName() {
exists(string pkgName | pkgName = getPackage().getName() |
if pkgName = "" then
result = nestedName()
else
result = pkgName + "." + nestedName()
if pkgName = "" then result = nestedName() else result = pkgName + "." + nestedName()
)
}
@@ -583,19 +602,17 @@ class RefType extends Type, Annotatable, Modifiable, @reftype {
}
/** A type that is the same as its source declaration. */
class SrcRefType extends RefType {
SrcRefType() { this.isSourceDeclaration() }
}
class SrcRefType extends RefType { SrcRefType() { this.isSourceDeclaration() } }
/** A class declaration. */
class Class extends RefType, @class {
/** Holds if this class is an anonymous class. */
predicate isAnonymous() { isAnonymClass(this,_) }
predicate isAnonymous() { isAnonymClass(this, _) }
/** Holds if this class is a local class. */
predicate isLocal() { isLocalClass(this,_) }
predicate isLocal() { isLocalClass(this, _) }
override RefType getSourceDeclaration() { classes(this,_,_,result) }
override RefType getSourceDeclaration() { classes(this, _, _, result) }
/**
* Gets an annotation that applies to this class.
@@ -603,7 +620,8 @@ class Class extends RefType, @class {
* Note that a class may inherit annotations from super-classes.
*/
override Annotation getAnAnnotation() {
result = RefType.super.getAnAnnotation() or
result = RefType.super.getAnAnnotation()
or
exists(AnnotationType tp | tp = result.getType() |
tp.isInherited() and
not exists(Annotation ann | ann = RefType.super.getAnAnnotation() | ann.getType() = tp) and
@@ -620,14 +638,16 @@ class IntersectionType extends RefType, @class {
shortname.matches("% & ...")
)
}
private RefType superType() { extendsReftype(this, result) }
private RefType superInterface() { implInterface(this, result) }
string getLongName() {
result = superType().toString() + concat(" & " + superInterface().toString())
}
RefType getFirstBound() {
extendsReftype(this, result)
}
RefType getFirstBound() { extendsReftype(this, result) }
}
/** An anonymous class. */
@@ -656,7 +676,9 @@ class AnonymousClass extends NestedClass {
*/
override string getTypeDescriptor() {
exists(RefType parent | parent = this.getEnclosingType() |
exists(int num | num = 1 + count(AnonymousClass other | other.rankInParent(parent) < rankInParent(parent)) |
exists(int num |
num = 1 + count(AnonymousClass other | other.rankInParent(parent) < rankInParent(parent))
|
exists(string parentWithSemi | parentWithSemi = parent.getTypeDescriptor() |
result = parentWithSemi.prefix(parentWithSemi.length() - 1) + "$" + num + ";"
)
@@ -667,7 +689,9 @@ class AnonymousClass extends NestedClass {
/** Gets the class instance expression where this anonymous class occurs. */
ClassInstanceExpr getClassInstanceExpr() { isAnonymClass(this, result) }
override string toString() { result = "new " + this.getClassInstanceExpr().getTypeName() + "(...) { ... }" }
override string toString() {
result = "new " + this.getClassInstanceExpr().getTypeName() + "(...) { ... }"
}
/**
* Gets the qualified name of this type.
@@ -689,32 +713,26 @@ class LocalClass extends NestedClass {
/** A top-level type. */
class TopLevelType extends RefType {
TopLevelType() {
not enclInReftype(this,_) and
not enclInReftype(this, _) and
(this instanceof Class or this instanceof Interface)
}
}
/** A top-level class. */
class TopLevelClass extends TopLevelType, Class {
}
class TopLevelClass extends TopLevelType, Class { }
/** A nested type is a type declared within another type. */
class NestedType extends RefType {
NestedType() {
enclInReftype(this,_)
}
NestedType() { enclInReftype(this, _) }
/** Gets the type enclosing this nested type. */
override RefType getEnclosingType() {
enclInReftype(this,result)
}
override RefType getEnclosingType() { enclInReftype(this, result) }
/** Gets the nesting depth of this nested type. Top-level types have nesting depth 0. */
int getNestingDepth() {
if getEnclosingType() instanceof NestedType then
result = getEnclosingType().(NestedType).getNestingDepth() + 1
else
result = 1
if getEnclosingType() instanceof NestedType
then result = getEnclosingType().(NestedType).getNestingDepth() + 1
else result = 1
}
override predicate isPublic() {
@@ -760,17 +778,14 @@ class NestedType extends RefType {
* This includes (static and non-static) member classes,
* local classes and anonymous classes.
*/
class NestedClass extends NestedType, Class {
}
class NestedClass extends NestedType, Class { }
/**
* An inner class is a nested class that is neither
* explicitly nor implicitly declared static.
*/
class InnerClass extends NestedClass {
InnerClass() {
not this.isStatic()
}
InnerClass() { not this.isStatic() }
/**
* Holds if an instance of this inner class holds a reference to its
@@ -785,7 +800,7 @@ class InnerClass extends NestedClass {
/** An interface. */
class Interface extends RefType, @interface {
override RefType getSourceDeclaration() { interfaces(this,_,_,result) }
override RefType getSourceDeclaration() { interfaces(this, _, _, result) }
override predicate isAbstract() {
// JLS 9.1.1.1: "Every interface is implicitly abstract"
@@ -809,26 +824,29 @@ class ClassOrInterface extends RefType {
* and `double`.
*/
class PrimitiveType extends Type, @primitive {
PrimitiveType() {
this.getName().regexpMatch("float|double|int|boolean|short|byte|char|long")
}
PrimitiveType() { this.getName().regexpMatch("float|double|int|boolean|short|byte|char|long") }
/** Gets the boxed type corresponding to this primitive type. */
BoxedType getBoxedType() {
result.getPrimitiveType() = this
}
BoxedType getBoxedType() { result.getPrimitiveType() = this }
/**
* Gets the JVM descriptor for this type, as used in bytecode.
*/
override string getTypeDescriptor() {
(this.hasName("float") and result = "F") or
(this.hasName("double") and result = "D") or
(this.hasName("int") and result = "I") or
(this.hasName("boolean") and result = "Z") or
(this.hasName("short") and result = "S") or
(this.hasName("byte") and result = "B") or
(this.hasName("char") and result = "C") or
(this.hasName("float") and result = "F")
or
(this.hasName("double") and result = "D")
or
(this.hasName("int") and result = "I")
or
(this.hasName("boolean") and result = "Z")
or
(this.hasName("short") and result = "S")
or
(this.hasName("byte") and result = "B")
or
(this.hasName("char") and result = "C")
or
(this.hasName("long") and result = "J")
}
@@ -842,16 +860,18 @@ class PrimitiveType extends Type, @primitive {
* require an explicit cast.
*/
Literal getADefaultValue() {
getName() = "boolean" and result.getLiteral() = "false" or
getName() = "char" and (result.getLiteral() = "'\\0'" or result.getLiteral() = "'\\u0000'") or
getName().regexpMatch("(float|double|int|short|byte|long)") and result.getLiteral().regexpMatch("0(\\.0)?+[lLfFdD]?+")
getName() = "boolean" and result.getLiteral() = "false"
or
getName() = "char" and
(result.getLiteral() = "'\\0'" or result.getLiteral() = "'\\u0000'")
or
getName().regexpMatch("(float|double|int|short|byte|long)") and
result.getLiteral().regexpMatch("0(\\.0)?+[lLfFdD]?+")
}
}
/** The type of the `null` literal. */
class NullType extends Type, @primitive {
NullType() { this.hasName("<nulltype>") }
}
class NullType extends Type, @primitive { NullType() { this.hasName("<nulltype>") } }
/** The `void` type. */
class VoidType extends Type, @primitive {
@@ -860,9 +880,7 @@ class VoidType extends Type, @primitive {
/**
* Gets the JVM descriptor for this type, as used in bytecode.
*/
override string getTypeDescriptor() {
result = "V"
}
override string getTypeDescriptor() { result = "V" }
}
/**
@@ -886,13 +904,20 @@ class BoxedType extends RefType {
/** Gets the primitive type corresponding to this boxed type. */
PrimitiveType getPrimitiveType() {
(this.hasName("Float") and result.hasName("float")) or
(this.hasName("Double") and result.hasName("double")) or
(this.hasName("Integer") and result.hasName("int")) or
(this.hasName("Boolean") and result.hasName("boolean")) or
(this.hasName("Short") and result.hasName("short")) or
(this.hasName("Byte") and result.hasName("byte")) or
(this.hasName("Character") and result.hasName("char")) or
(this.hasName("Float") and result.hasName("float"))
or
(this.hasName("Double") and result.hasName("double"))
or
(this.hasName("Integer") and result.hasName("int"))
or
(this.hasName("Boolean") and result.hasName("boolean"))
or
(this.hasName("Short") and result.hasName("short"))
or
(this.hasName("Byte") and result.hasName("byte"))
or
(this.hasName("Character") and result.hasName("char"))
or
(this.hasName("Long") and result.hasName("long"))
}
}
@@ -917,13 +942,11 @@ class EnumType extends Class {
/** Gets the enum constant with the specified name. */
EnumConstant getEnumConstant(string name) {
fields(result,_,_,this,_) and result.hasName(name)
fields(result, _, _, this, _) and result.hasName(name)
}
/** Gets an enum constant declared in this enum type. */
EnumConstant getAnEnumConstant() {
fields(result,_,_,this,_)
}
EnumConstant getAnEnumConstant() { fields(result, _, _, this, _) }
override predicate isFinal() {
// JLS 8.9: An enum declaration is implicitly `final` unless it contains
@@ -940,7 +963,9 @@ class EnumConstant extends Field {
// [enum type] `E`, `E` has an implicitly declared `public static final`
// field of type `E` that has the same name as `c`.
override predicate isPublic() { any() }
override predicate isStatic() { any() }
override predicate isFinal() { any() }
}
@@ -949,15 +974,23 @@ class EnumConstant extends Field {
*
* See JLS v8, section 4.6 (Type Erasure).
*/
private cached Type erase(Type t) {
result = t.(Class).getSourceDeclaration() and not t instanceof IntersectionType or
result = erase(t.(IntersectionType).getFirstBound()) or
result = t.(Interface).getSourceDeclaration() or
result.(Array).getComponentType() = erase(t.(Array).getComponentType()) or
result = erase(t.(BoundedType).getFirstUpperBoundType()) or
result = (NullType)t or
result = (VoidType)t or
result = (PrimitiveType)t
cached
private Type erase(Type t) {
result = t.(Class).getSourceDeclaration() and not t instanceof IntersectionType
or
result = erase(t.(IntersectionType).getFirstBound())
or
result = t.(Interface).getSourceDeclaration()
or
result.(Array).getComponentType() = erase(t.(Array).getComponentType())
or
result = erase(t.(BoundedType).getFirstUpperBoundType())
or
result = t.(NullType)
or
result = t.(VoidType)
or
result = t.(PrimitiveType)
}
/**
@@ -984,7 +1017,9 @@ predicate haveIntersection(RefType t1, RefType t2) {
* types `t1` and `t2`.
*/
predicate erasedHaveIntersection(RefType t1, RefType t2) {
exists(SrcRefType commonSub | commonSub.getASourceSupertype*() = t1 and commonSub.getASourceSupertype*() = t2) and
exists(SrcRefType commonSub |
commonSub.getASourceSupertype*() = t1 and commonSub.getASourceSupertype*() = t2
) and
t1 = erase(_) and
t2 = erase(_)
}
@@ -994,7 +1029,7 @@ class IntegralType extends Type {
IntegralType() {
exists(string name |
name = this.(PrimitiveType).getName() or name = this.(BoxedType).getPrimitiveType().getName()
|
|
name.regexpMatch("byte|char|short|int|long")
)
}
@@ -1005,7 +1040,7 @@ class BooleanType extends Type {
BooleanType() {
exists(string name |
name = this.(PrimitiveType).getName() or name = this.(BoxedType).getPrimitiveType().getName()
|
|
name = "boolean"
)
}
@@ -1016,7 +1051,7 @@ class CharacterType extends Type {
CharacterType() {
exists(string name |
name = this.(PrimitiveType).getName() or name = this.(BoxedType).getPrimitiveType().getName()
|
|
name = "char"
)
}
@@ -1027,7 +1062,7 @@ class NumericOrCharType extends Type {
NumericOrCharType() {
exists(string name |
name = this.(PrimitiveType).getName() or name = this.(BoxedType).getPrimitiveType().getName()
|
|
name.regexpMatch("byte|char|short|int|long|double|float")
)
}
@@ -1038,7 +1073,7 @@ class FloatingPointType extends Type {
FloatingPointType() {
exists(string name |
name = this.(PrimitiveType).getName() or name = this.(BoxedType).getPrimitiveType().getName()
|
|
name.regexpMatch("float|double")
)
}

View File

@@ -8,30 +8,22 @@ import semmle.code.java.frameworks.JUnitAnnotations
/** The Java class `junit.framework.TestCase`. */
class TypeJUnitTestCase extends RefType {
TypeJUnitTestCase() {
this.hasQualifiedName("junit.framework", "TestCase")
}
TypeJUnitTestCase() { this.hasQualifiedName("junit.framework", "TestCase") }
}
/** The Java interface `junit.framework.Test`. */
class TypeJUnitTest extends RefType {
TypeJUnitTest() {
this.hasQualifiedName("junit.framework", "Test")
}
TypeJUnitTest() { this.hasQualifiedName("junit.framework", "Test") }
}
/** The Java class `junit.framework.TestSuite`. */
class TypeJUnitTestSuite extends RefType {
TypeJUnitTestSuite() {
this.hasQualifiedName("junit.framework", "TestSuite")
}
TypeJUnitTestSuite() { this.hasQualifiedName("junit.framework", "TestSuite") }
}
/** A JUnit 3.8 test class. */
class JUnit38TestClass extends Class {
JUnit38TestClass() {
exists(TypeJUnitTestCase tc | this.hasSupertype+(tc))
}
JUnit38TestClass() { exists(TypeJUnitTestCase tc | this.hasSupertype+(tc)) }
}
/** A JUnit 3.8 `tearDown` method. */
@@ -40,9 +32,7 @@ class TearDownMethod extends Method {
this.hasName("tearDown") and
this.hasNoParameters() and
this.getReturnType().hasName("void") and
exists(Method m | m.getDeclaringType() instanceof TypeJUnitTestCase |
this.overrides*(m)
)
exists(Method m | m.getDeclaringType() instanceof TypeJUnitTestCase | this.overrides*(m))
}
}
@@ -87,14 +77,11 @@ class JUnit3TestSuite extends Method {
}
}
/**
* A JUnit test method that is annotated with the `org.junit.Test` annotation.
*/
class JUnit4TestMethod extends Method {
JUnit4TestMethod() {
this.getAnAnnotation().getType().hasQualifiedName("org.junit", "Test")
}
JUnit4TestMethod() { this.getAnAnnotation().getType().hasQualifiedName("org.junit", "Test") }
}
/**
@@ -110,9 +97,7 @@ class JUnitJupiterTestMethod extends Method {
* A JUnit `@Ignore` annotation.
*/
class JUnitIgnoreAnnotation extends Annotation {
JUnitIgnoreAnnotation() {
getType().hasQualifiedName("org.junit", "Ignore")
}
JUnitIgnoreAnnotation() { getType().hasQualifiedName("org.junit", "Ignore") }
}
/**
@@ -121,10 +106,9 @@ class JUnitIgnoreAnnotation extends Annotation {
*/
class JUnitIgnoredMethod extends Method {
JUnitIgnoredMethod() {
getAnAnnotation() instanceof JUnitIgnoreAnnotation or
exists(Class c |
c = this.getDeclaringType()
|
getAnAnnotation() instanceof JUnitIgnoreAnnotation
or
exists(Class c | c = this.getDeclaringType() |
c.getAnAnnotation() instanceof JUnitIgnoreAnnotation
)
}
@@ -134,27 +118,21 @@ class JUnitIgnoredMethod extends Method {
* An annotation in TestNG.
*/
class TestNGAnnotation extends Annotation {
TestNGAnnotation() {
getType().getPackage().hasName("org.testng.annotations")
}
TestNGAnnotation() { getType().getPackage().hasName("org.testng.annotations") }
}
/**
* An annotation of type `org.test.ng.annotations.Test`.
*/
class TestNGTestAnnotation extends TestNGAnnotation {
TestNGTestAnnotation() {
getType().hasName("Test")
}
TestNGTestAnnotation() { getType().hasName("Test") }
}
/**
* A TestNG test method, annotated with the `org.testng.annotations.Test` annotation.
*/
class TestNGTestMethod extends Method {
TestNGTestMethod() {
this.getAnAnnotation() instanceof TestNGTestAnnotation
}
TestNGTestMethod() { this.getAnAnnotation() instanceof TestNGTestAnnotation }
/**
* Identify a possible `DataProvider` for this method, if the annotation includes a `dataProvider`
@@ -164,12 +142,19 @@ class TestNGTestMethod extends Method {
exists(TestNGTestAnnotation testAnnotation |
testAnnotation = getAnAnnotation() and
// The data provider must have the same name as the referenced data provider
result.getDataProviderName() = testAnnotation.getValue("dataProvider").(StringLiteral).getRepresentedString()
|
result.getDataProviderName() = testAnnotation
.getValue("dataProvider")
.(StringLiteral)
.getRepresentedString()
|
// Either the data provider should be on the current class, or a supertype
getDeclaringType().getAnAncestor() = result.getDeclaringType() or
// Or the data provider class should be declared
result.getDeclaringType() = testAnnotation.getValue("dataProviderClass").(TypeLiteral).getTypeName().getType()
result.getDeclaringType() = testAnnotation
.getValue("dataProviderClass")
.(TypeLiteral)
.getTypeName()
.getType()
)
}
}
@@ -191,18 +176,14 @@ class TestMethod extends Method {
* A TestNG annotation used to mark a method that runs "before".
*/
class TestNGBeforeAnnotation extends TestNGAnnotation {
TestNGBeforeAnnotation() {
getType().getName().matches("Before%")
}
TestNGBeforeAnnotation() { getType().getName().matches("Before%") }
}
/**
* A TestNG annotation used to mark a method that runs "after".
*/
class TestNGAfterAnnotation extends TestNGAnnotation {
TestNGAfterAnnotation() {
getType().getName().matches("After%")
}
TestNGAfterAnnotation() { getType().getName().matches("After%") }
}
/**
@@ -210,9 +191,7 @@ class TestNGAfterAnnotation extends TestNGAnnotation {
* them as data provider methods for TestNG.
*/
class TestNGDataProviderAnnotation extends TestNGAnnotation {
TestNGDataProviderAnnotation() {
getType().hasName("DataProvider")
}
TestNGDataProviderAnnotation() { getType().hasName("DataProvider") }
}
/**
@@ -220,9 +199,7 @@ class TestNGDataProviderAnnotation extends TestNGAnnotation {
* them as factory methods for TestNG.
*/
class TestNGFactoryAnnotation extends TestNGAnnotation {
TestNGFactoryAnnotation() {
getType().hasName("Factory")
}
TestNGFactoryAnnotation() { getType().hasName("Factory") }
}
/**
@@ -230,9 +207,7 @@ class TestNGFactoryAnnotation extends TestNGAnnotation {
* which listeners apply to them.
*/
class TestNGListenersAnnotation extends TestNGAnnotation {
TestNGListenersAnnotation() {
getType().hasName("Listeners")
}
TestNGListenersAnnotation() { getType().hasName("Listeners") }
/**
* Gets a listener defined in this annotation.
@@ -246,9 +221,7 @@ class TestNGListenersAnnotation extends TestNGAnnotation {
* A concrete implementation class of one or more of the TestNG listener interfaces.
*/
class TestNGListenerImpl extends Class {
TestNGListenerImpl() {
getAnAncestor().hasQualifiedName("org.testng", "ITestNGListener")
}
TestNGListenerImpl() { getAnAncestor().hasQualifiedName("org.testng", "ITestNGListener") }
}
/**
@@ -259,15 +232,17 @@ class TestNGListenerImpl extends Class {
* an instance of a particular value when running a test method.
*/
class TestNGDataProviderMethod extends Method {
TestNGDataProviderMethod() {
getAnAnnotation() instanceof TestNGDataProviderAnnotation
}
TestNGDataProviderMethod() { getAnAnnotation() instanceof TestNGDataProviderAnnotation }
/**
* Gets the name associated with this data provider.
*/
string getDataProviderName() {
result = getAnAnnotation().(TestNGDataProviderAnnotation).getValue("name").(StringLiteral).getRepresentedString()
result = getAnAnnotation()
.(TestNGDataProviderAnnotation)
.getValue("name")
.(StringLiteral)
.getRepresentedString()
}
}
@@ -278,9 +253,7 @@ class TestNGDataProviderMethod extends Method {
* This factory callable is used to generate instances of parameterized test classes.
*/
class TestNGFactoryCallable extends Callable {
TestNGFactoryCallable() {
getAnAnnotation() instanceof TestNGFactoryAnnotation
}
TestNGFactoryCallable() { getAnAnnotation() instanceof TestNGFactoryAnnotation }
}
/**
@@ -288,7 +261,11 @@ class TestNGFactoryCallable extends Callable {
*/
class ParameterizedJUnitTest extends Class {
ParameterizedJUnitTest() {
getAnAnnotation().(RunWithAnnotation).getRunner().(Class).hasQualifiedName("org.junit.runners", "Parameterized")
getAnAnnotation()
.(RunWithAnnotation)
.getRunner()
.(Class)
.hasQualifiedName("org.junit.runners", "Parameterized")
}
}
@@ -309,7 +286,8 @@ class JUnitCategoryAnnotation extends Annotation {
(
literal = value or
literal = value.(ArrayCreationExpr).getInit().getAnInit()
) |
)
|
result = literal.getTypeName().getType()
)
}
@@ -320,6 +298,10 @@ class JUnitCategoryAnnotation extends Annotation {
*/
class JUnitTheoryTest extends Class {
JUnitTheoryTest() {
getAnAnnotation().(RunWithAnnotation).getRunner().(Class).hasQualifiedName("org.junit.experimental.theories", "Theories")
getAnAnnotation()
.(RunWithAnnotation)
.getRunner()
.(Class)
.hasQualifiedName("org.junit.experimental.theories", "Theories")
}
}

View File

@@ -10,24 +10,22 @@ class Variable extends @variable, Annotatable, Element, Modifiable {
/*abstract*/ Type getType() { none() }
/** Gets an access to this variable. */
VarAccess getAnAccess() { variableBinding(result,this) }
VarAccess getAnAccess() { variableBinding(result, this) }
/** Gets an expression on the right-hand side of an assignment to this variable. */
Expr getAnAssignedValue() {
exists(LocalVariableDeclExpr e | e.getVariable() = this and result = e.getInit())
or
exists(AssignExpr e | e.getDest().getProperExpr() = this.getAnAccess() and result = e.getSource())
exists(AssignExpr e |
e.getDest().getProperExpr() = this.getAnAccess() and result = e.getSource()
)
}
/** Gets the initializer expression of this variable. */
Expr getInitializer() {
none()
}
Expr getInitializer() { none() }
/** Gets a printable representation of this variable together with its type. */
string pp() {
result = this.getType().getName() + " " + this.getName()
}
string pp() { result = this.getType().getName() + " " + this.getName() }
}
/** A locally scoped variable, that is, either a local variable or a parameter. */
@@ -39,13 +37,13 @@ class LocalScopeVariable extends Variable, @localscopevariable {
/** A local variable declaration */
class LocalVariableDecl extends @localvar, LocalScopeVariable {
/** Gets the type of this local variable. */
override Type getType() { localvars(this,_,result,_) }
override Type getType() { localvars(this, _, result, _) }
/** Gets the expression declaring this variable. */
LocalVariableDeclExpr getDeclExpr() { localvars(this, _, _, result) }
/** Gets the parent of this declaration. */
Expr getParent() { localvars(this,_,_,result) }
Expr getParent() { localvars(this, _, _, result) }
/** Gets the callable in which this declaration occurs. */
override Callable getCallable() { result = this.getParent().getEnclosingCallable() }
@@ -56,35 +54,31 @@ class LocalVariableDecl extends @localvar, LocalScopeVariable {
override string toString() { result = this.getType().getName() + " " + this.getName() }
/** Gets the initializer expression of this local variable declaration. */
override Expr getInitializer() {
result = getDeclExpr().getInit()
}
override Expr getInitializer() { result = getDeclExpr().getInit() }
}
/** A formal parameter of a callable. */
class Parameter extends Element, @param, LocalScopeVariable {
/** Gets the type of this formal parameter. */
override Type getType() { params(this,result,_,_,_) }
override Type getType() { params(this, result, _, _, _) }
/** Holds if the parameter is never assigned a value in the body of the callable. */
predicate isEffectivelyFinal() { not exists(getAnAssignedValue()) }
/** Gets the (zero-based) index of this formal parameter. */
int getPosition() { params(this,_,result,_,_) }
int getPosition() { params(this, _, result, _, _) }
/** Gets the callable that declares this formal parameter. */
override Callable getCallable() { params(this,_,_,result,_) }
override Callable getCallable() { params(this, _, _, result, _) }
/** Gets the source declaration of this formal parameter. */
Parameter getSourceDeclaration() { params(this,_,_,_,result) }
Parameter getSourceDeclaration() { params(this, _, _, _, result) }
/** Holds if this formal parameter is the same as its source declaration. */
predicate isSourceDeclaration() { this.getSourceDeclaration() = this }
/** Holds if this formal parameter is a variable arity parameter. */
predicate isVarargs() {
isVarargsParam(this)
}
predicate isVarargs() { isVarargsParam(this) }
/**
* Gets an argument for this parameter in any call to the callable that declares this formal
@@ -97,7 +91,8 @@ class Parameter extends Element, @param, LocalScopeVariable {
result = getACallArgument(getPosition())
}
private pragma[noinline] Expr getACallArgument(int i) {
pragma[noinline]
private Expr getACallArgument(int i) {
exists(Call call |
result = call.getArgument(i) and
call.getCallee().getSourceDeclaration().getAParameter() = this

View File

@@ -6,9 +6,13 @@ import java
* Used as basis for the transitive closure in `exprImplies`.
*/
private predicate exprImpliesStep(Expr e1, boolean b1, Expr e2, boolean b2) {
e1.(ParExpr).getProperExpr() = e2 and b2 = b1 and (b1 = true or b1 = false)
e1.(ParExpr).getProperExpr() = e2 and
b2 = b1 and
(b1 = true or b1 = false)
or
e1.(LogNotExpr).getExpr() = e2 and b2 = b1.booleanNot() and (b1 = true or b1 = false)
e1.(LogNotExpr).getExpr() = e2 and
b2 = b1.booleanNot() and
(b1 = true or b1 = false)
or
b1 = true and e1.(AndLogicalExpr).getAnOperand() = e2 and b2 = true
or
@@ -17,7 +21,11 @@ private predicate exprImpliesStep(Expr e1, boolean b1, Expr e2, boolean b2) {
/** If `e1` evaluates to `b1` then the subexpression `e2` evaluates to `b2`. */
predicate exprImplies(Expr e1, boolean b1, Expr e2, boolean b2) {
e1 = e2 and b1 = b2 and (b1 = true or b1 = false)
e1 = e2 and
b1 = b2 and
(b1 = true or b1 = false)
or
exists(Expr emid, boolean bmid | exprImplies(e1, b1, emid, bmid) and exprImpliesStep(emid, bmid, e2, b2))
exists(Expr emid, boolean bmid |
exprImplies(e1, b1, emid, bmid) and exprImpliesStep(emid, bmid, e2, b2)
)
}