From a20c935475c85a6ab7c921b2af13b505c1d2efa8 Mon Sep 17 00:00:00 2001 From: Iskander Sharipov Date: Wed, 6 Jan 2021 16:56:17 +0300 Subject: [PATCH] dsl: add experimental API related to the custom filters `dsl/types` is a wrapper around `go/types` that provides the minimal interface that is useful for custom filter. We may add `dsl/ast` later to mimic `go/ast` as well for node-related custom filters. See https://github.com/quasilyte/go-ruleguard/issues/129#issuecomment-754300523 to get more context on what this is about. --- dsl/dsl.go | 2 ++ dsl/filter.go | 25 +++++++++++++++++++++++++ dsl/types/ext.go | 9 +++++++++ dsl/types/type_impl.go | 11 +++++++++++ dsl/types/types.go | 32 ++++++++++++++++++++++++++++++++ 5 files changed, 79 insertions(+) create mode 100644 dsl/filter.go create mode 100644 dsl/types/ext.go create mode 100644 dsl/types/type_impl.go create mode 100644 dsl/types/types.go diff --git a/dsl/dsl.go b/dsl/dsl.go index ec9934b0..80135cdd 100644 --- a/dsl/dsl.go +++ b/dsl/dsl.go @@ -87,6 +87,8 @@ type Var struct { Node MatchedNode } +func (Var) Filter(pred func(*VarFilterContext) bool) bool { return boolResult } + // MatchedNode represents an AST node associated with a named submatch. type MatchedNode struct{} diff --git a/dsl/filter.go b/dsl/filter.go new file mode 100644 index 00000000..4a89363e --- /dev/null +++ b/dsl/filter.go @@ -0,0 +1,25 @@ +package dsl + +import ( + "github.com/quasilyte/go-ruleguard/dsl/types" +) + +// VarFilterContext carries Var and environment information into the filter function. +// It's an input parameter type for the Var.Filter function callback. +type VarFilterContext struct { + // Type is mapped to Var.Type field. + Type types.Type +} + +// SizeOf returns the size of the given type. +func (*VarFilterContext) SizeOf(x types.Type) int { return 0 } + +// GetType finds a type value by a given name. +// A name can be: +// - builtin type name, like `error` or `string` +// - fully-qualified type name, like `github.com/username/pkgname.TypeName` +func (*VarFilterContext) GetType(name string) types.Type { return nil } + +// GetInterface finds a type value that represents an interface by a given name. +// Works like `types.AsInterface(ctx.GetType(name))`. +func (*VarFilterContext) GetInterface(name string) *types.Interface { return nil } diff --git a/dsl/types/ext.go b/dsl/types/ext.go new file mode 100644 index 00000000..74be93ad --- /dev/null +++ b/dsl/types/ext.go @@ -0,0 +1,9 @@ +package types + +// AsPointer is a type-assert like operation, x.(*Pointer), but never panics. +// Returns nil if type is not a pointer. +func AsPointer(x Type) *Pointer { return nil } + +// AsInterface is a type-assert like operation, x.(*Interface), but never panics. +// Returns nil if type is not an interface. +func AsInterface(x Type) *Interface { return nil } diff --git a/dsl/types/type_impl.go b/dsl/types/type_impl.go new file mode 100644 index 00000000..59362e11 --- /dev/null +++ b/dsl/types/type_impl.go @@ -0,0 +1,11 @@ +package types + +// Method stubs to make various types implement Type interface. +// +// Nothing interesting here, hence it's moved to a separate file. + +func (*Pointer) String() string { return "" } +func (*Interface) String() string { return "" } + +func (*Pointer) Underlying() Type { return nil } +func (*Interface) Underlying() Type { return nil } diff --git a/dsl/types/types.go b/dsl/types/types.go new file mode 100644 index 00000000..917df364 --- /dev/null +++ b/dsl/types/types.go @@ -0,0 +1,32 @@ +// Package types mimics the https://golang.org/pkg/go/types/ package. +// It also contains some extra utility functions, they're defined in ext.go file. +package types + +// Implements reports whether a given type implements the specified interface. +func Implements(typ Type, iface *Interface) bool { return false } + +// Identical reports whether x and y are identical types. Receivers of Signature types are ignored. +func Identical(x, y Type) bool { return false } + +// A Type represents a type of Go. All types implement the Type interface. +type Type interface { + // Underlying returns the underlying type of a type. + Underlying() Type + + // String returns a string representation of a type. + String() string +} + +type ( + // A Pointer represents a pointer type. + Pointer struct{} + + // An Interface represents an interface type. + Interface struct{} +) + +// NewPointer returns a new pointer type for the given element (base) type. +func NewPointer(elem Type) *Pointer { return nil } + +// Elem returns the element type for the given pointer. +func (*Pointer) Elem() Type { return nil }