package dsl // Matcher is a main API group-level entry point. // It's used to define and configure the group rules. // It also represents a map of all rule-local variables. type Matcher map[string]Var // Import loads given package path into a rule group imports table. // // That table is used during the rules compilation. // // The table has the following effect on the rules: // * For type expressions, it's used to resolve the // full package paths of qualified types, like `foo.Bar`. // If Import(`a/b/foo`) is called, `foo.Bar` will match // `a/b/foo.Bar` type during the pattern execution. func (m Matcher) Import(pkgPath string) {} // Match specifies a set of patterns that match a rule being defined. // Pattern matching succeeds if at least 1 pattern matches. // // If none of the given patterns matched, rule execution stops. func (m Matcher) Match(pattern string, alternatives ...string) Matcher { return m } // MatchComment is like Match, but handles only comments and uses regexp patterns. // // Multi-line /**/ comments are passed as a single string. // Single-line // comments are passed line-by-line. // // Hint: if you want to match a plain text and don't want to do meta char escaping, // prepend `\Q` to your pattern. `\Qf(x)` will match `f(x)` as a plain text // and there is no need to escape the `(` and `)` chars. // // Named regexp capture groups can be accessed using the usual indexing notation. // // Given this pattern: // // `(?P\d+)\.(\d+).(?P\d+)` // // And this input comment: `// 14.6.600` // // We'll get these submatches: // // m["$$"] => `14.6.600` // m["first"] => `14` // m["second"] => `600` // // All usual filters can be applied: // // Where(!m["first"].Text.Matches(`foo`)) // // You can use this to reject some matches (allow-list behavior). func (m Matcher) MatchComment(pattern string, alternatives ...string) Matcher { return m } // Where applies additional constraint to a match. // If a given cond is not satisfied, a match is rejected and // rule execution stops. func (m Matcher) Where(cond bool) Matcher { return m } // Report prints a message if associated rule match is successful. // // A message is a string that can contain interpolated expressions. // For every matched variable it's possible to interpolate // their printed representation into the message text with $. // An entire match can be addressed with $$. func (m Matcher) Report(message string) Matcher { return m } // Suggest assigns a quickfix suggestion for the matched code. func (m Matcher) Suggest(suggestion string) Matcher { return m } func (m Matcher) Do(fn func(*DoContext)) Matcher { return m } // At binds the reported node to a named submatch. // If no explicit location is given, the outermost node ($$) is used. func (m Matcher) At(v Var) Matcher { return m } // File returns the current file context. func (m Matcher) File() File { return File{} } // GoVersion returns the analyzer associated target Go language version. func (m Matcher) GoVersion() GoVersion { return GoVersion{} } // Deadcode reports whether this match is contained inside a dead code path. func (m Matcher) Deadcode() bool { return boolResult } // Var is a pattern variable that describes a named submatch. type Var struct { // Pure reports whether expr matched by var is side-effect-free. Pure bool // Const reports whether expr matched by var is a constant value. Const bool // ConstSlice reports whether expr matched by var is a slice literal // consisting of contant elements. // // We need a separate Const-like predicate here because Go doesn't // treat slices of const elements as constants, so including // them in Const would be incorrect. // Use `m["x"].Const || m["x"].ConstSlice` when you need // to have extended definition of "constant value". // // Some examples: // []byte("foo") -- constant byte slice // []byte{'f', 'o', 'o'} -- same constant byte slice // []int{1, 2} -- constant int slice ConstSlice bool // Value is a compile-time computable value of the expression. Value ExprValue // Addressable reports whether the corresponding expression is addressable. // See https://golang.org/ref/spec#Address_operators. Addressable bool // Comparable reports whether the corresponding expression value is comparable. // See https://pkg.go.dev/go/types#Comparable. Comparable bool // Type is a type of a matched expr. // // For function call expressions, a type is a function result type, // but for a function expression itself it's a *types.Signature. // // Suppose we have a `a.b()` expression: // `$x()` m["x"].Type is `a.b` function type // `$x` m["x"].Type is `a.b()` function call result type Type ExprType SinkType SinkType // Object is an associated "go/types" Object. Object TypesObject // Text is a captured node text as in the source code. Text MatchedText // Node is a captured AST node. Node MatchedNode // Line is a source code line number that contains this match. // If this match is multi-line, this is the first line number. Line int } // Filter applies a custom predicate function on a submatch. // // The callback function should use VarFilterContext to access the // information that is usually accessed through Var. // For example, `VarFilterContext.Type` is mapped to `Var.Type`. func (Var) Filter(pred func(*VarFilterContext) bool) bool { return boolResult } // Contains runs a sub-search from a given pattern using the captured // vars from the original pattern match. // // For example, given the Match(`$lhs = append($lhs, $x)`) pattern, // we can do m["lhs"].Contains(`$x`) and learn whether $lhs contains // $x as its sub-expression. // // Experimental: this function is not part of the stable API. func (Var) Contains(pattern string) bool { return boolResult } // MatchedNode represents an AST node associated with a named submatch. type MatchedNode struct{} // Is reports whether a matched node AST type is compatible with the specified type. // A valid argument is a ast.Node implementing type name from the "go/ast" package. // Examples: "BasicLit", "Expr", "Stmt", "Ident", "ParenExpr". // See https://golang.org/pkg/go/ast/. func (MatchedNode) Is(typ string) bool { return boolResult } // Parent returns a matched node parent. func (MatchedNode) Parent() Node { return Node{} } // Node represents an AST node somewhere inside a match. // Unlike MatchedNode, it doesn't have to be associated with a named submatch. type Node struct{} // Is reports whether a node AST type is compatible with the specified type. // See `MatchedNode.Is` for the full reference. func (Node) Is(typ string) bool { return boolResult } // ExprValue describes a compile-time computable value of a matched expr. type ExprValue struct{} // Int returns compile-time computable int value of the expression. // If value can't be computed, condition will fail. func (ExprValue) Int() int { return intResult } // TypesObject is a types.Object mapping. type TypesObject struct{} // Is reports whether an associated types.Object is compatible with the specified type. // A valid argument is a types.Object type name from the "go/types" package. // Examples: "Func", "Var", "Const", "TypeName", "Label", "PkgName", "Builtin", "Nil" // See https://golang.org/pkg/go/types/. func (TypesObject) Is(typ string) bool { return boolResult } // IsGlobal reports whether an associated types.Object is defined in global scope. func (TypesObject) IsGlobal() bool { return boolResult } // IsVariadicParam reports whether this object represents a function variadic param. // This property is not propagated between the assignments. func (TypesObject) IsVariadicParam() bool { return boolResult } type SinkType struct{} // Is reports whether a type is identical to a given type. // Works like ExprType.Is method. func (SinkType) Is(typ string) bool { return boolResult } // ExprType describes a type of a matcher expr. type ExprType struct { // Size represents expression type size in bytes. // // For expressions of unknown size, like type params in generics, // any filter using this operand will fail. Size int } // IdenticalTo applies types.Identical(this, v.Type) operation. // See https://golang.org/pkg/go/types/#Identical function documentation. // // Experimental: this function is not part of the stable API. func (ExprType) IdenticalTo(v Var) bool { return boolResult } // Underlying returns expression type underlying type. // See https://golang.org/pkg/go/types/#Type Underlying() method documentation. // Read https://golang.org/ref/spec#Types section to learn more about underlying types. func (ExprType) Underlying() ExprType { return underlyingType } // AssignableTo reports whether a type is assign-compatible with a given type. // See https://golang.org/pkg/go/types/#AssignableTo. func (ExprType) AssignableTo(typ string) bool { return boolResult } // ConvertibleTo reports whether a type is conversible to a given type. // See https://golang.org/pkg/go/types/#ConvertibleTo. func (ExprType) ConvertibleTo(typ string) bool { return boolResult } // Implements reports whether a type implements a given interface. // See https://golang.org/pkg/go/types/#Implements. func (ExprType) Implements(typ typeName) bool { return boolResult } // HasMethod reports whether a type has a given method. // Unlike Implements(), it will work for both value and pointer types. // // fn argument is a function signature, like `WriteString(string) (int, error)`. // It can also be in form of a method reference for importable types: `io.StringWriter.WriteString`. // // To avoid confusion with Implements() method, here is a hint when to use which: // // - To check if it's possible to call F on x, use HasMethod(F) // - To check if x can be passed as I interface, use Implements(I) func (ExprType) HasMethod(fn string) bool { return boolResult } // Is reports whether a type is identical to a given type. func (ExprType) Is(typ string) bool { return boolResult } // HasPointers reports whether a type contains at least one pointer. // // We try to be as close to the Go sense of pointer-free objects as possible, // therefore string type is not considered to be a pointer-free type. // // This function may return "true" for some complicated cases as a // conservative result. It never returns "false" for a type that // actually contains a pointer. // // So this function is mostly useful for !HasPointers() form. func (ExprType) HasPointers() bool { return boolResult } // OfKind reports whether a matched expr type is compatible with the specified kind. // // Only a few "kinds" are recognized, the list is provided below. // // "integer" -- typ is *types.Basic, where typ.Info()&types.Integer != 0 // "unsigned" -- typ is *types.Basic, where typ.Info()&types.Unsigned != 0 // "float" -- typ is *types.Basic, where typ.Info()&types.Float != 0 // "complex" -- typ is *types.Basic, where typ.Info()&types.Complex != 0 // "untyped" -- typ is *types.Basic, where typ.Info()&types.Untyped != 0 // "numeric" -- typ is *types.Basic, where typ.Info()&types.Numeric != 0 // "signed" -- identical to `OfKind("integer") && !OfKind("unsigned")` // "int" -- int, int8, int16, int32, int64 // "uint" -- uint, uint8, uint16, uint32, uint64 // // Note: "int" will include "rune" as well, as it's an alias. // In the same manner, "uint" includes the "byte" type. // // Using OfKind("unsigned") is more efficient (and concise) than using a set // of or-conditions with Is("uint8"), Is("uint16") and so on. func (ExprType) OfKind(kind string) bool { return boolResult } // MatchedText represents a source text associated with a matched node. type MatchedText string // Matches reports whether the text matches the given regexp pattern. func (MatchedText) Matches(pattern string) bool { return boolResult } // String represents an arbitrary string-typed data. type String string // Matches reports whether a string matches the given regexp pattern. func (String) Matches(pattern string) bool { return boolResult } // File represents the current Go source file. type File struct { // Name is a file base name. Name String // PkgPath is a file package path. // Examples: "io/ioutil", "strings", "github.com/quasilyte/go-ruleguard/dsl". PkgPath String } // Imports reports whether the current file imports the given path. func (File) Imports(path string) bool { return boolResult } // GoVersion is an analysis target go language version. // It can be compared to Go versions like "1.10", "1.16" using // the associated methods. type GoVersion struct{} // Eq asserts that target Go version is equal to (==) specified version. func (GoVersion) Eq(version string) bool { return boolResult } // GreaterEqThan asserts that target Go version is greater or equal than (>=) specified version. func (GoVersion) GreaterEqThan(version string) bool { return boolResult } // GreaterThan asserts that target Go version is greater than (>) specified version. func (GoVersion) GreaterThan(version string) bool { return boolResult } // LessThan asserts that target Go version is less than (<) specified version. func (GoVersion) LessThan(version string) bool { return boolResult } // LessEqThan asserts that target Go version is less or equal than (<=) specified version. func (GoVersion) LessEqThan(version string) bool { return boolResult } // typeName is a helper type used to document function params better. // // A type name can be: // - builtin type name: `error`, `string`, etc. // - qualified name from a standard library: `io.Reader`, etc. // - fully-qualified type name, like `github.com/username/pkgname.TypeName` // // typeName is also affected by a local import table, which can override // how qualified names are interpreted. // See `Matcher.Import` for more info. type typeName = string