Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9641403

Browse files
committed
Java: Support wildcards in paramters and generic collection like parameters.
1 parent efe802d commit 9641403

3 files changed

Lines changed: 56 additions & 22 deletions

File tree

csharp/ql/src/utils/model-generator/internal/CaptureTypeBasedSummaryModels.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ private string getSyntheticField(TypeParameter tp) {
6464
*/
6565
private string implicit(DotNet::Callable callable, TypeParameter tp) {
6666
classTypeParameter(callable, tp) and
67+
not callable.(Modifiable).isStatic() and
6768
exists(string access |
6869
if genericCollectionType(callable.getDeclaringType(), tp)
6970
then access = ".Element"

java/ql/src/utils/model-generator/internal/CaptureModelsSpecific.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ string asPartialNegativeModel(TargetApiSpecific api) {
143143
)
144144
}
145145

146-
private predicate isPrimitiveTypeUsedForBulkData(J::Type t) {
146+
predicate isPrimitiveTypeUsedForBulkData(J::Type t) {
147147
t.hasName(["byte", "char", "Byte", "Character"])
148148
}
149149

@@ -177,7 +177,7 @@ predicate isRelevantType(J::Type t) {
177177
*/
178178
string qualifierString() { result = "Argument[-1]" }
179179

180-
string parameterAccess(J::Parameter p) {
180+
private string parameterAccess(J::Parameter p) {
181181
if
182182
p.getType() instanceof J::Array and
183183
not isPrimitiveTypeUsedForBulkData(p.getType().(J::Array).getElementType())

java/ql/src/utils/model-generator/internal/CaptureTypeBasedSummaryModels.qll

Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,33 +5,55 @@ private import CaptureModelsSpecific as Specific
55
private import CaptureModels
66

77
/**
8-
* A type representing classes that has a method which returns an iterator.
8+
* A type representing class types of instantiations of class types
9+
* that has a method which returns an iterator.
910
*/
1011
private class IterableType extends Class {
1112
private Type elementType;
1213

1314
IterableType() {
14-
exists(Method m, Type return | m.getDeclaringType() = this |
15+
exists(Method m, Type return, Type t | m.getDeclaringType() = t |
1516
return = m.getReturnType() and
1617
return.getName().matches("Iterator%") and
17-
elementType = return.(ParameterizedType).getTypeArgument(0)
18+
elementType = return.(ParameterizedType).getTypeArgument(0) and
19+
(this = t or instantiates(this, t, _, _))
1820
)
1921
}
2022

2123
/**
2224
* Returns the iterator element type of `this`.
25+
* TODO: Improve this as it doesn't return the correct type instantiations.
2326
*/
2427
Type getElementType() { result = elementType }
2528
}
2629

30+
/**
31+
* Holds if type `bound` is an upper bound for type `t` or equal to `t`.
32+
*/
33+
private predicate isEffectivelyUpperBound(Type t, Type bound) {
34+
t = bound or
35+
t.(Wildcard).getUpperBound().getType() = bound
36+
}
37+
38+
/**
39+
* Holds if type `bound` is a lower bound for type `t` or equal to `t`.
40+
*/
41+
private predicate isEffectivelyLowerBound(Type t, Type bound) {
42+
t = bound or
43+
t.(Wildcard).getLowerBound().getType() = bound
44+
}
45+
2746
/**
2847
* Holds if `t` is a container like type of `tv` (eg. `List<T>`).
48+
* Note that collections are covariant in their element type.
2949
*/
3050
private predicate genericContainerType(RefType t, TypeVariable tv) {
31-
(
32-
t.(ContainerType).getElementType() = tv
51+
exists(Type et |
52+
et = t.(ContainerType).getElementType()
3353
or
34-
t.(IterableType).getElementType() = tv
54+
et = t.(IterableType).getElementType()
55+
|
56+
isEffectivelyUpperBound(et, tv)
3557
)
3658
}
3759

@@ -50,19 +72,33 @@ private predicate localTypeParameter(Callable callable, TypeVariable tv) {
5072
callable.(GenericCallable).getATypeParameter() = tv
5173
}
5274

75+
private string parameterAccess(Parameter p) {
76+
exists(Type t | t = p.getType() |
77+
if
78+
t instanceof Array and
79+
not Specific::isPrimitiveTypeUsedForBulkData(p.getType().(Array).getElementType())
80+
then result = "Argument[" + p.getPosition() + "].ArrayElement"
81+
else
82+
if t instanceof ContainerType or t instanceof IterableType
83+
then result = "Argument[" + p.getPosition() + "].Element"
84+
else result = "Argument[" + p.getPosition() + "]"
85+
)
86+
}
87+
5388
/**
5489
* Holds if `callable` has a type parameter `tv` or container parameterized over type `tv`.
5590
*/
5691
private predicate parameter(Callable callable, string input, TypeVariable tv) {
57-
exists(Parameter p |
58-
input = Specific::parameterAccess(p) and
92+
exists(Parameter p, Type pt |
93+
input = parameterAccess(p) and
5994
p = callable.getAParameter() and
95+
pt = p.getType() and
6096
(
6197
// Parameter of type tv
62-
p.getType() = tv
98+
isEffectivelyUpperBound(pt, tv)
6399
or
64100
// Parameter is a container of type tv
65-
genericContainerType(p.getType(), tv)
101+
genericContainerType(pt, tv)
66102
)
67103
)
68104
}
@@ -80,6 +116,7 @@ private string getSyntheticField(TypeVariable tv) {
80116
*/
81117
private string implicit(Callable callable, TypeVariable tv) {
82118
classTypeParameter(callable, tv) and
119+
not callable.isStatic() and
83120
exists(string access |
84121
if genericContainerType(callable.getDeclaringType(), tv)
85122
then access = ".Element"
@@ -113,11 +150,9 @@ private class Function extends ParameterizedType {
113150
* Note that functions are contravariant in their parameter types.
114151
*/
115152
Type getParameterType(int position) {
116-
exists(Type t | fi.getRunMethod().getParameterType(position) = getTypeReplacement(t) |
117-
(
118-
result = t or
119-
result = t.(Wildcard).getLowerBound().getType()
120-
)
153+
exists(Type t |
154+
fi.getRunMethod().getParameterType(position) = getTypeReplacement(t) and
155+
isEffectivelyLowerBound(t, result)
121156
)
122157
}
123158

@@ -126,11 +161,9 @@ private class Function extends ParameterizedType {
126161
* Note that functions are covariant in their return type.
127162
*/
128163
Type getReturnType() {
129-
exists(Type t | fi.getRunMethod().getReturnType() = getTypeReplacement(t) |
130-
(
131-
result = t or
132-
result = t.(Wildcard).getUpperBound().getType()
133-
)
164+
exists(Type t |
165+
fi.getRunMethod().getReturnType() = getTypeReplacement(t) and
166+
isEffectivelyUpperBound(t, result)
134167
)
135168
}
136169
}

0 commit comments

Comments
 (0)