Extract type parameters in types, not just decls

This commit is contained in:
Owen Mansel-Chan
2022-03-29 14:54:49 +01:00
committed by Chris Smowton
parent 213fa1fec2
commit 92c331402d
5 changed files with 58 additions and 18 deletions

View File

@@ -682,6 +682,9 @@ var ObjectType = NewPrimaryKeyType("@object")
// ObjectKind is a case type for distinguishing different kinds of built-in and declared objects
var ObjectKind = NewCaseType(ObjectType, "kind")
// TypeParamParentObjectType is the type of objects that can have type parameters as children
var TypeParamParentObjectType = NewUnionType("@typeparamparentobject")
// DeclObjectType is the type of declared objects
var DeclObjectType = NewUnionType("@declobject")
@@ -695,7 +698,7 @@ var PkgObjectType = ObjectKind.NewBranch("@pkgobject")
var TypeObjectType = NewUnionType("@typeobject")
// DeclTypeObjectType is the type of declared named types
var DeclTypeObjectType = ObjectKind.NewBranch("@decltypeobject", TypeObjectType, DeclObjectType)
var DeclTypeObjectType = ObjectKind.NewBranch("@decltypeobject", TypeObjectType, DeclObjectType, TypeParamParentObjectType)
// BuiltinTypeObjectType is the type of built-in named types
var BuiltinTypeObjectType = ObjectKind.NewBranch("@builtintypeobject", TypeObjectType, BuiltinObjectType)
@@ -722,7 +725,7 @@ var DeclVarObjectType = ObjectKind.NewBranch("@declvarobject", VarObjectType, De
var FunctionObjectType = NewUnionType("@functionobject", ValueObjectType)
// DeclFuncObjectType is the type of declared functions, including (abstract and concrete) methods
var DeclFuncObjectType = ObjectKind.NewBranch("@declfunctionobject", FunctionObjectType, DeclObjectType)
var DeclFuncObjectType = ObjectKind.NewBranch("@declfunctionobject", FunctionObjectType, DeclObjectType, TypeParamParentObjectType)
// BuiltinFuncObjectType is the type of built-in functions
var BuiltinFuncObjectType = ObjectKind.NewBranch("@builtinfunctionobject", FunctionObjectType, BuiltinObjectType)
@@ -1206,8 +1209,11 @@ var VariadicTable = NewTable("variadic",
EntityColumn(SignatureType, "id"),
)
// TypeParamTable is the table describing type parameter types
var TypeParamTable = NewTable("typeparam",
EntityColumn(TypeParamType, "tp").Unique(),
StringColumn("name"),
EntityColumn(CompositeType, "bound"),
)
EntityColumn(TypeParamParentObjectType, "parent"),
IntColumn("idx"),
).KeySet("parent", "idx")

View File

@@ -363,6 +363,15 @@ func extractObjects(tw *trap.Writer, scope *types.Scope, scopeLabel trap.Label)
obj := scope.Lookup(name)
lbl, exists := tw.Labeler.ScopedObjectID(obj, func() trap.Label { return extractType(tw, obj.Type()) })
if !exists {
if funcObj, ok := obj.(*types.Func); ok {
populateTypeParamParents(tw, funcObj.Type().(*types.Signature).TypeParams(), lbl)
populateTypeParamParents(tw, funcObj.Type().(*types.Signature).RecvTypeParams(), lbl)
}
if typeNameObj, ok := obj.(*types.TypeName); ok {
if tp, ok := typeNameObj.Type().(*types.Named); ok {
populateTypeParamParents(tw, tp.TypeParams(), lbl)
}
}
extractObject(tw, obj, lbl)
}
@@ -378,10 +387,14 @@ func extractObjects(tw *trap.Writer, scope *types.Scope, scopeLabel trap.Label)
func extractMethod(tw *trap.Writer, meth *types.Func) trap.Label {
// get the receiver type of the method
recvtyp := meth.Type().(*types.Signature).Recv().Type()
recvlbl := extractType(tw, recvtyp) // ensure receiver type has been extracted
// ensure receiver type has been extracted
recvlbl := extractType(tw, recvtyp)
// if the method label does not exist, extract it
methlbl, exists := tw.Labeler.MethodID(meth, recvlbl)
if !exists {
populateTypeParamParents(tw, meth.Type().(*types.Signature).TypeParams(), methlbl)
populateTypeParamParents(tw, meth.Type().(*types.Signature).RecvTypeParams(), methlbl)
extractObject(tw, meth, methlbl)
}
@@ -1512,7 +1525,12 @@ func extractType(tw *trap.Writer, tp types.Type) trap.Label {
}
case *types.TypeParam:
kind = dbscheme.TypeParamType.Index()
dbscheme.TypeParamTable.Emit(tw, lbl, tp.Obj().Name(), extractType(tw, tp.Constraint()))
parentlbl, exists := tw.TypeParamParent[tp]
if !exists {
log.Fatalf("Parent of type parameter does not exist: %s", tp.String())
}
constraintLabel := extractType(tw, tp.Constraint())
dbscheme.TypeParamTable.Emit(tw, lbl, tp.Obj().Name(), constraintLabel, parentlbl, tp.Index())
case *types.Union:
kind = dbscheme.TypeSetLiteral.Index()
for i := 0; i < tp.Len(); i++ {
@@ -1651,7 +1669,8 @@ func getTypeLabel(tw *trap.Writer, tp types.Type) (trap.Label, bool) {
}
lbl = tw.Labeler.GlobalID(fmt.Sprintf("{%s};namedtype", entitylbl))
case *types.TypeParam:
lbl = tw.Labeler.GlobalID(fmt.Sprintf("{%s},{%s};typeparamtype", tp.Obj().Name(), extractType(tw, tp.Constraint())))
parentlbl := tw.TypeParamParent[tp]
lbl = tw.Labeler.GlobalID(fmt.Sprintf("{%v},%s;typeparamtype", parentlbl, tp.Obj().Name()))
case *types.Union:
var b strings.Builder
for i := 0; i < tp.Len(); i++ {
@@ -1828,3 +1847,12 @@ func extractTypeParamDecls(tw *trap.Writer, fields *ast.FieldList, parent trap.L
idx += 1
}
}
// populateTypeParamParents sets `parentlbl` as the parent of the elements of `typeparams`
func populateTypeParamParents(tw *trap.Writer, typeparams *types.TypeParamList, parentlbl trap.Label) {
if typeparams != nil {
for idx := 0; idx < typeparams.Len(); idx++ {
tw.TypeParamParent[typeparams.At(idx)] = parentlbl
}
}
}

View File

@@ -18,14 +18,15 @@ import (
// A Writer provides methods for writing data to a TRAP file
type Writer struct {
zip *gzip.Writer
w *bufio.Writer
file *os.File
Labeler *Labeler
path string
trapFilePath string
Package *packages.Package
TypesOverride map[ast.Expr]types.Type
zip *gzip.Writer
w *bufio.Writer
file *os.File
Labeler *Labeler
path string
trapFilePath string
Package *packages.Package
TypesOverride map[ast.Expr]types.Type
TypeParamParent map[*types.TypeParam]Label
}
func FileFor(path string) (string, error) {
@@ -64,6 +65,7 @@ func NewWriter(path string, pkg *packages.Package) (*Writer, error) {
trapFilePath,
pkg,
make(map[ast.Expr]types.Type),
make(map[*types.TypeParam]Label),
}
tw.Labeler = newLabeler(tw)
return tw, nil

View File

@@ -227,7 +227,9 @@ has_ellipsis(int id: @callorconversionexpr ref);
variadic(int id: @signaturetype ref);
typeparam(unique int tp: @typeparamtype ref, string name: string ref, int bound: @compositetype ref);
#keyset[parent, idx]
typeparam(unique int tp: @typeparamtype ref, string name: string ref, int bound: @compositetype ref,
int parent: @typeparamparentobject ref, int idx: int ref);
@container = @file | @folder;
@@ -248,7 +250,7 @@ typeparam(unique int tp: @typeparamtype ref, string name: string ref, int bound:
@declparent = @file | @declstmt;
@typeparamdeclparent = @functypeexpr | @typespec;
@typeparamdeclparent = @funcdecl | @typespec;
@funcdef = @funclit | @funcdecl;
@@ -439,6 +441,8 @@ case @object.kind of
| 7 = @builtinfunctionobject
| 8 = @labelobject;
@typeparamparentobject = @decltypeobject | @declfunctionobject;
@declobject = @decltypeobject | @declconstobject | @declvarobject | @declfunctionobject;
@builtinobject = @builtintypeobject | @builtinconstobject | @builtinfunctionobject;

View File

@@ -367,10 +367,10 @@ class CompositeType extends @compositetype, Type { }
/** A type that comes from a type parameter. */
class TypeParamType extends @typeparamtype, CompositeType {
/** Gets the name of this type parameter type. */
string getParamName() { typeparam(this, result, _) }
string getParamName() { typeparam(this, result, _, _, _) }
/** Gets the constraint of this type parameter type. */
Type getConstraint() { typeparam(this, _, result) }
Type getConstraint() { typeparam(this, _, result, _, _) }
override InterfaceType getUnderlyingType() { result = this.getConstraint().getUnderlyingType() }