Skip to content

Commit 89778ef

Browse files
authored
Merge pull request #1849 from markshannon/python-add-syntax-comments
Python: Add syntax example comments for automatic document generation.
2 parents c3e1fb4 + ad46303 commit 89778ef

File tree

7 files changed

+115
-0
lines changed

7 files changed

+115
-0
lines changed

python/ql/src/semmle/python/AstExtended.qll

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ import python
33
/** Syntactic node (Class, Function, Module, Expr, Stmt or Comprehension) corresponding to a flow node */
44
abstract class AstNode extends AstNode_ {
55

6+
/* Special comment for documentation generation.
7+
* All subclasses of `AstNode` that represent concrete syntax should have
8+
* a comment of the form: */
9+
/* syntax: ... */
10+
611
/** Gets the scope that this node occurs in */
712
abstract Scope getScope();
813

@@ -206,6 +211,8 @@ class ComprehensionList extends ComprehensionList_ {
206211
/** A list of expressions */
207212
class ExprList extends ExprList_ {
208213

214+
/* syntax: Expr, ... */
215+
209216
}
210217

211218

python/ql/src/semmle/python/Class.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ class ClassExpr extends ClassExpr_ {
6363
/** A class statement. Note that ClassDef extends Assign as a class definition binds the newly created class */
6464
class ClassDef extends Assign {
6565

66+
/* syntax: class name(...): ... */
67+
6668
ClassDef() {
6769
/* This is an artificial assignment the rhs of which is a (possibly decorated) ClassExpr */
6870
exists(ClassExpr c | this.getValue() = c or this.getValue() = c.getADecoratorCall())

python/ql/src/semmle/python/Exprs.qll

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ class Expr extends Expr_, AstNode {
131131
/** An attribute expression, such as `value.attr` */
132132
class Attribute extends Attribute_ {
133133

134+
/* syntax: Expr.name */
135+
134136
override Expr getASubExpression() {
135137
result = this.getObject()
136138
}
@@ -160,6 +162,8 @@ class Attribute extends Attribute_ {
160162
/** A subscript expression, such as `value[slice]` */
161163
class Subscript extends Subscript_ {
162164

165+
/* syntax: Expr[Expr] */
166+
163167
override Expr getASubExpression() {
164168
result = this.getIndex()
165169
or
@@ -176,6 +180,8 @@ class Subscript extends Subscript_ {
176180
/** A call expression, such as `func(...)` */
177181
class Call extends Call_ {
178182

183+
/* syntax: Expr(...) */
184+
179185
override Expr getASubExpression() {
180186
result = this.getAPositionalArg() or
181187
result = this.getAKeyword().getValue() or
@@ -268,6 +274,8 @@ class Call extends Call_ {
268274
/** A conditional expression such as, `body if test else orelse` */
269275
class IfExp extends IfExp_ {
270276

277+
/* syntax: Expr if Expr else Expr */
278+
271279
override Expr getASubExpression() {
272280
result = this.getTest() or result = this.getBody() or result = this.getOrelse()
273281
}
@@ -278,6 +286,8 @@ class IfExp extends IfExp_ {
278286
/** A starred expression, such as the `*rest` in the assignment `first, *rest = seq` */
279287
class Starred extends Starred_ {
280288

289+
/* syntax: *Expr */
290+
281291
override Expr getASubExpression() {
282292
result = this.getValue()
283293
}
@@ -288,6 +298,8 @@ class Starred extends Starred_ {
288298
/** A yield expression, such as `yield value` */
289299
class Yield extends Yield_ {
290300

301+
/* syntax: yield Expr */
302+
291303
override Expr getASubExpression() {
292304
result = this.getValue()
293305
}
@@ -301,6 +313,8 @@ class Yield extends Yield_ {
301313
/** A yield expression, such as `yield from value` */
302314
class YieldFrom extends YieldFrom_ {
303315

316+
/* syntax: yield from Expr */
317+
304318
override Expr getASubExpression() {
305319
result = this.getValue()
306320
}
@@ -314,6 +328,8 @@ class YieldFrom extends YieldFrom_ {
314328
/** A repr (backticks) expression, such as `` `value` `` */
315329
class Repr extends Repr_ {
316330

331+
/* syntax: `Expr` */
332+
317333
override Expr getASubExpression() {
318334
result = this.getValue()
319335
}
@@ -330,6 +346,8 @@ class Repr extends Repr_ {
330346
`"hello"` are treated as Bytes for Python2, but Unicode for Python3. */
331347
class Bytes extends StrConst {
332348

349+
/* syntax: b"hello" */
350+
333351
Bytes() {
334352
not this.isUnicode()
335353
}
@@ -355,6 +373,8 @@ class Bytes extends StrConst {
355373
/** An ellipsis expression, such as `...` */
356374
class Ellipsis extends Ellipsis_ {
357375

376+
/* syntax: ... */
377+
358378
override Expr getASubExpression() {
359379
none()
360380
}
@@ -394,6 +414,8 @@ abstract class Num extends Num_, ImmutableLiteral {
394414
/** An integer numeric constant, such as `7` or `0x9` */
395415
class IntegerLiteral extends Num {
396416

417+
/* syntax: 4 */
418+
397419
IntegerLiteral() {
398420
not this instanceof FloatLiteral and not this instanceof ImaginaryLiteral
399421
}
@@ -425,6 +447,8 @@ class IntegerLiteral extends Num {
425447
/** A floating point numeric constant, such as `0.4` or `4e3` */
426448
class FloatLiteral extends Num {
427449

450+
/* syntax: 4.2 */
451+
428452
FloatLiteral() {
429453
not this instanceof ImaginaryLiteral and
430454
this.getN().regexpMatch(".*[.eE].*")
@@ -456,6 +480,8 @@ class FloatLiteral extends Num {
456480
class ImaginaryLiteral extends Num {
457481
private float value;
458482

483+
/* syntax: 1.0j */
484+
459485
ImaginaryLiteral() {
460486
value = this.getN().regexpCapture("(.+)j.*", 1).toFloat()
461487
}
@@ -513,6 +539,8 @@ class NegativeIntegerLiteral extends ImmutableLiteral, UnaryExpr {
513539
"hello" are treated as Bytes for Python2, but Unicode for Python3. */
514540
class Unicode extends StrConst {
515541

542+
/* syntax: "hello" */
543+
516544
Unicode() {
517545
this.isUnicode()
518546
}
@@ -541,6 +569,8 @@ class Unicode extends StrConst {
541569
/** A dictionary expression, such as `{'key':'value'}` */
542570
class Dict extends Dict_ {
543571

572+
/* syntax: {Expr: Expr, ...} */
573+
544574
/** Gets the value of an item of this dict display */
545575
Expr getAValue() {
546576
result = this.getAnItem().(DictDisplayItem).getValue()
@@ -566,6 +596,8 @@ class Dict extends Dict_ {
566596
/** A list expression, such as `[ 1, 3, 5, 7, 9 ]` */
567597
class List extends List_ {
568598

599+
/* syntax: [Expr, ...] */
600+
569601
override Expr getASubExpression() {
570602
result = this.getAnElt()
571603
}
@@ -575,6 +607,8 @@ class List extends List_ {
575607
/** A set expression such as `{ 1, 3, 5, 7, 9 }` */
576608
class Set extends Set_ {
577609

610+
/* syntax: {Expr, ...} */
611+
578612
override Expr getASubExpression() {
579613
result = this.getAnElt()
580614
}
@@ -601,6 +635,8 @@ class PlaceHolder extends PlaceHolder_ {
601635
/** A tuple expression such as `( 1, 3, 5, 7, 9 )` */
602636
class Tuple extends Tuple_ {
603637

638+
/* syntax: (Expr, ...) */
639+
604640
override Expr getASubExpression() {
605641
result = this.getAnElt()
606642
}
@@ -612,6 +648,8 @@ class Tuple extends Tuple_ {
612648
*/
613649
class Name extends Name_ {
614650

651+
/* syntax: name */
652+
615653
string getId() {
616654
result = this.getVariable().getId()
617655
}
@@ -705,6 +743,8 @@ class Slice extends Slice_ {
705743
/** A string constant. */
706744
class StrConst extends Str_, ImmutableLiteral {
707745

746+
/* syntax: "hello" */
747+
708748
predicate isUnicode() {
709749
this.getPrefix().charAt(_) = "u"
710750
or
@@ -790,6 +830,8 @@ abstract class BooleanLiteral extends NameConstant {
790830
/** The boolean named constant `True` */
791831
class True extends BooleanLiteral {
792832

833+
/* syntax: True */
834+
793835
True() {
794836
name_consts(this, "True")
795837
}
@@ -807,6 +849,8 @@ class True extends BooleanLiteral {
807849
/** The boolean named constant `False` */
808850
class False extends BooleanLiteral {
809851

852+
/* syntax: False */
853+
810854
False() {
811855
name_consts(this, "False")
812856
}
@@ -824,6 +868,8 @@ class False extends BooleanLiteral {
824868
/** `None` */
825869
class None extends NameConstant {
826870

871+
/* syntax: None */
872+
827873
None() {
828874
name_consts(this, "None")
829875
}
@@ -840,6 +886,8 @@ class None extends NameConstant {
840886
/** An await expression such as `await coro`. */
841887
class Await extends Await_ {
842888

889+
/* syntax: await Expr */
890+
843891
override Expr getASubExpression() {
844892
result = this.getValue()
845893
}
@@ -849,6 +897,8 @@ class Await extends Await_ {
849897
/** A formatted string literal expression, such as `f'hello {world!s}'` */
850898
class Fstring extends Fstring_ {
851899

900+
/* syntax: f"Yes!" */
901+
852902
override Expr getASubExpression() {
853903
result = this.getAValue()
854904
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,8 @@ class Function extends Function_, Scope, AstNode {
187187
/** A def statement. Note that FunctionDef extends Assign as a function definition binds the newly created function */
188188
class FunctionDef extends Assign {
189189

190+
/* syntax: def name(...): ... */
191+
190192
FunctionDef() {
191193
/* This is an artificial assignment the rhs of which is a (possibly decorated) FunctionExpr */
192194
exists(FunctionExpr f | this.getValue() = f or this.getValue() = f.getADecoratorCall())

python/ql/src/semmle/python/Import.qll

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,8 @@ class ImportMember extends ImportMember_ {
170170
/** An import statement */
171171
class Import extends Import_ {
172172

173+
/* syntax: import modname */
174+
173175
private ImportExpr getAModuleExpr() {
174176
result = this.getAName().getValue()
175177
or
@@ -222,6 +224,8 @@ class Import extends Import_ {
222224
/** An import * statement */
223225
class ImportStar extends ImportStar_ {
224226

227+
/* syntax: from modname import * */
228+
225229
ImportExpr getModuleExpr() {
226230
result = this.getModule()
227231
or

python/ql/src/semmle/python/Keywords.qll

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import python
22

33
class KeyValuePair extends KeyValuePair_, DictDisplayItem {
44

5+
/* syntax: Expr : Expr */
6+
57
override Location getLocation() {
68
result = KeyValuePair_.super.getLocation()
79
}
@@ -76,6 +78,8 @@ abstract class DictDisplayItem extends DictItem {
7678
/** A keyword argument in a call. For example `arg=expr` in `foo(0, arg=expr)` */
7779
class Keyword extends Keyword_, DictUnpackingOrKeyword {
7880

81+
/* syntax: name = Expr */
82+
7983
override Location getLocation() {
8084
result = Keyword_.super.getLocation()
8185
}

0 commit comments

Comments
 (0)