mirror of
https://github.com/github/codeql.git
synced 2026-01-28 22:02:57 +01:00
Extract type param declarations
This commit is contained in:
committed by
Chris Smowton
parent
3510f2cdcd
commit
1e08201632
@@ -275,6 +275,9 @@ var StmtParentType = NewUnionType("@stmtparent", NodeType)
|
||||
// DeclParentType is the type of AST nodes that can have declarations as children
|
||||
var DeclParentType = NewUnionType("@declparent", NodeType)
|
||||
|
||||
// TypeParamDeclParentType is the type of AST nodes that can have type parameter declarations as children
|
||||
var TypeParamDeclParentType = NewUnionType("@typeparamdeclparent", NodeType)
|
||||
|
||||
// FuncDefType is the type of AST nodes that define functions, that is, function
|
||||
// declarations and function literals
|
||||
var FuncDefType = NewUnionType("@funcdef", StmtParentType, ExprParentType)
|
||||
@@ -309,6 +312,9 @@ var StmtType = NewPrimaryKeyType("@stmt", ExprParentType, StmtParentType)
|
||||
// DeclType is the type of declaration AST nodes
|
||||
var DeclType = NewPrimaryKeyType("@decl", ExprParentType, StmtParentType, FieldParentType)
|
||||
|
||||
// TypeParamDeclType is the type of type parameter declaration AST nodes
|
||||
var TypeParamDeclType = NewPrimaryKeyType("@typeparamdecl", DocumentableType, ExprParentType)
|
||||
|
||||
// SpecType is the type of spec AST nodes
|
||||
var SpecType = NewPrimaryKeyType("@spec", ExprParentType, DocumentableType)
|
||||
|
||||
@@ -650,7 +656,7 @@ var TypeDeclType = DeclKind.NewBranch("@typedecl", GenDeclType)
|
||||
var VarDeclType = DeclKind.NewBranch("@vardecl", GenDeclType)
|
||||
|
||||
// FuncDeclType is the type of function declaration AST nodes
|
||||
var FuncDeclType = DeclKind.NewBranch("@funcdecl", DocumentableType, FuncDefType)
|
||||
var FuncDeclType = DeclKind.NewBranch("@funcdecl", DocumentableType, FuncDefType, TypeParamDeclParentType)
|
||||
|
||||
// SpecKind is a case type for distinguishing different kinds of declaration specification nodes
|
||||
var SpecKind = NewCaseType(SpecType, "kind")
|
||||
@@ -662,7 +668,7 @@ var ImportSpecType = SpecKind.NewBranch("@importspec")
|
||||
var ValueSpecType = SpecKind.NewBranch("@valuespec")
|
||||
|
||||
// TypeSpecType is the type of type declaration specification nodes
|
||||
var TypeSpecType = NewUnionType("@typespec")
|
||||
var TypeSpecType = NewUnionType("@typespec", TypeParamDeclParentType)
|
||||
|
||||
// TypeDefSpecType is the type of type declaration specification nodes corresponding to type definitions
|
||||
var TypeDefSpecType = SpecKind.NewBranch("@typedefspec", TypeSpecType)
|
||||
@@ -991,6 +997,13 @@ var FieldsTable = NewTable("fields",
|
||||
IntColumn("idx"),
|
||||
)
|
||||
|
||||
// TypeParamDeclsTable is the table defining type param declaration AST nodes
|
||||
var TypeParamDeclsTable = NewTable("typeparamdecls",
|
||||
EntityColumn(TypeParamDeclType, "id").Key(),
|
||||
EntityColumn(TypeParamDeclParentType, "parent"),
|
||||
IntColumn("idx"),
|
||||
)
|
||||
|
||||
// StmtsTable is the table defining statement AST nodes
|
||||
var StmtsTable = NewTable("stmts",
|
||||
EntityColumn(StmtType, "id").Key(),
|
||||
|
||||
@@ -1336,6 +1336,12 @@ func extractDecl(tw *trap.Writer, decl ast.Decl, parent trap.Label, idx int) {
|
||||
extractExpr(tw, decl.Type, lbl, 1)
|
||||
extractStmt(tw, decl.Body, lbl, 2)
|
||||
extractDoc(tw, decl.Doc, lbl)
|
||||
extractTypeParamDecls(tw, decl.Type.TypeParams, lbl)
|
||||
|
||||
// Note that we currently don't extract any kind of declaration for
|
||||
// receiver type parameters. There isn't an explicit declaration, but
|
||||
// we could consider the index/indices of an IndexExpr/IndexListExpr
|
||||
// receiver as declarations.
|
||||
default:
|
||||
log.Fatalf("unknown declaration of type %T", decl)
|
||||
}
|
||||
@@ -1377,6 +1383,7 @@ func extractSpec(tw *trap.Writer, spec ast.Spec, parent trap.Label, idx int) {
|
||||
kind = dbscheme.TypeDefSpecType.Index()
|
||||
}
|
||||
extractExpr(tw, spec.Name, lbl, 0)
|
||||
extractTypeParamDecls(tw, spec.TypeParams, lbl)
|
||||
extractExpr(tw, spec.Type, lbl, 1)
|
||||
extractDoc(tw, spec.Doc, lbl)
|
||||
}
|
||||
@@ -1798,3 +1805,26 @@ func flattenBinaryExprTree(tw *trap.Writer, e ast.Expr, parent trap.Label, idx i
|
||||
}
|
||||
return idx
|
||||
}
|
||||
|
||||
func extractTypeParamDecls(tw *trap.Writer, fields *ast.FieldList, parent trap.Label) {
|
||||
if fields == nil || fields.List == nil {
|
||||
return
|
||||
}
|
||||
|
||||
overrideTypesOfTypeSetLiterals(tw, fields)
|
||||
|
||||
idx := 0
|
||||
for _, field := range fields.List {
|
||||
lbl := tw.Labeler.LocalID(field)
|
||||
dbscheme.TypeParamDeclsTable.Emit(tw, lbl, parent, idx)
|
||||
extractNodeLocation(tw, field, lbl)
|
||||
if field.Names != nil {
|
||||
for i, name := range field.Names {
|
||||
extractExpr(tw, name, lbl, i+1)
|
||||
}
|
||||
}
|
||||
extractExpr(tw, field.Type, lbl, 0)
|
||||
extractDoc(tw, field.Doc, lbl)
|
||||
idx += 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,6 +157,8 @@ constvalues(unique int expr: @expr ref, string value: string ref, string exact:
|
||||
|
||||
fields(unique int id: @field, int parent: @fieldparent ref, int idx: int ref);
|
||||
|
||||
typeparamdecls(unique int id: @typeparamdecl, int parent: @typeparamdeclparent ref, int idx: int ref);
|
||||
|
||||
#keyset[parent, idx]
|
||||
stmts(unique int id: @stmt, int kind: int ref, int parent: @stmtparent ref, int idx: int ref);
|
||||
|
||||
@@ -231,12 +233,12 @@ typeparam(unique int tp: @typeparamtype ref, string name: string ref, int bound:
|
||||
|
||||
@locatable = @xmllocatable | @node | @localscope;
|
||||
|
||||
@node = @documentable | @exprparent | @modexprparent | @fieldparent | @stmtparent | @declparent | @scopenode
|
||||
| @comment_group | @comment;
|
||||
@node = @documentable | @exprparent | @modexprparent | @fieldparent | @stmtparent | @declparent | @typeparamdeclparent
|
||||
| @scopenode | @comment_group | @comment;
|
||||
|
||||
@documentable = @file | @field | @spec | @gendecl | @funcdecl | @modexpr;
|
||||
@documentable = @file | @field | @typeparamdecl | @spec | @gendecl | @funcdecl | @modexpr;
|
||||
|
||||
@exprparent = @funcdef | @file | @expr | @field | @stmt | @decl | @spec;
|
||||
@exprparent = @funcdef | @file | @expr | @field | @stmt | @decl | @typeparamdecl | @spec;
|
||||
|
||||
@modexprparent = @file | @modexpr;
|
||||
|
||||
@@ -246,6 +248,8 @@ typeparam(unique int tp: @typeparamtype ref, string name: string ref, int bound:
|
||||
|
||||
@declparent = @file | @declstmt;
|
||||
|
||||
@typeparamdeclparent = @functypeexpr | @typespec;
|
||||
|
||||
@funcdef = @funclit | @funcdecl;
|
||||
|
||||
@scopenode = @file | @functypeexpr | @blockstmt | @ifstmt | @caseclause | @switchstmt | @commclause | @loopstmt;
|
||||
|
||||
@@ -216,6 +216,24 @@ class FieldParent extends @fieldparent, AstNode {
|
||||
int getNumFields() { result = count(getAField()) }
|
||||
}
|
||||
|
||||
/**
|
||||
* An AST node whose children include type parameter declarations.
|
||||
*/
|
||||
class TypeParamDeclParent extends @typeparamdeclparent, AstNode {
|
||||
/**
|
||||
* Gets the `i`th type parameter declaration of this node.
|
||||
*
|
||||
* Note that the precise indices of type parameters are considered an implementation detail
|
||||
* and are subject to change without notice.
|
||||
*/
|
||||
TypeParamDecl getTypeParameterDecl(int i) { typeparamdecls(result, this, i) }
|
||||
|
||||
/**
|
||||
* Gets a child field of this node in the AST.
|
||||
*/
|
||||
TypeParamDecl getATypeParameterDecl() { result = getTypeParameterDecl(_) }
|
||||
}
|
||||
|
||||
/**
|
||||
* An AST node which may induce a scope.
|
||||
*
|
||||
|
||||
@@ -146,7 +146,7 @@ class FuncDef extends @funcdef, StmtParent, ExprParent {
|
||||
/**
|
||||
* A function declaration.
|
||||
*/
|
||||
class FuncDecl extends @funcdecl, Decl, Documentable, FuncDef {
|
||||
class FuncDecl extends @funcdecl, Decl, Documentable, FuncDef, TypeParamDeclParent {
|
||||
/** Gets the identifier denoting the name of this function. */
|
||||
Ident getNameExpr() { result = this.getChildExpr(0) }
|
||||
|
||||
@@ -376,7 +376,7 @@ class ValueSpec extends @valuespec, Spec {
|
||||
* )
|
||||
* ```
|
||||
*/
|
||||
class TypeSpec extends @typespec, Spec {
|
||||
class TypeSpec extends @typespec, Spec, TypeParamDeclParent {
|
||||
/** Gets the identifier denoting the name of the declared type. */
|
||||
Ident getNameExpr() { result = this.getChildExpr(0) }
|
||||
|
||||
@@ -562,6 +562,57 @@ class ResultVariableDecl extends ParameterOrResultDecl {
|
||||
override string getAPrimaryQlClass() { result = "ResultVariableDecl" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A type parameter declaration in a type specification.
|
||||
*/
|
||||
class TypeParamDecl extends @typeparamdecl, Documentable, ExprParent {
|
||||
TypeParamDecl() { typeparamdecls(this, _, _) }
|
||||
|
||||
/**
|
||||
* Gets the expression representing the type constraint of the type
|
||||
* parameters in this declaration.
|
||||
*
|
||||
* If you want the type constraint type itself then use `getTypeConstraint`,
|
||||
* as that wraps type set literals with implicit interface types.
|
||||
*/
|
||||
Expr getTypeConstraintExpr() { result = this.getChildExpr(0) }
|
||||
|
||||
/**
|
||||
* Gets the type constraint of the type parameters in this declaration.
|
||||
*
|
||||
* If the type constraint is a type set literal then it will be wrapped
|
||||
* with an implicit interface type.
|
||||
*/
|
||||
Type getTypeConstraint() {
|
||||
exists(Type t | t = this.getTypeConstraintExpr().getType() |
|
||||
if t instanceof TypeSetLiteralType
|
||||
then result = t.(TypeSetLiteralType).getInterfaceType()
|
||||
else result = t
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the expression representing the name of the `i`th type parameter
|
||||
* in this declaration (0-based).
|
||||
*/
|
||||
Expr getNameExpr(int i) {
|
||||
i >= 0 and
|
||||
result = this.getChildExpr(i + 1)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `i`th type parameter type in this declaration (0-based).
|
||||
*/
|
||||
TypeParamType getTypeParamType(int i) {
|
||||
i >= 0 and
|
||||
result = this.getNameExpr(i).getType()
|
||||
}
|
||||
|
||||
override string toString() { result = "type parameter declaration" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "TypeParamDecl" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A method or embedding specification in an interface type expression.
|
||||
*/
|
||||
|
||||
@@ -2096,6 +2096,10 @@ private predicate isTypeExprTopDown(Expr e) {
|
||||
or
|
||||
e = any(ParameterDecl pd).getTypeExpr()
|
||||
or
|
||||
e = any(TypeParamDecl tpd).getTypeConstraintExpr()
|
||||
or
|
||||
e = any(TypeParamDecl tpd).getNameExpr(_)
|
||||
or
|
||||
e = any(ReceiverDecl rd).getTypeExpr()
|
||||
or
|
||||
e = any(ResultVariableDecl rvd).getTypeExpr()
|
||||
|
||||
Reference in New Issue
Block a user