mirror of
https://github.com/github/codeql.git
synced 2026-05-03 20:58:03 +02:00
Merge pull request #7635 from github/python/support-match
Python/support match
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
description: Add new statements and expressions for the match syntax.
|
||||
compatibility: backwards
|
||||
py_exprs.rel: run py_exprs.qlo
|
||||
py_stmts.rel: run py_stmts.qlo
|
||||
py_patterns.rel: delete
|
||||
py_patterns_lists.rel: delete
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,42 @@
|
||||
// First we need to wrap some database types
|
||||
class Location extends @location {
|
||||
/** Gets the start line of this location */
|
||||
int getStartLine() {
|
||||
locations_default(this, _, result, _, _, _) or
|
||||
locations_ast(this, _, result, _, _, _)
|
||||
}
|
||||
|
||||
string toString() { result = "<some file>" + ":" + this.getStartLine().toString() }
|
||||
}
|
||||
|
||||
class Expr_ extends @py_expr {
|
||||
string toString() { result = "Expr" }
|
||||
|
||||
Location getLocation() { py_locations(result, this) }
|
||||
}
|
||||
|
||||
class ExprParent_ extends @py_expr_parent {
|
||||
string toString() { result = "ExprParent" }
|
||||
}
|
||||
|
||||
/**
|
||||
* New kinds have been inserted such that
|
||||
* `@py_Name` which used to have index 18 now has index 19.
|
||||
* Entries with lower indices are unchanged.
|
||||
*/
|
||||
bindingset[new_index]
|
||||
int old_index(int new_index) {
|
||||
if new_index < 18 then result = new_index else result + (19 - 18) = new_index
|
||||
}
|
||||
|
||||
// The schema for py_exprs is:
|
||||
//
|
||||
// py_exprs(unique int id : @py_expr,
|
||||
// int kind: int ref,
|
||||
// int parent : @py_expr_parent ref,
|
||||
// int idx : int ref);
|
||||
from Expr_ expr, int new_kind, ExprParent_ parent, int idx, int old_kind
|
||||
where
|
||||
py_exprs(expr, new_kind, parent, idx) and
|
||||
old_kind = old_index(new_kind)
|
||||
select expr, old_kind, parent, idx
|
||||
@@ -0,0 +1,42 @@
|
||||
// First we need to wrap some database types
|
||||
class Location extends @location {
|
||||
/** Gets the start line of this location */
|
||||
int getStartLine() {
|
||||
locations_default(this, _, result, _, _, _) or
|
||||
locations_ast(this, _, result, _, _, _)
|
||||
}
|
||||
|
||||
string toString() { result = "<some file>" + ":" + this.getStartLine().toString() }
|
||||
}
|
||||
|
||||
class Stmt_ extends @py_stmt {
|
||||
string toString() { result = "Stmt" }
|
||||
|
||||
Location getLocation() { py_locations(result, this) }
|
||||
}
|
||||
|
||||
class StmtList_ extends @py_stmt_list {
|
||||
string toString() { result = "StmtList" }
|
||||
}
|
||||
|
||||
/**
|
||||
* New kinds have been inserted such that
|
||||
* `@py_Nonlocal` which used to have index 14 now has index 16.
|
||||
* Entries with lower indices are unchanged.
|
||||
*/
|
||||
bindingset[new_index]
|
||||
int old_index(int new_index) {
|
||||
if new_index < 14 then result = new_index else result + (16 - 14) = new_index
|
||||
}
|
||||
|
||||
// The schema for py_stmts is:
|
||||
//
|
||||
// py_stmts(unique int id : @py_stmt,
|
||||
// int kind: int ref,
|
||||
// int parent : @py_stmt_list ref,
|
||||
// int idx : int ref);
|
||||
from Stmt_ expr, int new_kind, StmtList_ parent, int idx, int old_kind
|
||||
where
|
||||
py_stmts(expr, new_kind, parent, idx) and
|
||||
old_kind = old_index(new_kind)
|
||||
select expr, old_kind, parent, idx
|
||||
@@ -0,0 +1,994 @@
|
||||
/*
|
||||
* This dbscheme is auto-generated by 'semmle/dbscheme_gen.py'.
|
||||
* WARNING: Any modifications to this file will be lost.
|
||||
* Relations can be changed by modifying master.py or
|
||||
* by adding rules to dbscheme.template
|
||||
*/
|
||||
|
||||
/* This is a dummy line to alter the dbscheme, so we can make a database upgrade
|
||||
* without actually changing any of the dbscheme predicates. It contains a date
|
||||
* to allow for such updates in the future as well.
|
||||
*
|
||||
* 2020-07-02
|
||||
*
|
||||
* DO NOT remove this comment carelessly, since it can revert the dbscheme back to a
|
||||
* previously seen state (matching a previously seen SHA), which would make the upgrade
|
||||
* mechanism not work properly.
|
||||
*/
|
||||
|
||||
/*
|
||||
* External artifacts
|
||||
*/
|
||||
|
||||
externalDefects(
|
||||
unique int id : @externalDefect,
|
||||
varchar(900) queryPath : string ref,
|
||||
int location : @location ref,
|
||||
varchar(900) message : string ref,
|
||||
float severity : float ref
|
||||
);
|
||||
|
||||
externalMetrics(
|
||||
unique int id : @externalMetric,
|
||||
varchar(900) queryPath : string ref,
|
||||
int location : @location ref,
|
||||
float value : float ref
|
||||
);
|
||||
|
||||
externalData(
|
||||
int id : @externalDataElement,
|
||||
varchar(900) queryPath : string ref,
|
||||
int column: int ref,
|
||||
varchar(900) data : string ref
|
||||
);
|
||||
|
||||
snapshotDate(unique date snapshotDate : date ref);
|
||||
|
||||
sourceLocationPrefix(varchar(900) prefix : string ref);
|
||||
|
||||
|
||||
/*
|
||||
* Duplicate code
|
||||
*/
|
||||
|
||||
duplicateCode(
|
||||
unique int id : @duplication,
|
||||
varchar(900) relativePath : string ref,
|
||||
int equivClass : int ref);
|
||||
|
||||
similarCode(
|
||||
unique int id : @similarity,
|
||||
varchar(900) relativePath : string ref,
|
||||
int equivClass : int ref);
|
||||
|
||||
@duplication_or_similarity = @duplication | @similarity
|
||||
|
||||
tokens(
|
||||
int id : @duplication_or_similarity ref,
|
||||
int offset : int ref,
|
||||
int beginLine : int ref,
|
||||
int beginColumn : int ref,
|
||||
int endLine : int ref,
|
||||
int endColumn : int ref);
|
||||
|
||||
/*
|
||||
* Line metrics
|
||||
*/
|
||||
py_codelines(int id : @py_scope ref,
|
||||
int count : int ref);
|
||||
|
||||
py_commentlines(int id : @py_scope ref,
|
||||
int count : int ref);
|
||||
|
||||
py_docstringlines(int id : @py_scope ref,
|
||||
int count : int ref);
|
||||
|
||||
py_alllines(int id : @py_scope ref,
|
||||
int count : int ref);
|
||||
|
||||
/*
|
||||
* Version history
|
||||
*/
|
||||
|
||||
svnentries(
|
||||
int id : @svnentry,
|
||||
varchar(500) revision : string ref,
|
||||
varchar(500) author : string ref,
|
||||
date revisionDate : date ref,
|
||||
int changeSize : int ref
|
||||
)
|
||||
|
||||
svnaffectedfiles(
|
||||
int id : @svnentry ref,
|
||||
int file : @file ref,
|
||||
varchar(500) action : string ref
|
||||
)
|
||||
|
||||
svnentrymsg(
|
||||
int id : @svnentry ref,
|
||||
varchar(500) message : string ref
|
||||
)
|
||||
|
||||
svnchurn(
|
||||
int commit : @svnentry ref,
|
||||
int file : @file ref,
|
||||
int addedLines : int ref,
|
||||
int deletedLines : int ref
|
||||
)
|
||||
|
||||
/****************************
|
||||
Python dbscheme
|
||||
****************************/
|
||||
|
||||
files(unique int id: @file,
|
||||
varchar(900) name: string ref);
|
||||
|
||||
folders(unique int id: @folder,
|
||||
varchar(900) name: string ref);
|
||||
|
||||
@container = @folder | @file;
|
||||
|
||||
containerparent(int parent: @container ref,
|
||||
unique int child: @container ref);
|
||||
|
||||
@sourceline = @file | @py_Module | @xmllocatable;
|
||||
|
||||
numlines(int element_id: @sourceline ref,
|
||||
int num_lines: int ref,
|
||||
int num_code: int ref,
|
||||
int num_comment: int ref
|
||||
);
|
||||
|
||||
@location = @location_ast | @location_default ;
|
||||
|
||||
locations_default(unique int id: @location_default,
|
||||
int file: @file ref,
|
||||
int beginLine: int ref,
|
||||
int beginColumn: int ref,
|
||||
int endLine: int ref,
|
||||
int endColumn: int ref);
|
||||
|
||||
locations_ast(unique int id: @location_ast,
|
||||
int module: @py_Module ref,
|
||||
int beginLine: int ref,
|
||||
int beginColumn: int ref,
|
||||
int endLine: int ref,
|
||||
int endColumn: int ref);
|
||||
|
||||
file_contents(unique int file: @file ref, string contents: string ref);
|
||||
|
||||
py_module_path(int module: @py_Module ref, int file: @container ref);
|
||||
|
||||
variable(unique int id : @py_variable,
|
||||
int scope : @py_scope ref,
|
||||
varchar(1) name : string ref);
|
||||
|
||||
py_line_lengths(unique int id : @py_line,
|
||||
int file: @py_Module ref,
|
||||
int line : int ref,
|
||||
int length : int ref);
|
||||
|
||||
py_extracted_version(int module : @py_Module ref,
|
||||
varchar(1) version : string ref);
|
||||
|
||||
/* AUTO GENERATED PART STARTS HERE */
|
||||
|
||||
|
||||
/* <Field> AnnAssign.location = 0, location */
|
||||
/* <Field> AnnAssign.value = 1, expr */
|
||||
/* <Field> AnnAssign.annotation = 2, expr */
|
||||
/* <Field> AnnAssign.target = 3, expr */
|
||||
|
||||
/* <Field> Assert.location = 0, location */
|
||||
/* <Field> Assert.test = 1, expr */
|
||||
/* <Field> Assert.msg = 2, expr */
|
||||
|
||||
/* <Field> Assign.location = 0, location */
|
||||
/* <Field> Assign.value = 1, expr */
|
||||
/* <Field> Assign.targets = 2, expr_list */
|
||||
|
||||
/* <Field> AssignExpr.location = 0, location */
|
||||
/* <Field> AssignExpr.parenthesised = 1, bool */
|
||||
/* <Field> AssignExpr.value = 2, expr */
|
||||
/* <Field> AssignExpr.target = 3, expr */
|
||||
|
||||
/* <Field> Attribute.location = 0, location */
|
||||
/* <Field> Attribute.parenthesised = 1, bool */
|
||||
/* <Field> Attribute.value = 2, expr */
|
||||
/* <Field> Attribute.attr = 3, str */
|
||||
/* <Field> Attribute.ctx = 4, expr_context */
|
||||
|
||||
/* <Field> AugAssign.location = 0, location */
|
||||
/* <Field> AugAssign.operation = 1, BinOp */
|
||||
|
||||
/* <Field> Await.location = 0, location */
|
||||
/* <Field> Await.parenthesised = 1, bool */
|
||||
/* <Field> Await.value = 2, expr */
|
||||
|
||||
/* <Field> BinaryExpr.location = 0, location */
|
||||
/* <Field> BinaryExpr.parenthesised = 1, bool */
|
||||
/* <Field> BinaryExpr.left = 2, expr */
|
||||
/* <Field> BinaryExpr.op = 3, operator */
|
||||
/* <Field> BinaryExpr.right = 4, expr */
|
||||
/* <Parent> BinaryExpr = AugAssign */
|
||||
|
||||
/* <Field> BoolExpr.location = 0, location */
|
||||
/* <Field> BoolExpr.parenthesised = 1, bool */
|
||||
/* <Field> BoolExpr.op = 2, boolop */
|
||||
/* <Field> BoolExpr.values = 3, expr_list */
|
||||
|
||||
/* <Field> Break.location = 0, location */
|
||||
|
||||
/* <Field> Bytes.location = 0, location */
|
||||
/* <Field> Bytes.parenthesised = 1, bool */
|
||||
/* <Field> Bytes.s = 2, bytes */
|
||||
/* <Field> Bytes.prefix = 3, bytes */
|
||||
/* <Field> Bytes.implicitly_concatenated_parts = 4, StringPart_list */
|
||||
|
||||
/* <Field> Call.location = 0, location */
|
||||
/* <Field> Call.parenthesised = 1, bool */
|
||||
/* <Field> Call.func = 2, expr */
|
||||
/* <Field> Call.positional_args = 3, expr_list */
|
||||
/* <Field> Call.named_args = 4, dict_item_list */
|
||||
|
||||
/* <Field> Class.name = 0, str */
|
||||
/* <Field> Class.body = 1, stmt_list */
|
||||
/* <Parent> Class = ClassExpr */
|
||||
|
||||
/* <Field> ClassExpr.location = 0, location */
|
||||
/* <Field> ClassExpr.parenthesised = 1, bool */
|
||||
/* <Field> ClassExpr.name = 2, str */
|
||||
/* <Field> ClassExpr.bases = 3, expr_list */
|
||||
/* <Field> ClassExpr.keywords = 4, dict_item_list */
|
||||
/* <Field> ClassExpr.inner_scope = 5, Class */
|
||||
|
||||
/* <Field> Compare.location = 0, location */
|
||||
/* <Field> Compare.parenthesised = 1, bool */
|
||||
/* <Field> Compare.left = 2, expr */
|
||||
/* <Field> Compare.ops = 3, cmpop_list */
|
||||
/* <Field> Compare.comparators = 4, expr_list */
|
||||
|
||||
/* <Field> Continue.location = 0, location */
|
||||
|
||||
/* <Field> Delete.location = 0, location */
|
||||
/* <Field> Delete.targets = 1, expr_list */
|
||||
|
||||
/* <Field> Dict.location = 0, location */
|
||||
/* <Field> Dict.parenthesised = 1, bool */
|
||||
/* <Field> Dict.items = 2, dict_item_list */
|
||||
|
||||
/* <Field> DictComp.location = 0, location */
|
||||
/* <Field> DictComp.parenthesised = 1, bool */
|
||||
/* <Field> DictComp.function = 2, Function */
|
||||
/* <Field> DictComp.iterable = 3, expr */
|
||||
|
||||
/* <Field> DictUnpacking.location = 0, location */
|
||||
/* <Field> DictUnpacking.value = 1, expr */
|
||||
|
||||
/* <Field> Ellipsis.location = 0, location */
|
||||
/* <Field> Ellipsis.parenthesised = 1, bool */
|
||||
|
||||
/* <Field> ExceptStmt.location = 0, location */
|
||||
/* <Field> ExceptStmt.type = 1, expr */
|
||||
/* <Field> ExceptStmt.name = 2, expr */
|
||||
/* <Field> ExceptStmt.body = 3, stmt_list */
|
||||
|
||||
/* <Field> Exec.location = 0, location */
|
||||
/* <Field> Exec.body = 1, expr */
|
||||
/* <Field> Exec.globals = 2, expr */
|
||||
/* <Field> Exec.locals = 3, expr */
|
||||
|
||||
/* <Field> ExprStmt.location = 0, location */
|
||||
/* <Field> ExprStmt.value = 1, expr */
|
||||
|
||||
/* <Field> Filter.location = 0, location */
|
||||
/* <Field> Filter.parenthesised = 1, bool */
|
||||
/* <Field> Filter.value = 2, expr */
|
||||
/* <Field> Filter.filter = 3, expr */
|
||||
|
||||
/* <Field> For.location = 0, location */
|
||||
/* <Field> For.target = 1, expr */
|
||||
/* <Field> For.iter = 2, expr */
|
||||
/* <Field> For.body = 3, stmt_list */
|
||||
/* <Field> For.orelse = 4, stmt_list */
|
||||
/* <Field> For.is_async = 5, bool */
|
||||
|
||||
/* <Field> FormattedValue.location = 0, location */
|
||||
/* <Field> FormattedValue.parenthesised = 1, bool */
|
||||
/* <Field> FormattedValue.value = 2, expr */
|
||||
/* <Field> FormattedValue.conversion = 3, str */
|
||||
/* <Field> FormattedValue.format_spec = 4, JoinedStr */
|
||||
|
||||
/* <Field> Function.name = 0, str */
|
||||
/* <Field> Function.args = 1, parameter_list */
|
||||
/* <Field> Function.vararg = 2, expr */
|
||||
/* <Field> Function.kwonlyargs = 3, expr_list */
|
||||
/* <Field> Function.kwarg = 4, expr */
|
||||
/* <Field> Function.body = 5, stmt_list */
|
||||
/* <Field> Function.is_async = 6, bool */
|
||||
/* <Parent> Function = FunctionParent */
|
||||
|
||||
/* <Field> FunctionExpr.location = 0, location */
|
||||
/* <Field> FunctionExpr.parenthesised = 1, bool */
|
||||
/* <Field> FunctionExpr.name = 2, str */
|
||||
/* <Field> FunctionExpr.args = 3, arguments */
|
||||
/* <Field> FunctionExpr.returns = 4, expr */
|
||||
/* <Field> FunctionExpr.inner_scope = 5, Function */
|
||||
|
||||
/* <Field> GeneratorExp.location = 0, location */
|
||||
/* <Field> GeneratorExp.parenthesised = 1, bool */
|
||||
/* <Field> GeneratorExp.function = 2, Function */
|
||||
/* <Field> GeneratorExp.iterable = 3, expr */
|
||||
|
||||
/* <Field> Global.location = 0, location */
|
||||
/* <Field> Global.names = 1, str_list */
|
||||
|
||||
/* <Field> If.location = 0, location */
|
||||
/* <Field> If.test = 1, expr */
|
||||
/* <Field> If.body = 2, stmt_list */
|
||||
/* <Field> If.orelse = 3, stmt_list */
|
||||
|
||||
/* <Field> IfExp.location = 0, location */
|
||||
/* <Field> IfExp.parenthesised = 1, bool */
|
||||
/* <Field> IfExp.test = 2, expr */
|
||||
/* <Field> IfExp.body = 3, expr */
|
||||
/* <Field> IfExp.orelse = 4, expr */
|
||||
|
||||
/* <Field> Import.location = 0, location */
|
||||
/* <Field> Import.names = 1, alias_list */
|
||||
|
||||
/* <Field> ImportExpr.location = 0, location */
|
||||
/* <Field> ImportExpr.parenthesised = 1, bool */
|
||||
/* <Field> ImportExpr.level = 2, int */
|
||||
/* <Field> ImportExpr.name = 3, str */
|
||||
/* <Field> ImportExpr.top = 4, bool */
|
||||
|
||||
/* <Field> ImportStar.location = 0, location */
|
||||
/* <Field> ImportStar.module = 1, expr */
|
||||
|
||||
/* <Field> ImportMember.location = 0, location */
|
||||
/* <Field> ImportMember.parenthesised = 1, bool */
|
||||
/* <Field> ImportMember.module = 2, expr */
|
||||
/* <Field> ImportMember.name = 3, str */
|
||||
|
||||
/* <Field> Fstring.location = 0, location */
|
||||
/* <Field> Fstring.parenthesised = 1, bool */
|
||||
/* <Field> Fstring.values = 2, expr_list */
|
||||
/* <Parent> Fstring = FormattedValue */
|
||||
|
||||
/* <Field> KeyValuePair.location = 0, location */
|
||||
/* <Field> KeyValuePair.value = 1, expr */
|
||||
/* <Field> KeyValuePair.key = 2, expr */
|
||||
|
||||
/* <Field> Lambda.location = 0, location */
|
||||
/* <Field> Lambda.parenthesised = 1, bool */
|
||||
/* <Field> Lambda.args = 2, arguments */
|
||||
/* <Field> Lambda.inner_scope = 3, Function */
|
||||
|
||||
/* <Field> List.location = 0, location */
|
||||
/* <Field> List.parenthesised = 1, bool */
|
||||
/* <Field> List.elts = 2, expr_list */
|
||||
/* <Field> List.ctx = 3, expr_context */
|
||||
|
||||
/* <Field> ListComp.location = 0, location */
|
||||
/* <Field> ListComp.parenthesised = 1, bool */
|
||||
/* <Field> ListComp.function = 2, Function */
|
||||
/* <Field> ListComp.iterable = 3, expr */
|
||||
/* <Field> ListComp.generators = 4, comprehension_list */
|
||||
/* <Field> ListComp.elt = 5, expr */
|
||||
|
||||
/* <Field> Module.name = 0, str */
|
||||
/* <Field> Module.hash = 1, str */
|
||||
/* <Field> Module.body = 2, stmt_list */
|
||||
/* <Field> Module.kind = 3, str */
|
||||
|
||||
/* <Field> Name.location = 0, location */
|
||||
/* <Field> Name.parenthesised = 1, bool */
|
||||
/* <Field> Name.variable = 2, variable */
|
||||
/* <Field> Name.ctx = 3, expr_context */
|
||||
/* <Parent> Name = ParameterList */
|
||||
|
||||
/* <Field> Nonlocal.location = 0, location */
|
||||
/* <Field> Nonlocal.names = 1, str_list */
|
||||
|
||||
/* <Field> Num.location = 0, location */
|
||||
/* <Field> Num.parenthesised = 1, bool */
|
||||
/* <Field> Num.n = 2, number */
|
||||
/* <Field> Num.text = 3, number */
|
||||
|
||||
/* <Field> Pass.location = 0, location */
|
||||
|
||||
/* <Field> PlaceHolder.location = 0, location */
|
||||
/* <Field> PlaceHolder.parenthesised = 1, bool */
|
||||
/* <Field> PlaceHolder.variable = 2, variable */
|
||||
/* <Field> PlaceHolder.ctx = 3, expr_context */
|
||||
|
||||
/* <Field> Print.location = 0, location */
|
||||
/* <Field> Print.dest = 1, expr */
|
||||
/* <Field> Print.values = 2, expr_list */
|
||||
/* <Field> Print.nl = 3, bool */
|
||||
|
||||
/* <Field> Raise.location = 0, location */
|
||||
/* <Field> Raise.exc = 1, expr */
|
||||
/* <Field> Raise.cause = 2, expr */
|
||||
/* <Field> Raise.type = 3, expr */
|
||||
/* <Field> Raise.inst = 4, expr */
|
||||
/* <Field> Raise.tback = 5, expr */
|
||||
|
||||
/* <Field> Repr.location = 0, location */
|
||||
/* <Field> Repr.parenthesised = 1, bool */
|
||||
/* <Field> Repr.value = 2, expr */
|
||||
|
||||
/* <Field> Return.location = 0, location */
|
||||
/* <Field> Return.value = 1, expr */
|
||||
|
||||
/* <Field> Set.location = 0, location */
|
||||
/* <Field> Set.parenthesised = 1, bool */
|
||||
/* <Field> Set.elts = 2, expr_list */
|
||||
|
||||
/* <Field> SetComp.location = 0, location */
|
||||
/* <Field> SetComp.parenthesised = 1, bool */
|
||||
/* <Field> SetComp.function = 2, Function */
|
||||
/* <Field> SetComp.iterable = 3, expr */
|
||||
|
||||
/* <Field> Slice.location = 0, location */
|
||||
/* <Field> Slice.parenthesised = 1, bool */
|
||||
/* <Field> Slice.start = 2, expr */
|
||||
/* <Field> Slice.stop = 3, expr */
|
||||
/* <Field> Slice.step = 4, expr */
|
||||
|
||||
/* <Field> SpecialOperation.location = 0, location */
|
||||
/* <Field> SpecialOperation.parenthesised = 1, bool */
|
||||
/* <Field> SpecialOperation.name = 2, str */
|
||||
/* <Field> SpecialOperation.arguments = 3, expr_list */
|
||||
|
||||
/* <Field> Starred.location = 0, location */
|
||||
/* <Field> Starred.parenthesised = 1, bool */
|
||||
/* <Field> Starred.value = 2, expr */
|
||||
/* <Field> Starred.ctx = 3, expr_context */
|
||||
|
||||
/* <Field> Str.location = 0, location */
|
||||
/* <Field> Str.parenthesised = 1, bool */
|
||||
/* <Field> Str.s = 2, str */
|
||||
/* <Field> Str.prefix = 3, str */
|
||||
/* <Field> Str.implicitly_concatenated_parts = 4, StringPart_list */
|
||||
|
||||
/* <Field> StringPart.text = 0, str */
|
||||
/* <Field> StringPart.location = 1, location */
|
||||
/* <Parent> StringPart = StringPartList */
|
||||
/* <Parent> StringPartList = BytesOrStr */
|
||||
|
||||
/* <Field> Subscript.location = 0, location */
|
||||
/* <Field> Subscript.parenthesised = 1, bool */
|
||||
/* <Field> Subscript.value = 2, expr */
|
||||
/* <Field> Subscript.index = 3, expr */
|
||||
/* <Field> Subscript.ctx = 4, expr_context */
|
||||
|
||||
/* <Field> TemplateDottedNotation.location = 0, location */
|
||||
/* <Field> TemplateDottedNotation.parenthesised = 1, bool */
|
||||
/* <Field> TemplateDottedNotation.value = 2, expr */
|
||||
/* <Field> TemplateDottedNotation.attr = 3, str */
|
||||
/* <Field> TemplateDottedNotation.ctx = 4, expr_context */
|
||||
|
||||
/* <Field> TemplateWrite.location = 0, location */
|
||||
/* <Field> TemplateWrite.value = 1, expr */
|
||||
|
||||
/* <Field> Try.location = 0, location */
|
||||
/* <Field> Try.body = 1, stmt_list */
|
||||
/* <Field> Try.orelse = 2, stmt_list */
|
||||
/* <Field> Try.handlers = 3, stmt_list */
|
||||
/* <Field> Try.finalbody = 4, stmt_list */
|
||||
|
||||
/* <Field> Tuple.location = 0, location */
|
||||
/* <Field> Tuple.parenthesised = 1, bool */
|
||||
/* <Field> Tuple.elts = 2, expr_list */
|
||||
/* <Field> Tuple.ctx = 3, expr_context */
|
||||
/* <Parent> Tuple = ParameterList */
|
||||
|
||||
/* <Field> UnaryExpr.location = 0, location */
|
||||
/* <Field> UnaryExpr.parenthesised = 1, bool */
|
||||
/* <Field> UnaryExpr.op = 2, unaryop */
|
||||
/* <Field> UnaryExpr.operand = 3, expr */
|
||||
|
||||
/* <Field> While.location = 0, location */
|
||||
/* <Field> While.test = 1, expr */
|
||||
/* <Field> While.body = 2, stmt_list */
|
||||
/* <Field> While.orelse = 3, stmt_list */
|
||||
|
||||
/* <Field> With.location = 0, location */
|
||||
/* <Field> With.context_expr = 1, expr */
|
||||
/* <Field> With.optional_vars = 2, expr */
|
||||
/* <Field> With.body = 3, stmt_list */
|
||||
/* <Field> With.is_async = 4, bool */
|
||||
|
||||
/* <Field> Yield.location = 0, location */
|
||||
/* <Field> Yield.parenthesised = 1, bool */
|
||||
/* <Field> Yield.value = 2, expr */
|
||||
|
||||
/* <Field> YieldFrom.location = 0, location */
|
||||
/* <Field> YieldFrom.parenthesised = 1, bool */
|
||||
/* <Field> YieldFrom.value = 2, expr */
|
||||
|
||||
/* <Field> Alias.value = 0, expr */
|
||||
/* <Field> Alias.asname = 1, expr */
|
||||
/* <Parent> Alias = AliasList */
|
||||
/* <Parent> AliasList = Import */
|
||||
|
||||
/* <Field> Arguments.kw_defaults = 0, expr_list */
|
||||
/* <Field> Arguments.defaults = 1, expr_list */
|
||||
/* <Field> Arguments.annotations = 2, expr_list */
|
||||
/* <Field> Arguments.varargannotation = 3, expr */
|
||||
/* <Field> Arguments.kwargannotation = 4, expr */
|
||||
/* <Field> Arguments.kw_annotations = 5, expr_list */
|
||||
/* <Parent> Arguments = ArgumentsParent */
|
||||
/* <Parent> boolean = BoolParent */
|
||||
/* <Parent> Boolop = BoolExpr */
|
||||
/* <Parent> string = Bytes */
|
||||
/* <Parent> Cmpop = CmpopList */
|
||||
/* <Parent> CmpopList = Compare */
|
||||
|
||||
/* <Field> Comprehension.location = 0, location */
|
||||
/* <Field> Comprehension.iter = 1, expr */
|
||||
/* <Field> Comprehension.target = 2, expr */
|
||||
/* <Field> Comprehension.ifs = 3, expr_list */
|
||||
/* <Parent> Comprehension = ComprehensionList */
|
||||
/* <Parent> ComprehensionList = ListComp */
|
||||
/* <Parent> DictItem = DictItemList */
|
||||
/* <Parent> DictItemList = DictItemListParent */
|
||||
|
||||
/* <Field> Expr.location = 0, location */
|
||||
/* <Field> Expr.parenthesised = 1, bool */
|
||||
/* <Parent> Expr = ExprParent */
|
||||
/* <Parent> ExprContext = ExprContextParent */
|
||||
/* <Parent> ExprList = ExprListParent */
|
||||
/* <Parent> int = ImportExpr */
|
||||
|
||||
/* <Field> Keyword.location = 0, location */
|
||||
/* <Field> Keyword.value = 1, expr */
|
||||
/* <Field> Keyword.arg = 2, str */
|
||||
/* <Parent> Location = LocationParent */
|
||||
/* <Parent> string = Num */
|
||||
/* <Parent> Operator = BinaryExpr */
|
||||
/* <Parent> ParameterList = Function */
|
||||
|
||||
/* <Field> Stmt.location = 0, location */
|
||||
/* <Parent> Stmt = StmtList */
|
||||
/* <Parent> StmtList = StmtListParent */
|
||||
/* <Parent> string = StrParent */
|
||||
/* <Parent> StringList = StrListParent */
|
||||
/* <Parent> Unaryop = UnaryExpr */
|
||||
/* <Parent> Variable = VariableParent */
|
||||
py_Classes(unique int id : @py_Class,
|
||||
unique int parent : @py_ClassExpr ref);
|
||||
|
||||
py_Functions(unique int id : @py_Function,
|
||||
unique int parent : @py_Function_parent ref);
|
||||
|
||||
py_Modules(unique int id : @py_Module);
|
||||
|
||||
py_StringParts(unique int id : @py_StringPart,
|
||||
int parent : @py_StringPart_list ref,
|
||||
int idx : int ref);
|
||||
|
||||
py_StringPart_lists(unique int id : @py_StringPart_list,
|
||||
unique int parent : @py_Bytes_or_Str ref);
|
||||
|
||||
py_aliases(unique int id : @py_alias,
|
||||
int parent : @py_alias_list ref,
|
||||
int idx : int ref);
|
||||
|
||||
py_alias_lists(unique int id : @py_alias_list,
|
||||
unique int parent : @py_Import ref);
|
||||
|
||||
py_arguments(unique int id : @py_arguments,
|
||||
unique int parent : @py_arguments_parent ref);
|
||||
|
||||
py_bools(int parent : @py_bool_parent ref,
|
||||
int idx : int ref);
|
||||
|
||||
py_boolops(unique int id : @py_boolop,
|
||||
int kind: int ref,
|
||||
unique int parent : @py_BoolExpr ref);
|
||||
|
||||
py_bytes(varchar(1) id : string ref,
|
||||
int parent : @py_Bytes ref,
|
||||
int idx : int ref);
|
||||
|
||||
py_cmpops(unique int id : @py_cmpop,
|
||||
int kind: int ref,
|
||||
int parent : @py_cmpop_list ref,
|
||||
int idx : int ref);
|
||||
|
||||
py_cmpop_lists(unique int id : @py_cmpop_list,
|
||||
unique int parent : @py_Compare ref);
|
||||
|
||||
py_comprehensions(unique int id : @py_comprehension,
|
||||
int parent : @py_comprehension_list ref,
|
||||
int idx : int ref);
|
||||
|
||||
py_comprehension_lists(unique int id : @py_comprehension_list,
|
||||
unique int parent : @py_ListComp ref);
|
||||
|
||||
py_dict_items(unique int id : @py_dict_item,
|
||||
int kind: int ref,
|
||||
int parent : @py_dict_item_list ref,
|
||||
int idx : int ref);
|
||||
|
||||
py_dict_item_lists(unique int id : @py_dict_item_list,
|
||||
unique int parent : @py_dict_item_list_parent ref);
|
||||
|
||||
py_exprs(unique int id : @py_expr,
|
||||
int kind: int ref,
|
||||
int parent : @py_expr_parent ref,
|
||||
int idx : int ref);
|
||||
|
||||
py_expr_contexts(unique int id : @py_expr_context,
|
||||
int kind: int ref,
|
||||
unique int parent : @py_expr_context_parent ref);
|
||||
|
||||
py_expr_lists(unique int id : @py_expr_list,
|
||||
int parent : @py_expr_list_parent ref,
|
||||
int idx : int ref);
|
||||
|
||||
py_ints(int id : int ref,
|
||||
unique int parent : @py_ImportExpr ref);
|
||||
|
||||
py_locations(unique int id : @location ref,
|
||||
unique int parent : @py_location_parent ref);
|
||||
|
||||
py_numbers(varchar(1) id : string ref,
|
||||
int parent : @py_Num ref,
|
||||
int idx : int ref);
|
||||
|
||||
py_operators(unique int id : @py_operator,
|
||||
int kind: int ref,
|
||||
unique int parent : @py_BinaryExpr ref);
|
||||
|
||||
py_parameter_lists(unique int id : @py_parameter_list,
|
||||
unique int parent : @py_Function ref);
|
||||
|
||||
py_stmts(unique int id : @py_stmt,
|
||||
int kind: int ref,
|
||||
int parent : @py_stmt_list ref,
|
||||
int idx : int ref);
|
||||
|
||||
py_stmt_lists(unique int id : @py_stmt_list,
|
||||
int parent : @py_stmt_list_parent ref,
|
||||
int idx : int ref);
|
||||
|
||||
py_strs(varchar(1) id : string ref,
|
||||
int parent : @py_str_parent ref,
|
||||
int idx : int ref);
|
||||
|
||||
py_str_lists(unique int id : @py_str_list,
|
||||
unique int parent : @py_str_list_parent ref);
|
||||
|
||||
py_unaryops(unique int id : @py_unaryop,
|
||||
int kind: int ref,
|
||||
unique int parent : @py_UnaryExpr ref);
|
||||
|
||||
py_variables(int id : @py_variable ref,
|
||||
unique int parent : @py_variable_parent ref);
|
||||
|
||||
case @py_boolop.kind of
|
||||
0 = @py_And
|
||||
| 1 = @py_Or;
|
||||
|
||||
case @py_cmpop.kind of
|
||||
0 = @py_Eq
|
||||
| 1 = @py_Gt
|
||||
| 2 = @py_GtE
|
||||
| 3 = @py_In
|
||||
| 4 = @py_Is
|
||||
| 5 = @py_IsNot
|
||||
| 6 = @py_Lt
|
||||
| 7 = @py_LtE
|
||||
| 8 = @py_NotEq
|
||||
| 9 = @py_NotIn;
|
||||
|
||||
case @py_dict_item.kind of
|
||||
0 = @py_DictUnpacking
|
||||
| 1 = @py_KeyValuePair
|
||||
| 2 = @py_keyword;
|
||||
|
||||
case @py_expr.kind of
|
||||
0 = @py_Attribute
|
||||
| 1 = @py_BinaryExpr
|
||||
| 2 = @py_BoolExpr
|
||||
| 3 = @py_Bytes
|
||||
| 4 = @py_Call
|
||||
| 5 = @py_ClassExpr
|
||||
| 6 = @py_Compare
|
||||
| 7 = @py_Dict
|
||||
| 8 = @py_DictComp
|
||||
| 9 = @py_Ellipsis
|
||||
| 10 = @py_FunctionExpr
|
||||
| 11 = @py_GeneratorExp
|
||||
| 12 = @py_IfExp
|
||||
| 13 = @py_ImportExpr
|
||||
| 14 = @py_ImportMember
|
||||
| 15 = @py_Lambda
|
||||
| 16 = @py_List
|
||||
| 17 = @py_ListComp
|
||||
| 18 = @py_Name
|
||||
| 19 = @py_Num
|
||||
| 20 = @py_Repr
|
||||
| 21 = @py_Set
|
||||
| 22 = @py_SetComp
|
||||
| 23 = @py_Slice
|
||||
| 24 = @py_Starred
|
||||
| 25 = @py_Str
|
||||
| 26 = @py_Subscript
|
||||
| 27 = @py_Tuple
|
||||
| 28 = @py_UnaryExpr
|
||||
| 29 = @py_Yield
|
||||
| 30 = @py_YieldFrom
|
||||
| 31 = @py_TemplateDottedNotation
|
||||
| 32 = @py_Filter
|
||||
| 33 = @py_PlaceHolder
|
||||
| 34 = @py_Await
|
||||
| 35 = @py_Fstring
|
||||
| 36 = @py_FormattedValue
|
||||
| 37 = @py_AssignExpr
|
||||
| 38 = @py_SpecialOperation;
|
||||
|
||||
case @py_expr_context.kind of
|
||||
0 = @py_AugLoad
|
||||
| 1 = @py_AugStore
|
||||
| 2 = @py_Del
|
||||
| 3 = @py_Load
|
||||
| 4 = @py_Param
|
||||
| 5 = @py_Store;
|
||||
|
||||
case @py_operator.kind of
|
||||
0 = @py_Add
|
||||
| 1 = @py_BitAnd
|
||||
| 2 = @py_BitOr
|
||||
| 3 = @py_BitXor
|
||||
| 4 = @py_Div
|
||||
| 5 = @py_FloorDiv
|
||||
| 6 = @py_LShift
|
||||
| 7 = @py_Mod
|
||||
| 8 = @py_Mult
|
||||
| 9 = @py_Pow
|
||||
| 10 = @py_RShift
|
||||
| 11 = @py_Sub
|
||||
| 12 = @py_MatMult;
|
||||
|
||||
case @py_stmt.kind of
|
||||
0 = @py_Assert
|
||||
| 1 = @py_Assign
|
||||
| 2 = @py_AugAssign
|
||||
| 3 = @py_Break
|
||||
| 4 = @py_Continue
|
||||
| 5 = @py_Delete
|
||||
| 6 = @py_ExceptStmt
|
||||
| 7 = @py_Exec
|
||||
| 8 = @py_Expr_stmt
|
||||
| 9 = @py_For
|
||||
| 10 = @py_Global
|
||||
| 11 = @py_If
|
||||
| 12 = @py_Import
|
||||
| 13 = @py_ImportStar
|
||||
| 14 = @py_Nonlocal
|
||||
| 15 = @py_Pass
|
||||
| 16 = @py_Print
|
||||
| 17 = @py_Raise
|
||||
| 18 = @py_Return
|
||||
| 19 = @py_Try
|
||||
| 20 = @py_While
|
||||
| 21 = @py_With
|
||||
| 22 = @py_TemplateWrite
|
||||
| 23 = @py_AnnAssign;
|
||||
|
||||
case @py_unaryop.kind of
|
||||
0 = @py_Invert
|
||||
| 1 = @py_Not
|
||||
| 2 = @py_UAdd
|
||||
| 3 = @py_USub;
|
||||
|
||||
@py_Bytes_or_Str = @py_Bytes | @py_Str;
|
||||
|
||||
@py_Function_parent = @py_DictComp | @py_FunctionExpr | @py_GeneratorExp | @py_Lambda | @py_ListComp | @py_SetComp;
|
||||
|
||||
@py_arguments_parent = @py_FunctionExpr | @py_Lambda;
|
||||
|
||||
@py_ast_node = @py_Class | @py_Function | @py_Module | @py_StringPart | @py_comprehension | @py_dict_item | @py_expr | @py_stmt;
|
||||
|
||||
@py_bool_parent = @py_For | @py_Function | @py_Print | @py_With | @py_expr;
|
||||
|
||||
@py_dict_item_list_parent = @py_Call | @py_ClassExpr | @py_Dict;
|
||||
|
||||
@py_expr_context_parent = @py_Attribute | @py_List | @py_Name | @py_PlaceHolder | @py_Starred | @py_Subscript | @py_TemplateDottedNotation | @py_Tuple;
|
||||
|
||||
@py_expr_list_parent = @py_Assign | @py_BoolExpr | @py_Call | @py_ClassExpr | @py_Compare | @py_Delete | @py_Fstring | @py_Function | @py_List | @py_Print | @py_Set | @py_SpecialOperation | @py_Tuple | @py_arguments | @py_comprehension;
|
||||
|
||||
@py_expr_or_stmt = @py_expr | @py_stmt;
|
||||
|
||||
@py_expr_parent = @py_AnnAssign | @py_Assert | @py_Assign | @py_AssignExpr | @py_Attribute | @py_AugAssign | @py_Await | @py_BinaryExpr | @py_Call | @py_Compare | @py_DictComp | @py_DictUnpacking | @py_ExceptStmt | @py_Exec | @py_Expr_stmt | @py_Filter | @py_For | @py_FormattedValue | @py_Function | @py_FunctionExpr | @py_GeneratorExp | @py_If | @py_IfExp | @py_ImportMember | @py_ImportStar | @py_KeyValuePair | @py_ListComp | @py_Print | @py_Raise | @py_Repr | @py_Return | @py_SetComp | @py_Slice | @py_Starred | @py_Subscript | @py_TemplateDottedNotation | @py_TemplateWrite | @py_UnaryExpr | @py_While | @py_With | @py_Yield | @py_YieldFrom | @py_alias | @py_arguments | @py_comprehension | @py_expr_list | @py_keyword | @py_parameter_list;
|
||||
|
||||
@py_location_parent = @py_DictUnpacking | @py_KeyValuePair | @py_StringPart | @py_comprehension | @py_expr | @py_keyword | @py_stmt;
|
||||
|
||||
@py_parameter = @py_Name | @py_Tuple;
|
||||
|
||||
@py_scope = @py_Class | @py_Function | @py_Module;
|
||||
|
||||
@py_stmt_list_parent = @py_Class | @py_ExceptStmt | @py_For | @py_Function | @py_If | @py_Module | @py_Try | @py_While | @py_With;
|
||||
|
||||
@py_str_list_parent = @py_Global | @py_Nonlocal;
|
||||
|
||||
@py_str_parent = @py_Attribute | @py_Class | @py_ClassExpr | @py_FormattedValue | @py_Function | @py_FunctionExpr | @py_ImportExpr | @py_ImportMember | @py_Module | @py_SpecialOperation | @py_Str | @py_StringPart | @py_TemplateDottedNotation | @py_keyword | @py_str_list;
|
||||
|
||||
@py_variable_parent = @py_Name | @py_PlaceHolder;
|
||||
|
||||
|
||||
/*
|
||||
* End of auto-generated part
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* Map relative names to absolute names for imports */
|
||||
py_absolute_names(int module : @py_Module ref,
|
||||
varchar(1) relname : string ref,
|
||||
varchar(1) absname : string ref);
|
||||
|
||||
py_exports(int id : @py_Module ref,
|
||||
varchar(1) name : string ref);
|
||||
|
||||
/* Successor information */
|
||||
py_successors(int predecessor : @py_flow_node ref,
|
||||
int successor : @py_flow_node ref);
|
||||
|
||||
py_true_successors(int predecessor : @py_flow_node ref,
|
||||
int successor : @py_flow_node ref);
|
||||
|
||||
py_exception_successors(int predecessor : @py_flow_node ref,
|
||||
int successor : @py_flow_node ref);
|
||||
|
||||
py_false_successors(int predecessor : @py_flow_node ref,
|
||||
int successor : @py_flow_node ref);
|
||||
|
||||
py_flow_bb_node(unique int flownode : @py_flow_node,
|
||||
int realnode : @py_ast_node ref,
|
||||
int basicblock : @py_flow_node ref,
|
||||
int index : int ref);
|
||||
|
||||
py_scope_flow(int flow : @py_flow_node ref,
|
||||
int scope : @py_scope ref,
|
||||
int kind : int ref);
|
||||
|
||||
py_idoms(unique int node : @py_flow_node ref,
|
||||
int immediate_dominator : @py_flow_node ref);
|
||||
|
||||
py_ssa_phi(int phi : @py_ssa_var ref,
|
||||
int arg: @py_ssa_var ref);
|
||||
|
||||
py_ssa_var(unique int id : @py_ssa_var,
|
||||
int var : @py_variable ref);
|
||||
|
||||
py_ssa_use(int node: @py_flow_node ref,
|
||||
int var : @py_ssa_var ref);
|
||||
|
||||
py_ssa_defn(unique int id : @py_ssa_var ref,
|
||||
int node: @py_flow_node ref);
|
||||
|
||||
@py_base_var = @py_variable | @py_ssa_var;
|
||||
|
||||
py_scopes(unique int node : @py_expr_or_stmt ref,
|
||||
int scope : @py_scope ref);
|
||||
|
||||
py_scope_location(unique int id : @location ref,
|
||||
unique int scope : @py_scope ref);
|
||||
|
||||
py_flags_versioned(varchar(1) name : string ref,
|
||||
varchar(1) value : string ref,
|
||||
varchar(1) version : string ref);
|
||||
|
||||
py_syntax_error_versioned(unique int id : @location ref,
|
||||
varchar(1) message : string ref,
|
||||
varchar(1) version : string ref);
|
||||
|
||||
py_comments(unique int id : @py_comment,
|
||||
varchar(1) text : string ref,
|
||||
unique int location : @location ref);
|
||||
|
||||
/* Type information support */
|
||||
|
||||
py_cobjects(unique int obj : @py_cobject);
|
||||
|
||||
py_cobjecttypes(unique int obj : @py_cobject ref,
|
||||
int typeof : @py_cobject ref);
|
||||
|
||||
py_cobjectnames(unique int obj : @py_cobject ref,
|
||||
varchar(1) name : string ref);
|
||||
|
||||
/* Kind should be 0 for introspection, > 0 from source, as follows:
|
||||
1 from C extension source
|
||||
*/
|
||||
py_cobject_sources(int obj : @py_cobject ref,
|
||||
int kind : int ref);
|
||||
|
||||
py_cmembers_versioned(int object : @py_cobject ref,
|
||||
varchar(1) name : string ref,
|
||||
int member : @py_cobject ref,
|
||||
varchar(1) version : string ref);
|
||||
|
||||
py_citems(int object : @py_cobject ref,
|
||||
int index : int ref,
|
||||
int member : @py_cobject ref);
|
||||
|
||||
ext_argtype(int funcid : @py_object ref,
|
||||
int arg : int ref,
|
||||
int typeid : @py_object ref);
|
||||
|
||||
ext_rettype(int funcid : @py_object ref,
|
||||
int typeid : @py_object ref);
|
||||
|
||||
ext_proptype(int propid : @py_object ref,
|
||||
int typeid : @py_object ref);
|
||||
|
||||
ext_argreturn(int funcid : @py_object ref,
|
||||
int arg : int ref);
|
||||
|
||||
py_special_objects(unique int obj : @py_cobject ref,
|
||||
unique varchar(1) name : string ref);
|
||||
|
||||
py_decorated_object(int object : @py_object ref,
|
||||
int level: int ref);
|
||||
|
||||
@py_object = @py_cobject | @py_flow_node;
|
||||
|
||||
@py_source_element = @py_ast_node | @container;
|
||||
|
||||
/* XML Files */
|
||||
|
||||
xmlEncoding (unique int id: @file ref, varchar(900) encoding: string ref);
|
||||
|
||||
xmlDTDs (unique int id: @xmldtd,
|
||||
varchar(900) root: string ref,
|
||||
varchar(900) publicId: string ref,
|
||||
varchar(900) systemId: string ref,
|
||||
int fileid: @file ref);
|
||||
|
||||
xmlElements (unique int id: @xmlelement,
|
||||
varchar(900) name: string ref,
|
||||
int parentid: @xmlparent ref,
|
||||
int idx: int ref,
|
||||
int fileid: @file ref);
|
||||
|
||||
xmlAttrs (unique int id: @xmlattribute,
|
||||
int elementid: @xmlelement ref,
|
||||
varchar(900) name: string ref,
|
||||
varchar(3600) value: string ref,
|
||||
int idx: int ref,
|
||||
int fileid: @file ref);
|
||||
|
||||
xmlNs (int id: @xmlnamespace,
|
||||
varchar(900) prefixName: string ref,
|
||||
varchar(900) URI: string ref,
|
||||
int fileid: @file ref);
|
||||
|
||||
xmlHasNs (int elementId: @xmlnamespaceable ref,
|
||||
int nsId: @xmlnamespace ref,
|
||||
int fileid: @file ref);
|
||||
|
||||
xmlComments (unique int id: @xmlcomment,
|
||||
varchar(3600) text: string ref,
|
||||
int parentid: @xmlparent ref,
|
||||
int fileid: @file ref);
|
||||
|
||||
xmlChars (unique int id: @xmlcharacters,
|
||||
varchar(3600) text: string ref,
|
||||
int parentid: @xmlparent ref,
|
||||
int idx: int ref,
|
||||
int isCDATA: int ref,
|
||||
int fileid: @file ref);
|
||||
|
||||
@xmlparent = @file | @xmlelement;
|
||||
@xmlnamespaceable = @xmlelement | @xmlattribute;
|
||||
|
||||
xmllocations(int xmlElement: @xmllocatable ref,
|
||||
int location: @location_default ref);
|
||||
|
||||
@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;
|
||||
@@ -10,6 +10,7 @@ import semmle.python.Class
|
||||
import semmle.python.Import
|
||||
import semmle.python.Stmts
|
||||
import semmle.python.Exprs
|
||||
import semmle.python.Patterns
|
||||
import semmle.python.Keywords
|
||||
import semmle.python.Comprehensions
|
||||
import semmle.python.Flow
|
||||
|
||||
@@ -82,6 +82,12 @@ library class StrListParent extends StrListParent_ { }
|
||||
/** Internal implementation class */
|
||||
library class ExprParent extends ExprParent_ { }
|
||||
|
||||
/** Internal implementation class */
|
||||
class PatternListParent extends PatternListParent_ { }
|
||||
|
||||
/** Internal implementation class */
|
||||
library class PatternParent extends PatternParent_ { }
|
||||
|
||||
library class DictItem extends DictItem_, AstNode {
|
||||
override string toString() { result = DictItem_.super.toString() }
|
||||
|
||||
@@ -162,6 +168,9 @@ class ExprList extends ExprList_ {
|
||||
/* syntax: Expr, ... */
|
||||
}
|
||||
|
||||
/** A list of patterns */
|
||||
class PatternList extends PatternList_ { }
|
||||
|
||||
library class DictItemList extends DictItemList_ { }
|
||||
|
||||
library class DictItemListParent extends DictItemListParent_ { }
|
||||
|
||||
@@ -218,6 +218,26 @@ library class Call_ extends @py_Call, Expr {
|
||||
override string toString() { result = "Call" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Case` for further information. */
|
||||
library class Case_ extends @py_Case, Stmt {
|
||||
/** Gets the pattern of this case statement. */
|
||||
Pattern getPattern() { py_patterns(result, _, this, 1) }
|
||||
|
||||
/** Gets the guard of this case statement. */
|
||||
Expr getGuard() { py_exprs(result, _, this, 2) }
|
||||
|
||||
/** Gets the body of this case statement. */
|
||||
StmtList getBody() { py_stmt_lists(result, this, 3) }
|
||||
|
||||
/** Gets the nth statement of this case statement. */
|
||||
Stmt getStmt(int index) { result = this.getBody().getItem(index) }
|
||||
|
||||
/** Gets a statement of this case statement. */
|
||||
Stmt getAStmt() { result = this.getBody().getAnItem() }
|
||||
|
||||
override string toString() { result = "Case" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Class` for further information. */
|
||||
library class Class_ extends @py_Class {
|
||||
/** Gets the name of this class. */
|
||||
@@ -232,6 +252,7 @@ library class Class_ extends @py_Class {
|
||||
/** Gets a statement of this class. */
|
||||
Stmt getAStmt() { result = this.getBody().getAnItem() }
|
||||
|
||||
/** Gets a parent of this class */
|
||||
ClassExpr getParent() { py_Classes(this, result) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
@@ -513,6 +534,7 @@ library class Function_ extends @py_Function {
|
||||
/** Whether the async property of this function is true. */
|
||||
predicate isAsync() { py_bools(this, 6) }
|
||||
|
||||
/** Gets a parent of this function */
|
||||
FunctionParent getParent() { py_Functions(this, result) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
@@ -577,6 +599,14 @@ library class GtE_ extends @py_GtE, Cmpop {
|
||||
override string toString() { result = "GtE" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Guard` for further information. */
|
||||
library class Guard_ extends @py_Guard, Expr {
|
||||
/** Gets the test of this guard expression. */
|
||||
Expr getTest() { py_exprs(result, _, this, 2) }
|
||||
|
||||
override string toString() { result = "Guard" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `If` for further information. */
|
||||
library class If_ extends @py_If, Stmt {
|
||||
/** Gets the test of this if statement. */
|
||||
@@ -790,6 +820,172 @@ library class MatMult_ extends @py_MatMult, Operator {
|
||||
override string toString() { result = "MatMult" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `MatchStmt` for further information. */
|
||||
library class MatchStmt_ extends @py_MatchStmt, Stmt {
|
||||
/** Gets the subject of this match statement. */
|
||||
Expr getSubject() { py_exprs(result, _, this, 1) }
|
||||
|
||||
/** Gets the cases of this match statement. */
|
||||
StmtList getCases() { py_stmt_lists(result, this, 2) }
|
||||
|
||||
/** Gets the nth case of this match statement. */
|
||||
Stmt getCase(int index) { result = this.getCases().getItem(index) }
|
||||
|
||||
/** Gets a case of this match statement. */
|
||||
Stmt getACase() { result = this.getCases().getAnItem() }
|
||||
|
||||
override string toString() { result = "MatchStmt" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `MatchAsPattern` for further information. */
|
||||
library class MatchAsPattern_ extends @py_MatchAsPattern, Pattern {
|
||||
/** Gets the pattern of this matchaspattern pattern. */
|
||||
Pattern getPattern() { py_patterns(result, _, this, 2) }
|
||||
|
||||
/** Gets the alias of this matchaspattern pattern. */
|
||||
Expr getAlias() { py_exprs(result, _, this, 3) }
|
||||
|
||||
override string toString() { result = "MatchAsPattern" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `MatchCapturePattern` for further information. */
|
||||
library class MatchCapturePattern_ extends @py_MatchCapturePattern, Pattern {
|
||||
/** Gets the variable of this matchcapturepattern pattern. */
|
||||
Expr getVariable() { py_exprs(result, _, this, 2) }
|
||||
|
||||
override string toString() { result = "MatchCapturePattern" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `MatchClassPattern` for further information. */
|
||||
library class MatchClassPattern_ extends @py_MatchClassPattern, Pattern {
|
||||
/** Gets the class of this matchclasspattern pattern. */
|
||||
Expr getClass() { py_exprs(result, _, this, 2) }
|
||||
|
||||
/** Gets the class_name of this matchclasspattern pattern. */
|
||||
Expr getClassName() { py_exprs(result, _, this, 3) }
|
||||
|
||||
/** Gets the positional of this matchclasspattern pattern. */
|
||||
PatternList getPositional() { py_pattern_lists(result, this, 4) }
|
||||
|
||||
/** Gets the nth positional of this matchclasspattern pattern. */
|
||||
Pattern getPositional(int index) { result = this.getPositional().getItem(index) }
|
||||
|
||||
/** Gets a positional of this matchclasspattern pattern. */
|
||||
Pattern getAPositional() { result = this.getPositional().getAnItem() }
|
||||
|
||||
/** Gets the keyword of this matchclasspattern pattern. */
|
||||
PatternList getKeyword() { py_pattern_lists(result, this, 5) }
|
||||
|
||||
/** Gets the nth keyword of this matchclasspattern pattern. */
|
||||
Pattern getKeyword(int index) { result = this.getKeyword().getItem(index) }
|
||||
|
||||
/** Gets a keyword of this matchclasspattern pattern. */
|
||||
Pattern getAKeyword() { result = this.getKeyword().getAnItem() }
|
||||
|
||||
override string toString() { result = "MatchClassPattern" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `MatchDoubleStarPattern` for further information. */
|
||||
library class MatchDoubleStarPattern_ extends @py_MatchDoubleStarPattern, Pattern {
|
||||
/** Gets the target of this matchdoublestarpattern pattern. */
|
||||
Pattern getTarget() { py_patterns(result, _, this, 2) }
|
||||
|
||||
override string toString() { result = "MatchDoubleStarPattern" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `MatchKeyValuePattern` for further information. */
|
||||
library class MatchKeyValuePattern_ extends @py_MatchKeyValuePattern, Pattern {
|
||||
/** Gets the key of this matchkeyvaluepattern pattern. */
|
||||
Pattern getKey() { py_patterns(result, _, this, 2) }
|
||||
|
||||
/** Gets the value of this matchkeyvaluepattern pattern. */
|
||||
Pattern getValue() { py_patterns(result, _, this, 3) }
|
||||
|
||||
override string toString() { result = "MatchKeyValuePattern" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `MatchKeywordPattern` for further information. */
|
||||
library class MatchKeywordPattern_ extends @py_MatchKeywordPattern, Pattern {
|
||||
/** Gets the attribute of this matchkeywordpattern pattern. */
|
||||
Expr getAttribute() { py_exprs(result, _, this, 2) }
|
||||
|
||||
/** Gets the value of this matchkeywordpattern pattern. */
|
||||
Pattern getValue() { py_patterns(result, _, this, 3) }
|
||||
|
||||
override string toString() { result = "MatchKeywordPattern" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `MatchLiteralPattern` for further information. */
|
||||
library class MatchLiteralPattern_ extends @py_MatchLiteralPattern, Pattern {
|
||||
/** Gets the literal of this matchliteralpattern pattern. */
|
||||
Expr getLiteral() { py_exprs(result, _, this, 2) }
|
||||
|
||||
override string toString() { result = "MatchLiteralPattern" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `MatchMappingPattern` for further information. */
|
||||
library class MatchMappingPattern_ extends @py_MatchMappingPattern, Pattern {
|
||||
/** Gets the mappings of this matchmappingpattern pattern. */
|
||||
PatternList getMappings() { py_pattern_lists(result, this, 2) }
|
||||
|
||||
/** Gets the nth mapping of this matchmappingpattern pattern. */
|
||||
Pattern getMapping(int index) { result = this.getMappings().getItem(index) }
|
||||
|
||||
/** Gets a mapping of this matchmappingpattern pattern. */
|
||||
Pattern getAMapping() { result = this.getMappings().getAnItem() }
|
||||
|
||||
override string toString() { result = "MatchMappingPattern" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `MatchOrPattern` for further information. */
|
||||
library class MatchOrPattern_ extends @py_MatchOrPattern, Pattern {
|
||||
/** Gets the patterns of this matchorpattern pattern. */
|
||||
PatternList getPatterns() { py_pattern_lists(result, this, 2) }
|
||||
|
||||
/** Gets the nth pattern of this matchorpattern pattern. */
|
||||
Pattern getPattern(int index) { result = this.getPatterns().getItem(index) }
|
||||
|
||||
/** Gets a pattern of this matchorpattern pattern. */
|
||||
Pattern getAPattern() { result = this.getPatterns().getAnItem() }
|
||||
|
||||
override string toString() { result = "MatchOrPattern" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `MatchSequencePattern` for further information. */
|
||||
library class MatchSequencePattern_ extends @py_MatchSequencePattern, Pattern {
|
||||
/** Gets the patterns of this matchsequencepattern pattern. */
|
||||
PatternList getPatterns() { py_pattern_lists(result, this, 2) }
|
||||
|
||||
/** Gets the nth pattern of this matchsequencepattern pattern. */
|
||||
Pattern getPattern(int index) { result = this.getPatterns().getItem(index) }
|
||||
|
||||
/** Gets a pattern of this matchsequencepattern pattern. */
|
||||
Pattern getAPattern() { result = this.getPatterns().getAnItem() }
|
||||
|
||||
override string toString() { result = "MatchSequencePattern" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `MatchStarPattern` for further information. */
|
||||
library class MatchStarPattern_ extends @py_MatchStarPattern, Pattern {
|
||||
/** Gets the target of this matchstarpattern pattern. */
|
||||
Pattern getTarget() { py_patterns(result, _, this, 2) }
|
||||
|
||||
override string toString() { result = "MatchStarPattern" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `MatchValuePattern` for further information. */
|
||||
library class MatchValuePattern_ extends @py_MatchValuePattern, Pattern {
|
||||
/** Gets the value of this matchvaluepattern pattern. */
|
||||
Expr getValue() { py_exprs(result, _, this, 2) }
|
||||
|
||||
override string toString() { result = "MatchValuePattern" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `MatchWildcardPattern` for further information. */
|
||||
library class MatchWildcardPattern_ extends @py_MatchWildcardPattern, Pattern {
|
||||
override string toString() { result = "MatchWildcardPattern" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Mod` for further information. */
|
||||
library class Mod_ extends @py_Mod, Operator {
|
||||
override string toString() { result = "Mod" }
|
||||
@@ -1073,6 +1269,7 @@ library class StringPart_ extends @py_StringPart {
|
||||
/** Gets the location of this implicitly concatenated part. */
|
||||
Location getLocation() { py_locations(result, this) }
|
||||
|
||||
/** Gets a parent of this implicitly concatenated part */
|
||||
StringPartList getParent() { py_StringParts(this, result, _) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
@@ -1081,6 +1278,7 @@ library class StringPart_ extends @py_StringPart {
|
||||
|
||||
/** INTERNAL: See the class `StringPartList` for further information. */
|
||||
library class StringPartList_ extends @py_StringPart_list {
|
||||
/** Gets a parent of this implicitly concatenated part list */
|
||||
BytesOrStr getParent() { py_StringPart_lists(this, result) }
|
||||
|
||||
/** Gets an item of this implicitly concatenated part list */
|
||||
@@ -1288,6 +1486,7 @@ library class Alias_ extends @py_alias {
|
||||
/** Gets the name of this alias. */
|
||||
Expr getAsname() { py_exprs(result, _, this, 1) }
|
||||
|
||||
/** Gets a parent of this alias */
|
||||
AliasList getParent() { py_aliases(this, result, _) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
@@ -1296,6 +1495,7 @@ library class Alias_ extends @py_alias {
|
||||
|
||||
/** INTERNAL: See the class `AliasList` for further information. */
|
||||
library class AliasList_ extends @py_alias_list {
|
||||
/** Gets a parent of this alias list */
|
||||
Import getParent() { py_alias_lists(this, result) }
|
||||
|
||||
/** Gets an item of this alias list */
|
||||
@@ -1352,6 +1552,7 @@ library class Arguments_ extends @py_arguments {
|
||||
/** Gets a keyword-only annotation of this parameters definition. */
|
||||
Expr getAKwAnnotation() { result = this.getKwAnnotations().getAnItem() }
|
||||
|
||||
/** Gets a parent of this parameters definition */
|
||||
ArgumentsParent getParent() { py_arguments(this, result) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
@@ -1378,6 +1579,7 @@ library class BoolParent_ extends @py_bool_parent {
|
||||
|
||||
/** INTERNAL: See the class `Boolop` for further information. */
|
||||
library class Boolop_ extends @py_boolop {
|
||||
/** Gets a parent of this boolean operator */
|
||||
BoolExpr getParent() { py_boolops(this, _, result) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
@@ -1386,6 +1588,7 @@ library class Boolop_ extends @py_boolop {
|
||||
|
||||
/** INTERNAL: See the class `Cmpop` for further information. */
|
||||
library class Cmpop_ extends @py_cmpop {
|
||||
/** Gets a parent of this comparison operator */
|
||||
CmpopList getParent() { py_cmpops(this, _, result, _) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
@@ -1394,6 +1597,7 @@ library class Cmpop_ extends @py_cmpop {
|
||||
|
||||
/** INTERNAL: See the class `CmpopList` for further information. */
|
||||
library class CmpopList_ extends @py_cmpop_list {
|
||||
/** Gets a parent of this comparison operator list */
|
||||
Compare getParent() { py_cmpop_lists(this, result) }
|
||||
|
||||
/** Gets an item of this comparison operator list */
|
||||
@@ -1426,6 +1630,7 @@ library class Comprehension_ extends @py_comprehension {
|
||||
/** Gets a condition of this comprehension. */
|
||||
Expr getAnIf() { result = this.getIfs().getAnItem() }
|
||||
|
||||
/** Gets a parent of this comprehension */
|
||||
ComprehensionList getParent() { py_comprehensions(this, result, _) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
@@ -1434,6 +1639,7 @@ library class Comprehension_ extends @py_comprehension {
|
||||
|
||||
/** INTERNAL: See the class `ComprehensionList` for further information. */
|
||||
library class ComprehensionList_ extends @py_comprehension_list {
|
||||
/** Gets a parent of this comprehension list */
|
||||
ListComp getParent() { py_comprehension_lists(this, result) }
|
||||
|
||||
/** Gets an item of this comprehension list */
|
||||
@@ -1448,6 +1654,7 @@ library class ComprehensionList_ extends @py_comprehension_list {
|
||||
|
||||
/** INTERNAL: See the class `DictItem` for further information. */
|
||||
library class DictItem_ extends @py_dict_item {
|
||||
/** Gets a parent of this dict_item */
|
||||
DictItemList getParent() { py_dict_items(this, _, result, _) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
@@ -1456,6 +1663,7 @@ library class DictItem_ extends @py_dict_item {
|
||||
|
||||
/** INTERNAL: See the class `DictItemList` for further information. */
|
||||
library class DictItemList_ extends @py_dict_item_list {
|
||||
/** Gets a parent of this dict_item list */
|
||||
DictItemListParent getParent() { py_dict_item_lists(this, result) }
|
||||
|
||||
/** Gets an item of this dict_item list */
|
||||
@@ -1482,6 +1690,7 @@ library class Expr_ extends @py_expr {
|
||||
/** Whether the parenthesised property of this expression is true. */
|
||||
predicate isParenthesised() { py_bools(this, 1) }
|
||||
|
||||
/** Gets a parent of this expression */
|
||||
ExprParent getParent() { py_exprs(this, _, result, _) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
@@ -1490,6 +1699,7 @@ library class Expr_ extends @py_expr {
|
||||
|
||||
/** INTERNAL: See the class `ExprContext` for further information. */
|
||||
library class ExprContext_ extends @py_expr_context {
|
||||
/** Gets a parent of this expression context */
|
||||
ExprContextParent getParent() { py_expr_contexts(this, _, result) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
@@ -1504,6 +1714,7 @@ library class ExprContextParent_ extends @py_expr_context_parent {
|
||||
|
||||
/** INTERNAL: See the class `ExprList` for further information. */
|
||||
library class ExprList_ extends @py_expr_list {
|
||||
/** Gets a parent of this expression list */
|
||||
ExprListParent getParent() { py_expr_lists(this, result, _) }
|
||||
|
||||
/** Gets an item of this expression list */
|
||||
@@ -1556,6 +1767,7 @@ library class LocationParent_ extends @py_location_parent {
|
||||
|
||||
/** INTERNAL: See the class `Operator` for further information. */
|
||||
library class Operator_ extends @py_operator {
|
||||
/** Gets a parent of this operator */
|
||||
BinaryExpr getParent() { py_operators(this, _, result) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
@@ -1568,6 +1780,48 @@ library class Parameter_ extends @py_parameter {
|
||||
string toString() { result = "Parameter" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Pattern` for further information. */
|
||||
library class Pattern_ extends @py_pattern {
|
||||
/** Gets the location of this pattern. */
|
||||
Location getLocation() { py_locations(result, this) }
|
||||
|
||||
/** Whether the parenthesised property of this pattern is true. */
|
||||
predicate isParenthesised() { py_bools(this, 1) }
|
||||
|
||||
/** Gets a parent of this pattern */
|
||||
PatternParent getParent() { py_patterns(this, _, result, _) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "Pattern" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `PatternList` for further information. */
|
||||
library class PatternList_ extends @py_pattern_list {
|
||||
/** Gets a parent of this pattern list */
|
||||
PatternListParent getParent() { py_pattern_lists(this, result, _) }
|
||||
|
||||
/** Gets an item of this pattern list */
|
||||
Pattern getAnItem() { py_patterns(result, _, this, _) }
|
||||
|
||||
/** Gets the nth item of this pattern list */
|
||||
Pattern getItem(int index) { py_patterns(result, _, this, index) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "PatternList" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `PatternListParent` for further information. */
|
||||
library class PatternListParent_ extends @py_pattern_list_parent {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "PatternListParent" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `PatternParent` for further information. */
|
||||
library class PatternParent_ extends @py_pattern_parent {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "PatternParent" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Scope` for further information. */
|
||||
library class Scope_ extends @py_scope {
|
||||
/** Gets a textual representation of this element. */
|
||||
@@ -1579,6 +1833,7 @@ library class Stmt_ extends @py_stmt {
|
||||
/** Gets the location of this statement. */
|
||||
Location getLocation() { py_locations(result, this) }
|
||||
|
||||
/** Gets a parent of this statement */
|
||||
StmtList getParent() { py_stmts(this, _, result, _) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
@@ -1587,6 +1842,7 @@ library class Stmt_ extends @py_stmt {
|
||||
|
||||
/** INTERNAL: See the class `StmtList` for further information. */
|
||||
library class StmtList_ extends @py_stmt_list {
|
||||
/** Gets a parent of this statement list */
|
||||
StmtListParent getParent() { py_stmt_lists(this, result, _) }
|
||||
|
||||
/** Gets an item of this statement list */
|
||||
@@ -1607,6 +1863,7 @@ library class StmtListParent_ extends @py_stmt_list_parent {
|
||||
|
||||
/** INTERNAL: See the class `StringList` for further information. */
|
||||
library class StringList_ extends @py_str_list {
|
||||
/** Gets a parent of this string list */
|
||||
StrListParent getParent() { py_str_lists(this, result) }
|
||||
|
||||
/** Gets an item of this string list */
|
||||
@@ -1633,6 +1890,7 @@ library class StrParent_ extends @py_str_parent {
|
||||
|
||||
/** INTERNAL: See the class `Unaryop` for further information. */
|
||||
library class Unaryop_ extends @py_unaryop {
|
||||
/** Gets a parent of this unary operation */
|
||||
UnaryExpr getParent() { py_unaryops(this, _, result) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
|
||||
@@ -718,6 +718,12 @@ class FormattedValue extends FormattedValue_ {
|
||||
}
|
||||
}
|
||||
|
||||
/** A guard in a case statement */
|
||||
class Guard extends Guard_ {
|
||||
/* syntax: if Expr */
|
||||
override Expr getASubExpression() { result = this.getTest() }
|
||||
}
|
||||
|
||||
/* Expression Contexts */
|
||||
/** A context in which an expression used */
|
||||
class ExprContext extends ExprContext_ { }
|
||||
|
||||
118
python/ql/lib/semmle/python/Patterns.qll
Normal file
118
python/ql/lib/semmle/python/Patterns.qll
Normal file
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* Wrapping generated AST classes: `Pattern_` and subclasses.
|
||||
*/
|
||||
|
||||
import python
|
||||
|
||||
/** A pattern in a match statement */
|
||||
class Pattern extends Pattern_, AstNode {
|
||||
/** Gets the scope of this pattern */
|
||||
override Scope getScope() { result = this.getCase().getScope() }
|
||||
|
||||
/** Gets the case statement containing this pattern */
|
||||
Case getCase() { result.contains(this) }
|
||||
|
||||
override string toString() { result = "Pattern" }
|
||||
|
||||
/** Gets the module enclosing this pattern */
|
||||
Module getEnclosingModule() { result = this.getScope().getEnclosingModule() }
|
||||
|
||||
/** Whether the parenthesized property of this expression is true. */
|
||||
predicate isParenthesized() { Pattern_.super.isParenthesised() }
|
||||
|
||||
override Location getLocation() { result = Pattern_.super.getLocation() }
|
||||
|
||||
/** Gets an immediate (non-nested) sub-expression of this pattern */
|
||||
Expr getASubExpression() { none() }
|
||||
|
||||
/** Gets an immediate (non-nested) sub-statement of this pattern */
|
||||
Stmt getASubStatement() { none() }
|
||||
|
||||
/** Gets an immediate (non-nested) sub-pattern of this pattern */
|
||||
Pattern getASubPattern() { none() }
|
||||
|
||||
override AstNode getAChildNode() {
|
||||
result = this.getASubExpression()
|
||||
or
|
||||
result = this.getASubStatement()
|
||||
or
|
||||
result = this.getASubPattern()
|
||||
}
|
||||
}
|
||||
|
||||
/** An as-pattern in a match statement: `<subpattern> as alias` */
|
||||
class MatchAsPattern extends MatchAsPattern_ {
|
||||
override Pattern getASubPattern() { result = this.getPattern() }
|
||||
|
||||
override Expr getASubExpression() { result = this.getAlias() }
|
||||
|
||||
override Name getAlias() { result = super.getAlias() }
|
||||
}
|
||||
|
||||
/** An or-pattern in a match statement: `(<pattern1>|<pattern2>)` */
|
||||
class MatchOrPattern extends MatchOrPattern_ {
|
||||
override Pattern getASubPattern() { result = this.getAPattern() }
|
||||
}
|
||||
|
||||
/** A literal pattern in a match statement: `42` */
|
||||
class MatchLiteralPattern extends MatchLiteralPattern_ {
|
||||
override Expr getASubExpression() { result = this.getLiteral() }
|
||||
}
|
||||
|
||||
/** A capture pattern in a match statement: `var` */
|
||||
class MatchCapturePattern extends MatchCapturePattern_ {
|
||||
/* syntax: varname */
|
||||
override Expr getASubExpression() { result = this.getVariable() }
|
||||
|
||||
/** Gets the variable that is bound by this capture pattern */
|
||||
override Name getVariable() { result = super.getVariable() }
|
||||
}
|
||||
|
||||
/** A wildcard pattern in a match statement: `_` */
|
||||
class MatchWildcardPattern extends MatchWildcardPattern_ { }
|
||||
|
||||
/** A value pattern in a match statement: `Http.OK` */
|
||||
class MatchValuePattern extends MatchValuePattern_ {
|
||||
override Expr getASubExpression() { result = this.getValue() }
|
||||
}
|
||||
|
||||
/** A sequence pattern in a match statement `<p1>, <p2>` */
|
||||
class MatchSequencePattern extends MatchSequencePattern_ {
|
||||
override Pattern getASubPattern() { result = this.getAPattern() }
|
||||
}
|
||||
|
||||
/** A star pattern in a match statement: `(..., *)` */
|
||||
class MatchStarPattern extends MatchStarPattern_ {
|
||||
override Pattern getASubPattern() { result = this.getTarget() }
|
||||
}
|
||||
|
||||
/** A mapping pattern in a match statement: `{'a': var}` */
|
||||
class MatchMappingPattern extends MatchMappingPattern_ {
|
||||
override Pattern getASubPattern() { result = this.getAMapping() }
|
||||
}
|
||||
|
||||
/** A double star pattern in a match statement: `{..., **}` */
|
||||
class MatchDoubleStarPattern extends MatchDoubleStarPattern_ {
|
||||
override Pattern getASubPattern() { result = this.getTarget() }
|
||||
}
|
||||
|
||||
/** A key-value pattern inside a mapping pattern: `a: var` */
|
||||
class MatchKeyValuePattern extends MatchKeyValuePattern_ {
|
||||
override Pattern getASubPattern() { result = this.getKey() or result = this.getValue() }
|
||||
}
|
||||
|
||||
/** A class pattern in a match statement: `Circle(radius = 3)` */
|
||||
class MatchClassPattern extends MatchClassPattern_ {
|
||||
override Expr getASubExpression() { result = this.getClassName() }
|
||||
|
||||
override Pattern getASubPattern() {
|
||||
result = this.getAPositional() or result = this.getAKeyword()
|
||||
}
|
||||
}
|
||||
|
||||
/** A keyword pattern inside a class pattern: `radius = 3` */
|
||||
class MatchKeywordPattern extends MatchKeywordPattern_ {
|
||||
override Expr getASubExpression() { result = this.getAttribute() }
|
||||
|
||||
override Pattern getASubPattern() { result = this.getValue() }
|
||||
}
|
||||
@@ -18,10 +18,15 @@ class Stmt extends Stmt_, AstNode {
|
||||
/** Gets an immediate (non-nested) sub-statement of this statement */
|
||||
Stmt getASubStatement() { none() }
|
||||
|
||||
/** Gets an immediate (non-nested) sub-pattern of this statement */
|
||||
Pattern getASubPattern() { none() }
|
||||
|
||||
override AstNode getAChildNode() {
|
||||
result = this.getASubExpression()
|
||||
or
|
||||
result = this.getASubStatement()
|
||||
or
|
||||
result = this.getASubPattern()
|
||||
}
|
||||
|
||||
private ControlFlowNode possibleEntryNode() {
|
||||
@@ -412,6 +417,24 @@ class With extends With_ {
|
||||
override Stmt getLastStatement() { result = this.getBody().getLastItem().getLastStatement() }
|
||||
}
|
||||
|
||||
/** A match statement */
|
||||
class MatchStmt extends MatchStmt_ {
|
||||
/* syntax: match subject: */
|
||||
override Expr getASubExpression() { result = this.getSubject() }
|
||||
|
||||
override Stmt getASubStatement() { result = this.getCase(_) }
|
||||
}
|
||||
|
||||
/** A case statement */
|
||||
class Case extends Case_ {
|
||||
/* syntax: case pattern if guard: */
|
||||
override Expr getASubExpression() { result = this.getGuard() }
|
||||
|
||||
override Stmt getASubStatement() { result = this.getStmt(_) }
|
||||
|
||||
override Pattern getASubPattern() { result = this.getPattern() }
|
||||
}
|
||||
|
||||
/** A plain text used in a template is wrapped in a TemplateWrite statement */
|
||||
class TemplateWrite extends TemplateWrite_ {
|
||||
override Expr getASubExpression() { result = this.getValue() }
|
||||
|
||||
@@ -249,6 +249,8 @@ module EssaFlow {
|
||||
// Flow inside an unpacking assignment
|
||||
iterableUnpackingFlowStep(nodeFrom, nodeTo)
|
||||
or
|
||||
matchFlowStep(nodeFrom, nodeTo)
|
||||
or
|
||||
// Overflow keyword argument
|
||||
exists(CallNode call, CallableValue callable |
|
||||
call = callable.getACall() and
|
||||
@@ -982,6 +984,8 @@ predicate storeStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
posOverflowStoreStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
kwOverflowStoreStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
matchStoreStep(nodeFrom, c, nodeTo)
|
||||
}
|
||||
|
||||
/** Data flows from an element of a list to the list. */
|
||||
@@ -1124,6 +1128,8 @@ predicate readStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
or
|
||||
iterableUnpackingReadStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
matchReadStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
popReadStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
forReadStep(nodeFrom, c, nodeTo)
|
||||
@@ -1553,6 +1559,318 @@ module IterableUnpacking {
|
||||
|
||||
import IterableUnpacking
|
||||
|
||||
/**
|
||||
* There are a number of patterns available for the match statement.
|
||||
* Each one transfers data and content differently to its parts.
|
||||
*
|
||||
* Furthermore, given a successful match, we can infer some data about
|
||||
* the subject. Consider the example:
|
||||
* ```python
|
||||
* match choice:
|
||||
* case 'Y':
|
||||
* ...body
|
||||
* ```
|
||||
* Inside `body`, we know that `choice` has the value `'Y'`.
|
||||
*
|
||||
* A similar thing happens with the "as pattern". Consider the example:
|
||||
* ```python
|
||||
* match choice:
|
||||
* case ('y'|'Y') as c:
|
||||
* ...body
|
||||
* ```
|
||||
* By the binding rules, there is data flow from `choice` to `c`. But we
|
||||
* can infer the value of `c` to be either `'y'` or `'Y'` if the match succeeds.
|
||||
*
|
||||
* We will treat such inferences separately as guards. First we will model the data flow
|
||||
* stemming from the bindings and the matching of shape. Below, 'subject' is not necessarily the
|
||||
* top-level subject of the match, but rather the part recursively matched by the current pattern.
|
||||
* For instance, in the example:
|
||||
* ```python
|
||||
* match command:
|
||||
* case ('quit' as c) | ('go', ('up'|'down') as c):
|
||||
* ...body
|
||||
* ```
|
||||
* `command` is the subject of first the as-pattern, while the second component of `command`
|
||||
* is the subject of the second as-pattern. As such, 'subject' refers to the pattern under evaluation.
|
||||
*
|
||||
* - as pattern: subject flows to alias as well as to the interior pattern
|
||||
* - or pattern: subject flows to each alternative
|
||||
* - literal pattern: flow from the literal to the pattern, to add information
|
||||
* - capture pattern: subject flows to the variable
|
||||
* - wildcard pattern: no flow
|
||||
* - value pattern: flow from the value to the pattern, to add information
|
||||
* - sequence pattern: each element reads from subject at the associated index
|
||||
* - star pattern: subject flows to the variable, possibly via a conversion
|
||||
* - mapping pattern: each value reads from subject at the associated key
|
||||
* - double star pattern: subject flows to the variable, possibly via a conversion
|
||||
* - key-value pattern: the value reads from the subject at the key (see mapping pattern)
|
||||
* - class pattern: all keywords read the appropriate attribute from the subject
|
||||
* - keyword pattern: the appropriate attribute is read from the subject (see class pattern)
|
||||
*
|
||||
* Inside the class pattern, we also find positional arguments. They are converted to
|
||||
* keyword arguments using the `__match_args__` attribute on the class. We do not
|
||||
* currently model this.
|
||||
*/
|
||||
module MatchUnpacking {
|
||||
/**
|
||||
* The subject of a match flows to each top-level pattern
|
||||
* (a pattern directly under a `case` statement).
|
||||
*
|
||||
* We could consider a model closer to use-use-flow, where the subject
|
||||
* only flows to the first top-level pattern and from there to the
|
||||
* following ones.
|
||||
*/
|
||||
predicate matchSubjectFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(MatchStmt match, Expr subject, Pattern target |
|
||||
subject = match.getSubject() and
|
||||
target = match.getCase(_).(Case).getPattern()
|
||||
|
|
||||
nodeFrom.asExpr() = subject and
|
||||
nodeTo.asCfgNode().getNode() = target
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* as pattern: subject flows to alias as well as to the interior pattern
|
||||
* syntax (toplevel): `case pattern as alias:`
|
||||
*/
|
||||
predicate matchAsFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(MatchAsPattern subject, Name alias | alias = subject.getAlias() |
|
||||
// We make the subject flow to the interior pattern via the alias.
|
||||
// That way, information can propagate from the interior pattern to the alias.
|
||||
//
|
||||
// the subject flows to the interior pattern
|
||||
nodeFrom.asCfgNode().getNode() = subject and
|
||||
nodeTo.asCfgNode().getNode() = subject.getPattern()
|
||||
or
|
||||
// the interior pattern flows to the alias
|
||||
nodeFrom.asCfgNode().getNode() = subject.getPattern() and
|
||||
nodeTo.asVar().getDefinition().(PatternAliasDefinition).getDefiningNode().getNode() = alias
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* or pattern: subject flows to each alternative
|
||||
* syntax (toplevel): `case alt1 | alt2:`
|
||||
*/
|
||||
predicate matchOrFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(MatchOrPattern subject, Pattern pattern | pattern = subject.getAPattern() |
|
||||
nodeFrom.asCfgNode().getNode() = subject and
|
||||
nodeTo.asCfgNode().getNode() = pattern
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* literal pattern: flow from the literal to the pattern, to add information
|
||||
* syntax (toplevel): `case literal:`
|
||||
*/
|
||||
predicate matchLiteralFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(MatchLiteralPattern pattern, Expr literal | literal = pattern.getLiteral() |
|
||||
nodeFrom.asExpr() = literal and
|
||||
nodeTo.asCfgNode().getNode() = pattern
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* capture pattern: subject flows to the variable
|
||||
* syntax (toplevel): `case var:`
|
||||
*/
|
||||
predicate matchCaptureFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(MatchCapturePattern capture, Name var | capture.getVariable() = var |
|
||||
nodeFrom.asCfgNode().getNode() = capture and
|
||||
nodeTo.asVar().getDefinition().(PatternCaptureDefinition).getDefiningNode().getNode() = var
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* value pattern: flow from the value to the pattern, to add information
|
||||
* syntax (toplevel): `case Dotted.value:`
|
||||
*/
|
||||
predicate matchValueFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(MatchValuePattern pattern, Expr value | value = pattern.getValue() |
|
||||
nodeFrom.asExpr() = value and
|
||||
nodeTo.asCfgNode().getNode() = pattern
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* sequence pattern: each element reads from subject at the associated index
|
||||
* syntax (toplevel): `case [a, b]:`
|
||||
*/
|
||||
predicate matchSequenceReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
exists(MatchSequencePattern subject, int index, Pattern element |
|
||||
element = subject.getPattern(index)
|
||||
|
|
||||
nodeFrom.asCfgNode().getNode() = subject and
|
||||
nodeTo.asCfgNode().getNode() = element and
|
||||
(
|
||||
// tuple content
|
||||
c.(TupleElementContent).getIndex() = index
|
||||
or
|
||||
// list content
|
||||
c instanceof ListElementContent
|
||||
// set content is excluded from sequence patterns,
|
||||
// see https://www.python.org/dev/peps/pep-0635/#sequence-patterns
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* star pattern: subject flows to the variable, possibly via a conversion
|
||||
* syntax (toplevel): `case *var:`
|
||||
*
|
||||
* We decompose this flow into a read step and a store step. The read step
|
||||
* reads both tuple and list content, the store step only stores list content.
|
||||
* This way, we convert all content to list content.
|
||||
*
|
||||
* This is the read step.
|
||||
*/
|
||||
predicate matchStarReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
exists(MatchSequencePattern subject, int index, MatchStarPattern star |
|
||||
star = subject.getPattern(index)
|
||||
|
|
||||
nodeFrom.asCfgNode().getNode() = subject and
|
||||
nodeTo = TStarPatternElementNode(star) and
|
||||
(
|
||||
// tuple content
|
||||
c.(TupleElementContent).getIndex() >= index
|
||||
or
|
||||
// list content
|
||||
c instanceof ListElementContent
|
||||
// set content is excluded from sequence patterns,
|
||||
// see https://www.python.org/dev/peps/pep-0635/#sequence-patterns
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* star pattern: subject flows to the variable, possibly via a conversion
|
||||
* syntax (toplevel): `case *var:`
|
||||
*
|
||||
* We decompose this flow into a read step and a store step. The read step
|
||||
* reads both tuple and list content, the store step only stores list content.
|
||||
* This way, we convert all content to list content.
|
||||
*
|
||||
* This is the store step.
|
||||
*/
|
||||
predicate matchStarStoreStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
exists(MatchStarPattern star |
|
||||
nodeFrom = TStarPatternElementNode(star) and
|
||||
nodeTo.asCfgNode().getNode() = star.getTarget() and
|
||||
c instanceof ListElementContent
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* mapping pattern: each value reads from subject at the associated key
|
||||
* syntax (toplevel): `case {"color": c, "height": x}:`
|
||||
*/
|
||||
predicate matchMappingReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
exists(
|
||||
MatchMappingPattern subject, MatchKeyValuePattern keyValue, MatchLiteralPattern key,
|
||||
Pattern value
|
||||
|
|
||||
keyValue = subject.getAMapping() and
|
||||
key = keyValue.getKey() and
|
||||
value = keyValue.getValue()
|
||||
|
|
||||
nodeFrom.asCfgNode().getNode() = subject and
|
||||
nodeTo.asCfgNode().getNode() = value and
|
||||
c.(DictionaryElementContent).getKey() = key.getLiteral().(StrConst).getText()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* double star pattern: subject flows to the variable, possibly via a conversion
|
||||
* syntax (toplevel): `case {**var}:`
|
||||
*
|
||||
* Dictionary content flows to the double star, but all mentioned keys in the
|
||||
* mapping pattern should be cleared.
|
||||
*/
|
||||
predicate matchMappingFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(MatchMappingPattern subject, MatchDoubleStarPattern dstar |
|
||||
dstar = subject.getAMapping()
|
||||
|
|
||||
nodeFrom.asCfgNode().getNode() = subject and
|
||||
nodeTo.asCfgNode().getNode() = dstar.getTarget()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Bindings that are mentioned in a mapping pattern will not be available
|
||||
* to a double star pattern in the same mapping pattern.
|
||||
*/
|
||||
predicate matchMappingClearStep(Node n, Content c) {
|
||||
exists(
|
||||
MatchMappingPattern subject, MatchKeyValuePattern keyValue, MatchLiteralPattern key,
|
||||
MatchDoubleStarPattern dstar
|
||||
|
|
||||
keyValue = subject.getAMapping() and
|
||||
key = keyValue.getKey() and
|
||||
dstar = subject.getAMapping()
|
||||
|
|
||||
n.asCfgNode().getNode() = dstar.getTarget() and
|
||||
c.(DictionaryElementContent).getKey() = key.getLiteral().(StrConst).getText()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* class pattern: all keywords read the appropriate attribute from the subject
|
||||
* syntax (toplevel): `case ClassName(attr = val):`
|
||||
*/
|
||||
predicate matchClassReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
exists(MatchClassPattern subject, MatchKeywordPattern keyword, Name attr, Pattern value |
|
||||
keyword = subject.getKeyword(_) and
|
||||
attr = keyword.getAttribute() and
|
||||
value = keyword.getValue()
|
||||
|
|
||||
nodeFrom.asCfgNode().getNode() = subject and
|
||||
nodeTo.asCfgNode().getNode() = value and
|
||||
c.(AttributeContent).getAttribute() = attr.getId()
|
||||
)
|
||||
}
|
||||
|
||||
/** All flow steps associated with match. */
|
||||
predicate matchFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
matchSubjectFlowStep(nodeFrom, nodeTo)
|
||||
or
|
||||
matchAsFlowStep(nodeFrom, nodeTo)
|
||||
or
|
||||
matchOrFlowStep(nodeFrom, nodeTo)
|
||||
or
|
||||
matchLiteralFlowStep(nodeFrom, nodeTo)
|
||||
or
|
||||
matchCaptureFlowStep(nodeFrom, nodeTo)
|
||||
or
|
||||
matchValueFlowStep(nodeFrom, nodeTo)
|
||||
or
|
||||
matchMappingFlowStep(nodeFrom, nodeTo)
|
||||
}
|
||||
|
||||
/** All read steps associated with match. */
|
||||
predicate matchReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
matchClassReadStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
matchSequenceReadStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
matchMappingReadStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
matchStarReadStep(nodeFrom, c, nodeTo)
|
||||
}
|
||||
|
||||
/** All store steps associated with match. */
|
||||
predicate matchStoreStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
matchStarStoreStep(nodeFrom, c, nodeTo)
|
||||
}
|
||||
|
||||
/**
|
||||
* All clear steps associated with match
|
||||
*/
|
||||
predicate matchClearStep(Node n, Content c) { matchMappingClearStep(n, c) }
|
||||
}
|
||||
|
||||
import MatchUnpacking
|
||||
|
||||
/** Data flows from a sequence to a call to `pop` on the sequence. */
|
||||
predicate popReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) {
|
||||
// set.pop or list.pop
|
||||
@@ -1635,11 +1953,10 @@ predicate kwUnpackReadStep(CfgNode nodeFrom, DictionaryElementContent c, Node no
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if values stored inside content `c` are cleared at node `n`. For example,
|
||||
* any value stored inside `f` is cleared at the pre-update node associated with `x`
|
||||
* in `x.f = newValue`.
|
||||
* Clear content at key `name` of the synthesized dictionary `TKwOverflowNode(call, callable)`,
|
||||
* whenever `call` unpacks `name`.
|
||||
*/
|
||||
predicate clearsContent(Node n, Content c) {
|
||||
predicate kwOverflowClearStep(Node n, Content c) {
|
||||
exists(CallNode call, CallableValue callable, string name |
|
||||
call_unpacks(call, _, callable, name, _) and
|
||||
n = TKwOverflowNode(call, callable) and
|
||||
@@ -1647,6 +1964,17 @@ predicate clearsContent(Node n, Content c) {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if values stored inside content `c` are cleared at node `n`. For example,
|
||||
* any value stored inside `f` is cleared at the pre-update node associated with `x`
|
||||
* in `x.f = newValue`.
|
||||
*/
|
||||
predicate clearsContent(Node n, Content c) {
|
||||
kwOverflowClearStep(n, c)
|
||||
or
|
||||
matchClearStep(n, c)
|
||||
}
|
||||
|
||||
//--------
|
||||
// Fancy context-sensitive guards
|
||||
//--------
|
||||
|
||||
@@ -25,7 +25,11 @@ newtype TNode =
|
||||
/** A node corresponding to an SSA variable. */
|
||||
TEssaNode(EssaVariable var) or
|
||||
/** A node corresponding to a control flow node. */
|
||||
TCfgNode(ControlFlowNode node) { isExpressionNode(node) } or
|
||||
TCfgNode(ControlFlowNode node) {
|
||||
isExpressionNode(node)
|
||||
or
|
||||
node.getNode() instanceof Pattern
|
||||
} or
|
||||
/** A synthetic node representing the value of an object before a state change */
|
||||
TSyntheticPreUpdateNode(NeedsSyntheticPreUpdateNode post) or
|
||||
/** A synthetic node representing the value of an object after a state change. */
|
||||
@@ -79,7 +83,11 @@ newtype TNode =
|
||||
* A synthetic node representing that there may be an iterable element
|
||||
* for `consumer` to consume.
|
||||
*/
|
||||
TIterableElementNode(UnpackingAssignmentTarget consumer)
|
||||
TIterableElementNode(UnpackingAssignmentTarget consumer) or
|
||||
/**
|
||||
* A synthetic node representing element content in a star pattern.
|
||||
*/
|
||||
TStarPatternElementNode(MatchStarPattern target)
|
||||
|
||||
/** Helper for `Node::getEnclosingCallable`. */
|
||||
private DataFlowCallable getCallableScope(Scope s) {
|
||||
@@ -476,6 +484,21 @@ class IterableElementNode extends Node, TIterableElementNode {
|
||||
override Location getLocation() { result = consumer.getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A synthetic node representing element content of a star pattern.
|
||||
*/
|
||||
class StarPatternElementNode extends Node, TStarPatternElementNode {
|
||||
CfgNode consumer;
|
||||
|
||||
StarPatternElementNode() { this = TStarPatternElementNode(consumer.getNode().getNode()) }
|
||||
|
||||
override string toString() { result = "StarPatternElement" }
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() { result = consumer.getEnclosingCallable() }
|
||||
|
||||
override Location getLocation() { result = consumer.getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A node that controls whether other nodes are evaluated.
|
||||
*/
|
||||
|
||||
@@ -70,6 +70,10 @@ abstract class SsaSourceVariable extends @py_variable {
|
||||
SsaSource::exception_capture(this, def)
|
||||
or
|
||||
SsaSource::with_definition(this, def)
|
||||
or
|
||||
SsaSource::pattern_capture_definition(this, def)
|
||||
or
|
||||
SsaSource::pattern_alias_definition(this, def)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -545,6 +545,24 @@ class WithDefinition extends EssaNodeDefinition {
|
||||
override string getRepresentation() { result = "with" }
|
||||
}
|
||||
|
||||
/** A definition of a variable via a capture pattern */
|
||||
class PatternCaptureDefinition extends EssaNodeDefinition {
|
||||
PatternCaptureDefinition() {
|
||||
SsaSource::pattern_capture_definition(this.getSourceVariable(), this.getDefiningNode())
|
||||
}
|
||||
|
||||
override string getRepresentation() { result = "pattern capture" }
|
||||
}
|
||||
|
||||
/** A definition of a variable via a pattern alias */
|
||||
class PatternAliasDefinition extends EssaNodeDefinition {
|
||||
PatternAliasDefinition() {
|
||||
SsaSource::pattern_alias_definition(this.getSourceVariable(), this.getDefiningNode())
|
||||
}
|
||||
|
||||
override string getRepresentation() { result = "pattern alias" }
|
||||
}
|
||||
|
||||
/** A definition of a variable by declaring it as a parameter */
|
||||
class ParameterDefinition extends EssaNodeDefinition {
|
||||
ParameterDefinition() {
|
||||
|
||||
@@ -40,6 +40,28 @@ module SsaSource {
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `v` is defined by a capture pattern. */
|
||||
cached
|
||||
predicate pattern_capture_definition(Variable v, ControlFlowNode defn) {
|
||||
exists(MatchCapturePattern capture, Name var |
|
||||
capture.getVariable() = var and
|
||||
var.getAFlowNode() = defn
|
||||
|
|
||||
var = v.getAStore()
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `v` is defined by as the alias of an as-pattern. */
|
||||
cached
|
||||
predicate pattern_alias_definition(Variable v, ControlFlowNode defn) {
|
||||
exists(MatchAsPattern pattern, Name var |
|
||||
pattern.getAlias() = var and
|
||||
var.getAFlowNode() = defn
|
||||
|
|
||||
var = v.getAStore()
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `v` is defined by multiple assignment at `defn`. */
|
||||
cached
|
||||
predicate multi_assignment_definition(Variable v, ControlFlowNode defn, int n, SequenceNode lhs) {
|
||||
|
||||
@@ -231,6 +231,11 @@ py_extracted_version(int module : @py_Module ref,
|
||||
/* <Field> Call.positional_args = 3, expr_list */
|
||||
/* <Field> Call.named_args = 4, dict_item_list */
|
||||
|
||||
/* <Field> Case.location = 0, location */
|
||||
/* <Field> Case.pattern = 1, pattern */
|
||||
/* <Field> Case.guard = 2, expr */
|
||||
/* <Field> Case.body = 3, stmt_list */
|
||||
|
||||
/* <Field> Class.name = 0, str */
|
||||
/* <Field> Class.body = 1, stmt_list */
|
||||
/* <Parent> Class = ClassExpr */
|
||||
@@ -323,6 +328,10 @@ py_extracted_version(int module : @py_Module ref,
|
||||
/* <Field> Global.location = 0, location */
|
||||
/* <Field> Global.names = 1, str_list */
|
||||
|
||||
/* <Field> Guard.location = 0, location */
|
||||
/* <Field> Guard.parenthesised = 1, bool */
|
||||
/* <Field> Guard.test = 2, expr */
|
||||
|
||||
/* <Field> If.location = 0, location */
|
||||
/* <Field> If.test = 1, expr */
|
||||
/* <Field> If.body = 2, stmt_list */
|
||||
@@ -377,6 +386,67 @@ py_extracted_version(int module : @py_Module ref,
|
||||
/* <Field> ListComp.generators = 4, comprehension_list */
|
||||
/* <Field> ListComp.elt = 5, expr */
|
||||
|
||||
/* <Field> MatchStmt.location = 0, location */
|
||||
/* <Field> MatchStmt.subject = 1, expr */
|
||||
/* <Field> MatchStmt.cases = 2, stmt_list */
|
||||
|
||||
/* <Field> MatchAsPattern.location = 0, location */
|
||||
/* <Field> MatchAsPattern.parenthesised = 1, bool */
|
||||
/* <Field> MatchAsPattern.pattern = 2, pattern */
|
||||
/* <Field> MatchAsPattern.alias = 3, expr */
|
||||
|
||||
/* <Field> MatchCapturePattern.location = 0, location */
|
||||
/* <Field> MatchCapturePattern.parenthesised = 1, bool */
|
||||
/* <Field> MatchCapturePattern.variable = 2, expr */
|
||||
|
||||
/* <Field> MatchClassPattern.location = 0, location */
|
||||
/* <Field> MatchClassPattern.parenthesised = 1, bool */
|
||||
/* <Field> MatchClassPattern.class = 2, expr */
|
||||
/* <Field> MatchClassPattern.class_name = 3, expr */
|
||||
/* <Field> MatchClassPattern.positional = 4, pattern_list */
|
||||
/* <Field> MatchClassPattern.keyword = 5, pattern_list */
|
||||
|
||||
/* <Field> MatchDoubleStarPattern.location = 0, location */
|
||||
/* <Field> MatchDoubleStarPattern.parenthesised = 1, bool */
|
||||
/* <Field> MatchDoubleStarPattern.target = 2, pattern */
|
||||
|
||||
/* <Field> MatchKeyValuePattern.location = 0, location */
|
||||
/* <Field> MatchKeyValuePattern.parenthesised = 1, bool */
|
||||
/* <Field> MatchKeyValuePattern.key = 2, pattern */
|
||||
/* <Field> MatchKeyValuePattern.value = 3, pattern */
|
||||
|
||||
/* <Field> MatchKeywordPattern.location = 0, location */
|
||||
/* <Field> MatchKeywordPattern.parenthesised = 1, bool */
|
||||
/* <Field> MatchKeywordPattern.attribute = 2, expr */
|
||||
/* <Field> MatchKeywordPattern.value = 3, pattern */
|
||||
|
||||
/* <Field> MatchLiteralPattern.location = 0, location */
|
||||
/* <Field> MatchLiteralPattern.parenthesised = 1, bool */
|
||||
/* <Field> MatchLiteralPattern.literal = 2, expr */
|
||||
|
||||
/* <Field> MatchMappingPattern.location = 0, location */
|
||||
/* <Field> MatchMappingPattern.parenthesised = 1, bool */
|
||||
/* <Field> MatchMappingPattern.mappings = 2, pattern_list */
|
||||
|
||||
/* <Field> MatchOrPattern.location = 0, location */
|
||||
/* <Field> MatchOrPattern.parenthesised = 1, bool */
|
||||
/* <Field> MatchOrPattern.patterns = 2, pattern_list */
|
||||
|
||||
/* <Field> MatchSequencePattern.location = 0, location */
|
||||
/* <Field> MatchSequencePattern.parenthesised = 1, bool */
|
||||
/* <Field> MatchSequencePattern.patterns = 2, pattern_list */
|
||||
|
||||
/* <Field> MatchStarPattern.location = 0, location */
|
||||
/* <Field> MatchStarPattern.parenthesised = 1, bool */
|
||||
/* <Field> MatchStarPattern.target = 2, pattern */
|
||||
|
||||
/* <Field> MatchValuePattern.location = 0, location */
|
||||
/* <Field> MatchValuePattern.parenthesised = 1, bool */
|
||||
/* <Field> MatchValuePattern.value = 2, expr */
|
||||
|
||||
/* <Field> MatchWildcardPattern.location = 0, location */
|
||||
/* <Field> MatchWildcardPattern.parenthesised = 1, bool */
|
||||
|
||||
/* <Field> Module.name = 0, str */
|
||||
/* <Field> Module.hash = 1, str */
|
||||
/* <Field> Module.body = 2, stmt_list */
|
||||
@@ -551,6 +621,11 @@ py_extracted_version(int module : @py_Module ref,
|
||||
/* <Parent> Operator = BinaryExpr */
|
||||
/* <Parent> ParameterList = Function */
|
||||
|
||||
/* <Field> Pattern.location = 0, location */
|
||||
/* <Field> Pattern.parenthesised = 1, bool */
|
||||
/* <Parent> Pattern = PatternParent */
|
||||
/* <Parent> PatternList = PatternListParent */
|
||||
|
||||
/* <Field> Stmt.location = 0, location */
|
||||
/* <Parent> Stmt = StmtList */
|
||||
/* <Parent> StmtList = StmtListParent */
|
||||
@@ -647,6 +722,15 @@ py_operators(unique int id : @py_operator,
|
||||
py_parameter_lists(unique int id : @py_parameter_list,
|
||||
unique int parent : @py_Function ref);
|
||||
|
||||
py_patterns(unique int id : @py_pattern,
|
||||
int kind: int ref,
|
||||
int parent : @py_pattern_parent ref,
|
||||
int idx : int ref);
|
||||
|
||||
py_pattern_lists(unique int id : @py_pattern_list,
|
||||
int parent : @py_pattern_list_parent ref,
|
||||
int idx : int ref);
|
||||
|
||||
py_stmts(unique int id : @py_stmt,
|
||||
int kind: int ref,
|
||||
int parent : @py_stmt_list ref,
|
||||
@@ -710,27 +794,28 @@ case @py_expr.kind of
|
||||
| 15 = @py_Lambda
|
||||
| 16 = @py_List
|
||||
| 17 = @py_ListComp
|
||||
| 18 = @py_Name
|
||||
| 19 = @py_Num
|
||||
| 20 = @py_Repr
|
||||
| 21 = @py_Set
|
||||
| 22 = @py_SetComp
|
||||
| 23 = @py_Slice
|
||||
| 24 = @py_Starred
|
||||
| 25 = @py_Str
|
||||
| 26 = @py_Subscript
|
||||
| 27 = @py_Tuple
|
||||
| 28 = @py_UnaryExpr
|
||||
| 29 = @py_Yield
|
||||
| 30 = @py_YieldFrom
|
||||
| 31 = @py_TemplateDottedNotation
|
||||
| 32 = @py_Filter
|
||||
| 33 = @py_PlaceHolder
|
||||
| 34 = @py_Await
|
||||
| 35 = @py_Fstring
|
||||
| 36 = @py_FormattedValue
|
||||
| 37 = @py_AssignExpr
|
||||
| 38 = @py_SpecialOperation;
|
||||
| 18 = @py_Guard
|
||||
| 19 = @py_Name
|
||||
| 20 = @py_Num
|
||||
| 21 = @py_Repr
|
||||
| 22 = @py_Set
|
||||
| 23 = @py_SetComp
|
||||
| 24 = @py_Slice
|
||||
| 25 = @py_Starred
|
||||
| 26 = @py_Str
|
||||
| 27 = @py_Subscript
|
||||
| 28 = @py_Tuple
|
||||
| 29 = @py_UnaryExpr
|
||||
| 30 = @py_Yield
|
||||
| 31 = @py_YieldFrom
|
||||
| 32 = @py_TemplateDottedNotation
|
||||
| 33 = @py_Filter
|
||||
| 34 = @py_PlaceHolder
|
||||
| 35 = @py_Await
|
||||
| 36 = @py_Fstring
|
||||
| 37 = @py_FormattedValue
|
||||
| 38 = @py_AssignExpr
|
||||
| 39 = @py_SpecialOperation;
|
||||
|
||||
case @py_expr_context.kind of
|
||||
0 = @py_AugLoad
|
||||
@@ -755,6 +840,21 @@ case @py_operator.kind of
|
||||
| 11 = @py_Sub
|
||||
| 12 = @py_MatMult;
|
||||
|
||||
case @py_pattern.kind of
|
||||
0 = @py_MatchAsPattern
|
||||
| 1 = @py_MatchOrPattern
|
||||
| 2 = @py_MatchLiteralPattern
|
||||
| 3 = @py_MatchCapturePattern
|
||||
| 4 = @py_MatchWildcardPattern
|
||||
| 5 = @py_MatchValuePattern
|
||||
| 6 = @py_MatchSequencePattern
|
||||
| 7 = @py_MatchStarPattern
|
||||
| 8 = @py_MatchMappingPattern
|
||||
| 9 = @py_MatchDoubleStarPattern
|
||||
| 10 = @py_MatchKeyValuePattern
|
||||
| 11 = @py_MatchClassPattern
|
||||
| 12 = @py_MatchKeywordPattern;
|
||||
|
||||
case @py_stmt.kind of
|
||||
0 = @py_Assert
|
||||
| 1 = @py_Assign
|
||||
@@ -770,16 +870,18 @@ case @py_stmt.kind of
|
||||
| 11 = @py_If
|
||||
| 12 = @py_Import
|
||||
| 13 = @py_ImportStar
|
||||
| 14 = @py_Nonlocal
|
||||
| 15 = @py_Pass
|
||||
| 16 = @py_Print
|
||||
| 17 = @py_Raise
|
||||
| 18 = @py_Return
|
||||
| 19 = @py_Try
|
||||
| 20 = @py_While
|
||||
| 21 = @py_With
|
||||
| 22 = @py_TemplateWrite
|
||||
| 23 = @py_AnnAssign;
|
||||
| 14 = @py_MatchStmt
|
||||
| 15 = @py_Case
|
||||
| 16 = @py_Nonlocal
|
||||
| 17 = @py_Pass
|
||||
| 18 = @py_Print
|
||||
| 19 = @py_Raise
|
||||
| 20 = @py_Return
|
||||
| 21 = @py_Try
|
||||
| 22 = @py_While
|
||||
| 23 = @py_With
|
||||
| 24 = @py_TemplateWrite
|
||||
| 25 = @py_AnnAssign;
|
||||
|
||||
case @py_unaryop.kind of
|
||||
0 = @py_Invert
|
||||
@@ -793,9 +895,9 @@ case @py_unaryop.kind of
|
||||
|
||||
@py_arguments_parent = @py_FunctionExpr | @py_Lambda;
|
||||
|
||||
@py_ast_node = @py_Class | @py_Function | @py_Module | @py_StringPart | @py_comprehension | @py_dict_item | @py_expr | @py_stmt;
|
||||
@py_ast_node = @py_Class | @py_Function | @py_Module | @py_StringPart | @py_comprehension | @py_dict_item | @py_expr | @py_pattern | @py_stmt;
|
||||
|
||||
@py_bool_parent = @py_For | @py_Function | @py_Print | @py_With | @py_expr;
|
||||
@py_bool_parent = @py_For | @py_Function | @py_Print | @py_With | @py_expr | @py_pattern;
|
||||
|
||||
@py_dict_item_list_parent = @py_Call | @py_ClassExpr | @py_Dict;
|
||||
|
||||
@@ -805,15 +907,19 @@ case @py_unaryop.kind of
|
||||
|
||||
@py_expr_or_stmt = @py_expr | @py_stmt;
|
||||
|
||||
@py_expr_parent = @py_AnnAssign | @py_Assert | @py_Assign | @py_AssignExpr | @py_Attribute | @py_AugAssign | @py_Await | @py_BinaryExpr | @py_Call | @py_Compare | @py_DictComp | @py_DictUnpacking | @py_ExceptStmt | @py_Exec | @py_Expr_stmt | @py_Filter | @py_For | @py_FormattedValue | @py_Function | @py_FunctionExpr | @py_GeneratorExp | @py_If | @py_IfExp | @py_ImportMember | @py_ImportStar | @py_KeyValuePair | @py_ListComp | @py_Print | @py_Raise | @py_Repr | @py_Return | @py_SetComp | @py_Slice | @py_Starred | @py_Subscript | @py_TemplateDottedNotation | @py_TemplateWrite | @py_UnaryExpr | @py_While | @py_With | @py_Yield | @py_YieldFrom | @py_alias | @py_arguments | @py_comprehension | @py_expr_list | @py_keyword | @py_parameter_list;
|
||||
@py_expr_parent = @py_AnnAssign | @py_Assert | @py_Assign | @py_AssignExpr | @py_Attribute | @py_AugAssign | @py_Await | @py_BinaryExpr | @py_Call | @py_Case | @py_Compare | @py_DictComp | @py_DictUnpacking | @py_ExceptStmt | @py_Exec | @py_Expr_stmt | @py_Filter | @py_For | @py_FormattedValue | @py_Function | @py_FunctionExpr | @py_GeneratorExp | @py_Guard | @py_If | @py_IfExp | @py_ImportMember | @py_ImportStar | @py_KeyValuePair | @py_ListComp | @py_MatchAsPattern | @py_MatchCapturePattern | @py_MatchClassPattern | @py_MatchKeywordPattern | @py_MatchLiteralPattern | @py_MatchStmt | @py_MatchValuePattern | @py_Print | @py_Raise | @py_Repr | @py_Return | @py_SetComp | @py_Slice | @py_Starred | @py_Subscript | @py_TemplateDottedNotation | @py_TemplateWrite | @py_UnaryExpr | @py_While | @py_With | @py_Yield | @py_YieldFrom | @py_alias | @py_arguments | @py_comprehension | @py_expr_list | @py_keyword | @py_parameter_list;
|
||||
|
||||
@py_location_parent = @py_DictUnpacking | @py_KeyValuePair | @py_StringPart | @py_comprehension | @py_expr | @py_keyword | @py_stmt;
|
||||
@py_location_parent = @py_DictUnpacking | @py_KeyValuePair | @py_StringPart | @py_comprehension | @py_expr | @py_keyword | @py_pattern | @py_stmt;
|
||||
|
||||
@py_parameter = @py_Name | @py_Tuple;
|
||||
|
||||
@py_pattern_list_parent = @py_MatchClassPattern | @py_MatchMappingPattern | @py_MatchOrPattern | @py_MatchSequencePattern;
|
||||
|
||||
@py_pattern_parent = @py_Case | @py_MatchAsPattern | @py_MatchDoubleStarPattern | @py_MatchKeyValuePattern | @py_MatchKeywordPattern | @py_MatchStarPattern | @py_pattern_list;
|
||||
|
||||
@py_scope = @py_Class | @py_Function | @py_Module;
|
||||
|
||||
@py_stmt_list_parent = @py_Class | @py_ExceptStmt | @py_For | @py_Function | @py_If | @py_Module | @py_Try | @py_While | @py_With;
|
||||
@py_stmt_list_parent = @py_Case | @py_Class | @py_ExceptStmt | @py_For | @py_Function | @py_If | @py_MatchStmt | @py_Module | @py_Try | @py_While | @py_With;
|
||||
|
||||
@py_str_list_parent = @py_Global | @py_Nonlocal;
|
||||
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
<dbstats>
|
||||
<typesizes><e>
|
||||
<k>@py_Guard</k><v>100</v></e><e>
|
||||
<k>@py_MatchAsPattern</k><v>100</v></e><e>
|
||||
<k>@py_MatchOrPattern</k><v>100</v></e><e>
|
||||
<k>@py_MatchLiteralPattern</k><v>100</v></e><e>
|
||||
<k>@py_MatchCapturePattern</k><v>100</v></e><e>
|
||||
<k>@py_MatchWildcardPattern</k><v>100</v></e><e>
|
||||
<k>@py_MatchValuePattern</k><v>100</v></e><e>
|
||||
<k>@py_MatchSequencePattern</k><v>100</v></e><e>
|
||||
<k>@py_MatchStarPattern</k><v>100</v></e><e>
|
||||
<k>@py_MatchMappingPattern</k><v>100</v></e><e>
|
||||
<k>@py_MatchDoubleStarPattern</k><v>100</v></e><e>
|
||||
<k>@py_MatchKeyValuePattern</k><v>100</v></e><e>
|
||||
<k>@py_MatchClassPattern</k><v>100</v></e><e>
|
||||
<k>@py_MatchKeywordPattern</k><v>100</v></e><e>
|
||||
<k>@py_Case</k><v>100</v></e><e>
|
||||
<k>@py_MatchStmt</k><v>100</v></e><e>
|
||||
<k>@py_pattern_list</k><v>100</v></e><e>
|
||||
<k>@externalDefect</k>
|
||||
<v>100</v>
|
||||
</e>
|
||||
@@ -7480,6 +7497,48 @@
|
||||
<dependencies/>
|
||||
</relation>
|
||||
<relation>
|
||||
<name>py_patterns</name>
|
||||
<cardinality>1000</cardinality>
|
||||
<columnsizes>
|
||||
<e>
|
||||
<k>id</k>
|
||||
<v>1000</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>kind</k>
|
||||
<v>13</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>parent</k>
|
||||
<v>1000</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>idx</k>
|
||||
<v>100</v>
|
||||
</e>
|
||||
</columnsizes>
|
||||
<dependencies/>
|
||||
</relation>
|
||||
<relation>
|
||||
<name>py_pattern_lists</name>
|
||||
<cardinality>1000</cardinality>
|
||||
<columnsizes>
|
||||
<e>
|
||||
<k>id</k>
|
||||
<v>1000</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>parent</k>
|
||||
<v>1000</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>idx</k>
|
||||
<v>100</v>
|
||||
</e>
|
||||
</columnsizes>
|
||||
<dependencies/>
|
||||
</relation>
|
||||
<relation>
|
||||
<name>py_extracted_version</name>
|
||||
<cardinality>3337</cardinality>
|
||||
<columnsizes>
|
||||
|
||||
@@ -0,0 +1,994 @@
|
||||
/*
|
||||
* This dbscheme is auto-generated by 'semmle/dbscheme_gen.py'.
|
||||
* WARNING: Any modifications to this file will be lost.
|
||||
* Relations can be changed by modifying master.py or
|
||||
* by adding rules to dbscheme.template
|
||||
*/
|
||||
|
||||
/* This is a dummy line to alter the dbscheme, so we can make a database upgrade
|
||||
* without actually changing any of the dbscheme predicates. It contains a date
|
||||
* to allow for such updates in the future as well.
|
||||
*
|
||||
* 2020-07-02
|
||||
*
|
||||
* DO NOT remove this comment carelessly, since it can revert the dbscheme back to a
|
||||
* previously seen state (matching a previously seen SHA), which would make the upgrade
|
||||
* mechanism not work properly.
|
||||
*/
|
||||
|
||||
/*
|
||||
* External artifacts
|
||||
*/
|
||||
|
||||
externalDefects(
|
||||
unique int id : @externalDefect,
|
||||
varchar(900) queryPath : string ref,
|
||||
int location : @location ref,
|
||||
varchar(900) message : string ref,
|
||||
float severity : float ref
|
||||
);
|
||||
|
||||
externalMetrics(
|
||||
unique int id : @externalMetric,
|
||||
varchar(900) queryPath : string ref,
|
||||
int location : @location ref,
|
||||
float value : float ref
|
||||
);
|
||||
|
||||
externalData(
|
||||
int id : @externalDataElement,
|
||||
varchar(900) queryPath : string ref,
|
||||
int column: int ref,
|
||||
varchar(900) data : string ref
|
||||
);
|
||||
|
||||
snapshotDate(unique date snapshotDate : date ref);
|
||||
|
||||
sourceLocationPrefix(varchar(900) prefix : string ref);
|
||||
|
||||
|
||||
/*
|
||||
* Duplicate code
|
||||
*/
|
||||
|
||||
duplicateCode(
|
||||
unique int id : @duplication,
|
||||
varchar(900) relativePath : string ref,
|
||||
int equivClass : int ref);
|
||||
|
||||
similarCode(
|
||||
unique int id : @similarity,
|
||||
varchar(900) relativePath : string ref,
|
||||
int equivClass : int ref);
|
||||
|
||||
@duplication_or_similarity = @duplication | @similarity
|
||||
|
||||
tokens(
|
||||
int id : @duplication_or_similarity ref,
|
||||
int offset : int ref,
|
||||
int beginLine : int ref,
|
||||
int beginColumn : int ref,
|
||||
int endLine : int ref,
|
||||
int endColumn : int ref);
|
||||
|
||||
/*
|
||||
* Line metrics
|
||||
*/
|
||||
py_codelines(int id : @py_scope ref,
|
||||
int count : int ref);
|
||||
|
||||
py_commentlines(int id : @py_scope ref,
|
||||
int count : int ref);
|
||||
|
||||
py_docstringlines(int id : @py_scope ref,
|
||||
int count : int ref);
|
||||
|
||||
py_alllines(int id : @py_scope ref,
|
||||
int count : int ref);
|
||||
|
||||
/*
|
||||
* Version history
|
||||
*/
|
||||
|
||||
svnentries(
|
||||
int id : @svnentry,
|
||||
varchar(500) revision : string ref,
|
||||
varchar(500) author : string ref,
|
||||
date revisionDate : date ref,
|
||||
int changeSize : int ref
|
||||
)
|
||||
|
||||
svnaffectedfiles(
|
||||
int id : @svnentry ref,
|
||||
int file : @file ref,
|
||||
varchar(500) action : string ref
|
||||
)
|
||||
|
||||
svnentrymsg(
|
||||
int id : @svnentry ref,
|
||||
varchar(500) message : string ref
|
||||
)
|
||||
|
||||
svnchurn(
|
||||
int commit : @svnentry ref,
|
||||
int file : @file ref,
|
||||
int addedLines : int ref,
|
||||
int deletedLines : int ref
|
||||
)
|
||||
|
||||
/****************************
|
||||
Python dbscheme
|
||||
****************************/
|
||||
|
||||
files(unique int id: @file,
|
||||
varchar(900) name: string ref);
|
||||
|
||||
folders(unique int id: @folder,
|
||||
varchar(900) name: string ref);
|
||||
|
||||
@container = @folder | @file;
|
||||
|
||||
containerparent(int parent: @container ref,
|
||||
unique int child: @container ref);
|
||||
|
||||
@sourceline = @file | @py_Module | @xmllocatable;
|
||||
|
||||
numlines(int element_id: @sourceline ref,
|
||||
int num_lines: int ref,
|
||||
int num_code: int ref,
|
||||
int num_comment: int ref
|
||||
);
|
||||
|
||||
@location = @location_ast | @location_default ;
|
||||
|
||||
locations_default(unique int id: @location_default,
|
||||
int file: @file ref,
|
||||
int beginLine: int ref,
|
||||
int beginColumn: int ref,
|
||||
int endLine: int ref,
|
||||
int endColumn: int ref);
|
||||
|
||||
locations_ast(unique int id: @location_ast,
|
||||
int module: @py_Module ref,
|
||||
int beginLine: int ref,
|
||||
int beginColumn: int ref,
|
||||
int endLine: int ref,
|
||||
int endColumn: int ref);
|
||||
|
||||
file_contents(unique int file: @file ref, string contents: string ref);
|
||||
|
||||
py_module_path(int module: @py_Module ref, int file: @container ref);
|
||||
|
||||
variable(unique int id : @py_variable,
|
||||
int scope : @py_scope ref,
|
||||
varchar(1) name : string ref);
|
||||
|
||||
py_line_lengths(unique int id : @py_line,
|
||||
int file: @py_Module ref,
|
||||
int line : int ref,
|
||||
int length : int ref);
|
||||
|
||||
py_extracted_version(int module : @py_Module ref,
|
||||
varchar(1) version : string ref);
|
||||
|
||||
/* AUTO GENERATED PART STARTS HERE */
|
||||
|
||||
|
||||
/* <Field> AnnAssign.location = 0, location */
|
||||
/* <Field> AnnAssign.value = 1, expr */
|
||||
/* <Field> AnnAssign.annotation = 2, expr */
|
||||
/* <Field> AnnAssign.target = 3, expr */
|
||||
|
||||
/* <Field> Assert.location = 0, location */
|
||||
/* <Field> Assert.test = 1, expr */
|
||||
/* <Field> Assert.msg = 2, expr */
|
||||
|
||||
/* <Field> Assign.location = 0, location */
|
||||
/* <Field> Assign.value = 1, expr */
|
||||
/* <Field> Assign.targets = 2, expr_list */
|
||||
|
||||
/* <Field> AssignExpr.location = 0, location */
|
||||
/* <Field> AssignExpr.parenthesised = 1, bool */
|
||||
/* <Field> AssignExpr.value = 2, expr */
|
||||
/* <Field> AssignExpr.target = 3, expr */
|
||||
|
||||
/* <Field> Attribute.location = 0, location */
|
||||
/* <Field> Attribute.parenthesised = 1, bool */
|
||||
/* <Field> Attribute.value = 2, expr */
|
||||
/* <Field> Attribute.attr = 3, str */
|
||||
/* <Field> Attribute.ctx = 4, expr_context */
|
||||
|
||||
/* <Field> AugAssign.location = 0, location */
|
||||
/* <Field> AugAssign.operation = 1, BinOp */
|
||||
|
||||
/* <Field> Await.location = 0, location */
|
||||
/* <Field> Await.parenthesised = 1, bool */
|
||||
/* <Field> Await.value = 2, expr */
|
||||
|
||||
/* <Field> BinaryExpr.location = 0, location */
|
||||
/* <Field> BinaryExpr.parenthesised = 1, bool */
|
||||
/* <Field> BinaryExpr.left = 2, expr */
|
||||
/* <Field> BinaryExpr.op = 3, operator */
|
||||
/* <Field> BinaryExpr.right = 4, expr */
|
||||
/* <Parent> BinaryExpr = AugAssign */
|
||||
|
||||
/* <Field> BoolExpr.location = 0, location */
|
||||
/* <Field> BoolExpr.parenthesised = 1, bool */
|
||||
/* <Field> BoolExpr.op = 2, boolop */
|
||||
/* <Field> BoolExpr.values = 3, expr_list */
|
||||
|
||||
/* <Field> Break.location = 0, location */
|
||||
|
||||
/* <Field> Bytes.location = 0, location */
|
||||
/* <Field> Bytes.parenthesised = 1, bool */
|
||||
/* <Field> Bytes.s = 2, bytes */
|
||||
/* <Field> Bytes.prefix = 3, bytes */
|
||||
/* <Field> Bytes.implicitly_concatenated_parts = 4, StringPart_list */
|
||||
|
||||
/* <Field> Call.location = 0, location */
|
||||
/* <Field> Call.parenthesised = 1, bool */
|
||||
/* <Field> Call.func = 2, expr */
|
||||
/* <Field> Call.positional_args = 3, expr_list */
|
||||
/* <Field> Call.named_args = 4, dict_item_list */
|
||||
|
||||
/* <Field> Class.name = 0, str */
|
||||
/* <Field> Class.body = 1, stmt_list */
|
||||
/* <Parent> Class = ClassExpr */
|
||||
|
||||
/* <Field> ClassExpr.location = 0, location */
|
||||
/* <Field> ClassExpr.parenthesised = 1, bool */
|
||||
/* <Field> ClassExpr.name = 2, str */
|
||||
/* <Field> ClassExpr.bases = 3, expr_list */
|
||||
/* <Field> ClassExpr.keywords = 4, dict_item_list */
|
||||
/* <Field> ClassExpr.inner_scope = 5, Class */
|
||||
|
||||
/* <Field> Compare.location = 0, location */
|
||||
/* <Field> Compare.parenthesised = 1, bool */
|
||||
/* <Field> Compare.left = 2, expr */
|
||||
/* <Field> Compare.ops = 3, cmpop_list */
|
||||
/* <Field> Compare.comparators = 4, expr_list */
|
||||
|
||||
/* <Field> Continue.location = 0, location */
|
||||
|
||||
/* <Field> Delete.location = 0, location */
|
||||
/* <Field> Delete.targets = 1, expr_list */
|
||||
|
||||
/* <Field> Dict.location = 0, location */
|
||||
/* <Field> Dict.parenthesised = 1, bool */
|
||||
/* <Field> Dict.items = 2, dict_item_list */
|
||||
|
||||
/* <Field> DictComp.location = 0, location */
|
||||
/* <Field> DictComp.parenthesised = 1, bool */
|
||||
/* <Field> DictComp.function = 2, Function */
|
||||
/* <Field> DictComp.iterable = 3, expr */
|
||||
|
||||
/* <Field> DictUnpacking.location = 0, location */
|
||||
/* <Field> DictUnpacking.value = 1, expr */
|
||||
|
||||
/* <Field> Ellipsis.location = 0, location */
|
||||
/* <Field> Ellipsis.parenthesised = 1, bool */
|
||||
|
||||
/* <Field> ExceptStmt.location = 0, location */
|
||||
/* <Field> ExceptStmt.type = 1, expr */
|
||||
/* <Field> ExceptStmt.name = 2, expr */
|
||||
/* <Field> ExceptStmt.body = 3, stmt_list */
|
||||
|
||||
/* <Field> Exec.location = 0, location */
|
||||
/* <Field> Exec.body = 1, expr */
|
||||
/* <Field> Exec.globals = 2, expr */
|
||||
/* <Field> Exec.locals = 3, expr */
|
||||
|
||||
/* <Field> ExprStmt.location = 0, location */
|
||||
/* <Field> ExprStmt.value = 1, expr */
|
||||
|
||||
/* <Field> Filter.location = 0, location */
|
||||
/* <Field> Filter.parenthesised = 1, bool */
|
||||
/* <Field> Filter.value = 2, expr */
|
||||
/* <Field> Filter.filter = 3, expr */
|
||||
|
||||
/* <Field> For.location = 0, location */
|
||||
/* <Field> For.target = 1, expr */
|
||||
/* <Field> For.iter = 2, expr */
|
||||
/* <Field> For.body = 3, stmt_list */
|
||||
/* <Field> For.orelse = 4, stmt_list */
|
||||
/* <Field> For.is_async = 5, bool */
|
||||
|
||||
/* <Field> FormattedValue.location = 0, location */
|
||||
/* <Field> FormattedValue.parenthesised = 1, bool */
|
||||
/* <Field> FormattedValue.value = 2, expr */
|
||||
/* <Field> FormattedValue.conversion = 3, str */
|
||||
/* <Field> FormattedValue.format_spec = 4, JoinedStr */
|
||||
|
||||
/* <Field> Function.name = 0, str */
|
||||
/* <Field> Function.args = 1, parameter_list */
|
||||
/* <Field> Function.vararg = 2, expr */
|
||||
/* <Field> Function.kwonlyargs = 3, expr_list */
|
||||
/* <Field> Function.kwarg = 4, expr */
|
||||
/* <Field> Function.body = 5, stmt_list */
|
||||
/* <Field> Function.is_async = 6, bool */
|
||||
/* <Parent> Function = FunctionParent */
|
||||
|
||||
/* <Field> FunctionExpr.location = 0, location */
|
||||
/* <Field> FunctionExpr.parenthesised = 1, bool */
|
||||
/* <Field> FunctionExpr.name = 2, str */
|
||||
/* <Field> FunctionExpr.args = 3, arguments */
|
||||
/* <Field> FunctionExpr.returns = 4, expr */
|
||||
/* <Field> FunctionExpr.inner_scope = 5, Function */
|
||||
|
||||
/* <Field> GeneratorExp.location = 0, location */
|
||||
/* <Field> GeneratorExp.parenthesised = 1, bool */
|
||||
/* <Field> GeneratorExp.function = 2, Function */
|
||||
/* <Field> GeneratorExp.iterable = 3, expr */
|
||||
|
||||
/* <Field> Global.location = 0, location */
|
||||
/* <Field> Global.names = 1, str_list */
|
||||
|
||||
/* <Field> If.location = 0, location */
|
||||
/* <Field> If.test = 1, expr */
|
||||
/* <Field> If.body = 2, stmt_list */
|
||||
/* <Field> If.orelse = 3, stmt_list */
|
||||
|
||||
/* <Field> IfExp.location = 0, location */
|
||||
/* <Field> IfExp.parenthesised = 1, bool */
|
||||
/* <Field> IfExp.test = 2, expr */
|
||||
/* <Field> IfExp.body = 3, expr */
|
||||
/* <Field> IfExp.orelse = 4, expr */
|
||||
|
||||
/* <Field> Import.location = 0, location */
|
||||
/* <Field> Import.names = 1, alias_list */
|
||||
|
||||
/* <Field> ImportExpr.location = 0, location */
|
||||
/* <Field> ImportExpr.parenthesised = 1, bool */
|
||||
/* <Field> ImportExpr.level = 2, int */
|
||||
/* <Field> ImportExpr.name = 3, str */
|
||||
/* <Field> ImportExpr.top = 4, bool */
|
||||
|
||||
/* <Field> ImportStar.location = 0, location */
|
||||
/* <Field> ImportStar.module = 1, expr */
|
||||
|
||||
/* <Field> ImportMember.location = 0, location */
|
||||
/* <Field> ImportMember.parenthesised = 1, bool */
|
||||
/* <Field> ImportMember.module = 2, expr */
|
||||
/* <Field> ImportMember.name = 3, str */
|
||||
|
||||
/* <Field> Fstring.location = 0, location */
|
||||
/* <Field> Fstring.parenthesised = 1, bool */
|
||||
/* <Field> Fstring.values = 2, expr_list */
|
||||
/* <Parent> Fstring = FormattedValue */
|
||||
|
||||
/* <Field> KeyValuePair.location = 0, location */
|
||||
/* <Field> KeyValuePair.value = 1, expr */
|
||||
/* <Field> KeyValuePair.key = 2, expr */
|
||||
|
||||
/* <Field> Lambda.location = 0, location */
|
||||
/* <Field> Lambda.parenthesised = 1, bool */
|
||||
/* <Field> Lambda.args = 2, arguments */
|
||||
/* <Field> Lambda.inner_scope = 3, Function */
|
||||
|
||||
/* <Field> List.location = 0, location */
|
||||
/* <Field> List.parenthesised = 1, bool */
|
||||
/* <Field> List.elts = 2, expr_list */
|
||||
/* <Field> List.ctx = 3, expr_context */
|
||||
|
||||
/* <Field> ListComp.location = 0, location */
|
||||
/* <Field> ListComp.parenthesised = 1, bool */
|
||||
/* <Field> ListComp.function = 2, Function */
|
||||
/* <Field> ListComp.iterable = 3, expr */
|
||||
/* <Field> ListComp.generators = 4, comprehension_list */
|
||||
/* <Field> ListComp.elt = 5, expr */
|
||||
|
||||
/* <Field> Module.name = 0, str */
|
||||
/* <Field> Module.hash = 1, str */
|
||||
/* <Field> Module.body = 2, stmt_list */
|
||||
/* <Field> Module.kind = 3, str */
|
||||
|
||||
/* <Field> Name.location = 0, location */
|
||||
/* <Field> Name.parenthesised = 1, bool */
|
||||
/* <Field> Name.variable = 2, variable */
|
||||
/* <Field> Name.ctx = 3, expr_context */
|
||||
/* <Parent> Name = ParameterList */
|
||||
|
||||
/* <Field> Nonlocal.location = 0, location */
|
||||
/* <Field> Nonlocal.names = 1, str_list */
|
||||
|
||||
/* <Field> Num.location = 0, location */
|
||||
/* <Field> Num.parenthesised = 1, bool */
|
||||
/* <Field> Num.n = 2, number */
|
||||
/* <Field> Num.text = 3, number */
|
||||
|
||||
/* <Field> Pass.location = 0, location */
|
||||
|
||||
/* <Field> PlaceHolder.location = 0, location */
|
||||
/* <Field> PlaceHolder.parenthesised = 1, bool */
|
||||
/* <Field> PlaceHolder.variable = 2, variable */
|
||||
/* <Field> PlaceHolder.ctx = 3, expr_context */
|
||||
|
||||
/* <Field> Print.location = 0, location */
|
||||
/* <Field> Print.dest = 1, expr */
|
||||
/* <Field> Print.values = 2, expr_list */
|
||||
/* <Field> Print.nl = 3, bool */
|
||||
|
||||
/* <Field> Raise.location = 0, location */
|
||||
/* <Field> Raise.exc = 1, expr */
|
||||
/* <Field> Raise.cause = 2, expr */
|
||||
/* <Field> Raise.type = 3, expr */
|
||||
/* <Field> Raise.inst = 4, expr */
|
||||
/* <Field> Raise.tback = 5, expr */
|
||||
|
||||
/* <Field> Repr.location = 0, location */
|
||||
/* <Field> Repr.parenthesised = 1, bool */
|
||||
/* <Field> Repr.value = 2, expr */
|
||||
|
||||
/* <Field> Return.location = 0, location */
|
||||
/* <Field> Return.value = 1, expr */
|
||||
|
||||
/* <Field> Set.location = 0, location */
|
||||
/* <Field> Set.parenthesised = 1, bool */
|
||||
/* <Field> Set.elts = 2, expr_list */
|
||||
|
||||
/* <Field> SetComp.location = 0, location */
|
||||
/* <Field> SetComp.parenthesised = 1, bool */
|
||||
/* <Field> SetComp.function = 2, Function */
|
||||
/* <Field> SetComp.iterable = 3, expr */
|
||||
|
||||
/* <Field> Slice.location = 0, location */
|
||||
/* <Field> Slice.parenthesised = 1, bool */
|
||||
/* <Field> Slice.start = 2, expr */
|
||||
/* <Field> Slice.stop = 3, expr */
|
||||
/* <Field> Slice.step = 4, expr */
|
||||
|
||||
/* <Field> SpecialOperation.location = 0, location */
|
||||
/* <Field> SpecialOperation.parenthesised = 1, bool */
|
||||
/* <Field> SpecialOperation.name = 2, str */
|
||||
/* <Field> SpecialOperation.arguments = 3, expr_list */
|
||||
|
||||
/* <Field> Starred.location = 0, location */
|
||||
/* <Field> Starred.parenthesised = 1, bool */
|
||||
/* <Field> Starred.value = 2, expr */
|
||||
/* <Field> Starred.ctx = 3, expr_context */
|
||||
|
||||
/* <Field> Str.location = 0, location */
|
||||
/* <Field> Str.parenthesised = 1, bool */
|
||||
/* <Field> Str.s = 2, str */
|
||||
/* <Field> Str.prefix = 3, str */
|
||||
/* <Field> Str.implicitly_concatenated_parts = 4, StringPart_list */
|
||||
|
||||
/* <Field> StringPart.text = 0, str */
|
||||
/* <Field> StringPart.location = 1, location */
|
||||
/* <Parent> StringPart = StringPartList */
|
||||
/* <Parent> StringPartList = BytesOrStr */
|
||||
|
||||
/* <Field> Subscript.location = 0, location */
|
||||
/* <Field> Subscript.parenthesised = 1, bool */
|
||||
/* <Field> Subscript.value = 2, expr */
|
||||
/* <Field> Subscript.index = 3, expr */
|
||||
/* <Field> Subscript.ctx = 4, expr_context */
|
||||
|
||||
/* <Field> TemplateDottedNotation.location = 0, location */
|
||||
/* <Field> TemplateDottedNotation.parenthesised = 1, bool */
|
||||
/* <Field> TemplateDottedNotation.value = 2, expr */
|
||||
/* <Field> TemplateDottedNotation.attr = 3, str */
|
||||
/* <Field> TemplateDottedNotation.ctx = 4, expr_context */
|
||||
|
||||
/* <Field> TemplateWrite.location = 0, location */
|
||||
/* <Field> TemplateWrite.value = 1, expr */
|
||||
|
||||
/* <Field> Try.location = 0, location */
|
||||
/* <Field> Try.body = 1, stmt_list */
|
||||
/* <Field> Try.orelse = 2, stmt_list */
|
||||
/* <Field> Try.handlers = 3, stmt_list */
|
||||
/* <Field> Try.finalbody = 4, stmt_list */
|
||||
|
||||
/* <Field> Tuple.location = 0, location */
|
||||
/* <Field> Tuple.parenthesised = 1, bool */
|
||||
/* <Field> Tuple.elts = 2, expr_list */
|
||||
/* <Field> Tuple.ctx = 3, expr_context */
|
||||
/* <Parent> Tuple = ParameterList */
|
||||
|
||||
/* <Field> UnaryExpr.location = 0, location */
|
||||
/* <Field> UnaryExpr.parenthesised = 1, bool */
|
||||
/* <Field> UnaryExpr.op = 2, unaryop */
|
||||
/* <Field> UnaryExpr.operand = 3, expr */
|
||||
|
||||
/* <Field> While.location = 0, location */
|
||||
/* <Field> While.test = 1, expr */
|
||||
/* <Field> While.body = 2, stmt_list */
|
||||
/* <Field> While.orelse = 3, stmt_list */
|
||||
|
||||
/* <Field> With.location = 0, location */
|
||||
/* <Field> With.context_expr = 1, expr */
|
||||
/* <Field> With.optional_vars = 2, expr */
|
||||
/* <Field> With.body = 3, stmt_list */
|
||||
/* <Field> With.is_async = 4, bool */
|
||||
|
||||
/* <Field> Yield.location = 0, location */
|
||||
/* <Field> Yield.parenthesised = 1, bool */
|
||||
/* <Field> Yield.value = 2, expr */
|
||||
|
||||
/* <Field> YieldFrom.location = 0, location */
|
||||
/* <Field> YieldFrom.parenthesised = 1, bool */
|
||||
/* <Field> YieldFrom.value = 2, expr */
|
||||
|
||||
/* <Field> Alias.value = 0, expr */
|
||||
/* <Field> Alias.asname = 1, expr */
|
||||
/* <Parent> Alias = AliasList */
|
||||
/* <Parent> AliasList = Import */
|
||||
|
||||
/* <Field> Arguments.kw_defaults = 0, expr_list */
|
||||
/* <Field> Arguments.defaults = 1, expr_list */
|
||||
/* <Field> Arguments.annotations = 2, expr_list */
|
||||
/* <Field> Arguments.varargannotation = 3, expr */
|
||||
/* <Field> Arguments.kwargannotation = 4, expr */
|
||||
/* <Field> Arguments.kw_annotations = 5, expr_list */
|
||||
/* <Parent> Arguments = ArgumentsParent */
|
||||
/* <Parent> boolean = BoolParent */
|
||||
/* <Parent> Boolop = BoolExpr */
|
||||
/* <Parent> string = Bytes */
|
||||
/* <Parent> Cmpop = CmpopList */
|
||||
/* <Parent> CmpopList = Compare */
|
||||
|
||||
/* <Field> Comprehension.location = 0, location */
|
||||
/* <Field> Comprehension.iter = 1, expr */
|
||||
/* <Field> Comprehension.target = 2, expr */
|
||||
/* <Field> Comprehension.ifs = 3, expr_list */
|
||||
/* <Parent> Comprehension = ComprehensionList */
|
||||
/* <Parent> ComprehensionList = ListComp */
|
||||
/* <Parent> DictItem = DictItemList */
|
||||
/* <Parent> DictItemList = DictItemListParent */
|
||||
|
||||
/* <Field> Expr.location = 0, location */
|
||||
/* <Field> Expr.parenthesised = 1, bool */
|
||||
/* <Parent> Expr = ExprParent */
|
||||
/* <Parent> ExprContext = ExprContextParent */
|
||||
/* <Parent> ExprList = ExprListParent */
|
||||
/* <Parent> int = ImportExpr */
|
||||
|
||||
/* <Field> Keyword.location = 0, location */
|
||||
/* <Field> Keyword.value = 1, expr */
|
||||
/* <Field> Keyword.arg = 2, str */
|
||||
/* <Parent> Location = LocationParent */
|
||||
/* <Parent> string = Num */
|
||||
/* <Parent> Operator = BinaryExpr */
|
||||
/* <Parent> ParameterList = Function */
|
||||
|
||||
/* <Field> Stmt.location = 0, location */
|
||||
/* <Parent> Stmt = StmtList */
|
||||
/* <Parent> StmtList = StmtListParent */
|
||||
/* <Parent> string = StrParent */
|
||||
/* <Parent> StringList = StrListParent */
|
||||
/* <Parent> Unaryop = UnaryExpr */
|
||||
/* <Parent> Variable = VariableParent */
|
||||
py_Classes(unique int id : @py_Class,
|
||||
unique int parent : @py_ClassExpr ref);
|
||||
|
||||
py_Functions(unique int id : @py_Function,
|
||||
unique int parent : @py_Function_parent ref);
|
||||
|
||||
py_Modules(unique int id : @py_Module);
|
||||
|
||||
py_StringParts(unique int id : @py_StringPart,
|
||||
int parent : @py_StringPart_list ref,
|
||||
int idx : int ref);
|
||||
|
||||
py_StringPart_lists(unique int id : @py_StringPart_list,
|
||||
unique int parent : @py_Bytes_or_Str ref);
|
||||
|
||||
py_aliases(unique int id : @py_alias,
|
||||
int parent : @py_alias_list ref,
|
||||
int idx : int ref);
|
||||
|
||||
py_alias_lists(unique int id : @py_alias_list,
|
||||
unique int parent : @py_Import ref);
|
||||
|
||||
py_arguments(unique int id : @py_arguments,
|
||||
unique int parent : @py_arguments_parent ref);
|
||||
|
||||
py_bools(int parent : @py_bool_parent ref,
|
||||
int idx : int ref);
|
||||
|
||||
py_boolops(unique int id : @py_boolop,
|
||||
int kind: int ref,
|
||||
unique int parent : @py_BoolExpr ref);
|
||||
|
||||
py_bytes(varchar(1) id : string ref,
|
||||
int parent : @py_Bytes ref,
|
||||
int idx : int ref);
|
||||
|
||||
py_cmpops(unique int id : @py_cmpop,
|
||||
int kind: int ref,
|
||||
int parent : @py_cmpop_list ref,
|
||||
int idx : int ref);
|
||||
|
||||
py_cmpop_lists(unique int id : @py_cmpop_list,
|
||||
unique int parent : @py_Compare ref);
|
||||
|
||||
py_comprehensions(unique int id : @py_comprehension,
|
||||
int parent : @py_comprehension_list ref,
|
||||
int idx : int ref);
|
||||
|
||||
py_comprehension_lists(unique int id : @py_comprehension_list,
|
||||
unique int parent : @py_ListComp ref);
|
||||
|
||||
py_dict_items(unique int id : @py_dict_item,
|
||||
int kind: int ref,
|
||||
int parent : @py_dict_item_list ref,
|
||||
int idx : int ref);
|
||||
|
||||
py_dict_item_lists(unique int id : @py_dict_item_list,
|
||||
unique int parent : @py_dict_item_list_parent ref);
|
||||
|
||||
py_exprs(unique int id : @py_expr,
|
||||
int kind: int ref,
|
||||
int parent : @py_expr_parent ref,
|
||||
int idx : int ref);
|
||||
|
||||
py_expr_contexts(unique int id : @py_expr_context,
|
||||
int kind: int ref,
|
||||
unique int parent : @py_expr_context_parent ref);
|
||||
|
||||
py_expr_lists(unique int id : @py_expr_list,
|
||||
int parent : @py_expr_list_parent ref,
|
||||
int idx : int ref);
|
||||
|
||||
py_ints(int id : int ref,
|
||||
unique int parent : @py_ImportExpr ref);
|
||||
|
||||
py_locations(unique int id : @location ref,
|
||||
unique int parent : @py_location_parent ref);
|
||||
|
||||
py_numbers(varchar(1) id : string ref,
|
||||
int parent : @py_Num ref,
|
||||
int idx : int ref);
|
||||
|
||||
py_operators(unique int id : @py_operator,
|
||||
int kind: int ref,
|
||||
unique int parent : @py_BinaryExpr ref);
|
||||
|
||||
py_parameter_lists(unique int id : @py_parameter_list,
|
||||
unique int parent : @py_Function ref);
|
||||
|
||||
py_stmts(unique int id : @py_stmt,
|
||||
int kind: int ref,
|
||||
int parent : @py_stmt_list ref,
|
||||
int idx : int ref);
|
||||
|
||||
py_stmt_lists(unique int id : @py_stmt_list,
|
||||
int parent : @py_stmt_list_parent ref,
|
||||
int idx : int ref);
|
||||
|
||||
py_strs(varchar(1) id : string ref,
|
||||
int parent : @py_str_parent ref,
|
||||
int idx : int ref);
|
||||
|
||||
py_str_lists(unique int id : @py_str_list,
|
||||
unique int parent : @py_str_list_parent ref);
|
||||
|
||||
py_unaryops(unique int id : @py_unaryop,
|
||||
int kind: int ref,
|
||||
unique int parent : @py_UnaryExpr ref);
|
||||
|
||||
py_variables(int id : @py_variable ref,
|
||||
unique int parent : @py_variable_parent ref);
|
||||
|
||||
case @py_boolop.kind of
|
||||
0 = @py_And
|
||||
| 1 = @py_Or;
|
||||
|
||||
case @py_cmpop.kind of
|
||||
0 = @py_Eq
|
||||
| 1 = @py_Gt
|
||||
| 2 = @py_GtE
|
||||
| 3 = @py_In
|
||||
| 4 = @py_Is
|
||||
| 5 = @py_IsNot
|
||||
| 6 = @py_Lt
|
||||
| 7 = @py_LtE
|
||||
| 8 = @py_NotEq
|
||||
| 9 = @py_NotIn;
|
||||
|
||||
case @py_dict_item.kind of
|
||||
0 = @py_DictUnpacking
|
||||
| 1 = @py_KeyValuePair
|
||||
| 2 = @py_keyword;
|
||||
|
||||
case @py_expr.kind of
|
||||
0 = @py_Attribute
|
||||
| 1 = @py_BinaryExpr
|
||||
| 2 = @py_BoolExpr
|
||||
| 3 = @py_Bytes
|
||||
| 4 = @py_Call
|
||||
| 5 = @py_ClassExpr
|
||||
| 6 = @py_Compare
|
||||
| 7 = @py_Dict
|
||||
| 8 = @py_DictComp
|
||||
| 9 = @py_Ellipsis
|
||||
| 10 = @py_FunctionExpr
|
||||
| 11 = @py_GeneratorExp
|
||||
| 12 = @py_IfExp
|
||||
| 13 = @py_ImportExpr
|
||||
| 14 = @py_ImportMember
|
||||
| 15 = @py_Lambda
|
||||
| 16 = @py_List
|
||||
| 17 = @py_ListComp
|
||||
| 18 = @py_Name
|
||||
| 19 = @py_Num
|
||||
| 20 = @py_Repr
|
||||
| 21 = @py_Set
|
||||
| 22 = @py_SetComp
|
||||
| 23 = @py_Slice
|
||||
| 24 = @py_Starred
|
||||
| 25 = @py_Str
|
||||
| 26 = @py_Subscript
|
||||
| 27 = @py_Tuple
|
||||
| 28 = @py_UnaryExpr
|
||||
| 29 = @py_Yield
|
||||
| 30 = @py_YieldFrom
|
||||
| 31 = @py_TemplateDottedNotation
|
||||
| 32 = @py_Filter
|
||||
| 33 = @py_PlaceHolder
|
||||
| 34 = @py_Await
|
||||
| 35 = @py_Fstring
|
||||
| 36 = @py_FormattedValue
|
||||
| 37 = @py_AssignExpr
|
||||
| 38 = @py_SpecialOperation;
|
||||
|
||||
case @py_expr_context.kind of
|
||||
0 = @py_AugLoad
|
||||
| 1 = @py_AugStore
|
||||
| 2 = @py_Del
|
||||
| 3 = @py_Load
|
||||
| 4 = @py_Param
|
||||
| 5 = @py_Store;
|
||||
|
||||
case @py_operator.kind of
|
||||
0 = @py_Add
|
||||
| 1 = @py_BitAnd
|
||||
| 2 = @py_BitOr
|
||||
| 3 = @py_BitXor
|
||||
| 4 = @py_Div
|
||||
| 5 = @py_FloorDiv
|
||||
| 6 = @py_LShift
|
||||
| 7 = @py_Mod
|
||||
| 8 = @py_Mult
|
||||
| 9 = @py_Pow
|
||||
| 10 = @py_RShift
|
||||
| 11 = @py_Sub
|
||||
| 12 = @py_MatMult;
|
||||
|
||||
case @py_stmt.kind of
|
||||
0 = @py_Assert
|
||||
| 1 = @py_Assign
|
||||
| 2 = @py_AugAssign
|
||||
| 3 = @py_Break
|
||||
| 4 = @py_Continue
|
||||
| 5 = @py_Delete
|
||||
| 6 = @py_ExceptStmt
|
||||
| 7 = @py_Exec
|
||||
| 8 = @py_Expr_stmt
|
||||
| 9 = @py_For
|
||||
| 10 = @py_Global
|
||||
| 11 = @py_If
|
||||
| 12 = @py_Import
|
||||
| 13 = @py_ImportStar
|
||||
| 14 = @py_Nonlocal
|
||||
| 15 = @py_Pass
|
||||
| 16 = @py_Print
|
||||
| 17 = @py_Raise
|
||||
| 18 = @py_Return
|
||||
| 19 = @py_Try
|
||||
| 20 = @py_While
|
||||
| 21 = @py_With
|
||||
| 22 = @py_TemplateWrite
|
||||
| 23 = @py_AnnAssign;
|
||||
|
||||
case @py_unaryop.kind of
|
||||
0 = @py_Invert
|
||||
| 1 = @py_Not
|
||||
| 2 = @py_UAdd
|
||||
| 3 = @py_USub;
|
||||
|
||||
@py_Bytes_or_Str = @py_Bytes | @py_Str;
|
||||
|
||||
@py_Function_parent = @py_DictComp | @py_FunctionExpr | @py_GeneratorExp | @py_Lambda | @py_ListComp | @py_SetComp;
|
||||
|
||||
@py_arguments_parent = @py_FunctionExpr | @py_Lambda;
|
||||
|
||||
@py_ast_node = @py_Class | @py_Function | @py_Module | @py_StringPart | @py_comprehension | @py_dict_item | @py_expr | @py_stmt;
|
||||
|
||||
@py_bool_parent = @py_For | @py_Function | @py_Print | @py_With | @py_expr;
|
||||
|
||||
@py_dict_item_list_parent = @py_Call | @py_ClassExpr | @py_Dict;
|
||||
|
||||
@py_expr_context_parent = @py_Attribute | @py_List | @py_Name | @py_PlaceHolder | @py_Starred | @py_Subscript | @py_TemplateDottedNotation | @py_Tuple;
|
||||
|
||||
@py_expr_list_parent = @py_Assign | @py_BoolExpr | @py_Call | @py_ClassExpr | @py_Compare | @py_Delete | @py_Fstring | @py_Function | @py_List | @py_Print | @py_Set | @py_SpecialOperation | @py_Tuple | @py_arguments | @py_comprehension;
|
||||
|
||||
@py_expr_or_stmt = @py_expr | @py_stmt;
|
||||
|
||||
@py_expr_parent = @py_AnnAssign | @py_Assert | @py_Assign | @py_AssignExpr | @py_Attribute | @py_AugAssign | @py_Await | @py_BinaryExpr | @py_Call | @py_Compare | @py_DictComp | @py_DictUnpacking | @py_ExceptStmt | @py_Exec | @py_Expr_stmt | @py_Filter | @py_For | @py_FormattedValue | @py_Function | @py_FunctionExpr | @py_GeneratorExp | @py_If | @py_IfExp | @py_ImportMember | @py_ImportStar | @py_KeyValuePair | @py_ListComp | @py_Print | @py_Raise | @py_Repr | @py_Return | @py_SetComp | @py_Slice | @py_Starred | @py_Subscript | @py_TemplateDottedNotation | @py_TemplateWrite | @py_UnaryExpr | @py_While | @py_With | @py_Yield | @py_YieldFrom | @py_alias | @py_arguments | @py_comprehension | @py_expr_list | @py_keyword | @py_parameter_list;
|
||||
|
||||
@py_location_parent = @py_DictUnpacking | @py_KeyValuePair | @py_StringPart | @py_comprehension | @py_expr | @py_keyword | @py_stmt;
|
||||
|
||||
@py_parameter = @py_Name | @py_Tuple;
|
||||
|
||||
@py_scope = @py_Class | @py_Function | @py_Module;
|
||||
|
||||
@py_stmt_list_parent = @py_Class | @py_ExceptStmt | @py_For | @py_Function | @py_If | @py_Module | @py_Try | @py_While | @py_With;
|
||||
|
||||
@py_str_list_parent = @py_Global | @py_Nonlocal;
|
||||
|
||||
@py_str_parent = @py_Attribute | @py_Class | @py_ClassExpr | @py_FormattedValue | @py_Function | @py_FunctionExpr | @py_ImportExpr | @py_ImportMember | @py_Module | @py_SpecialOperation | @py_Str | @py_StringPart | @py_TemplateDottedNotation | @py_keyword | @py_str_list;
|
||||
|
||||
@py_variable_parent = @py_Name | @py_PlaceHolder;
|
||||
|
||||
|
||||
/*
|
||||
* End of auto-generated part
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* Map relative names to absolute names for imports */
|
||||
py_absolute_names(int module : @py_Module ref,
|
||||
varchar(1) relname : string ref,
|
||||
varchar(1) absname : string ref);
|
||||
|
||||
py_exports(int id : @py_Module ref,
|
||||
varchar(1) name : string ref);
|
||||
|
||||
/* Successor information */
|
||||
py_successors(int predecessor : @py_flow_node ref,
|
||||
int successor : @py_flow_node ref);
|
||||
|
||||
py_true_successors(int predecessor : @py_flow_node ref,
|
||||
int successor : @py_flow_node ref);
|
||||
|
||||
py_exception_successors(int predecessor : @py_flow_node ref,
|
||||
int successor : @py_flow_node ref);
|
||||
|
||||
py_false_successors(int predecessor : @py_flow_node ref,
|
||||
int successor : @py_flow_node ref);
|
||||
|
||||
py_flow_bb_node(unique int flownode : @py_flow_node,
|
||||
int realnode : @py_ast_node ref,
|
||||
int basicblock : @py_flow_node ref,
|
||||
int index : int ref);
|
||||
|
||||
py_scope_flow(int flow : @py_flow_node ref,
|
||||
int scope : @py_scope ref,
|
||||
int kind : int ref);
|
||||
|
||||
py_idoms(unique int node : @py_flow_node ref,
|
||||
int immediate_dominator : @py_flow_node ref);
|
||||
|
||||
py_ssa_phi(int phi : @py_ssa_var ref,
|
||||
int arg: @py_ssa_var ref);
|
||||
|
||||
py_ssa_var(unique int id : @py_ssa_var,
|
||||
int var : @py_variable ref);
|
||||
|
||||
py_ssa_use(int node: @py_flow_node ref,
|
||||
int var : @py_ssa_var ref);
|
||||
|
||||
py_ssa_defn(unique int id : @py_ssa_var ref,
|
||||
int node: @py_flow_node ref);
|
||||
|
||||
@py_base_var = @py_variable | @py_ssa_var;
|
||||
|
||||
py_scopes(unique int node : @py_expr_or_stmt ref,
|
||||
int scope : @py_scope ref);
|
||||
|
||||
py_scope_location(unique int id : @location ref,
|
||||
unique int scope : @py_scope ref);
|
||||
|
||||
py_flags_versioned(varchar(1) name : string ref,
|
||||
varchar(1) value : string ref,
|
||||
varchar(1) version : string ref);
|
||||
|
||||
py_syntax_error_versioned(unique int id : @location ref,
|
||||
varchar(1) message : string ref,
|
||||
varchar(1) version : string ref);
|
||||
|
||||
py_comments(unique int id : @py_comment,
|
||||
varchar(1) text : string ref,
|
||||
unique int location : @location ref);
|
||||
|
||||
/* Type information support */
|
||||
|
||||
py_cobjects(unique int obj : @py_cobject);
|
||||
|
||||
py_cobjecttypes(unique int obj : @py_cobject ref,
|
||||
int typeof : @py_cobject ref);
|
||||
|
||||
py_cobjectnames(unique int obj : @py_cobject ref,
|
||||
varchar(1) name : string ref);
|
||||
|
||||
/* Kind should be 0 for introspection, > 0 from source, as follows:
|
||||
1 from C extension source
|
||||
*/
|
||||
py_cobject_sources(int obj : @py_cobject ref,
|
||||
int kind : int ref);
|
||||
|
||||
py_cmembers_versioned(int object : @py_cobject ref,
|
||||
varchar(1) name : string ref,
|
||||
int member : @py_cobject ref,
|
||||
varchar(1) version : string ref);
|
||||
|
||||
py_citems(int object : @py_cobject ref,
|
||||
int index : int ref,
|
||||
int member : @py_cobject ref);
|
||||
|
||||
ext_argtype(int funcid : @py_object ref,
|
||||
int arg : int ref,
|
||||
int typeid : @py_object ref);
|
||||
|
||||
ext_rettype(int funcid : @py_object ref,
|
||||
int typeid : @py_object ref);
|
||||
|
||||
ext_proptype(int propid : @py_object ref,
|
||||
int typeid : @py_object ref);
|
||||
|
||||
ext_argreturn(int funcid : @py_object ref,
|
||||
int arg : int ref);
|
||||
|
||||
py_special_objects(unique int obj : @py_cobject ref,
|
||||
unique varchar(1) name : string ref);
|
||||
|
||||
py_decorated_object(int object : @py_object ref,
|
||||
int level: int ref);
|
||||
|
||||
@py_object = @py_cobject | @py_flow_node;
|
||||
|
||||
@py_source_element = @py_ast_node | @container;
|
||||
|
||||
/* XML Files */
|
||||
|
||||
xmlEncoding (unique int id: @file ref, varchar(900) encoding: string ref);
|
||||
|
||||
xmlDTDs (unique int id: @xmldtd,
|
||||
varchar(900) root: string ref,
|
||||
varchar(900) publicId: string ref,
|
||||
varchar(900) systemId: string ref,
|
||||
int fileid: @file ref);
|
||||
|
||||
xmlElements (unique int id: @xmlelement,
|
||||
varchar(900) name: string ref,
|
||||
int parentid: @xmlparent ref,
|
||||
int idx: int ref,
|
||||
int fileid: @file ref);
|
||||
|
||||
xmlAttrs (unique int id: @xmlattribute,
|
||||
int elementid: @xmlelement ref,
|
||||
varchar(900) name: string ref,
|
||||
varchar(3600) value: string ref,
|
||||
int idx: int ref,
|
||||
int fileid: @file ref);
|
||||
|
||||
xmlNs (int id: @xmlnamespace,
|
||||
varchar(900) prefixName: string ref,
|
||||
varchar(900) URI: string ref,
|
||||
int fileid: @file ref);
|
||||
|
||||
xmlHasNs (int elementId: @xmlnamespaceable ref,
|
||||
int nsId: @xmlnamespace ref,
|
||||
int fileid: @file ref);
|
||||
|
||||
xmlComments (unique int id: @xmlcomment,
|
||||
varchar(3600) text: string ref,
|
||||
int parentid: @xmlparent ref,
|
||||
int fileid: @file ref);
|
||||
|
||||
xmlChars (unique int id: @xmlcharacters,
|
||||
varchar(3600) text: string ref,
|
||||
int parentid: @xmlparent ref,
|
||||
int idx: int ref,
|
||||
int isCDATA: int ref,
|
||||
int fileid: @file ref);
|
||||
|
||||
@xmlparent = @file | @xmlelement;
|
||||
@xmlnamespaceable = @xmlelement | @xmlattribute;
|
||||
|
||||
xmllocations(int xmlElement: @xmllocatable ref,
|
||||
int location: @location_default ref);
|
||||
|
||||
@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;
|
||||
@@ -0,0 +1,42 @@
|
||||
// First we need to wrap some database types
|
||||
class Location extends @location {
|
||||
/** Gets the start line of this location */
|
||||
int getStartLine() {
|
||||
locations_default(this, _, result, _, _, _) or
|
||||
locations_ast(this, _, result, _, _, _)
|
||||
}
|
||||
|
||||
string toString() { result = "<some file>" + ":" + this.getStartLine().toString() }
|
||||
}
|
||||
|
||||
class Expr_ extends @py_expr {
|
||||
string toString() { result = "Expr" }
|
||||
|
||||
Location getLocation() { py_locations(result, this) }
|
||||
}
|
||||
|
||||
class ExprParent_ extends @py_expr_parent {
|
||||
string toString() { result = "ExprParent" }
|
||||
}
|
||||
|
||||
/**
|
||||
* New kinds have been inserted such that
|
||||
* `@py_Name` which used to have index 18 now has index 19.
|
||||
* Entries with lower indices are unchanged.
|
||||
*/
|
||||
bindingset[old_index]
|
||||
int new_index(int old_index) {
|
||||
if old_index < 18 then result = old_index else result = (19 - 18) + old_index
|
||||
}
|
||||
|
||||
// The schema for py_exprs is:
|
||||
//
|
||||
// py_exprs(unique int id : @py_expr,
|
||||
// int kind: int ref,
|
||||
// int parent : @py_expr_parent ref,
|
||||
// int idx : int ref);
|
||||
from Expr_ expr, int old_kind, ExprParent_ parent, int idx, int new_kind
|
||||
where
|
||||
py_exprs(expr, old_kind, parent, idx) and
|
||||
new_kind = new_index(old_kind)
|
||||
select expr, new_kind, parent, idx
|
||||
@@ -0,0 +1,42 @@
|
||||
// First we need to wrap some database types
|
||||
class Location extends @location {
|
||||
/** Gets the start line of this location */
|
||||
int getStartLine() {
|
||||
locations_default(this, _, result, _, _, _) or
|
||||
locations_ast(this, _, result, _, _, _)
|
||||
}
|
||||
|
||||
string toString() { result = "<some file>" + ":" + this.getStartLine().toString() }
|
||||
}
|
||||
|
||||
class Stmt_ extends @py_stmt {
|
||||
string toString() { result = "Stmt" }
|
||||
|
||||
Location getLocation() { py_locations(result, this) }
|
||||
}
|
||||
|
||||
class StmtList_ extends @py_stmt_list {
|
||||
string toString() { result = "StmtList" }
|
||||
}
|
||||
|
||||
/**
|
||||
* New kinds have been inserted such that
|
||||
* `@py_Nonlocal` which used to have index 14 now has index 16.
|
||||
* Entries with lower indices are unchanged.
|
||||
*/
|
||||
bindingset[old_index]
|
||||
int new_index(int old_index) {
|
||||
if old_index < 14 then result = old_index else result = (16 - 14) + old_index
|
||||
}
|
||||
|
||||
// The schema for py_stmts is:
|
||||
//
|
||||
// py_stmts(unique int id : @py_stmt,
|
||||
// int kind: int ref,
|
||||
// int parent : @py_stmt_list ref,
|
||||
// int idx : int ref);
|
||||
from Stmt_ expr, int old_kind, StmtList_ parent, int idx, int new_kind
|
||||
where
|
||||
py_stmts(expr, old_kind, parent, idx) and
|
||||
new_kind = new_index(old_kind)
|
||||
select expr, new_kind, parent, idx
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,4 @@
|
||||
description: Add new statements and expressions for the match syntax.
|
||||
compatibility: backwards
|
||||
py_exprs.rel: run py_exprs.qlo
|
||||
py_stmts.rel: run py_stmts.qlo
|
||||
13
python/ql/test/experimental/dataflow/match/dataflowTest.ql
Normal file
13
python/ql/test/experimental/dataflow/match/dataflowTest.ql
Normal file
@@ -0,0 +1,13 @@
|
||||
import python
|
||||
import experimental.dataflow.TestUtil.FlowTest
|
||||
import experimental.dataflow.testConfig
|
||||
|
||||
class DataFlowTest extends FlowTest {
|
||||
DataFlowTest() { this = "DataFlowTest" }
|
||||
|
||||
override string flowTag() { result = "flow" }
|
||||
|
||||
override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
|
||||
exists(TestConfiguration cfg | cfg.hasFlow(source, sink))
|
||||
}
|
||||
}
|
||||
156
python/ql/test/experimental/dataflow/match/test.py
Normal file
156
python/ql/test/experimental/dataflow/match/test.py
Normal file
@@ -0,0 +1,156 @@
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname((__file__))))
|
||||
from testlib import *
|
||||
|
||||
# These are defined so that we can evaluate the test code.
|
||||
NONSOURCE = "not a source"
|
||||
SOURCE = "source"
|
||||
|
||||
|
||||
def is_source(x):
|
||||
return x == "source" or x == b"source" or x == 42 or x == 42.0 or x == 42j
|
||||
|
||||
|
||||
def SINK(x):
|
||||
if is_source(x):
|
||||
print("OK")
|
||||
else:
|
||||
print("Unexpected flow", x)
|
||||
|
||||
|
||||
def SINK_F(x):
|
||||
if is_source(x):
|
||||
print("Unexpected flow", x)
|
||||
else:
|
||||
print("OK")
|
||||
|
||||
def test_guard():
|
||||
match SOURCE:
|
||||
case x if SINK(x): #$ flow="SOURCE, l:-1 -> x"
|
||||
pass
|
||||
|
||||
@expects(2)
|
||||
def test_as_pattern():
|
||||
match SOURCE:
|
||||
case x as y:
|
||||
SINK(x) #$ flow="SOURCE, l:-2 -> x"
|
||||
SINK(y) #$ flow="SOURCE, l:-3 -> y"
|
||||
|
||||
def test_or_pattern():
|
||||
match SOURCE:
|
||||
# We cannot use NONSOURCE in place of "" below, since it would be seen as a variable.
|
||||
case ("" as x) | x:
|
||||
SINK(x) #$ flow="SOURCE, l:-3 -> x"
|
||||
|
||||
# No flow for literal pattern
|
||||
def test_literal_pattern():
|
||||
match SOURCE:
|
||||
case 42 as x:
|
||||
SINK(x) #$ flow="SOURCE, l:-2 -> x" flow="42, l:-1 -> x"
|
||||
|
||||
def test_capture_pattern():
|
||||
match SOURCE:
|
||||
case x:
|
||||
SINK(x) #$ flow="SOURCE, l:-2 -> x"
|
||||
|
||||
# No flow for wildcard pattern
|
||||
|
||||
class Unsafe:
|
||||
VALUE = SOURCE
|
||||
|
||||
def test_value_pattern():
|
||||
match SOURCE:
|
||||
case Unsafe.VALUE as x:
|
||||
SINK(x) #$ flow="SOURCE, l:-2 -> x" MISSING: flow="SOURCE, l:-5 -> x"
|
||||
|
||||
@expects(2)
|
||||
def test_sequence_pattern_tuple():
|
||||
match (NONSOURCE, SOURCE):
|
||||
case (x, y):
|
||||
SINK_F(x)
|
||||
SINK(y) #$ flow="SOURCE, l:-3 -> y"
|
||||
|
||||
@expects(2)
|
||||
def test_sequence_pattern_list():
|
||||
match [NONSOURCE, SOURCE]:
|
||||
case [x, y]:
|
||||
SINK_F(x) #$ SPURIOUS: flow="SOURCE, l:-2 -> x"
|
||||
SINK(y) #$ flow="SOURCE, l:-3 -> y"
|
||||
|
||||
# Sets are excluded from sequence patterns,
|
||||
# see https://www.python.org/dev/peps/pep-0635/#sequence-patterns
|
||||
|
||||
@expects(2)
|
||||
def test_star_pattern_tuple():
|
||||
match (NONSOURCE, SOURCE):
|
||||
case (x, *y):
|
||||
SINK_F(x)
|
||||
SINK(y[0]) #$ flow="SOURCE, l:-3 -> y[0]"
|
||||
|
||||
@expects(2)
|
||||
def test_star_pattern_tuple_exclusion():
|
||||
match (SOURCE, NONSOURCE):
|
||||
case (x, *y):
|
||||
SINK(x) #$ flow="SOURCE, l:-2 -> x"
|
||||
SINK_F(y[0])
|
||||
|
||||
@expects(2)
|
||||
def test_star_pattern_list():
|
||||
match [NONSOURCE, SOURCE]:
|
||||
case [x, *y]:
|
||||
SINK_F(x) #$ SPURIOUS: flow="SOURCE, l:-2 -> x"
|
||||
SINK(y[0]) #$ flow="SOURCE, l:-3 -> y[0]"
|
||||
|
||||
@expects(2)
|
||||
def test_star_pattern_list_exclusion():
|
||||
match [SOURCE, NONSOURCE]:
|
||||
case [x, *y]:
|
||||
SINK(x) #$ flow="SOURCE, l:-2 -> x"
|
||||
SINK_F(y[0]) #$ SPURIOUS: flow="SOURCE, l:-3 -> y[0]"
|
||||
|
||||
@expects(2)
|
||||
def test_mapping_pattern():
|
||||
match {"a": NONSOURCE, "b": SOURCE}:
|
||||
case {"a": x, "b": y}:
|
||||
SINK_F(x)
|
||||
SINK(y) #$ flow="SOURCE, l:-3 -> y"
|
||||
|
||||
# also tests the key value pattern
|
||||
@expects(2)
|
||||
def test_double_star_pattern():
|
||||
match {"a": NONSOURCE, "b": SOURCE}:
|
||||
case {"a": x, **y}:
|
||||
SINK_F(x)
|
||||
SINK(y["b"]) #$ flow="SOURCE, l:-3 -> y['b']"
|
||||
|
||||
@expects(2)
|
||||
def test_double_star_pattern_exclusion():
|
||||
match {"a": SOURCE, "b": NONSOURCE}:
|
||||
case {"a": x, **y}:
|
||||
SINK(x) #$ flow="SOURCE, l:-2 -> x"
|
||||
SINK_F(y["b"])
|
||||
try:
|
||||
SINK_F(y["a"])
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
class Cell:
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
||||
# also tests the keyword pattern
|
||||
@expects(2)
|
||||
def test_class_pattern():
|
||||
bad_cell = Cell(SOURCE)
|
||||
good_cell = Cell(NONSOURCE)
|
||||
|
||||
match bad_cell:
|
||||
case Cell(value = x):
|
||||
SINK(x) #$ flow="SOURCE, l:-5 -> x"
|
||||
|
||||
match good_cell:
|
||||
case Cell(value = x):
|
||||
SINK_F(x)
|
||||
@@ -57,6 +57,10 @@ if __name__ == "__main__":
|
||||
check_tests_valid("variable-capture.nonlocal")
|
||||
check_tests_valid("variable-capture.dict")
|
||||
check_tests_valid("module-initialization.multiphase")
|
||||
|
||||
# The below will fail unless we use Python 3.10 or newer.
|
||||
# check_tests_valid("match.test")
|
||||
|
||||
# The below fails when trying to import modules
|
||||
# check_tests_valid("module-initialization.test")
|
||||
# check_tests_valid("module-initialization.testOnce")
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
edges
|
||||
nodes
|
||||
subpaths
|
||||
#select
|
||||
25
python/ql/test/experimental/meta/debug/dataflowTestPaths.ql
Normal file
25
python/ql/test/experimental/meta/debug/dataflowTestPaths.ql
Normal file
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* @kind path-problem
|
||||
*/
|
||||
|
||||
// This query is for debugging InlineTaintTestFailures.
|
||||
// The intended usage is
|
||||
// 1. load the database of the failing test
|
||||
// 2. run this query to see actual paths
|
||||
// 3. if necessary, look at partial paths by (un)commenting appropriate lines
|
||||
import python
|
||||
import semmle.python.dataflow.new.DataFlow
|
||||
import experimental.dataflow.testConfig
|
||||
// import DataFlow::PartialPathGraph
|
||||
import DataFlow::PathGraph
|
||||
|
||||
class Conf extends TestConfiguration {
|
||||
override int explorationLimit() { result = 5 }
|
||||
}
|
||||
|
||||
// from Conf config, DataFlow::PartialPathNode source, DataFlow::PartialPathNode sink
|
||||
// where config.hasPartialFlow(source, sink, _)
|
||||
from Conf config, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where config.hasFlowPath(source, sink)
|
||||
select sink.getNode(), source, sink, "This node receives taint from $@.", source.getNode(),
|
||||
"this source"
|
||||
Reference in New Issue
Block a user