Skip to content

Commit 4939136

Browse files
committed
Unified: Introduce ParameterEx
1 parent 1912c4a commit 4939136

5 files changed

Lines changed: 177 additions & 0 deletions

File tree

‎unified/ql/lib/codeql/unified/internal/AstPlugin.qll‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ class AstPlugin extends Unit {
2020

2121
bindingset[decl]
2222
string getVariableDeclarationKeyword(VariableDeclaration decl) { none() }
23+
24+
/**
25+
* Holds if a default constructor for `cls` would need to have a parameter
26+
* at index `i` with the given name. `i = 0` is reserved for the implicit
27+
* receiver parameter.
28+
*/
29+
bindingset[cd]
30+
predicate defaultConstructorParameter(ConstructorDeclaration cd, int i, string name) { none() }
2331
}
2432

2533
bindingset[f]
@@ -41,3 +49,8 @@ bindingset[decl]
4149
string getVariableDeclarationKeyword(VariableDeclaration decl) {
4250
result = any(AstPlugin p).getVariableDeclarationKeyword(decl)
4351
}
52+
53+
bindingset[cd]
54+
predicate defaultConstructorParameter(ConstructorDeclaration cd, int i, string name) {
55+
any(AstPlugin p).defaultConstructorParameter(cd, i, name)
56+
}

‎unified/ql/lib/codeql/unified/internal/AstPluginSwift.qll‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ private class AstPluginSwift extends AstPlugin {
1010
exists(f) and result = "func"
1111
}
1212

13+
bindingset[c]
14+
override string getConstructorDeclarationKeyword(ConstructorDeclaration c) {
15+
c.hasModifier(result) and
16+
result = "convenience"
17+
}
18+
1319
override string getClassLikeDeclarationKeyword(ClassLikeDeclaration cls) {
1420
cls.hasModifier(result) and
1521
result in ["class", "struct", "enum", "actor", "extension", "protocol"]
@@ -19,4 +25,27 @@ private class AstPluginSwift extends AstPlugin {
1925
decl.hasModifier(result) and
2026
result in ["var", "let"]
2127
}
28+
29+
bindingset[cd]
30+
override predicate defaultConstructorParameter(ConstructorDeclaration cd, int i, string name) {
31+
exists(ClassLikeDeclaration cls |
32+
cd = cls.getAMember() and
33+
cls.hasModifier("struct") and
34+
name =
35+
rank[i](VariableDeclaration decl, int j, string s |
36+
decl = cls.getMember(j) and
37+
not decl.hasModifier("static") and
38+
(
39+
// if `decl` has an initializer then this parameter has that initializer as a default value
40+
decl.hasModifier("var")
41+
or
42+
decl.hasModifier("let") and
43+
not exists(decl.getValue())
44+
) and
45+
s = decl.getPattern().(Identifier).getValue()
46+
|
47+
s order by j
48+
)
49+
)
50+
}
2251
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/**
2+
* Provides logic for synthesizing parameters.
3+
*/
4+
5+
private import unified
6+
private import AstPlugin
7+
private import NameBinding
8+
9+
private newtype TParameterEx =
10+
TAstParameter(Parameter p) or
11+
TImplicitReceiverParameter(Callable c) {
12+
exists(LocalVariable v | v.isImplicitReceiverParameter(c))
13+
} or
14+
TDefaultConstructorParameter(ConstructorDeclaration cd, int i, string name) {
15+
cd.hasModifier("generated") and
16+
defaultConstructorParameter(cd, i, name)
17+
}
18+
19+
final class ParameterEx = ParameterExImpl;
20+
21+
/**
22+
* A parameter from source code or a synthesized parameter.
23+
*/
24+
abstract private class ParameterExImpl extends TParameterEx {
25+
/**
26+
* Gets the source code parameter that this entity represents, if any.
27+
*/
28+
Parameter asParameter() { this = TAstParameter(result) }
29+
30+
/**
31+
* Holds if this entity represents a regular parameter from source code.
32+
*/
33+
predicate isParameter() { exists(this.asParameter()) }
34+
35+
/**
36+
* Holds if this entity represents an implicit receiver parameter of `c`.
37+
*/
38+
predicate isImplicitReceiverParameter(Callable c) { this = TImplicitReceiverParameter(c) }
39+
40+
/**
41+
* Holds if this entity represents the `i`th parameter of the default
42+
* constructor `cd` with name `name`.
43+
*/
44+
predicate isDefaultConstructorParameter(ConstructorDeclaration cd, int i, string name) {
45+
this = TDefaultConstructorParameter(cd, i, name)
46+
}
47+
48+
/** Gets the callable that this parameter belongs to. */
49+
Callable getCallable() {
50+
this.asParameter() =
51+
[
52+
result.(FunctionDeclaration).getAParameter(),
53+
result.(ConstructorDeclaration).getAParameter(),
54+
result.(AccessorDeclaration).getAParameter()
55+
]
56+
or
57+
this.isImplicitReceiverParameter(result)
58+
or
59+
this.isDefaultConstructorParameter(result, _, _)
60+
}
61+
62+
/** Gets a textual representation of this parameter. */
63+
abstract string toString();
64+
65+
/** Gets the location of this parameter. */
66+
abstract Location getLocation();
67+
}
68+
69+
private class AstParameterEx extends ParameterExImpl, TAstParameter {
70+
Parameter p;
71+
72+
AstParameterEx() { this = TAstParameter(p) }
73+
74+
override string toString() { result = p.toString() }
75+
76+
override Location getLocation() { result = p.getLocation() }
77+
}
78+
79+
private class ImplicitReceiverParameterEx extends ParameterExImpl, TImplicitReceiverParameter {
80+
Callable c;
81+
82+
ImplicitReceiverParameterEx() { this = TImplicitReceiverParameter(c) }
83+
84+
override string toString() {
85+
exists(LocalVariable v |
86+
v.isImplicitReceiverParameter(c) and
87+
result = v.getName()
88+
)
89+
}
90+
91+
override Location getLocation() { result = c.getLocation() }
92+
}
93+
94+
private class DefaultConstructorParameterEx extends ParameterExImpl, TDefaultConstructorParameter {
95+
ConstructorDeclaration cd;
96+
int i;
97+
string name;
98+
99+
DefaultConstructorParameterEx() { this = TDefaultConstructorParameter(cd, i, name) }
100+
101+
override string toString() { result = name + " [" + cd.getName() + " default constructor]" }
102+
103+
override Location getLocation() { result = cd.getLocation() }
104+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,23 @@
1+
generatedConstructor
12
| constructors.swift:1:1:1:0 | init |
23
| constructors.swift:3:1:3:0 | init |
34
| constructors.swift:19:1:19:0 | init |
45
| constructors.swift:31:1:31:0 | init |
56
| constructors.swift:39:1:39:0 | init |
7+
implicitReceiverParameter
8+
| constructors.swift:1:1:1:0 | self | constructors.swift:1:1:1:0 | init |
9+
| constructors.swift:3:1:3:0 | self | constructors.swift:3:1:3:0 | init |
10+
| constructors.swift:6:5:6:13 | self | constructors.swift:6:5:6:13 | init |
11+
| constructors.swift:10:5:12:5 | self | constructors.swift:10:5:12:5 | init |
12+
| constructors.swift:14:5:16:5 | self | constructors.swift:14:5:16:5 | convenience init |
13+
| constructors.swift:19:1:19:0 | self | constructors.swift:19:1:19:0 | init |
14+
| constructors.swift:22:5:22:25 | self | constructors.swift:22:5:22:25 | init |
15+
| constructors.swift:24:5:24:30 | self | constructors.swift:24:5:24:30 | init |
16+
| constructors.swift:26:5:28:5 | self | constructors.swift:26:5:28:5 | convenience init |
17+
| constructors.swift:31:1:31:0 | self | constructors.swift:31:1:31:0 | init |
18+
| constructors.swift:34:5:36:5 | self | constructors.swift:34:5:36:5 | convenience init |
19+
| constructors.swift:39:1:39:0 | self | constructors.swift:39:1:39:0 | init |
20+
callableExDefaultConstructorParameter
21+
| constructors.swift:39:1:39:0 | init | 1 | constructors.swift:39:1:39:0 | f1 [init default constructor] | f1 |
22+
| constructors.swift:39:1:39:0 | init | 2 | constructors.swift:39:1:39:0 | f2 [init default constructor] | f2 |
23+
| constructors.swift:39:1:39:0 | init | 3 | constructors.swift:39:1:39:0 | f4 [init default constructor] | f4 |
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,19 @@
11
import unified
2+
import codeql.unified.internal.ParameterEx
23

34
query predicate generatedConstructor(ConstructorDeclaration c) {
45
c = any(ClassLikeDeclaration cls | cls.fromSource()).getAMember() and
56
c.hasModifier("generated")
67
}
8+
9+
query predicate implicitReceiverParameter(ParameterEx p, Callable c) {
10+
p.isImplicitReceiverParameter(c) and
11+
c.getFile().fromSource()
12+
}
13+
14+
query predicate callableExDefaultConstructorParameter(
15+
ConstructorDeclaration cd, int i, ParameterEx p, string name
16+
) {
17+
p.isDefaultConstructorParameter(cd, i, name) and
18+
cd.getFile().fromSource()
19+
}

0 commit comments

Comments
 (0)