Skip to content

Commit c5e14f5

Browse files
committed
Python: Handle defaults and annotations for keyword-only arguments
This commit is based on a change to the extractor
1 parent 1fcbb6e commit c5e14f5

File tree

6 files changed

+48
-17
lines changed

6 files changed

+48
-17
lines changed

python/ql/src/semmle/python/AstGenerated.qll

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,13 +1191,13 @@ library class AliasList_ extends @py_alias_list {
11911191
}
11921192

11931193
library class Arguments_ extends @py_arguments {
1194-
/** Gets the keyword default values of this parameters definition. */
1194+
/** Gets the keyword-only default values of this parameters definition. */
11951195
ExprList getKwDefaults() { py_expr_lists(result, this, 0) }
11961196

1197-
/** Gets the nth keyword default value of this parameters definition. */
1197+
/** Gets the nth keyword-only default value of this parameters definition. */
11981198
Expr getKwDefault(int index) { result = this.getKwDefaults().getItem(index) }
11991199

1200-
/** Gets a keyword default value of this parameters definition. */
1200+
/** Gets a keyword-only default value of this parameters definition. */
12011201
Expr getAKwDefault() { result = this.getKwDefaults().getAnItem() }
12021202

12031203
/** Gets the default values of this parameters definition. */
@@ -1224,13 +1224,13 @@ library class Arguments_ extends @py_arguments {
12241224
/** Gets the **kwarg annotation of this parameters definition. */
12251225
Expr getKwargannotation() { py_exprs(result, _, this, 4) }
12261226

1227-
/** Gets the kw_annotations of this parameters definition. */
1227+
/** Gets the keyword-only annotations of this parameters definition. */
12281228
ExprList getKwAnnotations() { py_expr_lists(result, this, 5) }
12291229

1230-
/** Gets the nth kw_annotation of this parameters definition. */
1230+
/** Gets the nth keyword-only annotation of this parameters definition. */
12311231
Expr getKwAnnotation(int index) { result = this.getKwAnnotations().getItem(index) }
12321232

1233-
/** Gets a kw_annotation of this parameters definition. */
1233+
/** Gets a keyword-only annotation of this parameters definition. */
12341234
Expr getAKwAnnotation() { result = this.getKwAnnotations().getAnItem() }
12351235

12361236
ArgumentsParent getParent() { py_arguments(this, result) }

python/ql/src/semmle/python/Function.qll

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -209,19 +209,31 @@ class Parameter extends Parameter_ {
209209

210210
/** Gets the expression for the default value of this parameter */
211211
Expr getDefault() {
212-
exists(Function f, int n, int c, int d, Arguments args | args = f.getDefinition().getArgs() |
213-
f.getArg(n) = this and
214-
c = count(f.getAnArg()) and
215-
d = count(args.getADefault()) and
216-
result = args.getDefault(d - c + n)
212+
exists(Function f, int i, Arguments args | args = f.getDefinition().getArgs() |
213+
// positional (normal)
214+
f.getArg(i) = this and
215+
result = args.getDefault(i)
216+
)
217+
or
218+
exists(Function f, int i, Arguments args | args = f.getDefinition().getArgs() |
219+
// keyword-only
220+
f.getKeywordOnlyArg(i) = this and
221+
result = args.getKwDefault(i)
217222
)
218223
}
219224

220225
/** Gets the annotation expression of this parameter */
221226
Expr getAnnotation() {
222-
exists(Function f, int n, Arguments args | args = f.getDefinition().getArgs() |
223-
f.getArg(n) = this and
224-
result = args.getAnnotation(n)
227+
exists(Function f, int i, Arguments args | args = f.getDefinition().getArgs() |
228+
// positional (normal)
229+
f.getArg(i) = this and
230+
result = args.getAnnotation(i)
231+
)
232+
or
233+
exists(Function f, int i, Arguments args | args = f.getDefinition().getArgs() |
234+
// keyword-only
235+
f.getKeywordOnlyArg(i) = this and
236+
result = args.getKwAnnotation(i)
225237
)
226238
or
227239
exists(Function f, Arguments args | args = f.getDefinition().getArgs() |
@@ -342,4 +354,19 @@ class Arguments extends Arguments_ {
342354
result = this.getAKwAnnotation() or
343355
result = this.getKwargannotation()
344356
}
357+
358+
// The following 4 methods are overwritten to provide better QLdoc. Since the
359+
// Arguments_ is auto-generated, we can't change the poor auto-generated docs there :(
360+
361+
/** Gets the default value for the `index`'th positional parameter. */
362+
override Expr getDefault(int index) { result = super.getDefault(index) }
363+
364+
/** Gets the default value for the `index`'th keyword-only parameter. */
365+
override Expr getKwDefault(int index) { result = super.getKwDefault(index) }
366+
367+
/** Gets the annotation for the `index`'th positional parameter. */
368+
override Expr getAnnotation(int index) { result = super.getAnnotation(index) }
369+
370+
/** Gets the annotation for the `index`'th keyword-only parameter. */
371+
override Expr getKwAnnotation(int index) { result = super.getKwAnnotation(index) }
345372
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
| test.py:4:1:11:2 | FunctionExpr | 0 | test.py:5:21:5:22 | UnaryExpr |
22
| test.py:4:1:11:2 | FunctionExpr | 1 | test.py:7:19:7:20 | UnaryExpr |
3-
| test.py:23:1:31:2 | FunctionExpr | 0 | test.py:25:28:25:31 | None |
4-
| test.py:23:1:31:2 | FunctionExpr | 1 | test.py:26:20:26:23 | None |
3+
| test.py:23:1:31:2 | FunctionExpr | 1 | test.py:25:28:25:31 | None |
4+
| test.py:23:1:31:2 | FunctionExpr | 2 | test.py:26:20:26:23 | None |
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
| test.py:4:1:11:2 | FunctionExpr | 0 | test.py:9:25:9:26 | UnaryExpr |
2-
| test.py:23:1:31:2 | FunctionExpr | 0 | test.py:29:32:29:35 | None |
2+
| test.py:23:1:31:2 | FunctionExpr | 1 | test.py:29:32:29:35 | None |

python/ql/test/3/library-tests/parameters/Annotations.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
| args | test.py:8:12:8:23 | Str |
2+
| keyword_only | test.py:9:19:9:21 | int |
3+
| keyword_w_default | test.py:29:24:29:28 | Str |
24
| kwargs | test.py:10:15:10:30 | Str |
35
| normal | test.py:7:13:7:15 | int |
46
| pos_only | test.py:5:15:5:17 | int |

python/ql/test/3/library-tests/parameters/Defaults.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
| keyword_only | test.py:9:25:9:26 | UnaryExpr |
2+
| keyword_w_default | test.py:29:32:29:35 | None |
13
| normal | test.py:7:19:7:20 | UnaryExpr |
24
| pos_only | test.py:5:21:5:22 | UnaryExpr |
35
| pos_w_default | test.py:25:28:25:31 | None |

0 commit comments

Comments
 (0)