Extract type param declarations

This commit is contained in:
Owen Mansel-Chan
2022-03-29 12:30:29 +01:00
committed by Chris Smowton
parent 3510f2cdcd
commit 1e08201632
6 changed files with 128 additions and 8 deletions

View File

@@ -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(),

View File

@@ -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
}
}

View File

@@ -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;

View File

@@ -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.
*

View File

@@ -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.
*/

View File

@@ -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()